| 241 | if (r1 !== 'opened') throw new Error('composeur introuvable (' + r1 + ')'); |
241 | if (r1 !== 'opened') throw new Error('composeur introuvable (' + r1 + ')'); |
| 242 | await sleep(3000); |
242 | await sleep(3000); |
| 243 | |
243 | |
| 244 | − // 2) coller la légende via ClipboardEvent synthétique (base64, sans clavier) |
244 | + // 2) coller la légende dans le TEXTBOX VISIBLE (évite les dialogues empilés |
| |
245 | + // et le double collage) — atomique : ne colle que si le box est encore vide. |
| 245 | const b64cap = Buffer.from(caption, 'utf8').toString('base64'); |
246 | const b64cap = Buffer.from(caption, 'utf8').toString('base64'); |
| |
247 | + // trouve le contenteditable visible le plus « profond » (composeur actif) |
| |
248 | + const findBoxFn = `function(){ |
| |
249 | + var all=[].slice.call(document.querySelectorAll('div[role=dialog] div[contenteditable=true][role=textbox]')); |
| |
250 | + if(!all.length) all=[].slice.call(document.querySelectorAll('div[role=dialog] div[contenteditable=true]')); |
| |
251 | + var vis=all.filter(function(b){var r=b.getBoundingClientRect();return r.width>10&&r.height>10&&r.top>=0&&r.left>=0;}); |
| |
252 | + return vis.length?vis[vis.length-1]:(all.length?all[all.length-1]:null); |
| |
253 | + }`; |
| 246 | const pasteJS = `(function(){ |
254 | const pasteJS = `(function(){ |
| 247 | − var dlg=document.querySelector('div[role=dialog]'); if(!dlg) return 'NO_DIALOG'; |
255 | + var box=(${findBoxFn})(); if(!box) return 'NO_BOX'; |
| 248 | − var box=dlg.querySelector('div[contenteditable=true][role=textbox]'); if(!box) return 'NO_BOX'; |
256 | + if((box.innerText||'').replace(/\\s/g,'').length>20) return 'already:'+box.innerText.length; // déjà rempli -> ne pas recoller |
| 249 | box.focus(); |
257 | box.focus(); |
| 250 | var txt=decodeURIComponent(escape(atob('${b64cap}'))); |
258 | var txt=decodeURIComponent(escape(atob('${b64cap}'))); |
| 251 | var dt=new DataTransfer(); dt.setData('text/plain', txt); |
259 | var dt=new DataTransfer(); dt.setData('text/plain', txt); |
| 252 | box.dispatchEvent(new ClipboardEvent('paste',{clipboardData:dt,bubbles:true,cancelable:true})); |
260 | box.dispatchEvent(new ClipboardEvent('paste',{clipboardData:dt,bubbles:true,cancelable:true})); |
| 253 | return 'pasted'; |
261 | return 'pasted'; |
| 254 | })();`; |
262 | })();`; |
| 255 | − const checkLen = `(function(){var dlg=document.querySelector('div[role=dialog]');` + |
263 | + const checkLen = `(function(){var box=(${findBoxFn})();return 'len:'+(box?box.innerText.length:-1);})();`; |
| 256 | − `var box=dlg&&dlg.querySelector('div[contenteditable=true][role=textbox]');` + |
| |
| 257 | − `return 'len:'+(box?box.innerText.length:-1);})();`; |
| |
| 258 | let len = 0; |
264 | let len = 0; |
| 259 | for (let i = 0; i < 3; i++) { |
265 | for (let i = 0; i < 3; i++) { |
| 260 | − await osaJS(pasteJS); await sleep(2500); |
266 | + const r = await osaJS(pasteJS); |
| |
267 | + await sleep(2500); |
| 261 | const l = await osaJS(checkLen); len = parseInt((l.split(':')[1] || '0'), 10); |
268 | const l = await osaJS(checkLen); len = parseInt((l.split(':')[1] || '0'), 10); |
| 262 | − if (len > 40) break; await sleep(1500); |
269 | + if (len > 40) break; |
| |
270 | + await sleep(1200); |
| 263 | } |
271 | } |
| 264 | if (!(len > 40)) throw new Error('collage légende échoué'); |
272 | if (!(len > 40)) throw new Error('collage légende échoué'); |
| 265 | |
273 | |
| 266 | |
274 | |