asdf98 commited on
Commit
7967f6e
·
verified ·
1 Parent(s): 73ff76e

fix: hover ADD nonce captureId and cleanup old badge DOM to prevent duplicate old overlay handlers

Browse files
src-tauri/resources/scripts/hover_overlay.js CHANGED
@@ -1,27 +1,32 @@
1
  /* Refstudio hover overlay: + ADD button on web images.
2
- * v11fires ONLY through window.location.href (on_navigation handler).
3
- * Previous versions fired 3 channels causing duplicate images.
4
  */
5
  (function () {
6
- if (window.__muse_hover_v11) return;
7
- window.__muse_hover_v11 = true;
 
 
 
 
 
8
 
9
  var MIN = 90;
10
  var activeImg = null;
11
  var badge = null;
12
  var showTimer = 0;
13
  var hideTimer = 0;
14
- var capturing = false; // prevent double-click
15
 
16
  function injectCSS() {
17
- if (document.getElementById('__muse_badge_css3')) return;
18
- var s = document.createElement('style'); s.id = '__muse_badge_css3';
19
  s.textContent = '#__muse_add_badge{all:initial;position:fixed;z-index:2147483647;display:flex;align-items:center;gap:5px;padding:8px 16px;background:rgba(10,132,255,0.95);color:#fff;border-radius:999px;box-shadow:0 4px 20px rgba(0,0,0,0.4),0 0 0 1px rgba(255,255,255,0.1);font:700 12px/1 -apple-system,BlinkMacSystemFont,"Inter",sans-serif;cursor:pointer;opacity:0;transform:translateY(4px) scale(0.92);transition:opacity .2s,transform .2s,background .1s;pointer-events:auto;letter-spacing:0.01em;user-select:none}#__muse_add_badge.v{opacity:1;transform:none}#__muse_add_badge:hover{background:rgba(10,132,255,1);box-shadow:0 6px 28px rgba(10,132,255,0.4),0 0 0 1px rgba(255,255,255,0.2);transform:scale(1.06)}#__muse_add_badge:active{transform:scale(0.92);background:rgba(10,100,220,1)}#__muse_add_badge svg{width:14px;height:14px;stroke-width:2.5;pointer-events:none}#__mt7{all:initial;position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(8px);z-index:2147483647;padding:9px 16px;border-radius:999px;background:rgba(20,20,20,.97);border:1px solid rgba(255,255,255,.1);box-shadow:0 10px 36px rgba(0,0,0,.5);font:600 12px/1 -apple-system,sans-serif;color:#fff;opacity:0;transition:opacity .16s,transform .16s;pointer-events:none}#__mt7.s{opacity:1;transform:translateX(-50%) translateY(0)}';
20
  (document.head || document.documentElement).appendChild(s);
21
  }
22
 
23
  function enc(v) { return encodeURIComponent(v == null ? '' : String(v)); }
24
  function absUrl(s) { try { return new URL(s || '', location.href).href; } catch (_) { return s || ''; } }
 
25
 
26
  function bestImageUrl(img) {
27
  var srcset = img.getAttribute('srcset') || '';
@@ -37,19 +42,15 @@
37
  function fireAction(url, title, w, h) {
38
  if (capturing) return;
39
  capturing = true;
40
- // ONLY use window.location.href — Tauri on_navigation will intercept and return false.
41
- // This is the single reliable path. Do NOT also fire beacon/fetch (causes duplicates).
42
- var u = 'muse-action://board?url='+enc(url)+'&source='+enc(location.href)+'&title='+enc(title)+'&w='+enc(w)+'&h='+enc(h);
43
  window.location.href = u;
44
- // Reset after short delay (the page won't actually navigate since Rust returns false)
45
  setTimeout(function(){ capturing = false; }, 1000);
46
  }
47
 
48
  function clearHide(){clearTimeout(hideTimer);}
49
  function scheduleHide(){clearHide();hideTimer=setTimeout(hide,600);}
50
-
51
  function hide(){if(!badge)return;badge.classList.remove('v');activeImg=null;}
52
-
53
  function pos(el,img){var r=img.getBoundingClientRect();var x=r.right-80,y=r.top+10;if(x<r.left+4)x=r.left+4;if(x>innerWidth-90)x=innerWidth-90;if(y<4)y=4;if(y>innerHeight-40)y=innerHeight-40;el.style.left=x+'px';el.style.top=y+'px';}
54
 
55
  function show(img){
@@ -68,7 +69,6 @@
68
  }
69
 
70
  function isValid(el){if(!el||el.tagName!=='IMG')return false;if(el===badge)return false;var r=el.getBoundingClientRect();return r.width>=MIN&&r.height>=MIN;}
71
-
72
  document.addEventListener('mouseover',function(e){var t=e.target;if(badge&&(t===badge||badge.contains(t))){clearHide();return;}if(!isValid(t))return;if(t===activeImg){clearHide();return;}clearHide();clearTimeout(showTimer);showTimer=setTimeout(function(){show(t);},150);},true);
73
  document.addEventListener('mouseout',function(e){var t=e.target;if(!t||t.tagName!=='IMG'||t!==activeImg)return;var rel=e.relatedTarget;if(badge&&rel&&(badge===rel||badge.contains(rel))){clearHide();return;}clearTimeout(showTimer);scheduleHide();},true);
74
  window.addEventListener('scroll',function(){if(!badge||!activeImg)return;var r=activeImg.getBoundingClientRect();if(r.bottom<-20||r.top>innerHeight+20)hide();else pos(badge,activeImg);},{passive:true,capture:true});
 
1
  /* Refstudio hover overlay: + ADD button on web images.
2
+ * v12stable one-click capture with captureId nonce.
 
3
  */
4
  (function () {
5
+ if (window.__muse_hover_v12) return;
6
+ window.__muse_hover_v12 = true;
7
+
8
+ // Remove old badge DOM left by previous injected versions. Anonymous old listeners
9
+ // may still exist, but they cannot duplicate backend actions because v12 adds captureId
10
+ // and Rust dedupes captureIds.
11
+ try { var old = document.getElementById('__muse_add_badge'); if (old) old.remove(); } catch (_) {}
12
 
13
  var MIN = 90;
14
  var activeImg = null;
15
  var badge = null;
16
  var showTimer = 0;
17
  var hideTimer = 0;
18
+ var capturing = false;
19
 
20
  function injectCSS() {
21
+ if (document.getElementById('__muse_badge_css_v12')) return;
22
+ var s = document.createElement('style'); s.id = '__muse_badge_css_v12';
23
  s.textContent = '#__muse_add_badge{all:initial;position:fixed;z-index:2147483647;display:flex;align-items:center;gap:5px;padding:8px 16px;background:rgba(10,132,255,0.95);color:#fff;border-radius:999px;box-shadow:0 4px 20px rgba(0,0,0,0.4),0 0 0 1px rgba(255,255,255,0.1);font:700 12px/1 -apple-system,BlinkMacSystemFont,"Inter",sans-serif;cursor:pointer;opacity:0;transform:translateY(4px) scale(0.92);transition:opacity .2s,transform .2s,background .1s;pointer-events:auto;letter-spacing:0.01em;user-select:none}#__muse_add_badge.v{opacity:1;transform:none}#__muse_add_badge:hover{background:rgba(10,132,255,1);box-shadow:0 6px 28px rgba(10,132,255,0.4),0 0 0 1px rgba(255,255,255,0.2);transform:scale(1.06)}#__muse_add_badge:active{transform:scale(0.92);background:rgba(10,100,220,1)}#__muse_add_badge svg{width:14px;height:14px;stroke-width:2.5;pointer-events:none}#__mt7{all:initial;position:fixed;left:50%;bottom:24px;transform:translateX(-50%) translateY(8px);z-index:2147483647;padding:9px 16px;border-radius:999px;background:rgba(20,20,20,.97);border:1px solid rgba(255,255,255,.1);box-shadow:0 10px 36px rgba(0,0,0,.5);font:600 12px/1 -apple-system,sans-serif;color:#fff;opacity:0;transition:opacity .16s,transform .16s;pointer-events:none}#__mt7.s{opacity:1;transform:translateX(-50%) translateY(0)}';
24
  (document.head || document.documentElement).appendChild(s);
25
  }
26
 
27
  function enc(v) { return encodeURIComponent(v == null ? '' : String(v)); }
28
  function absUrl(s) { try { return new URL(s || '', location.href).href; } catch (_) { return s || ''; } }
29
+ function captureId() { return Date.now().toString(36) + '-' + Math.random().toString(36).slice(2); }
30
 
31
  function bestImageUrl(img) {
32
  var srcset = img.getAttribute('srcset') || '';
 
42
  function fireAction(url, title, w, h) {
43
  if (capturing) return;
44
  capturing = true;
45
+ var id = captureId();
46
+ var u = 'muse-action://board?captureId='+enc(id)+'&url='+enc(url)+'&source='+enc(location.href)+'&title='+enc(title)+'&w='+enc(w)+'&h='+enc(h);
 
47
  window.location.href = u;
 
48
  setTimeout(function(){ capturing = false; }, 1000);
49
  }
50
 
51
  function clearHide(){clearTimeout(hideTimer);}
52
  function scheduleHide(){clearHide();hideTimer=setTimeout(hide,600);}
 
53
  function hide(){if(!badge)return;badge.classList.remove('v');activeImg=null;}
 
54
  function pos(el,img){var r=img.getBoundingClientRect();var x=r.right-80,y=r.top+10;if(x<r.left+4)x=r.left+4;if(x>innerWidth-90)x=innerWidth-90;if(y<4)y=4;if(y>innerHeight-40)y=innerHeight-40;el.style.left=x+'px';el.style.top=y+'px';}
55
 
56
  function show(img){
 
69
  }
70
 
71
  function isValid(el){if(!el||el.tagName!=='IMG')return false;if(el===badge)return false;var r=el.getBoundingClientRect();return r.width>=MIN&&r.height>=MIN;}
 
72
  document.addEventListener('mouseover',function(e){var t=e.target;if(badge&&(t===badge||badge.contains(t))){clearHide();return;}if(!isValid(t))return;if(t===activeImg){clearHide();return;}clearHide();clearTimeout(showTimer);showTimer=setTimeout(function(){show(t);},150);},true);
73
  document.addEventListener('mouseout',function(e){var t=e.target;if(!t||t.tagName!=='IMG'||t!==activeImg)return;var rel=e.relatedTarget;if(badge&&rel&&(badge===rel||badge.contains(rel))){clearHide();return;}clearTimeout(showTimer);scheduleHide();},true);
74
  window.addEventListener('scroll',function(){if(!badge||!activeImg)return;var r=activeImg.getBoundingClientRect();if(r.bottom<-20||r.top>innerHeight+20)hide();else pos(badge,activeImg);},{passive:true,capture:true});