File: C:/Users/fred/AppData/Local/Microsoft/OneDrive/26.168.0830.0006/WebAssets/static/views/mosaic.js
(function(){"use strict";const l=document.getElementById("canvas"),r=l.getContext("2d"),h=document.getElementById("loading"),A=document.getElementById("hero-name"),V=document.getElementById("controls"),F=document.getElementById("toggle-controls"),N=document.getElementById("close-controls"),M=document.getElementById("grid-resolution"),O=document.getElementById("grid-value"),k=document.getElementById("color-tint"),W=document.getElementById("tint-value"),_=document.getElementById("next-hero");let g=[],C=null,R=null,S=[],c=40,m=0,T=30,p=null,$=null,L=0,x=0,s=1,Q=20,z=!1,Y=0,D=0;function H(){l.width=window.innerWidth,l.height=window.innerHeight,y()}window.addEventListener("resize",H),H();async function q(){try{const o=await(await fetch(ViewLib.Thumbnail.buildThumbnailListUrl(0,200),{_od4ApiName:"thumbnail.batch"})).json(),n=ViewLib.Thumbnail.filterValidThumbnails(o.items);for(let i=0;i<n.length;i++){const e=n[i];h.textContent=`Loading tiles... ${i+1}/${n.length}`;try{const a=await P(e);g.push(a)}catch(a){console.warn("Failed to load tile:",e.thumbnailId,a)}}if(g.length===0){h.textContent="No photos available";return}h.classList.add("hidden"),G()}catch(t){h.textContent="Error loading photos",console.error("Error loading tiles:",t)}}function P(t){return window._od4FetchThumbnailBlob(t.thumbnailId).then(function(o){return new Promise((n,i)=>{const e=new Image;e.onload=function(){const a=document.createElement("canvas");a.width=16,a.height=16;const w=a.getContext("2d");w.drawImage(e,0,0,16,16);const d=w.getImageData(0,0,16,16).data;let f=0,v=0,E=0,I=0;for(let u=0;u<d.length;u+=4)f+=d[u],v+=d[u+1],E+=d[u+2],I++;f=Math.round(f/I),v=Math.round(v/I),E=Math.round(E/I),URL.revokeObjectURL(o),n({img:e,r:f,g:v,b:E,thumbnailId:t.thumbnailId,name:t.name||"Untitled",width:e.width,height:e.height})},e.onerror=function(){URL.revokeObjectURL(o),i(new Error("Failed to load image"))},e.src=o})})}function G(){const t=Math.floor(Math.random()*g.length);R=g[t],C=R.img,A.textContent=R.name,U()}function U(){h.textContent="Building mosaic...",h.classList.remove("hidden"),setTimeout(()=>{const t=C.height/C.width;m=Math.round(c*t);const o=document.createElement("canvas");o.width=c,o.height=m;const n=o.getContext("2d");n.drawImage(C,0,0,c,m);const e=n.getImageData(0,0,c,m).data;S=[];for(let a=0;a<m;a++){const w=[];for(let b=0;b<c;b++){const d=(a*c+b)*4,f=e[d],v=e[d+1],E=e[d+2];let I=0,u=1/0;for(let B=0;B<g.length;B++){const X=g[B],j=Math.sqrt(Math.pow(X.r-f,2)+Math.pow(X.g-v,2)+Math.pow(X.b-E,2));j<u&&(u=j,I=B)}w.push({tileIndex:I,targetR:f,targetG:v,targetB:E})}S.push(w)}J(),K(),h.classList.add("hidden"),y()},10)}function J(){const o=c*100,n=m*100;p=document.createElement("canvas"),p.width=o,p.height=n,$=p.getContext("2d");for(let i=0;i<m;i++)for(let e=0;e<c;e++){const a=S[i][e],w=g[a.tileIndex],b=e*100,d=i*100;$.drawImage(w.img,b,d,100,100)}}function K(){const o=c*100,n=m*100,i=l.width/o,e=l.height/n;s=Math.min(i,e)*.9,L=(l.width-o*s)/2,x=(l.height-n*s)/2}function y(){if(r.fillStyle=getComputedStyle(document.body).backgroundColor||"#111",r.fillRect(0,0,l.width,l.height),!!p){if(r.save(),r.translate(L,x),r.scale(s,s),r.drawImage(p,0,0),T>0){const o=T/100*.5;for(let n=0;n<m;n++)for(let i=0;i<c;i++){const e=S[n][i];r.fillStyle=`rgba(${e.targetR}, ${e.targetG}, ${e.targetB}, ${o})`,r.fillRect(i*100,n*100,100,100)}}r.restore()}}l.addEventListener("mousedown",t=>{z=!0,Y=t.clientX,D=t.clientY,l.classList.add("grabbing")}),l.addEventListener("mousemove",t=>{if(!z)return;const o=t.clientX-Y,n=t.clientY-D;L+=o,x+=n,Y=t.clientX,D=t.clientY,y()}),l.addEventListener("mouseup",()=>{z=!1,l.classList.remove("grabbing")}),l.addEventListener("mouseleave",()=>{z=!1,l.classList.remove("grabbing")}),l.addEventListener("wheel",t=>{t.preventDefault();const o=t.clientX,n=t.clientY,i=(o-L)/s,e=(n-x)/s,a=t.deltaY>0?.9:1.1;s*=a,s=Math.max(.1,Math.min(10,s)),L=o-i*s,x=n-e*s,y()}),F.addEventListener("click",()=>{V.classList.remove("collapsed")}),N.addEventListener("click",()=>{V.classList.add("collapsed")}),M.addEventListener("input",()=>{const t=parseInt(M.value,10);O.textContent=t,c=t}),M.addEventListener("change",()=>{U()}),k.addEventListener("input",()=>{const t=parseInt(k.value,10);W.textContent=t,T=t,y()}),_.addEventListener("click",()=>{G()}),ViewLib.Messages.setupSpotlightResponder(function(){return g.filter(t=>t.thumbnailId).map(t=>t.thumbnailId)}),q()})();