/* widget: Foto & video */
/* =========================================================
Media widget — photos and videos from external sites
==========================================================*/
function mountMedia(root, initState){
let cur = null;
root.innerHTML = `
`;
const urlInp = root.querySelector(".m-url"),
goBtn = root.querySelector(".m-go"),
extBtn = root.querySelector(".m-ext"),
stage = root.querySelector(".media-stage");
function labels(){
urlInp.placeholder = T("mediaPh");
goBtn.textContent = T("mediaShow");
extBtn.title = T("mediaOpen");
const msg = stage.querySelector(".media-msg");
if(msg) msg.textContent = T(msg.dataset.err ? "mediaErr" : "mediaEmpty");
}
function showMsg(err){
stage.innerHTML = "";
const m = document.createElement("div");
m.className = "media-msg";
if(err) m.dataset.err = "1";
m.textContent = T(err ? "mediaErr" : "mediaEmpty");
stage.appendChild(m);
}
function show(raw){
let url = raw.trim();
if(!url){ showMsg(false); return; }
if(!/^https?:\/\//i.test(url)) url = "https://"+url;
let node = null;
const yt = url.match(/(?:youtube\.com\/(?:watch\?[^#]*v=|shorts\/|embed\/|live\/)|youtu\.be\/)([\w-]{6,})/);
const vi = url.match(/vimeo\.com\/(?:video\/)?(\d+)/);
if(yt){
/* show the thumbnail first (always works); play attempts the embed */
const id = yt[1];
stage.innerHTML = "";
const wrap = document.createElement("div");
wrap.className = "media-yt";
const im = document.createElement("img");
im.src = "https://i.ytimg.com/vi/"+id+"/hqdefault.jpg"; im.alt = "";
const pb = document.createElement("button");
pb.className = "media-play"; pb.textContent = "▶";
pb.addEventListener("click", ()=>{
const f = document.createElement("iframe");
f.src = "https://www.youtube.com/embed/"+id+"?rel=0&autoplay=1";
f.referrerPolicy = "strict-origin-when-cross-origin";
f.allow = "autoplay; encrypted-media; picture-in-picture";
f.allowFullscreen = true;
stage.innerHTML = "";
stage.appendChild(f);
});
wrap.appendChild(im); wrap.appendChild(pb);
stage.appendChild(wrap);
cur = url; urlInp.value = url;
return;
}
if(vi){
node = document.createElement("iframe");
node.src = "https://player.vimeo.com/video/"+vi[1];
node.allow = "autoplay; fullscreen; picture-in-picture";
node.allowFullscreen = true;
}else if(/\.(jpe?g|png|gif|webp|svg|avif)([?#]|$)/i.test(url)){
node = document.createElement("img");
node.src = url; node.alt = "";
node.addEventListener("error", ()=>showMsg(true));
}else if(/\.(mp4|webm|ogg|mov)([?#]|$)/i.test(url)){
node = document.createElement("video");
node.src = url; node.controls = true;
node.addEventListener("error", ()=>showMsg(true));
}
if(node){
stage.innerHTML = "";
stage.appendChild(node);
cur = url;
urlInp.value = url;
}else{
showMsg(true);
}
}
goBtn.addEventListener("click", ()=>show(urlInp.value));
extBtn.addEventListener("click", ()=>{
let u = (cur || urlInp.value).trim();
if(!u) return;
if(!/^https?:\/\//i.test(u)) u = "https://"+u;
window.open(u, "_blank");
});
urlInp.addEventListener("keydown", e=>{
e.stopPropagation();
if(e.key==="Enter") show(urlInp.value);
});
document.addEventListener("langchange", labels);
if(initState && initState.url){ urlInp.value = initState.url; show(initState.url); }
else showMsg(false);
labels();
return { getState: ()=>({url: cur || ""}) };
}