From 7ed6b81584b37678321c7d68a6e2133063a0ff6d Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 9 Mar 2026 23:58:02 +0100 Subject: [PATCH] Fix: Volume-Slider reaktionsschneller (Latenz reduziert) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Server: writeState() → writeStateDebounced() im Volume-Endpoint (kein synchroner Disk-Write bei jedem Slider-Tick mehr) - Frontend: Debounce von 120ms auf 50ms reduziert Co-Authored-By: Claude Opus 4.6 --- server/src/plugins/soundboard/index.ts | 2 +- web/dist/assets/{index-CUixApZu.js => index-CqHVUt2T.js} | 2 +- web/dist/index.html | 2 +- web/src/plugins/soundboard/SoundboardTab.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename web/dist/assets/{index-CUixApZu.js => index-CqHVUt2T.js} (94%) diff --git a/server/src/plugins/soundboard/index.ts b/server/src/plugins/soundboard/index.ts index 84eace7..77b49e3 100644 --- a/server/src/plugins/soundboard/index.ts +++ b/server/src/plugins/soundboard/index.ts @@ -1064,7 +1064,7 @@ const soundboardPlugin: Plugin = { if (state.currentResource?.volume) state.currentResource.volume.setVolume(safeVol); } persistedState.volumes[guildId] = safeVol; - writeState(); + writeStateDebounced(); sseBroadcast({ type: 'soundboard_volume', plugin: 'soundboard', guildId, volume: safeVol }); res.json({ ok: true, volume: safeVol }); }); diff --git a/web/dist/assets/index-CUixApZu.js b/web/dist/assets/index-CqHVUt2T.js similarity index 94% rename from web/dist/assets/index-CUixApZu.js rename to web/dist/assets/index-CqHVUt2T.js index db5599a..51f0cec 100644 --- a/web/dist/assets/index-CUixApZu.js +++ b/web/dist/assets/index-CqHVUt2T.js @@ -4827,4 +4827,4 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function aAe(i,e){return Jde(i)||iAe(i,e)||fI(i,e)||rAe()}function Cf(i){return eAe(i)||nAe(i)||fI(i)||sAe()}function oAe(i,e){if(typeof i!="object"||!i)return i;var t=i[Symbol.toPrimitive];if(t!==void 0){var n=t.call(i,e);if(typeof n!="object")return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return(e==="string"?String:Number)(i)}function lAe(i){var e=oAe(i,"string");return typeof e=="symbol"?e:e+""}function fI(i,e){if(i){if(typeof i=="string")return yT(i,e);var t={}.toString.call(i).slice(8,-1);return t==="Object"&&i.constructor&&(t=i.constructor.name),t==="Map"||t==="Set"?Array.from(i):t==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?yT(i,e):void 0}}var xr=window.THREE?window.THREE:{WebGLRenderer:FH,Scene:ZT,PerspectiveCamera:va,Raycaster:Jz,SRGBColorSpace:bn,TextureLoader:oM,Vector2:bt,Vector3:pe,Box3:Oc,Color:cn,Mesh:Oi,SphereGeometry:bu,MeshBasicMaterial:cd,BackSide:or,Clock:hD},dI=_s({props:{width:{default:window.innerWidth,onChange:function(e,t,n){isNaN(e)&&(t.width=n)}},height:{default:window.innerHeight,onChange:function(e,t,n){isNaN(e)&&(t.height=n)}},viewOffset:{default:[0,0]},backgroundColor:{default:"#000011"},backgroundImageUrl:{},onBackgroundImageLoaded:{},showNavInfo:{default:!0},skyRadius:{default:5e4},objects:{default:[]},lights:{default:[]},enablePointerInteraction:{default:!0,onChange:function(e,t){t.hoverObj=null,t.tooltip&&t.tooltip.content(null)},triggerUpdate:!1},pointerRaycasterThrottleMs:{default:50,triggerUpdate:!1},lineHoverPrecision:{default:1,triggerUpdate:!1},pointsHoverPrecision:{default:1,triggerUpdate:!1},hoverOrderComparator:{triggerUpdate:!1},hoverFilter:{default:function(){return!0},triggerUpdate:!1},tooltipContent:{triggerUpdate:!1},hoverDuringDrag:{default:!1,triggerUpdate:!1},clickAfterDrag:{default:!1,triggerUpdate:!1},onHover:{default:function(){},triggerUpdate:!1},onClick:{default:function(){},triggerUpdate:!1},onRightClick:{triggerUpdate:!1}},methods:{tick:function(e){if(e.initialised){e.controls.enabled&&e.controls.update&&e.controls.update(Math.min(1,e.clock.getDelta())),e.postProcessingComposer?e.postProcessingComposer.render():e.renderer.render(e.scene,e.camera),e.extraRenderers.forEach(function(a){return a.render(e.scene,e.camera)});var t=+new Date;if(e.enablePointerInteraction&&t-e.lastRaycasterCheck>=e.pointerRaycasterThrottleMs){e.lastRaycasterCheck=t;var n=null;if(e.hoverDuringDrag||!e.isPointerDragging){var r=this.intersectingObjects(e.pointerPos.x,e.pointerPos.y);e.hoverOrderComparator&&r.sort(function(a,l){return e.hoverOrderComparator(a.object,l.object)});var s=r.find(function(a){return e.hoverFilter(a.object)})||null;n=s?s.object:null,e.intersection=s||null}n!==e.hoverObj&&(e.onHover(n,e.hoverObj,e.intersection),e.tooltip.content(n&&Lt(e.tooltipContent)(n,e.intersection)||null),e.hoverObj=n)}e.tweenGroup.update()}return this},getPointerPos:function(e){var t=e.pointerPos,n=t.x,r=t.y;return{x:n,y:r}},cameraPosition:function(e,t,n,r){var s=e.camera;if(t&&e.initialised){var a=t,l=n||{x:0,y:0,z:0};if(!r)m(a),v(l);else{var u=Object.assign({},s.position),h=x();e.tweenGroup.add(new la(u).to(a,r).easing(os.Quadratic.Out).onUpdate(m).start()),e.tweenGroup.add(new la(h).to(l,r/3).easing(os.Quadratic.Out).onUpdate(v).start())}return this}return Object.assign({},s.position,{lookAt:x()});function m(S){var T=S.x,N=S.y,C=S.z;T!==void 0&&(s.position.x=T),N!==void 0&&(s.position.y=N),C!==void 0&&(s.position.z=C)}function v(S){var T=new xr.Vector3(S.x,S.y,S.z);e.controls.enabled&&e.controls.target?e.controls.target=T:s.lookAt(T)}function x(){return Object.assign(new xr.Vector3(0,0,-1e3).applyQuaternion(s.quaternion).add(s.position))}},zoomToFit:function(e){for(var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:0,n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:10,r=arguments.length,s=new Array(r>3?r-3:0),a=3;a2&&arguments[2]!==void 0?arguments[2]:0,r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:10,s=e.camera;if(t){var a=new xr.Vector3(0,0,0),l=Math.max.apply(Math,Cf(Object.entries(t).map(function(S){var T=aAe(S,2),N=T[0],C=T[1];return Math.max.apply(Math,Cf(C.map(function(E){return Math.abs(a[N]-E)})))})))*2,u=(1-r*2/e.height)*s.fov,h=l/Math.atan(u*Math.PI/180),m=h/s.aspect,v=Math.max(h,m);if(v>0){var x=a.clone().sub(s.position).normalize().multiplyScalar(-v);this.cameraPosition(x,a,n)}}return this},getBbox:function(e){var t=arguments.length>1&&arguments[1]!==void 0?arguments[1]:function(){return!0},n=new xr.Box3(new xr.Vector3(0,0,0),new xr.Vector3(0,0,0)),r=e.objects.filter(t);return r.length?(r.forEach(function(s){return n.expandByObject(s)}),Object.assign.apply(Object,Cf(["x","y","z"].map(function(s){return tAe({},s,[n.min[s],n.max[s]])})))):null},getScreenCoords:function(e,t,n,r){var s=new xr.Vector3(t,n,r);return s.project(this.camera()),{x:(s.x+1)*e.width/2,y:-(s.y-1)*e.height/2}},getSceneCoords:function(e,t,n){var r=arguments.length>3&&arguments[3]!==void 0?arguments[3]:0,s=new xr.Vector2(t/e.width*2-1,-(n/e.height)*2+1),a=new xr.Raycaster;return a.setFromCamera(s,e.camera),Object.assign({},a.ray.at(r,new xr.Vector3))},intersectingObjects:function(e,t,n){var r=new xr.Vector2(t/e.width*2-1,-(n/e.height)*2+1),s=new xr.Raycaster;return s.params.Line.threshold=e.lineHoverPrecision,s.params.Points.threshold=e.pointsHoverPrecision,s.setFromCamera(r,e.camera),s.intersectObjects(e.objects,!0)},renderer:function(e){return e.renderer},scene:function(e){return e.scene},camera:function(e){return e.camera},postProcessingComposer:function(e){return e.postProcessingComposer},controls:function(e){return e.controls},tbControls:function(e){return e.controls}},stateInit:function(){return{scene:new xr.Scene,camera:new xr.PerspectiveCamera,clock:new xr.Clock,tweenGroup:new wy,lastRaycasterCheck:0}},init:function(e,t){var n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:{},r=n.controlType,s=r===void 0?"trackball":r,a=n.useWebGPU,l=a===void 0?!1:a,u=n.rendererConfig,h=u===void 0?{}:u,m=n.extraRenderers,v=m===void 0?[]:m,x=n.waitForLoadComplete,S=x===void 0?!0:x;e.innerHTML="",e.appendChild(t.container=document.createElement("div")),t.container.className="scene-container",t.container.style.position="relative",t.container.appendChild(t.navInfo=document.createElement("div")),t.navInfo.className="scene-nav-info",t.navInfo.textContent={orbit:"Left-click: rotate, Mouse-wheel/middle-click: zoom, Right-click: pan",trackball:"Left-click: rotate, Mouse-wheel/middle-click: zoom, Right-click: pan",fly:"WASD: move, R|F: up | down, Q|E: roll, up|down: pitch, left|right: yaw"}[s]||"",t.navInfo.style.display=t.showNavInfo?null:"none",t.tooltip=new Qde(t.container),t.pointerPos=new xr.Vector2,t.pointerPos.x=-2,t.pointerPos.y=-2,["pointermove","pointerdown"].forEach(function(T){return t.container.addEventListener(T,function(N){if(T==="pointerdown"&&(t.isPointerPressed=!0),!t.isPointerDragging&&N.type==="pointermove"&&(N.pressure>0||t.isPointerPressed)&&(N.pointerType==="mouse"||N.movementX===void 0||[N.movementX,N.movementY].some(function(O){return Math.abs(O)>1}))&&(t.isPointerDragging=!0),t.enablePointerInteraction){var C=E(t.container);t.pointerPos.x=N.pageX-C.left,t.pointerPos.y=N.pageY-C.top}function E(O){var U=O.getBoundingClientRect(),I=window.pageXOffset||document.documentElement.scrollLeft,j=window.pageYOffset||document.documentElement.scrollTop;return{top:U.top+j,left:U.left+I}}},{passive:!0})}),t.container.addEventListener("pointerup",function(T){t.isPointerPressed&&(t.isPointerPressed=!1,!(t.isPointerDragging&&(t.isPointerDragging=!1,!t.clickAfterDrag))&&requestAnimationFrame(function(){T.button===0&&t.onClick(t.hoverObj||null,T,t.intersection),T.button===2&&t.onRightClick&&t.onRightClick(t.hoverObj||null,T,t.intersection)}))},{passive:!0,capture:!0}),t.container.addEventListener("contextmenu",function(T){t.onRightClick&&T.preventDefault()}),t.renderer=new(l?cO:xr.WebGLRenderer)(Object.assign({antialias:!0,alpha:!0},h)),t.renderer.setPixelRatio(Math.min(2,window.devicePixelRatio)),t.container.appendChild(t.renderer.domElement),t.extraRenderers=v,t.extraRenderers.forEach(function(T){T.domElement.style.position="absolute",T.domElement.style.top="0px",T.domElement.style.pointerEvents="none",t.container.appendChild(T.domElement)}),t.postProcessingComposer=new rhe(t.renderer),t.postProcessingComposer.addPass(new she(t.scene,t.camera)),t.controls=new{trackball:dce,orbit:Nce,fly:Vce}[s](t.camera,t.renderer.domElement),s==="fly"&&(t.controls.movementSpeed=300,t.controls.rollSpeed=Math.PI/6,t.controls.dragToLook=!0),(s==="trackball"||s==="orbit")&&(t.controls.minDistance=.1,t.controls.maxDistance=t.skyRadius,t.controls.addEventListener("start",function(){t.controlsEngaged=!0}),t.controls.addEventListener("change",function(){t.controlsEngaged&&(t.controlsDragging=!0)}),t.controls.addEventListener("end",function(){t.controlsEngaged=!1,t.controlsDragging=!1})),[t.renderer,t.postProcessingComposer].concat(Cf(t.extraRenderers)).forEach(function(T){return T.setSize(t.width,t.height)}),t.camera.aspect=t.width/t.height,t.camera.updateProjectionMatrix(),t.camera.position.z=1e3,t.scene.add(t.skysphere=new xr.Mesh),t.skysphere.visible=!1,t.loadComplete=t.scene.visible=!S,window.scene=t.scene},update:function(e,t){if(e.width&&e.height&&(t.hasOwnProperty("width")||t.hasOwnProperty("height"))){var n,r=e.width,s=e.height;e.container.style.width="".concat(r,"px"),e.container.style.height="".concat(s,"px"),[e.renderer,e.postProcessingComposer].concat(Cf(e.extraRenderers)).forEach(function(S){return S.setSize(r,s)}),e.camera.aspect=r/s;var a=e.viewOffset.slice(0,2);a.some(function(S){return S})&&(n=e.camera).setViewOffset.apply(n,[r,s].concat(Cf(a),[r,s])),e.camera.updateProjectionMatrix()}if(t.hasOwnProperty("viewOffset")){var l,u=e.width,h=e.height,m=e.viewOffset.slice(0,2);m.some(function(S){return S})?(l=e.camera).setViewOffset.apply(l,[u,h].concat(Cf(m),[u,h])):e.camera.clearViewOffset()}if(t.hasOwnProperty("skyRadius")&&e.skyRadius&&(e.controls.hasOwnProperty("maxDistance")&&t.skyRadius&&(e.controls.maxDistance=Math.min(e.controls.maxDistance,e.skyRadius)),e.camera.far=e.skyRadius*2.5,e.camera.updateProjectionMatrix(),e.skysphere.geometry=new xr.SphereGeometry(e.skyRadius)),t.hasOwnProperty("backgroundColor")){var v=O0(e.backgroundColor).alpha;v===void 0&&(v=1),e.renderer.setClearColor(new xr.Color(Ohe(1,e.backgroundColor)),v)}t.hasOwnProperty("backgroundImageUrl")&&(e.backgroundImageUrl?new xr.TextureLoader().load(e.backgroundImageUrl,function(S){S.colorSpace=xr.SRGBColorSpace,e.skysphere.material=new xr.MeshBasicMaterial({map:S,side:xr.BackSide}),e.skysphere.visible=!0,e.onBackgroundImageLoaded&&setTimeout(e.onBackgroundImageLoaded),!e.loadComplete&&x()}):(e.skysphere.visible=!1,e.skysphere.material.map=null,!e.loadComplete&&x())),t.hasOwnProperty("showNavInfo")&&(e.navInfo.style.display=e.showNavInfo?null:"none"),t.hasOwnProperty("lights")&&((t.lights||[]).forEach(function(S){return e.scene.remove(S)}),e.lights.forEach(function(S){return e.scene.add(S)})),t.hasOwnProperty("objects")&&((t.objects||[]).forEach(function(S){return e.scene.remove(S)}),e.objects.forEach(function(S){return e.scene.add(S)}));function x(){e.loadComplete=e.scene.visible=!0}}});function uAe(i,e){e===void 0&&(e={});var t=e.insertAt;if(!(typeof document>"u")){var n=document.head||document.getElementsByTagName("head")[0],r=document.createElement("style");r.type="text/css",t==="top"&&n.firstChild?n.insertBefore(r,n.firstChild):n.appendChild(r),r.styleSheet?r.styleSheet.cssText=i:r.appendChild(document.createTextNode(i))}}var cAe=`.scene-container .clickable { cursor: pointer; }`;uAe(cAe);function xT(i,e){(e==null||e>i.length)&&(e=i.length);for(var t=0,n=Array(e);t1?l-1:0),h=1;h1&&arguments[1]!==void 0?arguments[1]:{},n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,r=a();if(t.lat===void 0&&t.lng===void 0&&t.altitude===void 0)return r;var s=Object.assign({},r,t);if(["lat","lng","altitude"].forEach(function(u){return s[u]=+s[u]}),!n)l(s);else{for(;r.lng-s.lng>180;)r.lng-=360;for(;r.lng-s.lng<-180;)r.lng+=360;e.tweenGroup.add(new la(r).to(s,n).easing(os.Cubic.InOut).onUpdate(l).start())}return this;function a(){return e.globe.toGeoCoords(e.renderObjs.cameraPosition())}function l(u){var h=u.lat,m=u.lng,v=u.altitude;e.renderObjs.cameraPosition(e.globe.getCoords(h,m,v)),e.globe.setPointOfView(e.renderObjs.camera())}},getScreenCoords:function(e){for(var t,n=arguments.length,r=new Array(n>1?n-1:0),s=1;slocalStorage.getItem("radio-theme")||"default"),[a,l]=se.useState([]),[u,h]=se.useState(null),[m,v]=se.useState([]),[x,S]=se.useState(!1),[T,N]=se.useState({}),[C,E]=se.useState([]),[O,U]=se.useState(""),[I,j]=se.useState(""),[z,G]=se.useState(""),[H,q]=se.useState([]),[V,Q]=se.useState(!1),[J,ie]=se.useState([]),[le,re]=se.useState(!1),[Z,ne]=se.useState(!1),[de,be]=se.useState(.5),[Te,ae]=se.useState(null),[Me,Ve]=se.useState(!1),[Ce,Fe]=se.useState(!1),tt=se.useRef(void 0),je=se.useRef(void 0),Rt=se.useRef(O);se.useEffect(()=>{fetch("/api/radio/places").then(k=>k.json()).then(l).catch(console.error),fetch("/api/radio/guilds").then(k=>k.json()).then(k=>{if(E(k),k.length>0){U(k[0].id);const xe=k[0].voiceChannels.find(Oe=>Oe.members>0)??k[0].voiceChannels[0];xe&&j(xe.id)}}).catch(console.error),fetch("/api/radio/favorites").then(k=>k.json()).then(ie).catch(console.error)},[]),se.useEffect(()=>{Rt.current=O},[O]),se.useEffect(()=>{i!=null&&i.guildId&&"playing"in i&&i.type!=="radio_voicestats"?N(k=>{if(i.playing)return{...k,[i.guildId]:i.playing};const xe={...k};return delete xe[i.guildId],xe}):i!=null&&i.playing&&!(i!=null&&i.guildId)&&N(i.playing),i!=null&&i.favorites&&ie(i.favorites),i!=null&&i.volumes&&O&&i.volumes[O]!=null&&be(i.volumes[O]),(i==null?void 0:i.volume)!=null&&(i==null?void 0:i.guildId)===O&&be(i.volume),(i==null?void 0:i.type)==="radio_voicestats"&&i.guildId===Rt.current&&ae({voicePing:i.voicePing,gatewayPing:i.gatewayPing,status:i.status,channelName:i.channelName,connectedSince:i.connectedSince})},[i,O]),se.useEffect(()=>{if(localStorage.setItem("radio-theme",r),t.current&&e.current){const xe=getComputedStyle(e.current.parentElement).getPropertyValue("--accent-rgb").trim();t.current.pointColor(()=>`rgba(${xe}, 0.85)`).atmosphereColor(`rgba(${xe}, 0.25)`)}},[r]);const Et=se.useRef(u);Et.current=u;const Ft=se.useRef(le);Ft.current=le;const Ut=se.useCallback(()=>{var xe;const k=(xe=t.current)==null?void 0:xe.controls();k&&(k.autoRotate=!1),n.current&&clearTimeout(n.current),n.current=setTimeout(()=>{var Ue;if(Et.current||Ft.current)return;const Oe=(Ue=t.current)==null?void 0:Ue.controls();Oe&&(Oe.autoRotate=!0)},5e3)},[]);se.useEffect(()=>{var xe;const k=(xe=t.current)==null?void 0:xe.controls();k&&(u||le?(k.autoRotate=!1,n.current&&clearTimeout(n.current)):k.autoRotate=!0)},[u,le]);const Ke=se.useRef(void 0);Ke.current=k=>{h(k),re(!1),S(!0),v([]),Ut(),t.current&&t.current.pointOfView({lat:k.geo[1],lng:k.geo[0],altitude:.4},800),fetch(`/api/radio/place/${k.id}/channels`).then(xe=>xe.json()).then(xe=>{v(xe),S(!1)}).catch(()=>S(!1))},se.useEffect(()=>{const k=e.current;if(!k)return;k.clientWidth>0&&k.clientHeight>0&&Fe(!0);const xe=new ResizeObserver(Oe=>{for(const Ue of Oe){const{width:ee,height:we}=Ue.contentRect;ee>0&&we>0&&Fe(!0)}});return xe.observe(k),()=>xe.disconnect()},[]),se.useEffect(()=>{if(!e.current||a.length===0)return;const k=e.current.clientWidth,xe=e.current.clientHeight;if(t.current){t.current.pointsData(a),k>0&&xe>0&&t.current.width(k).height(xe);return}if(k===0||xe===0)return;const Ue=getComputedStyle(e.current.parentElement).getPropertyValue("--accent-rgb").trim()||"230, 126, 34",ee=new wAe(e.current).backgroundColor("rgba(0,0,0,0)").atmosphereColor(`rgba(${Ue}, 0.25)`).atmosphereAltitude(.12).globeImageUrl("/nasa-blue-marble.jpg").pointsData(a).pointLat(It=>It.geo[1]).pointLng(It=>It.geo[0]).pointColor(()=>`rgba(${Ue}, 0.85)`).pointRadius(It=>Math.max(.12,Math.min(.45,.06+(It.size??1)*.005))).pointAltitude(.001).pointResolution(24).pointLabel(It=>`
${It.title}
${It.country}
`).onPointClick(It=>{var lt;return(lt=Ke.current)==null?void 0:lt.call(Ke,It)}).width(e.current.clientWidth).height(e.current.clientHeight);ee.renderer().setPixelRatio(window.devicePixelRatio),ee.pointOfView({lat:48,lng:10,altitude:qS});const we=ee.controls();we&&(we.autoRotate=!0,we.autoRotateSpeed=.3);let Re=qS;const We=()=>{const lt=ee.pointOfView().altitude;if(Math.abs(lt-Re)/Re<.05)return;Re=lt;const jt=Math.sqrt(lt/qS);ee.pointRadius(Jt=>Math.max(.12,Math.min(.45,.06+(Jt.size??1)*.005))*Math.max(.15,Math.min(2.5,jt)))};we.addEventListener("change",We),t.current=ee;const Se=e.current,Le=()=>Ut();Se.addEventListener("mousedown",Le),Se.addEventListener("touchstart",Le),Se.addEventListener("wheel",Le);const ct=()=>{if(e.current&&t.current){const It=e.current.clientWidth,lt=e.current.clientHeight;It>0&<>0&&t.current.width(It).height(lt)}};window.addEventListener("resize",ct);const Dt=new ResizeObserver(()=>ct());return Dt.observe(Se),()=>{we.removeEventListener("change",We),Se.removeEventListener("mousedown",Le),Se.removeEventListener("touchstart",Le),Se.removeEventListener("wheel",Le),window.removeEventListener("resize",ct),Dt.disconnect()}},[a,Ut,Ce]);const ht=se.useCallback(async(k,xe,Oe,Ue)=>{if(!(!O||!I)){ne(!0);try{(await(await fetch("/api/radio/play",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:O,voiceChannelId:I,stationId:k,stationName:xe,placeName:Oe??(u==null?void 0:u.title)??"",country:Ue??(u==null?void 0:u.country)??""})})).json()).ok&&(N(Re=>{var We,Se;return{...Re,[O]:{stationId:k,stationName:xe,placeName:Oe??(u==null?void 0:u.title)??"",country:Ue??(u==null?void 0:u.country)??"",startedAt:new Date().toISOString(),channelName:((Se=(We=C.find(Le=>Le.id===O))==null?void 0:We.voiceChannels.find(Le=>Le.id===I))==null?void 0:Se.name)??""}}}),Ut())}catch(ee){console.error(ee)}ne(!1)}},[O,I,u,C]),fe=se.useCallback(async()=>{O&&(await fetch("/api/radio/stop",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:O})}),N(k=>{const xe={...k};return delete xe[O],xe}))},[O]),$t=se.useCallback(k=>{if(G(k),tt.current&&clearTimeout(tt.current),!k.trim()){q([]),Q(!1);return}tt.current=setTimeout(async()=>{try{const Oe=await(await fetch(`/api/radio/search?q=${encodeURIComponent(k)}`)).json();q(Oe),Q(!0)}catch{q([])}},350)},[]),_t=se.useCallback(k=>{var xe,Oe,Ue;if(Q(!1),G(""),q([]),k.type==="channel"){const ee=(xe=k.url.match(/\/listen\/[^/]+\/([^/]+)/))==null?void 0:xe[1];ee&&ht(ee,k.title,k.subtitle,"")}else if(k.type==="place"){const ee=(Oe=k.url.match(/\/visit\/[^/]+\/([^/]+)/))==null?void 0:Oe[1],we=a.find(Re=>Re.id===ee);we&&((Ue=Ke.current)==null||Ue.call(Ke,we))}},[a,ht]),Gt=se.useCallback(async(k,xe)=>{try{const Ue=await(await fetch("/api/radio/favorites",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({stationId:k,stationName:xe,placeName:(u==null?void 0:u.title)??"",country:(u==null?void 0:u.country)??"",placeId:(u==null?void 0:u.id)??""})})).json();Ue.favorites&&ie(Ue.favorites)}catch{}},[u]),yt=se.useCallback(k=>{be(k),O&&(je.current&&clearTimeout(je.current),je.current=setTimeout(()=>{fetch("/api/radio/volume",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:O,volume:k})}).catch(console.error)},100))},[O]),Ht=k=>J.some(xe=>xe.stationId===k),pt=O?T[O]:null,Ae=C.find(k=>k.id===O);return P.jsxs("div",{className:"radio-container","data-theme":r,children:[P.jsxs("header",{className:"radio-topbar",children:[P.jsxs("div",{className:"radio-topbar-left",children:[P.jsx("span",{className:"radio-topbar-logo",children:"🌍"}),P.jsx("span",{className:"radio-topbar-title",children:"World Radio"}),C.length>1&&P.jsx("select",{className:"radio-sel",value:O,onChange:k=>{U(k.target.value);const xe=C.find(Ue=>Ue.id===k.target.value),Oe=(xe==null?void 0:xe.voiceChannels.find(Ue=>Ue.members>0))??(xe==null?void 0:xe.voiceChannels[0]);j((Oe==null?void 0:Oe.id)??"")},children:C.map(k=>P.jsx("option",{value:k.id,children:k.name},k.id))}),P.jsxs("select",{className:"radio-sel",value:I,onChange:k=>j(k.target.value),children:[P.jsx("option",{value:"",children:"Voice Channel..."}),Ae==null?void 0:Ae.voiceChannels.map(k=>P.jsxs("option",{value:k.id,children:["🔊"," ",k.name,k.members>0?` (${k.members})`:""]},k.id))]})]}),pt&&P.jsxs("div",{className:"radio-topbar-np",children:[P.jsxs("div",{className:"radio-eq radio-eq-np",children:[P.jsx("span",{}),P.jsx("span",{}),P.jsx("span",{})]}),P.jsxs("div",{className:"radio-np-info",children:[P.jsx("span",{className:"radio-np-name",children:pt.stationName}),P.jsxs("span",{className:"radio-np-loc",children:[pt.placeName,pt.country?`, ${pt.country}`:""]})]})]}),P.jsxs("div",{className:"radio-topbar-right",children:[pt&&P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"radio-volume",children:[P.jsx("span",{className:"radio-volume-icon",children:de===0?"🔇":de<.4?"🔉":"🔊"}),P.jsx("input",{type:"range",className:"radio-volume-slider",min:0,max:1,step:.01,value:de,onChange:k=>yt(Number(k.target.value))}),P.jsxs("span",{className:"radio-volume-val",children:[Math.round(de*100),"%"]})]}),P.jsxs("div",{className:"radio-conn",onClick:()=>Ve(!0),title:"Verbindungsdetails",children:[P.jsx("span",{className:"radio-conn-dot"}),"Verbunden",(Te==null?void 0:Te.voicePing)!=null&&P.jsxs("span",{className:"radio-conn-ping",children:[Te.voicePing,"ms"]})]}),P.jsxs("button",{className:"radio-topbar-stop",onClick:fe,children:["⏹"," Stop"]})]}),P.jsx("div",{className:"radio-theme-inline",children:TAe.map(k=>P.jsx("div",{className:`radio-theme-dot ${r===k.id?"active":""}`,style:{background:k.color},title:k.label,onClick:()=>s(k.id)},k.id))})]})]}),P.jsxs("div",{className:"radio-globe-wrap",children:[P.jsx("div",{className:"radio-globe",ref:e}),P.jsxs("div",{className:"radio-search",children:[P.jsxs("div",{className:"radio-search-wrap",children:[P.jsx("span",{className:"radio-search-icon",children:"🔍"}),P.jsx("input",{className:"radio-search-input",type:"text",placeholder:"Sender oder Stadt suchen...",value:z,onChange:k=>$t(k.target.value),onFocus:()=>{H.length&&Q(!0)}}),z&&P.jsx("button",{className:"radio-search-clear",onClick:()=>{G(""),q([]),Q(!1)},children:"✕"})]}),V&&H.length>0&&P.jsx("div",{className:"radio-search-results",children:H.slice(0,12).map(k=>P.jsxs("button",{className:"radio-search-result",onClick:()=>_t(k),children:[P.jsx("span",{className:"radio-search-result-icon",children:k.type==="channel"?"📻":k.type==="place"?"📍":"🌍"}),P.jsxs("div",{className:"radio-search-result-text",children:[P.jsx("span",{className:"radio-search-result-title",children:k.title}),P.jsx("span",{className:"radio-search-result-sub",children:k.subtitle})]})]},k.id+k.url))})]}),!u&&!le&&P.jsxs("button",{className:"radio-fab",onClick:()=>{re(!0),h(null)},title:"Favoriten",children:["⭐",J.length>0&&P.jsx("span",{className:"radio-fab-badge",children:J.length})]}),le&&P.jsxs("div",{className:"radio-panel open",children:[P.jsxs("div",{className:"radio-panel-header",children:[P.jsxs("h3",{children:["⭐"," Favoriten"]}),P.jsx("button",{className:"radio-panel-close",onClick:()=>re(!1),children:"✕"})]}),P.jsx("div",{className:"radio-panel-body",children:J.length===0?P.jsx("div",{className:"radio-panel-empty",children:"Noch keine Favoriten"}):J.map(k=>P.jsxs("div",{className:`radio-station ${(pt==null?void 0:pt.stationId)===k.stationId?"playing":""}`,children:[P.jsxs("div",{className:"radio-station-info",children:[P.jsx("span",{className:"radio-station-name",children:k.stationName}),P.jsxs("span",{className:"radio-station-loc",children:[k.placeName,", ",k.country]})]}),P.jsxs("div",{className:"radio-station-btns",children:[P.jsx("button",{className:"radio-btn-play",onClick:()=>ht(k.stationId,k.stationName,k.placeName,k.country),disabled:!I||Z,children:"▶"}),P.jsx("button",{className:"radio-btn-fav active",onClick:()=>Gt(k.stationId,k.stationName),children:"★"})]})]},k.stationId))})]}),u&&!le&&P.jsxs("div",{className:"radio-panel open",children:[P.jsxs("div",{className:"radio-panel-header",children:[P.jsxs("div",{children:[P.jsx("h3",{children:u.title}),P.jsx("span",{className:"radio-panel-sub",children:u.country})]}),P.jsx("button",{className:"radio-panel-close",onClick:()=>h(null),children:"✕"})]}),P.jsx("div",{className:"radio-panel-body",children:x?P.jsxs("div",{className:"radio-panel-loading",children:[P.jsx("div",{className:"radio-spinner"}),"Sender werden geladen..."]}):m.length===0?P.jsx("div",{className:"radio-panel-empty",children:"Keine Sender gefunden"}):m.map(k=>P.jsxs("div",{className:`radio-station ${(pt==null?void 0:pt.stationId)===k.id?"playing":""}`,children:[P.jsxs("div",{className:"radio-station-info",children:[P.jsx("span",{className:"radio-station-name",children:k.title}),(pt==null?void 0:pt.stationId)===k.id&&P.jsxs("span",{className:"radio-station-live",children:[P.jsxs("span",{className:"radio-eq",children:[P.jsx("span",{}),P.jsx("span",{}),P.jsx("span",{})]}),"Live"]})]}),P.jsxs("div",{className:"radio-station-btns",children:[(pt==null?void 0:pt.stationId)===k.id?P.jsx("button",{className:"radio-btn-stop",onClick:fe,children:"⏹"}):P.jsx("button",{className:"radio-btn-play",onClick:()=>ht(k.id,k.title),disabled:!I||Z,children:"▶"}),P.jsx("button",{className:`radio-btn-fav ${Ht(k.id)?"active":""}`,onClick:()=>Gt(k.id,k.title),children:Ht(k.id)?"★":"☆"})]})]},k.id))})]}),P.jsxs("div",{className:"radio-counter",children:["📻"," ",a.length.toLocaleString("de-DE")," Sender weltweit"]}),P.jsx("a",{className:"radio-attribution",href:"https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/",target:"_blank",rel:"noreferrer",children:"Imagery © NASA Blue Marble"})]}),Me&&(()=>{const k=Te!=null&&Te.connectedSince?Math.floor((Date.now()-new Date(Te.connectedSince).getTime())/1e3):0,xe=Math.floor(k/3600),Oe=Math.floor(k%3600/60),Ue=k%60,ee=xe>0?`${xe}h ${String(Oe).padStart(2,"0")}m ${String(Ue).padStart(2,"0")}s`:Oe>0?`${Oe}m ${String(Ue).padStart(2,"0")}s`:`${Ue}s`,we=Re=>Re==null?"var(--text-faint)":Re<80?"var(--success)":Re<150?"#f0a830":"#e04040";return P.jsx("div",{className:"radio-modal-overlay",onClick:()=>Ve(!1),children:P.jsxs("div",{className:"radio-modal",onClick:Re=>Re.stopPropagation(),children:[P.jsxs("div",{className:"radio-modal-header",children:[P.jsx("span",{children:"📡"}),P.jsx("span",{children:"Verbindungsdetails"}),P.jsx("button",{className:"radio-modal-close",onClick:()=>Ve(!1),children:"✕"})]}),P.jsxs("div",{className:"radio-modal-body",children:[P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Voice Ping"}),P.jsxs("span",{className:"radio-modal-value",children:[P.jsx("span",{className:"radio-modal-dot",style:{background:we((Te==null?void 0:Te.voicePing)??null)}}),(Te==null?void 0:Te.voicePing)!=null?`${Te.voicePing} ms`:"---"]})]}),P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Gateway Ping"}),P.jsxs("span",{className:"radio-modal-value",children:[P.jsx("span",{className:"radio-modal-dot",style:{background:we((Te==null?void 0:Te.gatewayPing)??null)}}),Te&&Te.gatewayPing>=0?`${Te.gatewayPing} ms`:"---"]})]}),P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Status"}),P.jsx("span",{className:"radio-modal-value",style:{color:(Te==null?void 0:Te.status)==="ready"?"var(--success)":"#f0a830"},children:(Te==null?void 0:Te.status)==="ready"?"Verbunden":(Te==null?void 0:Te.status)??"Warte auf Verbindung"})]}),P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Kanal"}),P.jsx("span",{className:"radio-modal-value",children:(Te==null?void 0:Te.channelName)||"---"})]}),P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Verbunden seit"}),P.jsx("span",{className:"radio-modal-value",children:ee||"---"})]})]})]})})})()]})}function EAe(i,e,t=365){const n=new Date(Date.now()+t*24*60*60*1e3).toUTCString();document.cookie=`${encodeURIComponent(i)}=${encodeURIComponent(e)}; expires=${n}; path=/; SameSite=Lax`}function CAe(i){const e=`${encodeURIComponent(i)}=`,t=document.cookie.split(";");for(const n of t){const r=n.trim();if(r.startsWith(e))return decodeURIComponent(r.slice(e.length))}return null}const ca="/api/soundboard";async function NAe(i,e,t,n){const r=new URL(`${ca}/sounds`,window.location.origin);i&&r.searchParams.set("q",i),e!==void 0&&r.searchParams.set("folder",e),r.searchParams.set("fuzzy","0");const s=await fetch(r.toString());if(!s.ok)throw new Error("Fehler beim Laden der Sounds");return s.json()}async function RAe(){const i=await fetch(`${ca}/analytics`);if(!i.ok)throw new Error("Fehler beim Laden der Analytics");return i.json()}async function DAe(){const i=await fetch(`${ca}/categories`,{credentials:"include"});if(!i.ok)throw new Error("Fehler beim Laden der Kategorien");return i.json()}async function PAe(){const i=await fetch(`${ca}/channels`);if(!i.ok)throw new Error("Fehler beim Laden der Channels");return i.json()}async function LAe(){const i=await fetch(`${ca}/selected-channels`);if(!i.ok)throw new Error("Fehler beim Laden der Channel-Auswahl");const e=await i.json();return(e==null?void 0:e.selected)||{}}async function UAe(i,e){if(!(await fetch(`${ca}/selected-channel`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:i,channelId:e})})).ok)throw new Error("Channel-Auswahl setzen fehlgeschlagen")}async function BAe(i,e,t,n,r){const s=await fetch(`${ca}/play`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({soundName:i,guildId:e,channelId:t,volume:n,relativePath:r})});if(!s.ok){const a=await s.json().catch(()=>({}));throw new Error((a==null?void 0:a.error)||"Play fehlgeschlagen")}}async function OAe(i,e,t,n,r){const s=await fetch(`${ca}/play-url`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:i,guildId:e,channelId:t,volume:n,filename:r})}),a=await s.json().catch(()=>({}));if(!s.ok)throw new Error((a==null?void 0:a.error)||"Play-URL fehlgeschlagen");return a}async function IAe(i,e){const t=await fetch(`${ca}/download-url`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:i,filename:e})}),n=await t.json().catch(()=>({}));if(!t.ok)throw new Error((n==null?void 0:n.error)||"Download fehlgeschlagen");return n}async function FAe(i,e){if(!(await fetch(`${ca}/party/start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:i,channelId:e})})).ok)throw new Error("Partymode Start fehlgeschlagen")}async function kAe(i){if(!(await fetch(`${ca}/party/stop`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:i})})).ok)throw new Error("Partymode Stop fehlgeschlagen")}async function g7(i,e){const t=await fetch(`${ca}/volume`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:i,volume:e})});if(!t.ok){const n=await t.json().catch(()=>({}));throw new Error((n==null?void 0:n.error)||"Volume aendern fehlgeschlagen")}}async function zAe(i){const e=new URL(`${ca}/volume`,window.location.origin);e.searchParams.set("guildId",i);const t=await fetch(e.toString());if(!t.ok)throw new Error("Fehler beim Laden der Lautstaerke");const n=await t.json();return typeof(n==null?void 0:n.volume)=="number"?n.volume:1}async function GAe(i){if(!(await fetch(`${ca}/admin/sounds/delete`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({paths:i})})).ok)throw new Error("Loeschen fehlgeschlagen")}function qAe(i,e,t){return new Promise((n,r)=>{const s=new FormData;s.append("files",i),e&&s.append("customName",e);const a=new XMLHttpRequest;a.open("POST",`${ca}/upload`),a.upload.onprogress=l=>{l.lengthComputable&&t(Math.round(l.loaded/l.total*100))},a.onload=()=>{var l,u;if(a.status===200)try{const h=JSON.parse(a.responseText);n(((u=(l=h.files)==null?void 0:l[0])==null?void 0:u.name)??i.name)}catch{n(i.name)}else try{r(new Error(JSON.parse(a.responseText).error))}catch{r(new Error(`HTTP ${a.status}`))}},a.onerror=()=>r(new Error("Netzwerkfehler")),a.send(s)})}const VAe=[{id:"default",color:"#5865f2",label:"Discord"},{id:"purple",color:"#9b59b6",label:"Midnight"},{id:"forest",color:"#2ecc71",label:"Forest"},{id:"sunset",color:"#e67e22",label:"Sunset"},{id:"ocean",color:"#3498db",label:"Ocean"}],v7=["#3b82f6","#f59e0b","#8b5cf6","#ec4899","#14b8a6","#f97316","#06b6d4","#ef4444","#a855f7","#84cc16","#d946ef","#0ea5e9","#f43f5e","#10b981"];function jAe({data:i,isAdmin:e}){var qe,qt,Qt;const[t,n]=se.useState([]),[r,s]=se.useState(0),[a,l]=se.useState([]),[u,h]=se.useState([]),[m,v]=se.useState({totalSounds:0,totalPlays:0,mostPlayed:[]}),[x,S]=se.useState("all"),[T,N]=se.useState(""),[C,E]=se.useState(""),[O,U]=se.useState(""),[I,j]=se.useState(!1),[z,G]=se.useState(null),[H,q]=se.useState([]),[V,Q]=se.useState(""),J=se.useRef(""),[ie,le]=se.useState(!1),[re,Z]=se.useState(1),[ne,de]=se.useState(""),[be,Te]=se.useState({}),[ae,Me]=se.useState(()=>localStorage.getItem("jb-theme")||"default"),[Ve,Ce]=se.useState(()=>parseInt(localStorage.getItem("jb-card-size")||"110")),[Fe,tt]=se.useState(!1),[je,Rt]=se.useState([]),Et=se.useRef(!1),Ft=se.useRef(void 0),Ut=e??!1,[Ke,ht]=se.useState(!1),[fe,$t]=se.useState([]),[_t,Gt]=se.useState(!1),yt=se.useRef(0);se.useRef(void 0);const[Ht,pt]=se.useState([]),[Ae,k]=se.useState(0),[xe,Oe]=se.useState(""),[Ue,ee]=se.useState("naming"),[we,Re]=se.useState(0),[We,Se]=se.useState(null),[Le,ct]=se.useState(!1),[Dt,It]=se.useState(null),[lt,jt]=se.useState(""),[Jt,In]=se.useState(null),[me,Bt]=se.useState(0);se.useEffect(()=>{Et.current=Fe},[Fe]),se.useEffect(()=>{J.current=V},[V]),se.useEffect(()=>{const he=sn=>{var Tn;Array.from(((Tn=sn.dataTransfer)==null?void 0:Tn.items)??[]).some(Rn=>Rn.kind==="file")&&(yt.current++,ht(!0))},X=()=>{yt.current=Math.max(0,yt.current-1),yt.current===0&&ht(!1)},et=sn=>sn.preventDefault(),en=sn=>{var Rn;sn.preventDefault(),yt.current=0,ht(!1);const Tn=Array.from(((Rn=sn.dataTransfer)==null?void 0:Rn.files)??[]).filter(xi=>/\.(mp3|wav)$/i.test(xi.name));Tn.length&&xt(Tn)};return window.addEventListener("dragenter",he),window.addEventListener("dragleave",X),window.addEventListener("dragover",et),window.addEventListener("drop",en),()=>{window.removeEventListener("dragenter",he),window.removeEventListener("dragleave",X),window.removeEventListener("dragover",et),window.removeEventListener("drop",en)}},[Ut]);const ot=se.useCallback((he,X="info")=>{It({msg:he,type:X}),setTimeout(()=>It(null),3e3)},[]);se.useCallback(he=>he.relativePath??he.fileName,[]);const Tt=["youtube.com","www.youtube.com","m.youtube.com","youtu.be","music.youtube.com","instagram.com","www.instagram.com"],Wt=se.useCallback(he=>{const X=he.trim();return!X||/^https?:\/\//i.test(X)?X:"https://"+X},[]),Yt=se.useCallback(he=>{try{const X=new URL(Wt(he)),et=X.hostname.toLowerCase();return!!(X.pathname.toLowerCase().endsWith(".mp3")||Tt.some(en=>et===en||et.endsWith("."+en)))}catch{return!1}},[Wt]),pn=se.useCallback(he=>{try{const X=new URL(Wt(he)),et=X.hostname.toLowerCase();return et.includes("youtube")||et==="youtu.be"?"youtube":et.includes("instagram")?"instagram":X.pathname.toLowerCase().endsWith(".mp3")?"mp3":null}catch{return null}},[Wt]),$e=V?V.split(":")[0]:"",St=V?V.split(":")[1]:"",Kt=se.useMemo(()=>H.find(he=>`${he.guildId}:${he.channelId}`===V),[H,V]);se.useEffect(()=>{const he=()=>{const et=new Date,en=String(et.getHours()).padStart(2,"0"),sn=String(et.getMinutes()).padStart(2,"0"),Tn=String(et.getSeconds()).padStart(2,"0");jt(`${en}:${sn}:${Tn}`)};he();const X=setInterval(he,1e3);return()=>clearInterval(X)},[]),se.useEffect(()=>{(async()=>{try{const[he,X]=await Promise.all([PAe(),LAe()]);if(q(he),he.length){const et=he[0].guildId,en=X[et],sn=en&&he.find(Tn=>Tn.guildId===et&&Tn.channelId===en);Q(sn?`${et}:${en}`:`${he[0].guildId}:${he[0].channelId}`)}}catch(he){ot((he==null?void 0:he.message)||"Channel-Fehler","error")}try{const he=await DAe();h(he.categories||[])}catch{}})()},[]),se.useEffect(()=>{localStorage.setItem("jb-theme",ae)},[ae]);const wn=se.useRef(null);se.useEffect(()=>{const he=wn.current;if(!he)return;he.style.setProperty("--card-size",Ve+"px");const X=Ve/110;he.style.setProperty("--card-emoji",Math.round(28*X)+"px"),he.style.setProperty("--card-font",Math.max(9,Math.round(11*X))+"px"),localStorage.setItem("jb-card-size",String(Ve))},[Ve]),se.useEffect(()=>{var he,X,et,en,sn,Tn,Rn,xi;if(i){if(i.soundboard){const K=i.soundboard;Array.isArray(K.party)&&Rt(K.party);try{const hn=K.selected||{},Zt=(he=J.current)==null?void 0:he.split(":")[0];Zt&&hn[Zt]&&Q(`${Zt}:${hn[Zt]}`)}catch{}try{const hn=K.volumes||{},Zt=(X=J.current)==null?void 0:X.split(":")[0];Zt&&typeof hn[Zt]=="number"&&Z(hn[Zt])}catch{}try{const hn=K.nowplaying||{},Zt=(et=J.current)==null?void 0:et.split(":")[0];Zt&&typeof hn[Zt]=="string"&&de(hn[Zt])}catch{}try{const hn=K.voicestats||{},Zt=(en=J.current)==null?void 0:en.split(":")[0];Zt&&hn[Zt]&&Se(hn[Zt])}catch{}}if(i.type==="soundboard_party")Rt(K=>{const hn=new Set(K);return i.active?hn.add(i.guildId):hn.delete(i.guildId),Array.from(hn)});else if(i.type==="soundboard_channel"){const K=(sn=J.current)==null?void 0:sn.split(":")[0];i.guildId===K&&Q(`${i.guildId}:${i.channelId}`)}else if(i.type==="soundboard_volume"){const K=(Tn=J.current)==null?void 0:Tn.split(":")[0];i.guildId===K&&typeof i.volume=="number"&&Z(i.volume)}else if(i.type==="soundboard_nowplaying"){const K=(Rn=J.current)==null?void 0:Rn.split(":")[0];i.guildId===K&&de(i.name||"")}else if(i.type==="soundboard_voicestats"){const K=(xi=J.current)==null?void 0:xi.split(":")[0];i.guildId===K&&Se({voicePing:i.voicePing,gatewayPing:i.gatewayPing,status:i.status,channelName:i.channelName,connectedSince:i.connectedSince})}}},[i]),se.useEffect(()=>{tt($e?je.includes($e):!1)},[V,je,$e]),se.useEffect(()=>{(async()=>{try{let he="__all__";x==="recent"?he="__recent__":T&&(he=T);const X=await NAe(C,he,void 0,!1);n(X.items),s(X.total),l(X.folders)}catch(he){ot((he==null?void 0:he.message)||"Sounds-Fehler","error")}})()},[x,T,C,me,ot]),se.useEffect(()=>{qn()},[me]),se.useEffect(()=>{const he=CAe("favs");if(he)try{Te(JSON.parse(he))}catch{}},[]),se.useEffect(()=>{try{EAe("favs",JSON.stringify(be))}catch{}},[be]),se.useEffect(()=>{V&&(async()=>{try{const he=await zAe($e);Z(he)}catch{}})()},[V]),se.useEffect(()=>{const he=()=>{le(!1),In(null)};return document.addEventListener("click",he),()=>document.removeEventListener("click",he)},[]);async function qn(){try{const he=await RAe();v(he)}catch{}}async function Je(he){if(!V)return ot("Bitte einen Voice-Channel auswaehlen","error");try{await BAe(he.name,$e,St,re,he.relativePath),de(he.name),qn()}catch(X){ot((X==null?void 0:X.message)||"Play fehlgeschlagen","error")}}function dt(){var en;const he=Wt(O);if(!he)return ot("Bitte einen Link eingeben","error");if(!Yt(he))return ot("Nur YouTube, Instagram oder direkte MP3-Links","error");const X=pn(he);let et="";if(X==="mp3")try{et=((en=new URL(he).pathname.split("/").pop())==null?void 0:en.replace(/\.mp3$/i,""))??""}catch{}G({url:he,type:X,filename:et,phase:"input"})}async function Vt(){if(z){G(he=>he?{...he,phase:"downloading"}:null);try{let he;const X=z.filename.trim()||void 0;V&&$e&&St?he=(await OAe(z.url,$e,St,re,X)).saved:he=(await IAe(z.url,X)).saved,G(et=>et?{...et,phase:"done",savedName:he}:null),U(""),Bt(et=>et+1),qn(),setTimeout(()=>G(null),2500)}catch(he){G(X=>X?{...X,phase:"error",error:(he==null?void 0:he.message)||"Fehler"}:null)}}}async function xt(he){if(!Ut){ot("Admin-Login erforderlich zum Hochladen","error");return}if(he.length===0)return;pt(he),k(0);const X=he[0].name.replace(/\.(mp3|wav)$/i,"");Oe(X),ee("naming"),Re(0)}async function A(){if(Ht.length===0)return;const he=Ht[Ae],X=xe.trim()||he.name.replace(/\.(mp3|wav)$/i,"");ee("uploading"),Re(0);try{await qAe(he,X,et=>Re(et)),ee("done"),setTimeout(()=>{const et=Ae+1;if(eten+1),qn(),ot(`${Ht.length} Sound${Ht.length>1?"s":""} hochgeladen`,"info")},800)}catch(et){ot((et==null?void 0:et.message)||"Upload fehlgeschlagen","error"),pt([])}}function te(){const he=Ae+1;if(he0&&(Bt(X=>X+1),qn())}async function Vn(){if(V){de("");try{await fetch(`${ca}/stop?guildId=${encodeURIComponent($e)}`,{method:"POST"})}catch{}}}async function Wn(){if(!lr.length||!V)return;const he=lr[Math.floor(Math.random()*lr.length)];Je(he)}async function $n(){if(Fe){await Vn();try{await kAe($e)}catch{}}else{if(!V)return ot("Bitte einen Channel auswaehlen","error");try{await FAe($e,St)}catch{}}}async function dn(he){const X=`${he.guildId}:${he.channelId}`;Q(X),le(!1);try{await UAe(he.guildId,he.channelId)}catch{}}function Fn(he){Te(X=>({...X,[he]:!X[he]}))}const lr=se.useMemo(()=>x==="favorites"?t.filter(he=>be[he.relativePath??he.fileName]):t,[t,x,be]),an=se.useMemo(()=>Object.values(be).filter(Boolean).length,[be]),mn=se.useMemo(()=>a.filter(he=>!["__all__","__recent__","__top3__"].includes(he.key)),[a]),Er=se.useMemo(()=>{const he={};return mn.forEach((X,et)=>{he[X.key]=v7[et%v7.length]}),he},[mn]),Wi=se.useMemo(()=>{const he=new Set,X=new Set;return lr.forEach((et,en)=>{const sn=et.name.charAt(0).toUpperCase();he.has(sn)||(he.add(sn),X.add(en))}),X},[lr]),No=se.useMemo(()=>{const he={};return H.forEach(X=>{he[X.guildName]||(he[X.guildName]=[]),he[X.guildName].push(X)}),he},[H]),ce=m.mostPlayed.slice(0,10),Ge=m.totalSounds||r,rt=lt.slice(0,5),it=lt.slice(5);return P.jsxs("div",{className:"sb-app","data-theme":ae,ref:wn,children:[Fe&&P.jsx("div",{className:"party-overlay active"}),P.jsxs("header",{className:"topbar",children:[P.jsxs("div",{className:"topbar-left",children:[P.jsx("div",{className:"sb-app-logo",children:P.jsx("span",{className:"material-icons",style:{fontSize:16,color:"white"},children:"music_note"})}),P.jsx("span",{className:"sb-app-title",children:"Soundboard"}),P.jsxs("div",{className:"channel-dropdown",onClick:he=>he.stopPropagation(),children:[P.jsxs("button",{className:`channel-btn ${ie?"open":""}`,onClick:()=>le(!ie),children:[P.jsx("span",{className:"material-icons cb-icon",children:"headset"}),V&&P.jsx("span",{className:"channel-status"}),P.jsx("span",{className:"channel-label",children:Kt?`${Kt.channelName}${Kt.members?` (${Kt.members})`:""}`:"Channel..."}),P.jsx("span",{className:"material-icons chevron",children:"expand_more"})]}),ie&&P.jsxs("div",{className:"channel-menu visible",children:[Object.entries(No).map(([he,X])=>P.jsxs(FF.Fragment,{children:[P.jsx("div",{className:"channel-menu-header",children:he}),X.map(et=>P.jsxs("div",{className:`channel-option ${`${et.guildId}:${et.channelId}`===V?"active":""}`,onClick:()=>dn(et),children:[P.jsx("span",{className:"material-icons co-icon",children:"volume_up"}),et.channelName,et.members?` (${et.members})`:""]},`${et.guildId}:${et.channelId}`))]},he)),H.length===0&&P.jsx("div",{className:"channel-option",style:{color:"var(--text-faint)",cursor:"default"},children:"Keine Channels verfuegbar"})]})]})]}),P.jsx("div",{className:"clock-wrap",children:P.jsxs("div",{className:"clock",children:[rt,P.jsx("span",{className:"clock-seconds",children:it})]})}),P.jsxs("div",{className:"topbar-right",children:[ne&&P.jsxs("div",{className:"now-playing",children:[P.jsxs("div",{className:"np-waves active",children:[P.jsx("div",{className:"np-wave-bar"}),P.jsx("div",{className:"np-wave-bar"}),P.jsx("div",{className:"np-wave-bar"}),P.jsx("div",{className:"np-wave-bar"})]}),P.jsx("span",{className:"np-label",children:"Last Played:"})," ",P.jsx("span",{className:"np-name",children:ne})]}),V&&P.jsxs("div",{className:"connection",onClick:()=>ct(!0),style:{cursor:"pointer"},title:"Verbindungsdetails",children:[P.jsx("span",{className:"conn-dot"}),"Verbunden",(We==null?void 0:We.voicePing)!=null&&P.jsxs("span",{className:"conn-ping",children:[We.voicePing,"ms"]})]})]})]}),P.jsxs("div",{className:"toolbar",children:[P.jsxs("div",{className:"cat-tabs",children:[P.jsxs("button",{className:`cat-tab ${x==="all"?"active":""}`,onClick:()=>{S("all"),N("")},children:["Alle",P.jsx("span",{className:"tab-count",children:r})]}),P.jsx("button",{className:`cat-tab ${x==="recent"?"active":""}`,onClick:()=>{S("recent"),N("")},children:"Neu hinzugefuegt"}),P.jsxs("button",{className:`cat-tab ${x==="favorites"?"active":""}`,onClick:()=>{S("favorites"),N("")},children:["Favoriten",an>0&&P.jsx("span",{className:"tab-count",children:an})]})]}),P.jsxs("div",{className:"search-wrap",children:[P.jsx("span",{className:"material-icons search-icon",children:"search"}),P.jsx("input",{className:"search-input",type:"text",placeholder:"Suchen...",value:C,onChange:he=>E(he.target.value)}),C&&P.jsx("button",{className:"search-clear",onClick:()=>E(""),children:P.jsx("span",{className:"material-icons",style:{fontSize:14},children:"close"})})]}),P.jsxs("div",{className:"url-import-wrap",children:[P.jsx("span",{className:"material-icons url-import-icon",children:pn(O)==="youtube"?"smart_display":pn(O)==="instagram"?"photo_camera":"link"}),P.jsx("input",{className:"url-import-input",type:"text",placeholder:"YouTube / Instagram / MP3-Link...",value:O,onChange:he=>U(he.target.value),onKeyDown:he=>{he.key==="Enter"&&dt()}}),O&&P.jsx("span",{className:`url-import-tag ${Yt(O)?"valid":"invalid"}`,children:pn(O)==="youtube"?"YT":pn(O)==="instagram"?"IG":pn(O)==="mp3"?"MP3":"?"}),P.jsx("button",{className:"url-import-btn",onClick:()=>{dt()},disabled:I||!!O&&!Yt(O),title:"Sound herunterladen",children:I?"Laedt...":"Download"})]}),P.jsx("div",{className:"toolbar-spacer"}),P.jsxs("div",{className:"volume-control",children:[P.jsx("span",{className:"material-icons vol-icon",onClick:()=>{const he=re>0?0:.5;Z(he),$e&&g7($e,he).catch(()=>{})},children:re===0?"volume_off":re<.5?"volume_down":"volume_up"}),P.jsx("input",{type:"range",className:"vol-slider",min:0,max:1,step:.01,value:re,onChange:he=>{const X=parseFloat(he.target.value);Z(X),$e&&(Ft.current&&clearTimeout(Ft.current),Ft.current=setTimeout(()=>{g7($e,X).catch(()=>{})},120))},style:{"--vol":`${Math.round(re*100)}%`}}),P.jsxs("span",{className:"vol-pct",children:[Math.round(re*100),"%"]})]}),P.jsxs("button",{className:"tb-btn random",onClick:Wn,title:"Zufaelliger Sound",children:[P.jsx("span",{className:"material-icons tb-icon",children:"shuffle"}),"Random"]}),P.jsxs("button",{className:`tb-btn party ${Fe?"active":""}`,onClick:$n,title:"Party Mode",children:[P.jsx("span",{className:"material-icons tb-icon",children:Fe?"celebration":"auto_awesome"}),Fe?"Party!":"Party"]}),P.jsxs("button",{className:"tb-btn stop",onClick:Vn,title:"Alle stoppen",children:[P.jsx("span",{className:"material-icons tb-icon",children:"stop"}),"Stop"]}),P.jsxs("div",{className:"size-control",title:"Button-Groesse",children:[P.jsx("span",{className:"material-icons sc-icon",children:"grid_view"}),P.jsx("input",{type:"range",className:"size-slider",min:80,max:160,value:Ve,onChange:he=>Ce(parseInt(he.target.value))})]}),P.jsx("div",{className:"theme-selector",children:VAe.map(he=>P.jsx("div",{className:`theme-dot ${ae===he.id?"active":""}`,style:{background:he.color},title:he.label,onClick:()=>Me(he.id)},he.id))})]}),P.jsxs("div",{className:"analytics-strip",children:[P.jsxs("div",{className:"analytics-card",children:[P.jsx("span",{className:"material-icons analytics-icon",children:"library_music"}),P.jsxs("div",{className:"analytics-copy",children:[P.jsx("span",{className:"analytics-label",children:"Sounds gesamt"}),P.jsx("strong",{className:"analytics-value",children:Ge})]})]}),P.jsxs("div",{className:"analytics-card analytics-wide",children:[P.jsx("span",{className:"material-icons analytics-icon",children:"leaderboard"}),P.jsxs("div",{className:"analytics-copy",children:[P.jsx("span",{className:"analytics-label",children:"Most Played"}),P.jsx("div",{className:"analytics-top-list",children:ce.length===0?P.jsx("span",{className:"analytics-muted",children:"Noch keine Plays"}):ce.map((he,X)=>P.jsxs("span",{className:"analytics-chip",children:[X+1,". ",he.name," (",he.count,")"]},he.relativePath))})]})]})]}),x==="all"&&mn.length>0&&P.jsx("div",{className:"category-strip",children:mn.map(he=>{const X=Er[he.key]||"#888",et=T===he.key;return P.jsxs("button",{className:`cat-chip ${et?"active":""}`,onClick:()=>N(et?"":he.key),style:et?{borderColor:X,color:X}:void 0,children:[P.jsx("span",{className:"cat-dot",style:{background:X}}),he.name.replace(/\s*\(\d+\)\s*$/,""),P.jsx("span",{className:"cat-count",children:he.count})]},he.key)})}),P.jsx("main",{className:"main",children:lr.length===0?P.jsxs("div",{className:"empty-state visible",children:[P.jsx("div",{className:"empty-emoji",children:x==="favorites"?"⭐":"🔇"}),P.jsx("div",{className:"empty-title",children:x==="favorites"?"Noch keine Favoriten":C?`Kein Sound fuer "${C}" gefunden`:"Keine Sounds vorhanden"}),P.jsx("div",{className:"empty-desc",children:x==="favorites"?"Klick den Stern auf einem Sound!":"Hier gibt's noch nichts zu hoeren."})]}):P.jsx("div",{className:"sound-grid",children:lr.map((he,X)=>{var hn;const et=he.relativePath??he.fileName,en=!!be[et],sn=ne===he.name,Tn=he.isRecent||((hn=he.badges)==null?void 0:hn.includes("new")),Rn=he.name.charAt(0).toUpperCase(),xi=Wi.has(X),K=he.folder&&Er[he.folder]||"var(--accent)";return P.jsxs("div",{className:`sound-card ${sn?"playing":""} ${xi?"has-initial":""}`,style:{animationDelay:`${Math.min(X*20,400)}ms`},onClick:Zt=>{const gr=Zt.currentTarget,ui=gr.getBoundingClientRect(),vr=document.createElement("div");vr.className="ripple";const Ps=Math.max(ui.width,ui.height);vr.style.width=vr.style.height=Ps+"px",vr.style.left=Zt.clientX-ui.left-Ps/2+"px",vr.style.top=Zt.clientY-ui.top-Ps/2+"px",gr.appendChild(vr),setTimeout(()=>vr.remove(),500),Je(he)},onContextMenu:Zt=>{Zt.preventDefault(),Zt.stopPropagation(),In({x:Math.min(Zt.clientX,window.innerWidth-170),y:Math.min(Zt.clientY,window.innerHeight-140),sound:he})},title:`${he.name}${he.folder?` (${he.folder})`:""}`,children:[Tn&&P.jsx("span",{className:"new-badge",children:"NEU"}),P.jsx("span",{className:`fav-star ${en?"active":""}`,onClick:Zt=>{Zt.stopPropagation(),Fn(et)},children:P.jsx("span",{className:"material-icons fav-icon",children:en?"star":"star_border"})}),xi&&P.jsx("span",{className:"sound-emoji",style:{color:K},children:Rn}),P.jsx("span",{className:"sound-name",children:he.name}),he.folder&&P.jsx("span",{className:"sound-duration",children:he.folder}),P.jsxs("div",{className:"playing-indicator",children:[P.jsx("div",{className:"wave-bar"}),P.jsx("div",{className:"wave-bar"}),P.jsx("div",{className:"wave-bar"}),P.jsx("div",{className:"wave-bar"})]})]},et)})})}),Jt&&P.jsxs("div",{className:"ctx-menu visible",style:{left:Jt.x,top:Jt.y},onClick:he=>he.stopPropagation(),children:[P.jsxs("div",{className:"ctx-item",onClick:()=>{Je(Jt.sound),In(null)},children:[P.jsx("span",{className:"material-icons ctx-icon",children:"play_arrow"}),"Abspielen"]}),P.jsxs("div",{className:"ctx-item",onClick:()=>{Fn(Jt.sound.relativePath??Jt.sound.fileName),In(null)},children:[P.jsx("span",{className:"material-icons ctx-icon",children:be[Jt.sound.relativePath??Jt.sound.fileName]?"star":"star_border"}),"Favorit"]}),Ut&&P.jsxs(P.Fragment,{children:[P.jsx("div",{className:"ctx-sep"}),P.jsxs("div",{className:"ctx-item danger",onClick:async()=>{const he=Jt.sound.relativePath??Jt.sound.fileName;if(!window.confirm(`Sound "${Jt.sound.name}" loeschen?`)){In(null);return}try{await GAe([he]),ot("Sound geloescht"),Bt(X=>X+1)}catch(X){ot((X==null?void 0:X.message)||"Loeschen fehlgeschlagen","error")}In(null)},children:[P.jsx("span",{className:"material-icons ctx-icon",children:"delete"}),"Loeschen"]})]})]}),Le&&(()=>{const he=We!=null&&We.connectedSince?Math.floor((Date.now()-new Date(We.connectedSince).getTime())/1e3):0,X=Math.floor(he/3600),et=Math.floor(he%3600/60),en=he%60,sn=X>0?`${X}h ${String(et).padStart(2,"0")}m ${String(en).padStart(2,"0")}s`:et>0?`${et}m ${String(en).padStart(2,"0")}s`:`${en}s`,Tn=Rn=>Rn==null?"var(--muted)":Rn<80?"var(--green)":Rn<150?"#f0a830":"#e04040";return P.jsx("div",{className:"conn-modal-overlay",onClick:()=>ct(!1),children:P.jsxs("div",{className:"conn-modal",onClick:Rn=>Rn.stopPropagation(),children:[P.jsxs("div",{className:"conn-modal-header",children:[P.jsx("span",{className:"material-icons",style:{fontSize:20,color:"var(--green)"},children:"cell_tower"}),P.jsx("span",{children:"Verbindungsdetails"}),P.jsx("button",{className:"conn-modal-close",onClick:()=>ct(!1),children:P.jsx("span",{className:"material-icons",children:"close"})})]}),P.jsxs("div",{className:"conn-modal-body",children:[P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Voice Ping"}),P.jsxs("span",{className:"conn-stat-value",children:[P.jsx("span",{className:"conn-ping-dot",style:{background:Tn((We==null?void 0:We.voicePing)??null)}}),(We==null?void 0:We.voicePing)!=null?`${We.voicePing} ms`:"---"]})]}),P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Gateway Ping"}),P.jsxs("span",{className:"conn-stat-value",children:[P.jsx("span",{className:"conn-ping-dot",style:{background:Tn((We==null?void 0:We.gatewayPing)??null)}}),We&&We.gatewayPing>=0?`${We.gatewayPing} ms`:"---"]})]}),P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Status"}),P.jsx("span",{className:"conn-stat-value",style:{color:(We==null?void 0:We.status)==="ready"?"var(--green)":"#f0a830"},children:(We==null?void 0:We.status)==="ready"?"Verbunden":(We==null?void 0:We.status)??"Warte auf Verbindung"})]}),P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Kanal"}),P.jsx("span",{className:"conn-stat-value",children:(We==null?void 0:We.channelName)||"---"})]}),P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Verbunden seit"}),P.jsx("span",{className:"conn-stat-value",children:sn||"---"})]})]})]})})})(),Dt&&P.jsxs("div",{className:`toast ${Dt.type}`,children:[P.jsx("span",{className:"material-icons toast-icon",children:Dt.type==="error"?"error_outline":"check_circle"}),Dt.msg]}),Ke&&P.jsx("div",{className:"drop-overlay",children:P.jsxs("div",{className:"drop-zone",children:[P.jsx("span",{className:"material-icons drop-icon",children:"cloud_upload"}),P.jsx("div",{className:"drop-title",children:"MP3 & WAV hier ablegen"}),P.jsx("div",{className:"drop-sub",children:"Mehrere Dateien gleichzeitig moeglich"})]})}),_t&&fe.length>0&&P.jsxs("div",{className:"upload-queue",children:[P.jsxs("div",{className:"uq-header",children:[P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"upload"}),P.jsx("span",{children:fe.every(he=>he.status==="done"||he.status==="error")?`${fe.filter(he=>he.status==="done").length} von ${fe.length} hochgeladen`:`Lade hoch… (${fe.filter(he=>he.status==="done").length}/${fe.length})`}),P.jsx("button",{className:"uq-close",onClick:()=>{Gt(!1),$t([])},children:P.jsx("span",{className:"material-icons",style:{fontSize:14},children:"close"})})]}),P.jsx("div",{className:"uq-list",children:fe.map(he=>P.jsxs("div",{className:`uq-item uq-${he.status}`,children:[P.jsx("span",{className:"material-icons uq-file-icon",children:"audio_file"}),P.jsxs("div",{className:"uq-info",children:[P.jsx("div",{className:"uq-name",title:he.savedName??he.file.name,children:he.savedName??he.file.name}),P.jsxs("div",{className:"uq-size",children:[(he.file.size/1024).toFixed(0)," KB"]})]}),(he.status==="waiting"||he.status==="uploading")&&P.jsx("div",{className:"uq-progress-wrap",children:P.jsx("div",{className:"uq-progress-bar",style:{width:`${he.progress}%`}})}),P.jsx("span",{className:`material-icons uq-status-icon uq-status-${he.status}`,children:he.status==="done"?"check_circle":he.status==="error"?"error":he.status==="uploading"?"sync":"schedule"}),he.status==="error"&&P.jsx("div",{className:"uq-error",children:he.error})]},he.id))})]}),Ht.length>0&&P.jsx("div",{className:"dl-modal-overlay",onClick:()=>Ue==="naming"&&te(),children:P.jsxs("div",{className:"dl-modal",onClick:he=>he.stopPropagation(),children:[P.jsxs("div",{className:"dl-modal-header",children:[P.jsx("span",{className:"material-icons",style:{fontSize:20},children:"upload_file"}),P.jsxs("span",{children:[Ue==="naming"?"Sound benennen":Ue==="uploading"?"Wird hochgeladen...":"Gespeichert!",Ht.length>1&&` (${Ae+1}/${Ht.length})`]}),Ue==="naming"&&P.jsx("button",{className:"dl-modal-close",onClick:te,children:P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"close"})})]}),P.jsxs("div",{className:"dl-modal-body",children:[P.jsxs("div",{className:"dl-modal-url",children:[P.jsx("span",{className:"dl-modal-tag mp3",children:"Datei"}),P.jsx("span",{className:"dl-modal-url-text",title:(qe=Ht[Ae])==null?void 0:qe.name,children:(qt=Ht[Ae])==null?void 0:qt.name}),P.jsxs("span",{style:{marginLeft:"auto",opacity:.5,fontSize:12},children:[((((Qt=Ht[Ae])==null?void 0:Qt.size)??0)/1024).toFixed(0)," KB"]})]}),Ue==="naming"&&P.jsxs("div",{className:"dl-modal-field",children:[P.jsx("label",{className:"dl-modal-label",children:"Dateiname"}),P.jsxs("div",{className:"dl-modal-input-wrap",children:[P.jsx("input",{className:"dl-modal-input",type:"text",placeholder:"Dateiname eingeben...",value:xe,onChange:he=>Oe(he.target.value),onKeyDown:he=>{he.key==="Enter"&&A()},autoFocus:!0}),P.jsx("span",{className:"dl-modal-ext",children:".mp3"})]})]}),Ue==="uploading"&&P.jsxs("div",{className:"dl-modal-progress",children:[P.jsx("div",{className:"dl-modal-spinner"}),P.jsxs("span",{children:["Upload: ",we,"%"]})]}),Ue==="done"&&P.jsxs("div",{className:"dl-modal-success",children:[P.jsx("span",{className:"material-icons dl-modal-check",children:"check_circle"}),P.jsx("span",{children:"Erfolgreich hochgeladen!"})]})]}),Ue==="naming"&&P.jsxs("div",{className:"dl-modal-actions",children:[P.jsx("button",{className:"dl-modal-cancel",onClick:te,children:Ht.length>1?"Überspringen":"Abbrechen"}),P.jsxs("button",{className:"dl-modal-submit",onClick:()=>void A(),children:[P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"upload"}),"Hochladen"]})]})]})}),z&&P.jsx("div",{className:"dl-modal-overlay",onClick:()=>z.phase!=="downloading"&&G(null),children:P.jsxs("div",{className:"dl-modal",onClick:he=>he.stopPropagation(),children:[P.jsxs("div",{className:"dl-modal-header",children:[P.jsx("span",{className:"material-icons",style:{fontSize:20},children:z.type==="youtube"?"smart_display":z.type==="instagram"?"photo_camera":"audio_file"}),P.jsx("span",{children:z.phase==="input"?"Sound herunterladen":z.phase==="downloading"?"Wird heruntergeladen...":z.phase==="done"?"Fertig!":"Fehler"}),z.phase!=="downloading"&&P.jsx("button",{className:"dl-modal-close",onClick:()=>G(null),children:P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"close"})})]}),P.jsxs("div",{className:"dl-modal-body",children:[P.jsxs("div",{className:"dl-modal-url",children:[P.jsx("span",{className:`dl-modal-tag ${z.type??""}`,children:z.type==="youtube"?"YouTube":z.type==="instagram"?"Instagram":"MP3"}),P.jsx("span",{className:"dl-modal-url-text",title:z.url,children:z.url.length>60?z.url.slice(0,57)+"...":z.url})]}),z.phase==="input"&&P.jsxs("div",{className:"dl-modal-field",children:[P.jsx("label",{className:"dl-modal-label",children:"Dateiname"}),P.jsxs("div",{className:"dl-modal-input-wrap",children:[P.jsx("input",{className:"dl-modal-input",type:"text",placeholder:z.type==="mp3"?"Dateiname...":"Wird automatisch erkannt...",value:z.filename,onChange:he=>G(X=>X?{...X,filename:he.target.value}:null),onKeyDown:he=>{he.key==="Enter"&&Vt()},autoFocus:!0}),P.jsx("span",{className:"dl-modal-ext",children:".mp3"})]}),P.jsx("span",{className:"dl-modal-hint",children:"Leer lassen = automatischer Name"})]}),z.phase==="downloading"&&P.jsxs("div",{className:"dl-modal-progress",children:[P.jsx("div",{className:"dl-modal-spinner"}),P.jsx("span",{children:z.type==="youtube"||z.type==="instagram"?"Audio wird extrahiert...":"MP3 wird heruntergeladen..."})]}),z.phase==="done"&&P.jsxs("div",{className:"dl-modal-success",children:[P.jsx("span",{className:"material-icons dl-modal-check",children:"check_circle"}),P.jsxs("span",{children:["Gespeichert als ",P.jsx("b",{children:z.savedName})]})]}),z.phase==="error"&&P.jsxs("div",{className:"dl-modal-error",children:[P.jsx("span",{className:"material-icons",style:{color:"#e74c3c"},children:"error"}),P.jsx("span",{children:z.error})]})]}),z.phase==="input"&&P.jsxs("div",{className:"dl-modal-actions",children:[P.jsx("button",{className:"dl-modal-cancel",onClick:()=>G(null),children:"Abbrechen"}),P.jsxs("button",{className:"dl-modal-submit",onClick:()=>void Vt(),children:[P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"download"}),"Herunterladen"]})]}),z.phase==="error"&&P.jsxs("div",{className:"dl-modal-actions",children:[P.jsx("button",{className:"dl-modal-cancel",onClick:()=>G(null),children:"Schliessen"}),P.jsxs("button",{className:"dl-modal-submit",onClick:()=>G(he=>he?{...he,phase:"input",error:void 0}:null),children:[P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"refresh"}),"Nochmal"]})]})]})})]})}const _7={IRON:"#6b6b6b",BRONZE:"#8c6239",SILVER:"#8c8c8c",GOLD:"#d4a017",PLATINUM:"#28b29e",EMERALD:"#1e9e5e",DIAMOND:"#576cce",MASTER:"#9d48e0",GRANDMASTER:"#e44c3e",CHALLENGER:"#f4c874"},HAe={SOLORANKED:"Ranked Solo",FLEXRANKED:"Ranked Flex",NORMAL:"Normal",ARAM:"ARAM",ARENA:"Arena",URF:"URF",BOT:"Co-op vs AI"},WAe="https://ddragon.leagueoflegends.com/cdn/15.5.1/img";function mm(i){return`${WAe}/champion/${i}.png`}function y7(i){const e=Math.floor((Date.now()-new Date(i).getTime())/1e3);return e<60?`${e}s`:e<3600?`${Math.floor(e/60)}m`:e<86400?`${Math.floor(e/3600)}h`:`${Math.floor(e/86400)}d`}function $Ae(i){const e=Math.floor(i/60),t=i%60;return`${e}:${String(t).padStart(2,"0")}`}function x7(i,e,t){return e===0?"Perfect":((i+t)/e).toFixed(2)}function b7(i,e){const t=i+e;return t>0?Math.round(i/t*100):0}function XAe(i,e){if(!i)return"Unranked";const t=["","I","II","III","IV"];return`${i.charAt(0)}${i.slice(1).toLowerCase()}${e?" "+(t[e]??e):""}`}function YAe({data:i}){var yt,Ht,pt,Ae;const[e,t]=se.useState(""),[n,r]=se.useState("EUW"),[s,a]=se.useState([]),[l,u]=se.useState(null),[h,m]=se.useState([]),[v,x]=se.useState(!1),[S,T]=se.useState(null),[N,C]=se.useState([]),[E,O]=se.useState(null),[U,I]=se.useState({}),[j,z]=se.useState(!1),[G,H]=se.useState(!1),[q,V]=se.useState(null),[Q,J]=se.useState("aram"),[ie,le]=se.useState("EUW"),[re,Z]=se.useState([]),[ne,de]=se.useState(!1),[be,Te]=se.useState(null),[ae,Me]=se.useState([]),[Ve,Ce]=se.useState(""),[Fe,tt]=se.useState(!1),je=se.useRef(null),Rt=se.useRef(null);se.useEffect(()=>{fetch("/api/lolstats/regions").then(k=>k.json()).then(a).catch(()=>{}),fetch("/api/lolstats/recent").then(k=>k.json()).then(C).catch(()=>{}),fetch("/api/lolstats/modes").then(k=>k.json()).then(Me).catch(()=>{})},[]),se.useEffect(()=>{Q&&(de(!0),Te(null),tt(!1),fetch(`/api/lolstats/tierlist?mode=${Q}®ion=${ie}`).then(k=>{if(!k.ok)throw new Error(`HTTP ${k.status}`);return k.json()}).then(k=>Z(k.champions??[])).catch(k=>Te(k.message)).finally(()=>de(!1)))},[Q,ie]),se.useEffect(()=>{i&&(i.recentSearches&&C(i.recentSearches),i.regions&&!s.length&&a(i.regions))},[i]);const Et=se.useCallback(async(k,xe,Oe)=>{H(!0);try{const Ue=`gameName=${encodeURIComponent(k)}&tagLine=${encodeURIComponent(xe)}®ion=${Oe}`,ee=await fetch(`/api/lolstats/renew?${Ue}`,{method:"POST"});if(ee.ok){const we=await ee.json();return we.last_updated_at&&V(we.last_updated_at),we.renewed??!1}}catch{}return H(!1),!1},[]),Ft=se.useCallback(async(k,xe,Oe,Ue=!1)=>{var We,Se;let ee=k??"",we=xe??"";const Re=Oe??n;if(!ee){const Le=e.split("#");ee=((We=Le[0])==null?void 0:We.trim())??"",we=((Se=Le[1])==null?void 0:Se.trim())??""}if(!ee||!we){T("Bitte im Format Name#Tag eingeben");return}x(!0),T(null),u(null),m([]),O(null),I({}),Rt.current={gameName:ee,tagLine:we,region:Re},Ue||Et(ee,we,Re).finally(()=>H(!1));try{const Le=`gameName=${encodeURIComponent(ee)}&tagLine=${encodeURIComponent(we)}®ion=${Re}`,[ct,Dt]=await Promise.all([fetch(`/api/lolstats/profile?${Le}`),fetch(`/api/lolstats/matches?${Le}&limit=10`)]);if(!ct.ok){const lt=await ct.json();throw new Error(lt.error??`Fehler ${ct.status}`)}const It=await ct.json();if(u(It),It.updated_at&&V(It.updated_at),Dt.ok){const lt=await Dt.json();m(Array.isArray(lt)?lt:[])}}catch(Le){T(Le.message)}x(!1)},[e,n,Et]),Ut=se.useCallback(async()=>{const k=Rt.current;if(!(!k||G)){H(!0);try{await Et(k.gameName,k.tagLine,k.region),await new Promise(xe=>setTimeout(xe,1500)),await Ft(k.gameName,k.tagLine,k.region,!0)}finally{H(!1)}}},[Et,Ft,G]),Ke=se.useCallback(async()=>{if(!(!l||j)){z(!0);try{const k=`gameName=${encodeURIComponent(l.game_name)}&tagLine=${encodeURIComponent(l.tagline)}®ion=${n}&limit=20`,xe=await fetch(`/api/lolstats/matches?${k}`);if(xe.ok){const Oe=await xe.json();m(Array.isArray(Oe)?Oe:[])}}catch{}z(!1)}},[l,n,j]),ht=se.useCallback(async k=>{var xe;if(E===k.id){O(null);return}if(O(k.id),!(((xe=k.participants)==null?void 0:xe.length)>=10||U[k.id]))try{const Oe=`region=${n}&createdAt=${encodeURIComponent(k.created_at)}`,Ue=await fetch(`/api/lolstats/match/${encodeURIComponent(k.id)}?${Oe}`);if(Ue.ok){const ee=await Ue.json();I(we=>({...we,[k.id]:ee}))}}catch{}},[E,U,n]),fe=se.useCallback(k=>{t(`${k.game_name}#${k.tag_line}`),r(k.region),Ft(k.game_name,k.tag_line,k.region)},[Ft]),$t=se.useCallback(k=>{var Oe,Ue,ee;if(!l)return((Oe=k.participants)==null?void 0:Oe[0])??null;const xe=l.game_name.toLowerCase();return((Ue=k.participants)==null?void 0:Ue.find(we=>{var Re,We;return((We=(Re=we.summoner)==null?void 0:Re.game_name)==null?void 0:We.toLowerCase())===xe}))??((ee=k.participants)==null?void 0:ee[0])??null},[l]),_t=k=>{var Se,Le,ct;const xe=$t(k);if(!xe)return null;const Oe=((Se=xe.stats)==null?void 0:Se.result)==="WIN",Ue=x7(xe.stats.kill,xe.stats.death,xe.stats.assist),ee=(xe.stats.minion_kill??0)+(xe.stats.neutral_minion_kill??0),we=k.game_length_second>0?(ee/(k.game_length_second/60)).toFixed(1):"0",Re=E===k.id,We=U[k.id]??(((Le=k.participants)==null?void 0:Le.length)>=10?k:null);return P.jsxs("div",{children:[P.jsxs("div",{className:`lol-match ${Oe?"win":"loss"}`,onClick:()=>ht(k),children:[P.jsx("div",{className:"lol-match-result",children:Oe?"W":"L"}),P.jsxs("div",{className:"lol-match-champ",children:[P.jsx("img",{src:mm(xe.champion_name),alt:xe.champion_name,title:xe.champion_name}),P.jsx("span",{className:"lol-match-champ-level",children:xe.stats.champion_level})]}),P.jsxs("div",{className:"lol-match-kda",children:[P.jsxs("div",{className:"lol-match-kda-nums",children:[xe.stats.kill,"/",xe.stats.death,"/",xe.stats.assist]}),P.jsxs("div",{className:`lol-match-kda-ratio ${Ue==="Perfect"?"perfect":Number(Ue)>=4?"great":""}`,children:[Ue," KDA"]})]}),P.jsxs("div",{className:"lol-match-stats",children:[P.jsxs("span",{children:[ee," CS (",we,"/m)"]}),P.jsxs("span",{children:[xe.stats.ward_place," wards"]})]}),P.jsx("div",{className:"lol-match-items",children:(xe.items_names??[]).slice(0,7).map((Dt,It)=>Dt?P.jsx("img",{src:mm("Aatrox"),alt:Dt,title:Dt,style:{background:"var(--bg-deep)"},onError:lt=>{lt.target.style.display="none"}},It):P.jsx("div",{className:"lol-match-item-empty"},It))}),P.jsxs("div",{className:"lol-match-meta",children:[P.jsx("div",{className:"lol-match-duration",children:$Ae(k.game_length_second)}),P.jsx("div",{className:"lol-match-queue",children:HAe[k.game_type]??k.game_type}),P.jsxs("div",{className:"lol-match-ago",children:[y7(k.created_at)," ago"]})]})]}),Re&&We&&P.jsx("div",{className:"lol-match-detail",children:Gt(We,(ct=xe.summoner)==null?void 0:ct.game_name)})]},k.id)},Gt=(k,xe)=>{var Re,We,Se,Le,ct;const Oe=((Re=k.participants)==null?void 0:Re.filter(Dt=>Dt.team_key==="BLUE"))??[],Ue=((We=k.participants)==null?void 0:We.filter(Dt=>Dt.team_key==="RED"))??[],ee=(ct=(Le=(Se=k.teams)==null?void 0:Se.find(Dt=>Dt.key==="BLUE"))==null?void 0:Le.game_stat)==null?void 0:ct.is_win,we=(Dt,It,lt)=>P.jsxs("div",{className:"lol-match-detail-team",children:[P.jsxs("div",{className:`lol-match-detail-team-header ${It?"win":"loss"}`,children:[lt," — ",It?"Victory":"Defeat"]}),Dt.map((jt,Jt)=>{var Bt,ot,Tt,Wt,Yt,pn,$e,St,Kt,wn,qn,Je;const In=((ot=(Bt=jt.summoner)==null?void 0:Bt.game_name)==null?void 0:ot.toLowerCase())===(xe==null?void 0:xe.toLowerCase()),me=(((Tt=jt.stats)==null?void 0:Tt.minion_kill)??0)+(((Wt=jt.stats)==null?void 0:Wt.neutral_minion_kill)??0);return P.jsxs("div",{className:`lol-detail-row ${In?"me":""}`,children:[P.jsx("img",{className:"lol-detail-champ",src:mm(jt.champion_name),alt:jt.champion_name}),P.jsx("span",{className:"lol-detail-name",title:`${(Yt=jt.summoner)==null?void 0:Yt.game_name}#${(pn=jt.summoner)==null?void 0:pn.tagline}`,children:(($e=jt.summoner)==null?void 0:$e.game_name)??jt.champion_name}),P.jsxs("span",{className:"lol-detail-kda",children:[(St=jt.stats)==null?void 0:St.kill,"/",(Kt=jt.stats)==null?void 0:Kt.death,"/",(wn=jt.stats)==null?void 0:wn.assist]}),P.jsxs("span",{className:"lol-detail-cs",children:[me," CS"]}),P.jsxs("span",{className:"lol-detail-dmg",children:[((((qn=jt.stats)==null?void 0:qn.total_damage_dealt_to_champions)??0)/1e3).toFixed(1),"k"]}),P.jsxs("span",{className:"lol-detail-gold",children:[((((Je=jt.stats)==null?void 0:Je.gold_earned)??0)/1e3).toFixed(1),"k"]})]},Jt)})]});return P.jsxs(P.Fragment,{children:[we(Oe,ee,"Blue Team"),we(Ue,ee===void 0?void 0:!ee,"Red Team")]})};return P.jsxs("div",{className:"lol-container",children:[P.jsxs("div",{className:"lol-search",children:[P.jsx("input",{ref:je,className:"lol-search-input",placeholder:"Summoner Name#Tag",value:e,onChange:k=>t(k.target.value),onKeyDown:k=>k.key==="Enter"&&Ft()}),P.jsx("select",{className:"lol-search-region",value:n,onChange:k=>r(k.target.value),children:s.map(k=>P.jsx("option",{value:k.code,children:k.code},k.code))}),P.jsx("button",{className:"lol-search-btn",onClick:()=>Ft(),disabled:v,children:v?"...":"Search"})]}),N.length>0&&P.jsx("div",{className:"lol-recent",children:N.map((k,xe)=>P.jsxs("button",{className:"lol-recent-chip",onClick:()=>fe(k),children:[k.profile_image_url&&P.jsx("img",{src:k.profile_image_url,alt:""}),k.game_name,"#",k.tag_line,k.tier&&P.jsx("span",{className:"lol-recent-tier",style:{color:_7[k.tier]},children:k.tier})]},xe))}),S&&P.jsx("div",{className:"lol-error",children:S}),v&&P.jsxs("div",{className:"lol-loading",children:[P.jsx("div",{className:"lol-spinner"}),"Lade Profil..."]}),l&&!v&&P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"lol-profile",children:[P.jsx("img",{className:"lol-profile-icon",src:l.profile_image_url,alt:""}),P.jsxs("div",{className:"lol-profile-info",children:[P.jsxs("h2",{children:[l.game_name,P.jsxs("span",{children:["#",l.tagline]})]}),P.jsxs("div",{className:"lol-profile-level",children:["Level ",l.level]}),((yt=l.ladder_rank)==null?void 0:yt.rank)&&P.jsxs("div",{className:"lol-profile-ladder",children:["Ladder Rank #",l.ladder_rank.rank.toLocaleString()," / ",(Ht=l.ladder_rank.total)==null?void 0:Ht.toLocaleString()]}),q&&P.jsxs("div",{className:"lol-profile-updated",children:["Updated ",y7(q)," ago"]})]}),P.jsxs("button",{className:`lol-update-btn ${G?"renewing":""}`,onClick:Ut,disabled:G,title:"Refresh data from Riot servers",children:[P.jsx("span",{className:"lol-update-icon",children:G?"⟳":"↻"}),G?"Updating...":"Update"]})]}),P.jsx("div",{className:"lol-ranked-row",children:(l.league_stats??[]).filter(k=>k.game_type==="SOLORANKED"||k.game_type==="FLEXRANKED").map(k=>{const xe=k.tier_info,Oe=!!(xe!=null&&xe.tier),Ue=_7[(xe==null?void 0:xe.tier)??""]??"var(--text-normal)";return P.jsxs("div",{className:`lol-ranked-card ${Oe?"has-rank":""}`,style:{"--tier-color":Ue},children:[P.jsx("div",{className:"lol-ranked-type",children:k.game_type==="SOLORANKED"?"Ranked Solo/Duo":"Ranked Flex"}),Oe?P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"lol-ranked-tier",style:{color:Ue},children:[XAe(xe.tier,xe.division),P.jsxs("span",{className:"lol-ranked-lp",children:[xe.lp," LP"]})]}),P.jsxs("div",{className:"lol-ranked-record",children:[k.win,"W ",k.lose,"L",P.jsxs("span",{className:"lol-ranked-wr",children:["(",b7(k.win??0,k.lose??0),"%)"]}),k.is_hot_streak&&P.jsx("span",{className:"lol-ranked-streak",children:"🔥"})]})]}):P.jsx("div",{className:"lol-ranked-tier",children:"Unranked"})]},k.game_type)})}),((Ae=(pt=l.most_champions)==null?void 0:pt.champion_stats)==null?void 0:Ae.length)>0&&P.jsxs(P.Fragment,{children:[P.jsx("div",{className:"lol-section-title",children:"Top Champions"}),P.jsx("div",{className:"lol-champs",children:l.most_champions.champion_stats.slice(0,7).map(k=>{const xe=b7(k.win,k.lose),Oe=k.play>0?x7(k.kill/k.play,k.death/k.play,k.assist/k.play):"0";return P.jsxs("div",{className:"lol-champ-card",children:[P.jsx("img",{className:"lol-champ-icon",src:mm(k.champion_name),alt:k.champion_name}),P.jsxs("div",{children:[P.jsx("div",{className:"lol-champ-name",children:k.champion_name}),P.jsxs("div",{className:"lol-champ-stats",children:[k.play," games · ",xe,"% WR"]}),P.jsxs("div",{className:"lol-champ-kda",children:[Oe," KDA"]})]})]},k.champion_name)})})]}),h.length>0&&P.jsxs(P.Fragment,{children:[P.jsx("div",{className:"lol-section-title",children:"Match History"}),P.jsx("div",{className:"lol-matches",children:h.map(k=>_t(k))}),h.length<20&&P.jsx("button",{className:"lol-load-more",onClick:Ke,disabled:j,children:j?"Laden...":"Mehr laden"})]})]}),!l&&!v&&!S&&P.jsxs("div",{className:"lol-empty",children:[P.jsx("div",{className:"lol-empty-icon",children:"⚔️"}),P.jsx("h3",{children:"League of Legends Stats"}),P.jsx("p",{children:"Gib einen Summoner Name#Tag ein und wähle die Region"})]}),P.jsxs("div",{className:"lol-tier-section",children:[P.jsx("div",{className:"lol-section-title",children:"Champion Tier List"}),P.jsxs("div",{className:"lol-tier-controls",children:[P.jsx("div",{className:"lol-tier-modes",children:ae.map(k=>P.jsx("button",{className:`lol-tier-mode-btn ${Q===k.key?"active":""}`,onClick:()=>J(k.key),children:k.label},k.key))}),P.jsx("select",{className:"lol-search-region",value:ie,onChange:k=>le(k.target.value),children:s.map(k=>P.jsx("option",{value:k.code,children:k.code},k.code))}),P.jsx("input",{className:"lol-tier-filter",placeholder:"Filter champion...",value:Ve,onChange:k=>Ce(k.target.value)})]}),ne&&P.jsxs("div",{className:"lol-loading",children:[P.jsx("div",{className:"lol-spinner"}),"Lade Tier List..."]}),be&&P.jsx("div",{className:"lol-error",children:be}),!ne&&!be&&re.length>0&&P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"lol-tier-table",children:[P.jsxs("div",{className:"lol-tier-header",children:[P.jsx("span",{className:"lol-tier-col-rank",children:"#"}),P.jsx("span",{className:"lol-tier-col-champ",children:"Champion"}),P.jsx("span",{className:"lol-tier-col-tier",children:"Tier"}),P.jsx("span",{className:"lol-tier-col-wr",children:Q==="arena"?"Win":"Win %"}),P.jsx("span",{className:"lol-tier-col-pr",children:"Pick %"}),Q!=="arena"&&P.jsx("span",{className:"lol-tier-col-br",children:"Ban %"}),P.jsx("span",{className:"lol-tier-col-kda",children:Q==="arena"?"Avg Place":"KDA"})]}),re.filter(k=>!Ve||k.champion_name.toLowerCase().includes(Ve.toLowerCase())).slice(0,Fe?void 0:50).map(k=>{var Oe,Ue;const xe=["OP","1","2","3","4","5"];return P.jsxs("div",{className:`lol-tier-row tier-${k.tier}`,children:[P.jsx("span",{className:"lol-tier-col-rank",children:k.rank}),P.jsxs("span",{className:"lol-tier-col-champ",children:[P.jsx("img",{src:mm(k.champion_name),alt:k.champion_name}),k.champion_name]}),P.jsx("span",{className:`lol-tier-col-tier tier-badge-${k.tier}`,children:xe[k.tier]??k.tier}),P.jsx("span",{className:"lol-tier-col-wr",children:k.win_rate!=null?`${(k.win_rate*100).toFixed(1)}%`:"-"}),P.jsxs("span",{className:"lol-tier-col-pr",children:[(k.pick_rate*100).toFixed(1),"%"]}),Q!=="arena"&&P.jsx("span",{className:"lol-tier-col-br",children:k.ban_rate!=null?`${(k.ban_rate*100).toFixed(1)}%`:"-"}),P.jsx("span",{className:"lol-tier-col-kda",children:Q==="arena"?((Oe=k.average_placement)==null?void 0:Oe.toFixed(1))??"-":((Ue=k.kda)==null?void 0:Ue.toFixed(2))??"-"})]},k.champion_id)})]}),!Fe&&re.length>50&&P.jsxs("button",{className:"lol-load-more",onClick:()=>tt(!0),children:["Alle ",re.length," Champions anzeigen"]})]})]})]})}const S7={iceServers:[{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun1.l.google.com:19302"}]};function VS(i){const e=Math.max(0,Math.floor((Date.now()-new Date(i).getTime())/1e3)),t=Math.floor(e/3600),n=Math.floor(e%3600/60),r=e%60;return t>0?`${t}:${String(n).padStart(2,"0")}:${String(r).padStart(2,"0")}`:`${n}:${String(r).padStart(2,"0")}`}const jS=[{label:"Niedrig · 4 Mbit · 60fps",fps:60,bitrate:4e6},{label:"Mittel · 8 Mbit · 60fps",fps:60,bitrate:8e6},{label:"Hoch · 14 Mbit · 60fps",fps:60,bitrate:14e6},{label:"Ultra · 25 Mbit · 60fps",fps:60,bitrate:25e6},{label:"Max · 50 Mbit · 165fps",fps:165,bitrate:5e7}];function QAe({data:i,isAdmin:e}){var Re,We;const[t,n]=se.useState([]),[r,s]=se.useState(()=>localStorage.getItem("streaming_name")||""),[a,l]=se.useState("Screen Share"),[u,h]=se.useState(""),[m,v]=se.useState(1),[x,S]=se.useState(null),[T,N]=se.useState(null),[C,E]=se.useState(null),[O,U]=se.useState(!1),[I,j]=se.useState(!1),[z,G]=se.useState(null),[,H]=se.useState(0),[q,V]=se.useState(null),[Q,J]=se.useState(null),ie=se.useRef(null),le=se.useRef(""),re=se.useRef(null),Z=se.useRef(null),ne=se.useRef(null),de=se.useRef(new Map),be=se.useRef(null),Te=se.useRef(null),ae=se.useRef(new Map),Me=se.useRef(null),Ve=se.useRef(1e3),Ce=se.useRef(!1),Fe=se.useRef(null),tt=se.useRef(jS[1]);se.useEffect(()=>{Ce.current=O},[O]),se.useEffect(()=>{Fe.current=z},[z]),se.useEffect(()=>{tt.current=jS[m]},[m]),se.useEffect(()=>{var Se,Le;(Le=(Se=window.electronAPI)==null?void 0:Se.setStreaming)==null||Le.call(Se,O||z!==null)},[O,z]),se.useEffect(()=>{if(!(t.length>0||O))return;const Le=setInterval(()=>H(ct=>ct+1),1e3);return()=>clearInterval(Le)},[t.length,O]),se.useEffect(()=>{i!=null&&i.streams&&n(i.streams)},[i]),se.useEffect(()=>{r&&localStorage.setItem("streaming_name",r)},[r]),se.useEffect(()=>{if(!q)return;const Se=()=>V(null);return document.addEventListener("click",Se),()=>document.removeEventListener("click",Se)},[q]);const je=se.useCallback(Se=>{var Le;((Le=ie.current)==null?void 0:Le.readyState)===WebSocket.OPEN&&ie.current.send(JSON.stringify(Se))},[]),Rt=se.useCallback((Se,Le,ct)=>{if(Se.remoteDescription)Se.addIceCandidate(new RTCIceCandidate(ct)).catch(()=>{});else{let Dt=ae.current.get(Le);Dt||(Dt=[],ae.current.set(Le,Dt)),Dt.push(ct)}},[]),Et=se.useCallback((Se,Le)=>{const ct=ae.current.get(Le);if(ct){for(const Dt of ct)Se.addIceCandidate(new RTCIceCandidate(Dt)).catch(()=>{});ae.current.delete(Le)}},[]),Ft=se.useCallback((Se,Le)=>{Se.srcObject=Le;const ct=Se.play();ct&&ct.catch(()=>{Se.muted=!0,Se.play().catch(()=>{})})},[]),Ut=se.useCallback(()=>{document.fullscreenElement&&document.exitFullscreen().catch(()=>{}),be.current&&(be.current.close(),be.current=null),Te.current=null,ne.current&&(ne.current.srcObject=null)},[]),Ke=se.useRef(()=>{});Ke.current=Se=>{var Le,ct,Dt;switch(Se.type){case"welcome":le.current=Se.clientId,Se.streams&&n(Se.streams);break;case"broadcast_started":E(Se.streamId),U(!0),Ce.current=!0,j(!1),(Le=window.electronAPI)!=null&&Le.showNotification&&window.electronAPI.showNotification("Stream gestartet","Dein Stream ist jetzt live!");break;case"stream_available":n(lt=>lt.some(jt=>jt.id===Se.streamId)?lt:[...lt,{id:Se.streamId,broadcasterName:Se.broadcasterName,title:Se.title,startedAt:new Date().toISOString(),viewerCount:0,hasPassword:!!Se.hasPassword}]);const It=`${Se.broadcasterName} streamt: ${Se.title}`;(ct=window.electronAPI)!=null&&ct.showNotification?window.electronAPI.showNotification("Neuer Stream",It):Notification.permission==="granted"&&new Notification("Neuer Stream",{body:It,icon:"/assets/icon.png"});break;case"stream_ended":n(lt=>lt.filter(jt=>jt.id!==Se.streamId)),((Dt=Fe.current)==null?void 0:Dt.streamId)===Se.streamId&&(Ut(),G(null));break;case"viewer_joined":{const lt=Se.viewerId,jt=de.current.get(lt);jt&&(jt.close(),de.current.delete(lt)),ae.current.delete(lt);const Jt=new RTCPeerConnection(S7);de.current.set(lt,Jt);const In=re.current;if(In)for(const Bt of In.getTracks())Jt.addTrack(Bt,In);Jt.onicecandidate=Bt=>{Bt.candidate&&je({type:"ice_candidate",targetId:lt,candidate:Bt.candidate.toJSON()})};const me=Jt.getSenders().find(Bt=>{var ot;return((ot=Bt.track)==null?void 0:ot.kind)==="video"});if(me){const Bt=me.getParameters();(!Bt.encodings||Bt.encodings.length===0)&&(Bt.encodings=[{}]),Bt.encodings[0].maxFramerate=tt.current.fps,Bt.encodings[0].maxBitrate=tt.current.bitrate,me.setParameters(Bt).catch(()=>{})}Jt.createOffer().then(Bt=>Jt.setLocalDescription(Bt)).then(()=>je({type:"offer",targetId:lt,sdp:Jt.localDescription})).catch(console.error);break}case"viewer_left":{const lt=de.current.get(Se.viewerId);lt&&(lt.close(),de.current.delete(Se.viewerId)),ae.current.delete(Se.viewerId);break}case"offer":{const lt=Se.fromId;be.current&&(be.current.close(),be.current=null),ae.current.delete(lt);const jt=new RTCPeerConnection(S7);be.current=jt,jt.ontrack=Jt=>{const In=Jt.streams[0];if(!In)return;Te.current=In;const me=ne.current;me&&Ft(me,In),G(Bt=>Bt&&{...Bt,phase:"connected"})},jt.onicecandidate=Jt=>{Jt.candidate&&je({type:"ice_candidate",targetId:lt,candidate:Jt.candidate.toJSON()})},jt.oniceconnectionstatechange=()=>{(jt.iceConnectionState==="failed"||jt.iceConnectionState==="disconnected")&&G(Jt=>Jt&&{...Jt,phase:"error",error:"Verbindung verloren"})},jt.setRemoteDescription(new RTCSessionDescription(Se.sdp)).then(()=>(Et(jt,lt),jt.createAnswer())).then(Jt=>jt.setLocalDescription(Jt)).then(()=>je({type:"answer",targetId:lt,sdp:jt.localDescription})).catch(console.error);break}case"answer":{const lt=de.current.get(Se.fromId);lt&<.setRemoteDescription(new RTCSessionDescription(Se.sdp)).then(()=>Et(lt,Se.fromId)).catch(console.error);break}case"ice_candidate":{if(!Se.candidate)break;const lt=de.current.get(Se.fromId);lt?Rt(lt,Se.fromId,Se.candidate):be.current&&Rt(be.current,Se.fromId,Se.candidate);break}case"error":Se.code==="WRONG_PASSWORD"?N(lt=>lt&&{...lt,error:Se.message}):S(Se.message),j(!1);break}};const ht=se.useCallback(()=>{if(ie.current&&ie.current.readyState===WebSocket.OPEN)return;const Se=location.protocol==="https:"?"wss":"ws",Le=new WebSocket(`${Se}://${location.host}/ws/streaming`);ie.current=Le,Le.onopen=()=>{Ve.current=1e3},Le.onmessage=ct=>{let Dt;try{Dt=JSON.parse(ct.data)}catch{return}Ke.current(Dt)},Le.onclose=()=>{ie.current=null,Me.current=setTimeout(()=>{Ve.current=Math.min(Ve.current*2,1e4),ht()},Ve.current)},Le.onerror=()=>{Le.close()}},[]);se.useEffect(()=>(ht(),()=>{Me.current&&clearTimeout(Me.current)}),[ht]);const fe=se.useCallback(async()=>{var Se,Le;if(!r.trim()){S("Bitte gib einen Namen ein.");return}if(!((Se=navigator.mediaDevices)!=null&&Se.getDisplayMedia)){S("Dein Browser unterstützt keine Bildschirmfreigabe.");return}S(null),j(!0);try{const ct=tt.current,Dt=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:{ideal:ct.fps}},audio:!0});re.current=Dt,Z.current&&(Z.current.srcObject=Dt),(Le=Dt.getVideoTracks()[0])==null||Le.addEventListener("ended",()=>{$t()}),ht();const It=()=>{var lt;((lt=ie.current)==null?void 0:lt.readyState)===WebSocket.OPEN?je({type:"start_broadcast",name:r.trim(),title:a.trim()||"Screen Share",password:u.trim()||void 0}):setTimeout(It,100)};It()}catch(ct){j(!1),ct.name==="NotAllowedError"?S("Bildschirmfreigabe wurde abgelehnt."):S(`Fehler: ${ct.message}`)}},[r,a,u,ht,je]),$t=se.useCallback(()=>{var Se;je({type:"stop_broadcast"}),(Se=re.current)==null||Se.getTracks().forEach(Le=>Le.stop()),re.current=null,Z.current&&(Z.current.srcObject=null);for(const Le of de.current.values())Le.close();de.current.clear(),U(!1),Ce.current=!1,E(null),h("")},[je]),_t=se.useCallback(Se=>{S(null),G({streamId:Se,phase:"connecting"}),ht();const Le=()=>{var ct;((ct=ie.current)==null?void 0:ct.readyState)===WebSocket.OPEN?je({type:"join_viewer",name:r.trim()||"Viewer",streamId:Se}):setTimeout(Le,100)};Le()},[r,ht,je]),Gt=se.useCallback(Se=>{Se.hasPassword?N({streamId:Se.id,streamTitle:Se.title,broadcasterName:Se.broadcasterName,password:"",error:null}):_t(Se.id)},[_t]),yt=se.useCallback(()=>{if(!T)return;if(!T.password.trim()){N(Dt=>Dt&&{...Dt,error:"Passwort eingeben."});return}const{streamId:Se,password:Le}=T;N(null),S(null),G({streamId:Se,phase:"connecting"}),ht();const ct=()=>{var Dt;((Dt=ie.current)==null?void 0:Dt.readyState)===WebSocket.OPEN?je({type:"join_viewer",name:r.trim()||"Viewer",streamId:Se,password:Le.trim()}):setTimeout(ct,100)};ct()},[T,r,ht,je]),Ht=se.useCallback(()=>{je({type:"leave_viewer"}),Ut(),G(null)},[Ut,je]);se.useEffect(()=>{const Se=ct=>{(Ce.current||Fe.current)&&ct.preventDefault()},Le=()=>{le.current&&navigator.sendBeacon("/api/streaming/disconnect",JSON.stringify({clientId:le.current}))};return window.addEventListener("beforeunload",Se),window.addEventListener("pagehide",Le),()=>{window.removeEventListener("beforeunload",Se),window.removeEventListener("pagehide",Le)}},[]);const pt=se.useRef(null),[Ae,k]=se.useState(!1),xe=se.useCallback(()=>{const Se=pt.current;Se&&(document.fullscreenElement?document.exitFullscreen().catch(()=>{}):Se.requestFullscreen().catch(()=>{}))},[]);se.useEffect(()=>{const Se=()=>k(!!document.fullscreenElement);return document.addEventListener("fullscreenchange",Se),()=>document.removeEventListener("fullscreenchange",Se)},[]),se.useEffect(()=>()=>{var Se;(Se=re.current)==null||Se.getTracks().forEach(Le=>Le.stop());for(const Le of de.current.values())Le.close();be.current&&be.current.close(),ie.current&&ie.current.close(),Me.current&&clearTimeout(Me.current)},[]),se.useEffect(()=>{z&&Te.current&&ne.current&&!ne.current.srcObject&&Ft(ne.current,Te.current)},[z,Ft]);const Oe=se.useRef(null);se.useEffect(()=>{const Le=new URLSearchParams(location.search).get("viewStream");if(Le){Oe.current=Le;const ct=new URL(location.href);ct.searchParams.delete("viewStream"),window.history.replaceState({},"",ct.toString())}},[]),se.useEffect(()=>{const Se=Oe.current;if(!Se||t.length===0)return;const Le=t.find(ct=>ct.id===Se);Le&&(Oe.current=null,Gt(Le))},[t,Gt]);const Ue=se.useCallback(Se=>{const Le=new URL(location.href);return Le.searchParams.set("viewStream",Se),Le.hash="",Le.toString()},[]),ee=se.useCallback(Se=>{navigator.clipboard.writeText(Ue(Se)).then(()=>{J(Se),setTimeout(()=>J(null),2e3)}).catch(()=>{})},[Ue]),we=se.useCallback(Se=>{window.open(Ue(Se),"_blank","noopener"),V(null)},[Ue]);if(z){const Se=t.find(Le=>Le.id===z.streamId);return P.jsxs("div",{className:"stream-viewer-overlay",ref:pt,children:[P.jsxs("div",{className:"stream-viewer-header",children:[P.jsxs("div",{className:"stream-viewer-header-left",children:[P.jsxs("span",{className:"stream-live-badge",children:[P.jsx("span",{className:"stream-live-dot"})," LIVE"]}),P.jsxs("div",{children:[P.jsx("div",{className:"stream-viewer-title",children:(Se==null?void 0:Se.title)||"Stream"}),P.jsxs("div",{className:"stream-viewer-subtitle",children:[(Se==null?void 0:Se.broadcasterName)||"..."," ",Se?` · ${Se.viewerCount} Zuschauer`:""]})]})]}),P.jsxs("div",{className:"stream-viewer-header-right",children:[P.jsx("button",{className:"stream-viewer-fullscreen",onClick:xe,title:Ae?"Vollbild verlassen":"Vollbild",children:Ae?"✖":"⛶"}),P.jsx("button",{className:"stream-viewer-close",onClick:Ht,children:"Verlassen"})]})]}),P.jsxs("div",{className:"stream-viewer-video",children:[z.phase==="connecting"?P.jsxs("div",{className:"stream-viewer-connecting",children:[P.jsx("div",{className:"stream-viewer-spinner"}),"Verbindung wird hergestellt..."]}):z.phase==="error"?P.jsxs("div",{className:"stream-viewer-connecting",children:[z.error||"Verbindungsfehler",P.jsx("button",{className:"stream-btn",onClick:Ht,children:"Zurück"})]}):null,P.jsx("video",{ref:ne,autoPlay:!0,playsInline:!0,style:z.phase==="connected"?{}:{display:"none"}})]})]})}return P.jsxs("div",{className:"stream-container",children:[x&&P.jsxs("div",{className:"stream-error",children:[x,P.jsx("button",{className:"stream-error-dismiss",onClick:()=>S(null),children:"×"})]}),P.jsxs("div",{className:"stream-topbar",children:[P.jsxs("label",{className:"stream-field",children:[P.jsx("span",{className:"stream-field-label",children:"Name"}),P.jsx("input",{className:"stream-input stream-input-name",placeholder:"Dein Name",value:r,onChange:Se=>s(Se.target.value),disabled:O})]}),P.jsxs("label",{className:"stream-field stream-field-grow",children:[P.jsx("span",{className:"stream-field-label",children:"Titel"}),P.jsx("input",{className:"stream-input stream-input-title",placeholder:"Stream-Titel",value:a,onChange:Se=>l(Se.target.value),disabled:O})]}),P.jsxs("label",{className:"stream-field",children:[P.jsx("span",{className:"stream-field-label",children:"Passwort"}),P.jsx("input",{className:"stream-input stream-input-password",type:"password",placeholder:"optional",value:u,onChange:Se=>h(Se.target.value),disabled:O})]}),P.jsxs("label",{className:"stream-field",children:[P.jsxs("span",{className:"stream-field-label",children:["Qualit","ä","t"]}),P.jsx("select",{className:"stream-select-quality",value:m,onChange:Se=>v(Number(Se.target.value)),disabled:O,children:jS.map((Se,Le)=>P.jsx("option",{value:Le,children:Se.label},Se.label))})]}),O?P.jsxs("button",{className:"stream-btn stream-btn-stop",onClick:$t,children:["⏹"," Stream beenden"]}):P.jsx("button",{className:"stream-btn",onClick:fe,disabled:I,children:I?"Starte...":"🖥️ Stream starten"})]}),t.length===0&&!O?P.jsxs("div",{className:"stream-empty",children:[P.jsx("div",{className:"stream-empty-icon",children:"📺"}),P.jsx("h3",{children:"Keine aktiven Streams"}),P.jsx("p",{children:"Starte einen Stream, um deinen Bildschirm zu teilen."})]}):P.jsxs("div",{className:"stream-grid",children:[O&&P.jsxs("div",{className:"stream-tile own broadcasting",children:[P.jsxs("div",{className:"stream-tile-preview",children:[P.jsx("video",{ref:Z,autoPlay:!0,playsInline:!0,muted:!0}),P.jsxs("span",{className:"stream-live-badge",children:[P.jsx("span",{className:"stream-live-dot"})," LIVE"]}),P.jsxs("span",{className:"stream-tile-viewers",children:["👥"," ",((Re=t.find(Se=>Se.id===C))==null?void 0:Re.viewerCount)??0]})]}),P.jsxs("div",{className:"stream-tile-info",children:[P.jsxs("div",{className:"stream-tile-meta",children:[P.jsxs("div",{className:"stream-tile-name",children:[r," (Du)"]}),P.jsx("div",{className:"stream-tile-title",children:a})]}),P.jsx("span",{className:"stream-tile-time",children:C&&((We=t.find(Se=>Se.id===C))!=null&&We.startedAt)?VS(t.find(Se=>Se.id===C).startedAt):"0:00"})]})]}),t.filter(Se=>Se.id!==C).map(Se=>P.jsxs("div",{className:"stream-tile",onClick:()=>Gt(Se),children:[P.jsxs("div",{className:"stream-tile-preview",children:[P.jsx("span",{className:"stream-tile-icon",children:"🖥️"}),P.jsxs("span",{className:"stream-live-badge",children:[P.jsx("span",{className:"stream-live-dot"})," LIVE"]}),P.jsxs("span",{className:"stream-tile-viewers",children:["👥"," ",Se.viewerCount]}),Se.hasPassword&&P.jsx("span",{className:"stream-tile-lock",children:"🔒"})]}),P.jsxs("div",{className:"stream-tile-info",children:[P.jsxs("div",{className:"stream-tile-meta",children:[P.jsx("div",{className:"stream-tile-name",children:Se.broadcasterName}),P.jsx("div",{className:"stream-tile-title",children:Se.title})]}),P.jsx("span",{className:"stream-tile-time",children:VS(Se.startedAt)}),P.jsxs("div",{className:"stream-tile-menu-wrap",children:[P.jsx("button",{className:"stream-tile-menu",onClick:Le=>{Le.stopPropagation(),V(q===Se.id?null:Se.id)},children:"⋮"}),q===Se.id&&P.jsxs("div",{className:"stream-tile-dropdown",onClick:Le=>Le.stopPropagation(),children:[P.jsxs("div",{className:"stream-tile-dropdown-header",children:[P.jsx("div",{className:"stream-tile-dropdown-name",children:Se.broadcasterName}),P.jsx("div",{className:"stream-tile-dropdown-title",children:Se.title}),P.jsxs("div",{className:"stream-tile-dropdown-detail",children:["👥"," ",Se.viewerCount," Zuschauer · ",VS(Se.startedAt)]})]}),P.jsx("div",{className:"stream-tile-dropdown-divider"}),P.jsxs("button",{className:"stream-tile-dropdown-item",onClick:()=>we(Se.id),children:["🗗"," In neuem Fenster öffnen"]}),P.jsx("button",{className:"stream-tile-dropdown-item",onClick:()=>{ee(Se.id),V(null)},children:Q===Se.id?"✅ Kopiert!":"🔗 Link teilen"})]})]})]})]},Se.id))]}),T&&P.jsx("div",{className:"stream-pw-overlay",onClick:()=>N(null),children:P.jsxs("div",{className:"stream-pw-modal",onClick:Se=>Se.stopPropagation(),children:[P.jsx("h3",{children:T.broadcasterName}),P.jsx("p",{children:T.streamTitle}),T.error&&P.jsx("div",{className:"stream-pw-modal-error",children:T.error}),P.jsx("input",{className:"stream-input",type:"password",placeholder:"Stream-Passwort",value:T.password,onChange:Se=>N(Le=>Le&&{...Le,password:Se.target.value,error:null}),onKeyDown:Se=>{Se.key==="Enter"&&yt()},autoFocus:!0}),P.jsxs("div",{className:"stream-pw-actions",children:[P.jsx("button",{className:"stream-pw-cancel",onClick:()=>N(null),children:"Abbrechen"}),P.jsx("button",{className:"stream-btn",onClick:yt,children:"Beitreten"})]})]})})]})}function w7(i){const e=Math.floor(i),t=Math.floor(e/3600),n=Math.floor(e%3600/60),r=e%60;return t>0?`${t}:${String(n).padStart(2,"0")}:${String(r).padStart(2,"0")}`:`${n}:${String(r).padStart(2,"0")}`}function KAe(i){const e=i.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/);if(e)return{type:"youtube",videoId:e[1]};const t=i.match(/(?:dailymotion\.com\/video\/|dai\.ly\/)([a-zA-Z0-9]+)/);return t?{type:"dailymotion",videoId:t[1]}:/\.(mp4|webm|ogg)(\?|$)/i.test(i)||i.startsWith("http")?{type:"direct",url:i}:null}function ZAe({data:i}){var pn;const[e,t]=se.useState([]),[n,r]=se.useState(()=>localStorage.getItem("wt_name")||""),[s,a]=se.useState(""),[l,u]=se.useState(""),[h,m]=se.useState(null),[v,x]=se.useState(null),[S,T]=se.useState(null),[N,C]=se.useState(""),[E,O]=se.useState(()=>{const $e=localStorage.getItem("wt_volume");return $e?parseFloat($e):1}),[U,I]=se.useState(!1),[j,z]=se.useState(0),[G,H]=se.useState(0),[q,V]=se.useState(null),[Q,J]=se.useState(!1),[ie,le]=se.useState([]),[re,Z]=se.useState(""),[ne,de]=se.useState(null),[be,Te]=se.useState("synced"),[ae,Me]=se.useState(!0),[Ve,Ce]=se.useState(()=>localStorage.getItem("wt_yt_quality")||"hd1080"),Fe=se.useRef(null),tt=se.useRef(""),je=se.useRef(null),Rt=se.useRef(1e3),Et=se.useRef(null),Ft=se.useRef(null),Ut=se.useRef(null),Ke=se.useRef(null),ht=se.useRef(null),fe=se.useRef(null),$t=se.useRef(!1),_t=se.useRef(!1),Gt=se.useRef(null),yt=se.useRef(null),Ht=se.useRef(Ve),pt=se.useRef(null),Ae=se.useRef(!1),k=se.useRef(0),xe=se.useRef(0);se.useEffect(()=>{Et.current=h},[h]);const Oe=h!=null&&tt.current===h.hostId;se.useEffect(()=>{Ht.current=Ve,localStorage.setItem("wt_yt_quality",Ve),Ut.current&&typeof Ut.current.setPlaybackQuality=="function"&&Ut.current.setPlaybackQuality(Ve)},[Ve]),se.useEffect(()=>{i!=null&&i.rooms&&t(i.rooms)},[i]),se.useEffect(()=>{var $e;($e=yt.current)==null||$e.scrollIntoView({behavior:"smooth"})},[ie]),se.useEffect(()=>{const St=new URLSearchParams(window.location.search).get("wt");if(St&&n.trim()){const Kt=setTimeout(()=>ct(St),1500);return()=>clearTimeout(Kt)}},[]),se.useEffect(()=>{n&&localStorage.setItem("wt_name",n)},[n]),se.useEffect(()=>{var $e;localStorage.setItem("wt_volume",String(E)),Ut.current&&typeof Ut.current.setVolume=="function"&&Ut.current.setVolume(E*100),Ke.current&&(Ke.current.volume=E),($e=pt.current)!=null&&$e.contentWindow&&fe.current==="dailymotion"&&pt.current.contentWindow.postMessage(`volume?volume=${E}`,"https://www.dailymotion.com")},[E]),se.useEffect(()=>{if(window.YT){$t.current=!0;return}const $e=document.createElement("script");$e.src="https://www.youtube.com/iframe_api",document.head.appendChild($e);const St=window.onYouTubeIframeAPIReady;window.onYouTubeIframeAPIReady=()=>{$t.current=!0,St&&St()}},[]);const Ue=se.useCallback($e=>{var St;((St=Fe.current)==null?void 0:St.readyState)===WebSocket.OPEN&&Fe.current.send(JSON.stringify($e))},[]),ee=se.useCallback(()=>fe.current==="youtube"&&Ut.current&&typeof Ut.current.getCurrentTime=="function"?Ut.current.getCurrentTime():fe.current==="direct"&&Ke.current?Ke.current.currentTime:fe.current==="dailymotion"?k.current:null,[]);se.useCallback(()=>fe.current==="youtube"&&Ut.current&&typeof Ut.current.getDuration=="function"?Ut.current.getDuration()||0:fe.current==="direct"&&Ke.current?Ke.current.duration||0:fe.current==="dailymotion"?xe.current:0,[]);const we=se.useCallback(()=>{if(Ut.current){try{Ut.current.destroy()}catch{}Ut.current=null}Ke.current&&(Ke.current.pause(),Ke.current.removeAttribute("src"),Ke.current.load()),pt.current&&(pt.current.src="",Ae.current=!1,k.current=0,xe.current=0),fe.current=null,Gt.current&&(clearInterval(Gt.current),Gt.current=null)},[]),Re=se.useCallback($e=>{we(),V(null);const St=KAe($e);if(St)if(St.type==="youtube"){if(fe.current="youtube",!$t.current||!ht.current)return;const Kt=ht.current,wn=document.createElement("div");wn.id="wt-yt-player-"+Date.now(),Kt.innerHTML="",Kt.appendChild(wn),Ut.current=new window.YT.Player(wn.id,{videoId:St.videoId,playerVars:{autoplay:1,controls:0,modestbranding:1,rel:0},events:{onReady:qn=>{qn.target.setVolume(E*100),qn.target.setPlaybackQuality(Ht.current),z(qn.target.getDuration()||0),Gt.current=setInterval(()=>{Ut.current&&typeof Ut.current.getCurrentTime=="function"&&(H(Ut.current.getCurrentTime()),z(Ut.current.getDuration()||0))},500)},onStateChange:qn=>{if(qn.data===window.YT.PlayerState.ENDED){const Je=Et.current;Je&&tt.current===Je.hostId&&Ue({type:"skip"})}},onError:qn=>{const Je=qn.data;V(Je===101||Je===150?"Embedding deaktiviert — Video kann nur auf YouTube angesehen werden.":Je===100?"Video nicht gefunden oder entfernt.":"Wiedergabefehler — Video wird übersprungen."),setTimeout(()=>{const dt=Et.current;dt&&tt.current===dt.hostId&&Ue({type:"skip"})},3e3)}}})}else St.type==="dailymotion"?(fe.current="dailymotion",pt.current&&(pt.current.src=`https://www.dailymotion.com/embed/video/${St.videoId}?api=postMessage&autoplay=1&controls=0&mute=0&queue-enable=0`)):(fe.current="direct",Ke.current&&(Ke.current.src=St.url,Ke.current.volume=E,Ke.current.play().catch(()=>{})))},[we,E,Ue]);se.useEffect(()=>{const $e=Ke.current;if(!$e)return;const St=()=>{const wn=Et.current;wn&&tt.current===wn.hostId&&Ue({type:"skip"})},Kt=()=>{H($e.currentTime),z($e.duration||0)};return $e.addEventListener("ended",St),$e.addEventListener("timeupdate",Kt),()=>{$e.removeEventListener("ended",St),$e.removeEventListener("timeupdate",Kt)}},[Ue]),se.useEffect(()=>{const $e=St=>{var Je;if(St.origin!=="https://www.dailymotion.com"||typeof St.data!="string")return;const Kt=new URLSearchParams(St.data),wn=Kt.get("method"),qn=Kt.get("value");if(wn==="timeupdate"&&qn){const dt=parseFloat(qn);k.current=dt,H(dt)}else if(wn==="durationchange"&&qn){const dt=parseFloat(qn);xe.current=dt,z(dt)}else if(wn==="ended"){const dt=Et.current;dt&&tt.current===dt.hostId&&Ue({type:"skip"})}else wn==="apiready"&&(Ae.current=!0,(Je=pt.current)!=null&&Je.contentWindow&&pt.current.contentWindow.postMessage(`volume?volume=${E}`,"https://www.dailymotion.com"))};return window.addEventListener("message",$e),()=>window.removeEventListener("message",$e)},[Ue,E]);const We=se.useRef(()=>{});We.current=$e=>{var St,Kt,wn,qn,Je,dt,Vt,xt,A,te,Vn,Wn,$n,dn,Fn,lr;switch($e.type){case"welcome":tt.current=$e.clientId,$e.rooms&&t($e.rooms);break;case"room_created":{const an=$e.room;m({id:an.id,name:an.name,hostId:an.hostId,members:an.members||[],currentVideo:an.currentVideo||null,playing:an.playing||!1,currentTime:an.currentTime||0,queue:an.queue||[]});break}case"room_joined":{const an=$e.room;m({id:an.id,name:an.name,hostId:an.hostId,members:an.members||[],currentVideo:an.currentVideo||null,playing:an.playing||!1,currentTime:an.currentTime||0,queue:an.queue||[]}),(St=an.currentVideo)!=null&&St.url&&setTimeout(()=>Re(an.currentVideo.url),100);break}case"playback_state":{const an=Et.current;if(!an)break;const mn=$e.currentVideo,Er=(Kt=an.currentVideo)==null?void 0:Kt.url;if(mn!=null&&mn.url&&mn.url!==Er?Re(mn.url):!mn&&Er&&we(),fe.current==="youtube"&&Ut.current){const Wi=(qn=(wn=Ut.current).getPlayerState)==null?void 0:qn.call(wn);$e.playing&&Wi!==((dt=(Je=window.YT)==null?void 0:Je.PlayerState)==null?void 0:dt.PLAYING)?(xt=(Vt=Ut.current).playVideo)==null||xt.call(Vt):!$e.playing&&Wi===((te=(A=window.YT)==null?void 0:A.PlayerState)==null?void 0:te.PLAYING)&&((Wn=(Vn=Ut.current).pauseVideo)==null||Wn.call(Vn))}else fe.current==="direct"&&Ke.current?$e.playing&&Ke.current.paused?Ke.current.play().catch(()=>{}):!$e.playing&&!Ke.current.paused&&Ke.current.pause():fe.current==="dailymotion"&&(($n=pt.current)!=null&&$n.contentWindow)&&($e.playing?pt.current.contentWindow.postMessage("play","https://www.dailymotion.com"):pt.current.contentWindow.postMessage("pause","https://www.dailymotion.com"));if($e.currentTime!==void 0&&!_t.current){const Wi=ee();Wi!==null&&Math.abs(Wi-$e.currentTime)>2&&(fe.current==="youtube"&&Ut.current?(Fn=(dn=Ut.current).seekTo)==null||Fn.call(dn,$e.currentTime,!0):fe.current==="direct"&&Ke.current?Ke.current.currentTime=$e.currentTime:fe.current==="dailymotion"&&((lr=pt.current)!=null&&lr.contentWindow)&&pt.current.contentWindow.postMessage(`seek?to=${$e.currentTime}`,"https://www.dailymotion.com"))}if($e.currentTime!==void 0){const Wi=ee();if(Wi!==null){const No=Math.abs(Wi-$e.currentTime);No<1.5?Te("synced"):No<5?Te("drifting"):Te("desynced")}}m(Wi=>Wi&&{...Wi,currentVideo:mn||null,playing:$e.playing,currentTime:$e.currentTime??Wi.currentTime});break}case"queue_updated":m(an=>an&&{...an,queue:$e.queue});break;case"members_updated":m(an=>an&&{...an,members:$e.members,hostId:$e.hostId});break;case"vote_updated":de($e.votes);break;case"chat":le(an=>{const mn=[...an,{sender:$e.sender,text:$e.text,timestamp:$e.timestamp}];return mn.length>100?mn.slice(-100):mn});break;case"chat_history":le($e.messages||[]);break;case"error":$e.code==="WRONG_PASSWORD"?x(an=>an&&{...an,error:$e.message}):T($e.message);break}};const Se=se.useCallback(()=>{if(Fe.current&&(Fe.current.readyState===WebSocket.OPEN||Fe.current.readyState===WebSocket.CONNECTING))return;const $e=location.protocol==="https:"?"wss":"ws",St=new WebSocket(`${$e}://${location.host}/ws/watch-together`);Fe.current=St,St.onopen=()=>{Rt.current=1e3},St.onmessage=Kt=>{let wn;try{wn=JSON.parse(Kt.data)}catch{return}We.current(wn)},St.onclose=()=>{Fe.current===St&&(Fe.current=null),Et.current&&(je.current=setTimeout(()=>{Rt.current=Math.min(Rt.current*2,1e4),Se()},Rt.current))},St.onerror=()=>{St.close()}},[]),Le=se.useCallback(()=>{if(!n.trim()){T("Bitte gib einen Namen ein.");return}if(!s.trim()){T("Bitte gib einen Raumnamen ein.");return}T(null),Se();const $e=Date.now(),St=()=>{var Kt;((Kt=Fe.current)==null?void 0:Kt.readyState)===WebSocket.OPEN?Ue({type:"create_room",name:s.trim(),userName:n.trim(),password:l.trim()||void 0}):Date.now()-$e>1e4?T("Verbindung zum Server fehlgeschlagen."):setTimeout(St,100)};St()},[n,s,l,Se,Ue]),ct=se.useCallback(($e,St)=>{if(!n.trim()){T("Bitte gib einen Namen ein.");return}T(null),Se();const Kt=Date.now(),wn=()=>{var qn;((qn=Fe.current)==null?void 0:qn.readyState)===WebSocket.OPEN?Ue({type:"join_room",userName:n.trim(),roomId:$e,password:(St==null?void 0:St.trim())||void 0}):Date.now()-Kt>1e4?T("Verbindung zum Server fehlgeschlagen."):setTimeout(wn,100)};wn()},[n,Se,Ue]),Dt=se.useCallback(()=>{Ue({type:"leave_room"}),we(),m(null),C(""),z(0),H(0),le([]),de(null),Te("synced")},[Ue,we]),It=se.useCallback(async()=>{const $e=N.trim();if(!$e)return;C(""),J(!0);let St="";try{const Kt=await fetch(`/api/watch-together/video-info?url=${encodeURIComponent($e)}`);Kt.ok&&(St=(await Kt.json()).title||"")}catch{}Ue({type:"add_to_queue",url:$e,title:St||void 0}),J(!1)},[N,Ue]),lt=se.useCallback(()=>{const $e=re.trim();$e&&(Z(""),Ue({type:"chat_message",text:$e}))},[re,Ue]);se.useCallback(()=>{Ue({type:"vote_skip"})},[Ue]),se.useCallback(()=>{Ue({type:"vote_pause"})},[Ue]);const jt=se.useCallback(()=>{Ue({type:"clear_watched"})},[Ue]),Jt=se.useCallback(()=>{if(!h)return;const $e=`${window.location.origin}${window.location.pathname}?wt=${h.id}`;navigator.clipboard.writeText($e).catch(()=>{})},[h]),In=se.useCallback($e=>{Ue({type:"remove_from_queue",index:$e})},[Ue]),me=se.useCallback(()=>{const $e=Et.current;$e&&Ue({type:$e.playing?"pause":"resume"})},[Ue]),Bt=se.useCallback(()=>{Ue({type:"skip"})},[Ue]),ot=se.useCallback($e=>{var St,Kt,wn;_t.current=!0,Ue({type:"seek",time:$e}),fe.current==="youtube"&&Ut.current?(Kt=(St=Ut.current).seekTo)==null||Kt.call(St,$e,!0):fe.current==="direct"&&Ke.current?Ke.current.currentTime=$e:fe.current==="dailymotion"&&((wn=pt.current)!=null&&wn.contentWindow)&&pt.current.contentWindow.postMessage(`seek?to=${$e}`,"https://www.dailymotion.com"),H($e),setTimeout(()=>{_t.current=!1},3e3)},[Ue]);se.useEffect(()=>{if(!Oe||!(h!=null&&h.playing))return;const $e=setInterval(()=>{const St=ee();St!==null&&Ue({type:"report_time",time:St})},2e3);return()=>clearInterval($e)},[Oe,h==null?void 0:h.playing,Ue,ee]);const Tt=se.useCallback(()=>{const $e=Ft.current;$e&&(document.fullscreenElement?document.exitFullscreen().catch(()=>{}):$e.requestFullscreen().catch(()=>{}))},[]);se.useEffect(()=>{const $e=()=>I(!!document.fullscreenElement);return document.addEventListener("fullscreenchange",$e),()=>document.removeEventListener("fullscreenchange",$e)},[]),se.useEffect(()=>{const $e=Kt=>{Et.current&&Kt.preventDefault()},St=()=>{tt.current&&navigator.sendBeacon("/api/watch-together/disconnect",JSON.stringify({clientId:tt.current}))};return window.addEventListener("beforeunload",$e),window.addEventListener("pagehide",St),()=>{window.removeEventListener("beforeunload",$e),window.removeEventListener("pagehide",St)}},[]),se.useEffect(()=>()=>{we(),Fe.current&&Fe.current.close(),je.current&&clearTimeout(je.current)},[we]);const Wt=se.useCallback(()=>{if(!v)return;if(!v.password.trim()){x(Kt=>Kt&&{...Kt,error:"Passwort eingeben."});return}const{roomId:$e,password:St}=v;x(null),ct($e,St)},[v,ct]),Yt=se.useCallback($e=>{$e.hasPassword?x({roomId:$e.id,roomName:$e.name,password:"",error:null}):ct($e.id)},[ct]);if(h){const $e=h.members.find(St=>St.id===h.hostId);return P.jsxs("div",{className:"wt-room-overlay",ref:Ft,children:[P.jsxs("div",{className:"wt-room-header",children:[P.jsxs("div",{className:"wt-room-header-left",children:[P.jsx("span",{className:"wt-room-name",children:h.name}),P.jsxs("span",{className:"wt-room-members",children:[h.members.length," Mitglieder"]}),$e&&P.jsxs("span",{className:"wt-host-badge",children:["Host: ",$e.name]})]}),P.jsxs("div",{className:"wt-room-header-right",children:[P.jsx("div",{className:`wt-sync-dot wt-sync-${be}`,title:be==="synced"?"Synchron":be==="drifting"?"Leichte Verzögerung":"Nicht synchron"}),P.jsx("button",{className:"wt-header-btn",onClick:Jt,title:"Link kopieren",children:"Link"}),P.jsx("button",{className:"wt-header-btn",onClick:()=>Me(St=>!St),title:ae?"Chat ausblenden":"Chat einblenden",children:"Chat"}),P.jsx("button",{className:"wt-fullscreen-btn",onClick:Tt,title:U?"Vollbild verlassen":"Vollbild",children:U?"✖":"⛶"}),P.jsx("button",{className:"wt-leave-btn",onClick:Dt,children:"Verlassen"})]})]}),P.jsxs("div",{className:"wt-room-body",children:[P.jsxs("div",{className:"wt-player-section",children:[P.jsxs("div",{className:"wt-player-wrap",children:[P.jsx("div",{ref:ht,className:"wt-yt-container",style:fe.current==="youtube"?{}:{display:"none"}}),P.jsx("video",{ref:Ke,className:"wt-video-element",style:fe.current==="direct"?{}:{display:"none"},playsInline:!0}),P.jsx("iframe",{ref:pt,className:"wt-dm-container",style:fe.current==="dailymotion"?{}:{display:"none"},allow:"autoplay; fullscreen",allowFullScreen:!0}),q&&P.jsxs("div",{className:"wt-player-error",children:[P.jsx("div",{className:"wt-error-icon",children:"⚠️"}),P.jsx("p",{children:q}),((pn=h.currentVideo)==null?void 0:pn.url)&&P.jsx("a",{className:"wt-yt-link",href:h.currentVideo.url,target:"_blank",rel:"noopener noreferrer",children:"Auf YouTube öffnen ↗"}),P.jsx("p",{className:"wt-skip-info",children:"Wird in 3 Sekunden übersprungen..."})]}),!h.currentVideo&&P.jsxs("div",{className:"wt-player-placeholder",children:[P.jsx("div",{className:"wt-placeholder-icon",children:"🎬"}),P.jsx("p",{children:"Fuege ein Video zur Warteschlange hinzu"})]})]}),P.jsxs("div",{className:"wt-controls",children:[P.jsx("button",{className:"wt-ctrl-btn",onClick:me,disabled:!h.currentVideo,title:h.playing?"Pause":"Abspielen",children:h.playing?"⏸":"▶"}),P.jsxs("button",{className:"wt-ctrl-btn wt-next-btn",onClick:Bt,disabled:!h.currentVideo&&h.queue.length===0,title:"Nächstes Video",children:["⏭"," Weiter"]}),P.jsx("input",{className:"wt-seek",type:"range",min:0,max:j||0,step:.5,value:G,onChange:St=>ot(parseFloat(St.target.value)),disabled:!h.currentVideo}),P.jsxs("span",{className:"wt-time",children:[w7(G)," / ",w7(j)]}),P.jsxs("div",{className:"wt-volume",children:[P.jsx("span",{className:"wt-volume-icon",children:E===0?"🔇":E<.5?"🔉":"🔊"}),P.jsx("input",{className:"wt-volume-slider",type:"range",min:0,max:1,step:.01,value:E,onChange:St=>O(parseFloat(St.target.value))})]}),fe.current==="youtube"&&P.jsxs("select",{className:"wt-quality-select",value:Ve,onChange:St=>Ce(St.target.value),title:"Videoqualität",children:[P.jsx("option",{value:"highres",children:"4K+"}),P.jsx("option",{value:"hd2160",children:"2160p"}),P.jsx("option",{value:"hd1440",children:"1440p"}),P.jsx("option",{value:"hd1080",children:"1080p"}),P.jsx("option",{value:"hd720",children:"720p"}),P.jsx("option",{value:"large",children:"480p"}),P.jsx("option",{value:"medium",children:"360p"}),P.jsx("option",{value:"small",children:"240p"})]})]})]}),P.jsxs("div",{className:"wt-queue-panel",children:[P.jsxs("div",{className:"wt-queue-header",children:[P.jsxs("span",{children:["Warteschlange (",h.queue.length,")"]}),h.queue.some(St=>St.watched)&&P.jsx("button",{className:"wt-queue-clear-btn",onClick:jt,title:"Gesehene entfernen",children:"Gesehene entfernen"})]}),P.jsx("div",{className:"wt-queue-list",children:h.queue.length===0?P.jsx("div",{className:"wt-queue-empty",children:"Keine Videos in der Warteschlange"}):h.queue.map((St,Kt)=>{var qn,Je;const wn=((qn=h.currentVideo)==null?void 0:qn.url)===St.url;return P.jsxs("div",{className:`wt-queue-item${wn?" playing":""}${St.watched&&!wn?" watched":""} clickable`,onClick:()=>Ue({type:"play_video",index:Kt}),title:"Klicken zum Abspielen",children:[P.jsxs("div",{className:"wt-queue-item-info",children:[St.watched&&!wn&&P.jsx("span",{className:"wt-queue-item-check",children:"✓"}),St.url.match(/youtu/)&&P.jsx("img",{className:"wt-queue-thumb",src:`https://img.youtube.com/vi/${(Je=St.url.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/))==null?void 0:Je[1]}/default.jpg`,alt:""}),P.jsxs("div",{className:"wt-queue-item-text",children:[P.jsx("div",{className:"wt-queue-item-title",children:St.title||St.url}),P.jsx("div",{className:"wt-queue-item-by",children:St.addedBy})]})]}),Oe&&P.jsx("button",{className:"wt-queue-item-remove",onClick:dt=>{dt.stopPropagation(),In(Kt)},title:"Entfernen",children:"×"})]},Kt)})}),P.jsxs("div",{className:"wt-queue-add",children:[P.jsx("input",{className:"wt-input wt-queue-input",placeholder:"Video-URL eingeben",value:N,onChange:St=>C(St.target.value),onKeyDown:St=>{St.key==="Enter"&&It()}}),P.jsx("button",{className:"wt-btn wt-queue-add-btn",onClick:It,disabled:Q,children:Q?"Laden...":"Hinzufuegen"})]})]}),ae&&P.jsxs("div",{className:"wt-chat-panel",children:[P.jsx("div",{className:"wt-chat-header",children:"Chat"}),P.jsxs("div",{className:"wt-chat-messages",children:[ie.length===0?P.jsx("div",{className:"wt-chat-empty",children:"Noch keine Nachrichten"}):ie.map((St,Kt)=>P.jsxs("div",{className:"wt-chat-msg",children:[P.jsx("span",{className:"wt-chat-sender",children:St.sender}),P.jsx("span",{className:"wt-chat-text",children:St.text})]},Kt)),P.jsx("div",{ref:yt})]}),P.jsxs("div",{className:"wt-chat-input-row",children:[P.jsx("input",{className:"wt-input wt-chat-input",placeholder:"Nachricht...",value:re,onChange:St=>Z(St.target.value),onKeyDown:St=>{St.key==="Enter"&<()},maxLength:500}),P.jsx("button",{className:"wt-btn wt-chat-send-btn",onClick:lt,children:"Senden"})]})]})]})]})}return P.jsxs("div",{className:"wt-container",children:[S&&P.jsxs("div",{className:"wt-error",children:[S,P.jsx("button",{className:"wt-error-dismiss",onClick:()=>T(null),children:"×"})]}),P.jsxs("div",{className:"wt-topbar",children:[P.jsx("input",{className:"wt-input wt-input-name",placeholder:"Dein Name",value:n,onChange:$e=>r($e.target.value)}),P.jsx("input",{className:"wt-input wt-input-room",placeholder:"Raumname",value:s,onChange:$e=>a($e.target.value)}),P.jsx("input",{className:"wt-input wt-input-password",type:"password",placeholder:"Passwort (optional)",value:l,onChange:$e=>u($e.target.value)}),P.jsx("button",{className:"wt-btn",onClick:Le,children:"Raum erstellen"})]}),e.length===0?P.jsxs("div",{className:"wt-empty",children:[P.jsx("div",{className:"wt-empty-icon",children:"🎬"}),P.jsx("h3",{children:"Keine aktiven Raeume"}),P.jsx("p",{children:"Erstelle einen Raum, um gemeinsam Videos zu schauen."})]}):P.jsx("div",{className:"wt-grid",children:e.map($e=>P.jsxs("div",{className:"wt-tile",onClick:()=>Yt($e),children:[P.jsxs("div",{className:"wt-tile-preview",children:[P.jsx("span",{className:"wt-tile-icon",children:"🎬"}),P.jsxs("span",{className:"wt-tile-members",children:["👥"," ",$e.memberCount]}),$e.hasPassword&&P.jsx("span",{className:"wt-tile-lock",children:"🔒"}),$e.playing&&P.jsx("span",{className:"wt-tile-playing",children:"▶"})]}),P.jsxs("div",{className:"wt-tile-info",children:[P.jsxs("div",{className:"wt-tile-meta",children:[P.jsx("div",{className:"wt-tile-name",children:$e.name}),P.jsx("div",{className:"wt-tile-host",children:$e.hostName})]}),$e.memberNames&&$e.memberNames.length>0&&P.jsxs("div",{className:"wt-tile-members-list",children:[$e.memberNames.slice(0,5).join(", "),$e.memberNames.length>5&&` +${$e.memberNames.length-5}`]})]})]},$e.id))}),v&&P.jsx("div",{className:"wt-modal-overlay",onClick:()=>x(null),children:P.jsxs("div",{className:"wt-modal",onClick:$e=>$e.stopPropagation(),children:[P.jsx("h3",{children:v.roomName}),P.jsx("p",{children:"Raum-Passwort"}),v.error&&P.jsx("div",{className:"wt-modal-error",children:v.error}),P.jsx("input",{className:"wt-input",type:"password",placeholder:"Passwort",value:v.password,onChange:$e=>x(St=>St&&{...St,password:$e.target.value,error:null}),onKeyDown:$e=>{$e.key==="Enter"&&Wt()},autoFocus:!0}),P.jsxs("div",{className:"wt-modal-actions",children:[P.jsx("button",{className:"wt-modal-cancel",onClick:()=>x(null),children:"Abbrechen"}),P.jsx("button",{className:"wt-btn",onClick:Wt,children:"Beitreten"})]})]})})]})}function HS(i,e){return`https://media.steampowered.com/steamcommunity/public/images/apps/${i}/${e}.jpg`}function T7(i){if(i==null||i===0)return"—";if(i<60)return`${i} Min`;const e=Math.floor(i/60),t=i%60;return t>0?`${e}h ${t}m`:`${e}h`}function JAe(i){try{return new Date(i).toLocaleDateString("de-DE",{day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return i}}function e0e({data:i,isAdmin:e}){const[t,n]=se.useState([]),[r,s]=se.useState("overview"),[a,l]=se.useState(null),[u,h]=se.useState(new Set),[m,v]=se.useState(null),[x,S]=se.useState(null),[T,N]=se.useState(""),[C,E]=se.useState(null),[O,U]=se.useState(!1),[I,j]=se.useState(null),[z,G]=se.useState(new Set),[H,q]=se.useState("playtime"),V=se.useRef(null),Q=se.useRef(null),[J,ie]=se.useState("");se.useEffect(()=>{i!=null&&i.profiles&&n(i.profiles)},[i]);const le=se.useCallback(async()=>{try{const ee=await fetch("/api/game-library/profiles");if(ee.ok){const we=await ee.json();n(we.profiles||[])}}catch{}},[]),re=se.useCallback(()=>{const ee=window.open("/api/game-library/steam/login","_blank","width=800,height=600"),we=setInterval(()=>{ee&&ee.closed&&(clearInterval(we),setTimeout(le,1e3))},500)},[le]),Z=navigator.userAgent.includes("GamingHubDesktop"),[ne,de]=se.useState(!1),[be,Te]=se.useState(""),[ae,Me]=se.useState("idle"),[Ve,Ce]=se.useState(""),Fe=se.useCallback(()=>{const ee=a?`?linkTo=${a}`:"";if(Z){const we=window.open(`/api/game-library/gog/login${ee}`,"_blank","width=800,height=700"),Re=setInterval(()=>{we&&we.closed&&(clearInterval(Re),setTimeout(le,1e3))},500)}else window.open(`/api/game-library/gog/login${ee}`,"_blank","width=800,height=700"),Te(""),Me("idle"),Ce(""),de(!0)},[le,a,Z]),tt=se.useCallback(async()=>{let ee=be.trim();const we=ee.match(/[?&]code=([^&]+)/);if(we&&(ee=we[1]),!!ee){Me("loading"),Ce("Verbinde mit GOG...");try{const Re=await fetch("/api/game-library/gog/exchange",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:ee,linkTo:a||""})}),We=await Re.json();Re.ok&&We.ok?(Me("success"),Ce(`${We.profileName}: ${We.gameCount} Spiele geladen!`),le(),setTimeout(()=>de(!1),2e3)):(Me("error"),Ce(We.error||"Unbekannter Fehler"))}catch{Me("error"),Ce("Verbindung fehlgeschlagen.")}}},[be,a,le]);se.useEffect(()=>{const ee=()=>le();return window.addEventListener("gog-connected",ee),()=>window.removeEventListener("gog-connected",ee)},[le]),se.useEffect(()=>{const ee=()=>le();return window.addEventListener("focus",ee),()=>window.removeEventListener("focus",ee)},[le]);const je=se.useCallback(async ee=>{var we,Re;s("user"),l(ee),v(null),ie(""),U(!0);try{const We=await fetch(`/api/game-library/profile/${ee}/games`);if(We.ok){const Se=await We.json(),Le=Se.games||Se;v(Le);const ct=t.find(It=>It.id===ee),Dt=(Re=(we=ct==null?void 0:ct.platforms)==null?void 0:we.steam)==null?void 0:Re.steamId;Dt&&Le.filter(lt=>!lt.igdb).length>0&&(j(ee),fetch(`/api/game-library/igdb/enrich/${Dt}`).then(lt=>lt.ok?lt.json():null).then(()=>fetch(`/api/game-library/profile/${ee}/games`)).then(lt=>lt.ok?lt.json():null).then(lt=>{lt&&v(lt.games||lt)}).catch(()=>{}).finally(()=>j(null)))}}catch{}finally{U(!1)}},[t]),Rt=se.useCallback(async(ee,we)=>{var Se,Le;we&&we.stopPropagation();const Re=t.find(ct=>ct.id===ee),We=(Le=(Se=Re==null?void 0:Re.platforms)==null?void 0:Se.steam)==null?void 0:Le.steamId;try{We&&await fetch(`/api/game-library/user/${We}?refresh=true`),await le(),r==="user"&&a===ee&&je(ee)}catch{}},[le,r,a,je,t]),Et=se.useCallback(async ee=>{var We,Se;const we=t.find(Le=>Le.id===ee),Re=(Se=(We=we==null?void 0:we.platforms)==null?void 0:We.steam)==null?void 0:Se.steamId;if(Re){j(ee);try{(await fetch(`/api/game-library/igdb/enrich/${Re}`)).ok&&r==="user"&&a===ee&&je(ee)}catch{}finally{j(null)}}},[r,a,je,t]),Ft=se.useCallback(ee=>{h(we=>{const Re=new Set(we);return Re.has(ee)?Re.delete(ee):Re.add(ee),Re})},[]),Ut=se.useCallback(async()=>{if(!(u.size<2)){s("common"),S(null),U(!0);try{const ee=Array.from(u).join(","),we=await fetch(`/api/game-library/common-games?users=${ee}`);if(we.ok){const Re=await we.json();S(Re.games||Re)}else console.error("[GameLibrary] common-games error:",we.status,await we.text().catch(()=>"")),S([])}catch(ee){console.error("[GameLibrary] common-games fetch failed:",ee)}finally{U(!1)}}},[u]),Ke=se.useCallback(ee=>{if(N(ee),V.current&&clearTimeout(V.current),ee.length<2){E(null);return}V.current=setTimeout(async()=>{try{const we=await fetch(`/api/game-library/search?q=${encodeURIComponent(ee)}`);if(we.ok){const Re=await we.json();E(Re.results||Re)}}catch{}},300)},[]),ht=se.useCallback(ee=>{G(we=>{const Re=new Set(we);return Re.has(ee)?Re.delete(ee):Re.add(ee),Re})},[]),fe=se.useCallback(async(ee,we)=>{if(confirm(`${we==="steam"?"Steam":"GOG"}-Verknuepfung wirklich trennen?`))try{const Re=await fetch(`/api/game-library/profile/${ee}/${we}`,{method:"DELETE"});if(Re.ok&&(le(),(await Re.json()).ok)){const Se=t.find(ct=>ct.id===ee);(we==="steam"?Se==null?void 0:Se.platforms.gog:Se==null?void 0:Se.platforms.steam)||$t()}}catch{}},[le,t]);se.useCallback(async ee=>{const we=t.find(Re=>Re.id===ee);if(confirm(`Profil "${we==null?void 0:we.displayName}" wirklich komplett loeschen?`))try{(await fetch(`/api/game-library/profile/${ee}`,{method:"DELETE"})).ok&&(le(),$t())}catch{}},[le,t]);const $t=se.useCallback(()=>{s("overview"),l(null),v(null),S(null),ie(""),G(new Set),q("playtime")},[]),_t=$t,Gt=se.useCallback(ee=>t.find(we=>we.id===ee),[t]),yt=se.useCallback(ee=>typeof ee.playtime_forever=="number"?ee.playtime_forever:Array.isArray(ee.owners)?Math.max(...ee.owners.map(we=>we.playtime_forever||0)):0,[]),Ht=se.useCallback(ee=>[...ee].sort((we,Re)=>{var We,Se;if(H==="rating"){const Le=((We=we.igdb)==null?void 0:We.rating)??-1;return(((Se=Re.igdb)==null?void 0:Se.rating)??-1)-Le}return H==="name"?we.name.localeCompare(Re.name):yt(Re)-yt(we)}),[H,yt]),pt=se.useCallback(ee=>{var we,Re;return z.size===0?!0:(Re=(we=ee.igdb)==null?void 0:we.genres)!=null&&Re.length?ee.igdb.genres.some(We=>z.has(We)):!1},[z]),Ae=se.useCallback(ee=>{var Re;const we=new Map;for(const We of ee)if((Re=We.igdb)!=null&&Re.genres)for(const Se of We.igdb.genres)we.set(Se,(we.get(Se)||0)+1);return[...we.entries()].sort((We,Se)=>Se[1]-We[1]).map(([We])=>We)},[]),k=m?Ht(m.filter(ee=>!J||ee.name.toLowerCase().includes(J.toLowerCase())).filter(pt)):null,xe=m?Ae(m):[],Oe=x?Ae(x):[],Ue=x?Ht(x.filter(pt)):null;return P.jsxs("div",{className:"gl-container",children:[P.jsxs("div",{className:"gl-login-bar",children:[!a&&P.jsx("button",{className:"gl-connect-btn gl-steam-btn",onClick:re,children:"🎮 Steam verbinden"}),P.jsx("div",{className:"gl-login-bar-spacer"})]}),t.length>0&&P.jsx("div",{className:"gl-profile-chips",children:t.map(ee=>P.jsxs("div",{className:`gl-profile-chip${a===ee.id?" selected":""}`,onClick:()=>je(ee.id),children:[P.jsx("img",{className:"gl-profile-chip-avatar",src:ee.avatarUrl,alt:ee.displayName}),P.jsxs("div",{className:"gl-profile-chip-info",children:[P.jsx("span",{className:"gl-profile-chip-name",children:ee.displayName}),P.jsxs("span",{className:"gl-profile-chip-platforms",children:[ee.platforms.steam&&P.jsx("span",{className:"gl-platform-badge steam",title:`Steam: ${ee.platforms.steam.gameCount} Spiele`,children:"S"}),ee.platforms.gog&&P.jsx("span",{className:"gl-platform-badge gog",title:`GOG: ${ee.platforms.gog.gameCount} Spiele`,children:"G"})]})]}),P.jsxs("span",{className:"gl-profile-chip-count",children:["(",ee.totalGames,")"]})]},ee.id))}),r==="overview"&&P.jsx(P.Fragment,{children:t.length===0?P.jsxs("div",{className:"gl-empty",children:[P.jsx("div",{className:"gl-empty-icon",children:"🎮"}),P.jsx("h3",{children:"Keine Konten verbunden"}),P.jsx("p",{children:"Klicke oben auf “Steam verbinden” oder “GOG verbinden”, um deine Spielebibliothek hinzuzufuegen."})]}):P.jsxs(P.Fragment,{children:[P.jsx("p",{className:"gl-section-title",children:"Verbundene Spieler"}),P.jsx("div",{className:"gl-users-grid",children:t.map(ee=>P.jsxs("div",{className:"gl-user-card",onClick:()=>je(ee.id),children:[P.jsx("img",{className:"gl-user-card-avatar",src:ee.avatarUrl,alt:ee.displayName}),P.jsx("span",{className:"gl-user-card-name",children:ee.displayName}),P.jsxs("div",{className:"gl-profile-card-platforms",children:[ee.platforms.steam&&P.jsx("span",{className:"gl-platform-badge steam",title:"Steam",children:"S"}),ee.platforms.gog&&P.jsx("span",{className:"gl-platform-badge gog",title:"GOG",children:"G"})]}),P.jsxs("span",{className:"gl-user-card-games",children:[ee.totalGames," Spiele"]}),P.jsxs("span",{className:"gl-user-card-updated",children:["Aktualisiert: ",JAe(ee.lastUpdated)]})]},ee.id))}),t.length>=2&&P.jsxs("div",{className:"gl-common-finder",children:[P.jsx("h3",{children:"Gemeinsame Spiele finden"}),P.jsx("div",{className:"gl-common-users",children:t.map(ee=>P.jsxs("label",{className:`gl-common-check${u.has(ee.id)?" checked":""}`,children:[P.jsx("input",{type:"checkbox",checked:u.has(ee.id),onChange:()=>Ft(ee.id)}),P.jsx("img",{className:"gl-common-check-avatar",src:ee.avatarUrl,alt:ee.displayName}),ee.displayName,P.jsxs("span",{className:"gl-profile-chip-platforms",style:{marginLeft:4},children:[ee.platforms.steam&&P.jsx("span",{className:"gl-platform-badge steam",children:"S"}),ee.platforms.gog&&P.jsx("span",{className:"gl-platform-badge gog",children:"G"})]})]},ee.id))}),P.jsx("button",{className:"gl-common-find-btn",disabled:u.size<2,onClick:Ut,children:"Finden"})]}),P.jsx("div",{className:"gl-search",children:P.jsx("input",{className:"gl-search-input",type:"text",placeholder:"Spiel suchen...",value:T,onChange:ee=>Ke(ee.target.value)})}),C&&C.length>0&&P.jsxs(P.Fragment,{children:[P.jsxs("p",{className:"gl-search-results-title",children:[C.length," Ergebnis",C.length!==1?"se":""]}),P.jsx("div",{className:"gl-game-list",children:C.map(ee=>P.jsxs("div",{className:"gl-game-item",children:[ee.img_icon_url?P.jsx("img",{className:"gl-game-icon",src:HS(ee.appid,ee.img_icon_url),alt:""}):P.jsx("div",{className:"gl-game-icon"}),P.jsx("span",{className:"gl-game-name",children:ee.name}),P.jsx("div",{className:"gl-game-owners",children:ee.owners.map(we=>{const Re=t.find(We=>{var Se;return((Se=We.platforms.steam)==null?void 0:Se.steamId)===we.steamId});return Re?P.jsx("img",{className:"gl-game-owner-avatar",src:Re.avatarUrl,alt:we.personaName,title:we.personaName},we.steamId):null})})]},ee.appid))})]}),C&&C.length===0&&P.jsx("p",{className:"gl-search-results-title",children:"Keine Ergebnisse gefunden."})]})}),r==="user"&&(()=>{const ee=a?Gt(a):null;return P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"gl-detail-header",children:[P.jsx("button",{className:"gl-back-btn",onClick:_t,children:"← Zurueck"}),ee&&P.jsxs(P.Fragment,{children:[P.jsx("img",{className:"gl-detail-avatar",src:ee.avatarUrl,alt:ee.displayName}),P.jsxs("div",{className:"gl-detail-info",children:[P.jsxs("div",{className:"gl-detail-name",children:[ee.displayName,P.jsxs("span",{className:"gl-game-count",children:[ee.totalGames," Spiele"]})]}),P.jsxs("div",{className:"gl-detail-sub",children:[ee.platforms.steam&&P.jsxs("span",{className:"gl-platform-detail steam",children:[P.jsx("span",{className:"gl-platform-badge steam",children:"Steam ✓"}),P.jsx("button",{className:"gl-disconnect-btn",onClick:we=>{we.stopPropagation(),fe(ee.id,"steam")},title:"Steam trennen",children:"✕"})]}),ee.platforms.gog?P.jsxs("span",{className:"gl-platform-detail gog",children:[P.jsx("span",{className:"gl-platform-badge gog",children:"GOG ✓"}),P.jsx("button",{className:"gl-disconnect-btn",onClick:we=>{we.stopPropagation(),fe(ee.id,"gog")},title:"GOG trennen",children:"✕"})]}):P.jsx("button",{className:"gl-link-gog-btn",onClick:Fe,children:"🟣 GOG verknuepfen"})]})]}),P.jsx("button",{className:"gl-refresh-btn",onClick:()=>Rt(ee.id),title:"Aktualisieren",children:"↻"}),ee.platforms.steam&&P.jsxs("button",{className:`gl-enrich-btn ${I===a?"enriching":""}`,onClick:()=>Et(a),disabled:I===a,title:I===a?"IGDB-Daten werden geladen...":"Mit IGDB-Daten anreichern (erneut)",children:[I===a?"⏳":"🌐"," IGDB"]})]})]}),O?P.jsx("div",{className:"gl-loading",children:"Bibliothek wird geladen..."}):k?P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"gl-filter-bar",children:[P.jsx("input",{ref:Q,className:"gl-search-input",type:"text",placeholder:"Bibliothek durchsuchen...",value:J,onChange:we=>ie(we.target.value)}),P.jsxs("select",{className:"gl-sort-select",value:H,onChange:we=>q(we.target.value),children:[P.jsx("option",{value:"playtime",children:"Spielzeit"}),P.jsx("option",{value:"rating",children:"Bewertung"}),P.jsx("option",{value:"name",children:"Name"})]})]}),xe.length>0&&P.jsxs("div",{className:"gl-genre-filters",children:[z.size>0&&P.jsx("button",{className:"gl-genre-chip active clear",onClick:()=>G(new Set),children:"Alle"}),xe.map(we=>P.jsx("button",{className:`gl-genre-chip${z.has(we)?" active":""}`,onClick:()=>ht(we),children:we},we))]}),P.jsxs("p",{className:"gl-filter-count",children:[k.length," Spiele"]}),k.length===0?P.jsx("p",{className:"gl-search-results-title",children:"Keine Spiele gefunden."}):P.jsx("div",{className:"gl-game-list",children:k.map((we,Re)=>{var We,Se,Le;return P.jsxs("div",{className:`gl-game-item ${we.igdb?"enriched":""}`,children:[P.jsx("span",{className:`gl-game-platform-icon ${we.platform||"steam"}`,children:we.platform==="gog"?"G":"S"}),P.jsx("div",{className:"gl-game-visual",children:(We=we.igdb)!=null&&We.coverUrl?P.jsx("img",{className:"gl-game-cover",src:we.igdb.coverUrl,alt:""}):we.img_icon_url&&we.appid?P.jsx("img",{className:"gl-game-icon",src:HS(we.appid,we.img_icon_url),alt:""}):we.image?P.jsx("img",{className:"gl-game-icon",src:we.image,alt:""}):P.jsx("div",{className:"gl-game-icon"})}),P.jsxs("div",{className:"gl-game-info",children:[P.jsx("span",{className:"gl-game-name",children:we.name}),((Se=we.igdb)==null?void 0:Se.genres)&&we.igdb.genres.length>0&&P.jsx("div",{className:"gl-game-genres",children:we.igdb.genres.slice(0,3).map(ct=>P.jsx("span",{className:"gl-genre-tag",children:ct},ct))})]}),P.jsxs("div",{className:"gl-game-meta",children:[((Le=we.igdb)==null?void 0:Le.rating)!=null&&P.jsx("span",{className:`gl-game-rating ${we.igdb.rating>=75?"high":we.igdb.rating>=50?"mid":"low"}`,children:Math.round(we.igdb.rating)}),P.jsx("span",{className:"gl-game-playtime",children:T7(we.playtime_forever)})]})]},we.appid??we.gogId??Re)})})]}):null]})})(),r==="common"&&(()=>{const ee=Array.from(u).map(Re=>Gt(Re)).filter(Boolean),we=ee.map(Re=>Re.displayName).join(", ");return P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"gl-detail-header",children:[P.jsx("button",{className:"gl-back-btn",onClick:_t,children:"← Zurueck"}),P.jsx("div",{className:"gl-detail-avatars",children:ee.map(Re=>P.jsx("img",{src:Re.avatarUrl,alt:Re.displayName},Re.id))}),P.jsxs("div",{className:"gl-detail-info",children:[P.jsx("div",{className:"gl-detail-name",children:"Gemeinsame Spiele"}),P.jsxs("div",{className:"gl-detail-sub",children:["von ",we]})]})]}),O?P.jsx("div",{className:"gl-loading",children:"Gemeinsame Spiele werden gesucht..."}):x?x.length===0?P.jsxs("div",{className:"gl-empty",children:[P.jsx("div",{className:"gl-empty-icon",children:"😔"}),P.jsx("h3",{children:"Keine gemeinsamen Spiele"}),P.jsx("p",{children:"Die ausgewaehlten Spieler besitzen leider keine gemeinsamen Spiele."})]}):P.jsxs(P.Fragment,{children:[P.jsx("div",{className:"gl-filter-bar",children:P.jsxs("select",{className:"gl-sort-select",value:H,onChange:Re=>q(Re.target.value),children:[P.jsx("option",{value:"playtime",children:"Spielzeit"}),P.jsx("option",{value:"rating",children:"Bewertung"}),P.jsx("option",{value:"name",children:"Name"})]})}),Oe.length>0&&P.jsxs("div",{className:"gl-genre-filters",children:[z.size>0&&P.jsx("button",{className:"gl-genre-chip active clear",onClick:()=>G(new Set),children:"Alle"}),Oe.map(Re=>P.jsx("button",{className:`gl-genre-chip${z.has(Re)?" active":""}`,onClick:()=>ht(Re),children:Re},Re))]}),P.jsxs("p",{className:"gl-section-title",children:[Ue.length," gemeinsame",Ue.length!==1?" Spiele":"s Spiel",z.size>0?` (von ${x.length})`:""]}),P.jsx("div",{className:"gl-game-list",children:Ue.map(Re=>{var We,Se,Le;return P.jsxs("div",{className:`gl-game-item ${Re.igdb?"enriched":""}`,children:[P.jsx("div",{className:"gl-game-visual",children:(We=Re.igdb)!=null&&We.coverUrl?P.jsx("img",{className:"gl-game-cover",src:Re.igdb.coverUrl,alt:""}):Re.img_icon_url?P.jsx("img",{className:"gl-game-icon",src:HS(Re.appid,Re.img_icon_url),alt:""}):P.jsx("div",{className:"gl-game-icon"})}),P.jsxs("div",{className:"gl-game-info",children:[P.jsx("span",{className:"gl-game-name",children:Re.name}),((Se=Re.igdb)==null?void 0:Se.genres)&&Re.igdb.genres.length>0&&P.jsx("div",{className:"gl-game-genres",children:Re.igdb.genres.slice(0,3).map(ct=>P.jsx("span",{className:"gl-genre-tag",children:ct},ct))})]}),P.jsxs("div",{className:"gl-game-meta",children:[((Le=Re.igdb)==null?void 0:Le.rating)!=null&&P.jsx("span",{className:`gl-game-rating ${Re.igdb.rating>=75?"high":Re.igdb.rating>=50?"mid":"low"}`,children:Math.round(Re.igdb.rating)}),P.jsx("div",{className:"gl-common-playtimes",children:Re.owners.map(ct=>P.jsxs("span",{className:"gl-common-pt",children:[ct.personaName,": ",T7(ct.playtime_forever)]},ct.steamId))})]})]},Re.appid)})})]}):null]})})(),ne&&P.jsx("div",{className:"gl-dialog-overlay",onClick:()=>de(!1),children:P.jsxs("div",{className:"gl-dialog",onClick:ee=>ee.stopPropagation(),children:[P.jsx("h3",{children:"🟣 GOG verbinden"}),P.jsxs("p",{className:"gl-dialog-hint",children:["Nach dem GOG-Login wirst du auf eine Seite weitergeleitet. Kopiere die ",P.jsx("strong",{children:"komplette URL"})," aus der Adressleiste und füge sie hier ein:"]}),P.jsx("input",{className:"gl-dialog-input",type:"text",placeholder:"https://embed.gog.com/on_login_success?code=...",value:be,onChange:ee=>Te(ee.target.value),onKeyDown:ee=>{ee.key==="Enter"&&tt()},disabled:ae==="loading"||ae==="success",autoFocus:!0}),Ve&&P.jsx("p",{className:`gl-dialog-status ${ae}`,children:Ve}),P.jsxs("div",{className:"gl-dialog-actions",children:[P.jsx("button",{onClick:()=>de(!1),className:"gl-dialog-cancel",children:"Abbrechen"}),P.jsx("button",{onClick:tt,className:"gl-dialog-submit",disabled:!be.trim()||ae==="loading"||ae==="success",children:ae==="loading"?"Verbinde...":"Verbinden"})]})]})})]})}const lx="/api/soundboard";async function t0e(){const i=new URL(`${lx}/sounds`,window.location.origin);i.searchParams.set("folder","__all__"),i.searchParams.set("fuzzy","0");const e=await fetch(i.toString());if(!e.ok)throw new Error("Fehler beim Laden der Sounds");return e.json()}async function n0e(i){if(!(await fetch(`${lx}/admin/sounds/delete`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({paths:i})})).ok)throw new Error("Loeschen fehlgeschlagen")}async function i0e(i,e){const t=await fetch(`${lx}/admin/sounds/rename`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({from:i,to:e})});if(!t.ok)throw new Error("Umbenennen fehlgeschlagen");const n=await t.json();return n==null?void 0:n.to}function r0e(i,e){return new Promise((t,n)=>{const r=new FormData;r.append("files",i);const s=new XMLHttpRequest;s.open("POST",`${lx}/upload`),s.upload.onprogress=a=>{a.lengthComputable&&e(Math.round(a.loaded/a.total*100))},s.onload=()=>{var a,l;if(s.status===200)try{const u=JSON.parse(s.responseText);t(((l=(a=u.files)==null?void 0:a[0])==null?void 0:l.name)??i.name)}catch{t(i.name)}else try{n(new Error(JSON.parse(s.responseText).error))}catch{n(new Error(`HTTP ${s.status}`))}},s.onerror=()=>n(new Error("Netzwerkfehler")),s.send(r)})}function s0e({onClose:i,onLogout:e}){var Oe,Ue;const[t,n]=se.useState("soundboard"),[r,s]=se.useState(null),a=se.useCallback((ee,we="info")=>{s({msg:ee,type:we}),setTimeout(()=>s(null),3e3)},[]);se.useEffect(()=>{const ee=we=>{we.key==="Escape"&&i()};return window.addEventListener("keydown",ee),()=>window.removeEventListener("keydown",ee)},[i]);const[l,u]=se.useState([]),[h,m]=se.useState(!1),[v,x]=se.useState(""),[S,T]=se.useState({}),[N,C]=se.useState(""),[E,O]=se.useState(""),[U,I]=se.useState(null),j=se.useCallback(ee=>ee.relativePath??ee.fileName,[]),z=se.useCallback(async()=>{m(!0);try{const ee=await t0e();u(ee.items||[])}catch(ee){a((ee==null?void 0:ee.message)||"Sounds konnten nicht geladen werden","error")}finally{m(!1)}},[a]),[G,H]=se.useState(!1);se.useEffect(()=>{t==="soundboard"&&!G&&(H(!0),z())},[t,G,z]);const q=se.useMemo(()=>{const ee=v.trim().toLowerCase();return ee?l.filter(we=>{const Re=j(we).toLowerCase();return we.name.toLowerCase().includes(ee)||(we.folder||"").toLowerCase().includes(ee)||Re.includes(ee)}):l},[v,l,j]),V=se.useMemo(()=>Object.keys(S).filter(ee=>S[ee]),[S]),Q=se.useMemo(()=>q.filter(ee=>!!S[j(ee)]).length,[q,S,j]),J=q.length>0&&Q===q.length;function ie(ee){T(we=>({...we,[ee]:!we[ee]}))}function le(ee){C(j(ee)),O(ee.name)}function re(){C(""),O("")}async function Z(){if(!N)return;const ee=E.trim().replace(/\.(mp3|wav)$/i,"");if(!ee){a("Bitte einen gueltigen Namen eingeben","error");return}try{await i0e(N,ee),a("Sound umbenannt"),re(),await z()}catch(we){a((we==null?void 0:we.message)||"Umbenennen fehlgeschlagen","error")}}async function ne(ee){if(ee.length!==0)try{await n0e(ee),a(ee.length===1?"Sound geloescht":`${ee.length} Sounds geloescht`),T({}),re(),await z()}catch(we){a((we==null?void 0:we.message)||"Loeschen fehlgeschlagen","error")}}async function de(ee){I(0);try{await r0e(ee,we=>I(we)),a(`"${ee.name}" hochgeladen`),await z()}catch(we){a((we==null?void 0:we.message)||"Upload fehlgeschlagen","error")}finally{I(null)}}const[be,Te]=se.useState([]),[ae,Me]=se.useState([]),[Ve,Ce]=se.useState(!1),[Fe,tt]=se.useState(!1),[je,Rt]=se.useState({online:!1,botTag:null}),Et=se.useCallback(async()=>{Ce(!0);try{const[ee,we,Re]=await Promise.all([fetch("/api/notifications/status"),fetch("/api/notifications/channels",{credentials:"include"}),fetch("/api/notifications/config",{credentials:"include"})]);if(ee.ok){const We=await ee.json();Rt(We)}if(we.ok){const We=await we.json();Te(We.channels||[])}if(Re.ok){const We=await Re.json();Me(We.channels||[])}}catch{}finally{Ce(!1)}},[]),[Ft,Ut]=se.useState(!1);se.useEffect(()=>{t==="streaming"&&!Ft&&(Ut(!0),Et())},[t,Ft,Et]);const Ke=se.useCallback((ee,we,Re,We,Se)=>{Me(Le=>{const ct=Le.find(Dt=>Dt.channelId===ee);if(ct){const It=ct.events.includes(Se)?ct.events.filter(lt=>lt!==Se):[...ct.events,Se];return It.length===0?Le.filter(lt=>lt.channelId!==ee):Le.map(lt=>lt.channelId===ee?{...lt,events:It}:lt)}else return[...Le,{channelId:ee,channelName:we,guildId:Re,guildName:We,events:[Se]}]})},[]),ht=se.useCallback((ee,we)=>{const Re=ae.find(We=>We.channelId===ee);return(Re==null?void 0:Re.events.includes(we))??!1},[ae]),fe=se.useCallback(async()=>{tt(!0);try{await fetch("/api/notifications/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channels:ae}),credentials:"include"}),a("Konfiguration gespeichert")}catch{a("Speichern fehlgeschlagen","error")}finally{tt(!1)}},[ae,a]),[$t,_t]=se.useState([]),[Gt,yt]=se.useState(!1),Ht=se.useCallback(async()=>{yt(!0);try{const ee=await fetch("/api/game-library/admin/profiles",{credentials:"include"});if(ee.ok){const we=await ee.json();_t(we.profiles||[])}}catch{}finally{yt(!1)}},[]),[pt,Ae]=se.useState(!1);se.useEffect(()=>{t==="game-library"&&!pt&&(Ae(!0),Ht())},[t,pt,Ht]);const k=se.useCallback(async(ee,we)=>{if(confirm(`Profil "${we}" wirklich komplett loeschen? (Alle verknuepften Daten werden entfernt)`))try{(await fetch(`/api/game-library/admin/profile/${ee}`,{method:"DELETE",credentials:"include"})).ok&&(a("Profil geloescht"),Ht())}catch{a("Loeschen fehlgeschlagen","error")}},[Ht,a]),xe=[{id:"soundboard",icon:"🎵",label:"Soundboard"},{id:"streaming",icon:"📺",label:"Streaming"},{id:"game-library",icon:"🎮",label:"Game Library"}];return P.jsx("div",{className:"ap-overlay",onClick:ee=>{ee.target===ee.currentTarget&&i()},children:P.jsxs("div",{className:"ap-modal",children:[P.jsxs("div",{className:"ap-sidebar",children:[P.jsxs("div",{className:"ap-sidebar-title",children:["⚙️"," Admin"]}),P.jsx("nav",{className:"ap-nav",children:xe.map(ee=>P.jsxs("button",{className:`ap-nav-item ${t===ee.id?"active":""}`,onClick:()=>n(ee.id),children:[P.jsx("span",{className:"ap-nav-icon",children:ee.icon}),P.jsx("span",{className:"ap-nav-label",children:ee.label})]},ee.id))}),P.jsxs("button",{className:"ap-logout-btn",onClick:e,children:["🔒"," Abmelden"]})]}),P.jsxs("div",{className:"ap-content",children:[P.jsxs("div",{className:"ap-header",children:[P.jsxs("h2",{className:"ap-title",children:[(Oe=xe.find(ee=>ee.id===t))==null?void 0:Oe.icon," ",(Ue=xe.find(ee=>ee.id===t))==null?void 0:Ue.label]}),P.jsx("button",{className:"ap-close",onClick:i,children:"✕"})]}),P.jsxs("div",{className:"ap-body",children:[t==="soundboard"&&P.jsxs("div",{className:"ap-tab-content",children:[P.jsxs("div",{className:"ap-toolbar",children:[P.jsx("input",{type:"text",className:"ap-search",value:v,onChange:ee=>x(ee.target.value),placeholder:"Nach Name, Ordner oder Pfad filtern..."}),P.jsxs("button",{className:"ap-btn ap-btn-outline",onClick:()=>{z()},disabled:h,children:["↻"," Aktualisieren"]})]}),P.jsxs("label",{className:"ap-upload-zone",children:[P.jsx("input",{type:"file",accept:".mp3,.wav",style:{display:"none"},onChange:ee=>{var Re;const we=(Re=ee.target.files)==null?void 0:Re[0];we&&de(we),ee.target.value=""}}),U!==null?P.jsxs("span",{className:"ap-upload-progress",children:["Upload: ",U,"%"]}):P.jsxs("span",{className:"ap-upload-text",children:["⬆️"," Datei hochladen (MP3 / WAV)"]})]}),P.jsxs("div",{className:"ap-bulk-row",children:[P.jsxs("label",{className:"ap-select-all",children:[P.jsx("input",{type:"checkbox",checked:J,onChange:ee=>{const we=ee.target.checked,Re={...S};q.forEach(We=>{Re[j(We)]=we}),T(Re)}}),P.jsxs("span",{children:["Alle sichtbaren (",Q,"/",q.length,")"]})]}),P.jsxs("button",{className:"ap-btn ap-btn-danger",disabled:V.length===0,onClick:async()=>{window.confirm(`Wirklich ${V.length} Sound(s) loeschen?`)&&await ne(V)},children:["🗑️"," Ausgewaehlte loeschen"]})]}),P.jsx("div",{className:"ap-list-wrap",children:h?P.jsx("div",{className:"ap-empty",children:"Lade Sounds..."}):q.length===0?P.jsx("div",{className:"ap-empty",children:"Keine Sounds gefunden."}):P.jsx("div",{className:"ap-list",children:q.map(ee=>{const we=j(ee),Re=N===we;return P.jsxs("div",{className:"ap-item",children:[P.jsx("label",{className:"ap-item-check",children:P.jsx("input",{type:"checkbox",checked:!!S[we],onChange:()=>ie(we)})}),P.jsxs("div",{className:"ap-item-main",children:[P.jsx("div",{className:"ap-item-name",children:ee.name}),P.jsxs("div",{className:"ap-item-meta",children:[ee.folder?`Ordner: ${ee.folder}`:"Root"," · ",we]}),Re&&P.jsxs("div",{className:"ap-rename-row",children:[P.jsx("input",{className:"ap-rename-input",value:E,onChange:We=>O(We.target.value),onKeyDown:We=>{We.key==="Enter"&&Z(),We.key==="Escape"&&re()},placeholder:"Neuer Name...",autoFocus:!0}),P.jsx("button",{className:"ap-btn ap-btn-primary ap-btn-sm",onClick:()=>{Z()},children:"Speichern"}),P.jsx("button",{className:"ap-btn ap-btn-outline ap-btn-sm",onClick:re,children:"Abbrechen"})]})]}),!Re&&P.jsxs("div",{className:"ap-item-actions",children:[P.jsx("button",{className:"ap-btn ap-btn-outline ap-btn-sm",onClick:()=>le(ee),children:"Umbenennen"}),P.jsx("button",{className:"ap-btn ap-btn-danger ap-btn-sm",onClick:async()=>{window.confirm(`Sound "${ee.name}" loeschen?`)&&await ne([we])},children:"Loeschen"})]})]},we)})})})]}),t==="streaming"&&P.jsxs("div",{className:"ap-tab-content",children:[P.jsxs("div",{className:"ap-toolbar",children:[P.jsxs("span",{className:"ap-status-badge",children:[P.jsx("span",{className:`ap-status-dot ${je.online?"online":""}`}),je.online?P.jsxs(P.Fragment,{children:["Bot online: ",P.jsx("b",{children:je.botTag})]}):P.jsx(P.Fragment,{children:"Bot offline"})]}),P.jsxs("button",{className:"ap-btn ap-btn-outline",onClick:()=>{Et()},disabled:Ve,children:["↻"," Aktualisieren"]})]}),Ve?P.jsx("div",{className:"ap-empty",children:"Lade Kanaele..."}):be.length===0?P.jsx("div",{className:"ap-empty",children:je.online?"Keine Text-Kanaele gefunden. Bot hat moeglicherweise keinen Zugriff.":"Bot ist nicht verbunden. Bitte DISCORD_TOKEN_NOTIFICATIONS konfigurieren."}):P.jsxs(P.Fragment,{children:[P.jsx("p",{className:"ap-hint",children:"Waehle die Kanaele, in die Benachrichtigungen gesendet werden sollen:"}),P.jsx("div",{className:"ap-channel-list",children:be.map(ee=>P.jsxs("div",{className:"ap-channel-row",children:[P.jsxs("div",{className:"ap-channel-info",children:[P.jsxs("span",{className:"ap-channel-name",children:["#",ee.channelName]}),P.jsx("span",{className:"ap-channel-guild",children:ee.guildName})]}),P.jsxs("div",{className:"ap-channel-toggles",children:[P.jsxs("label",{className:`ap-toggle ${ht(ee.channelId,"stream_start")?"active":""}`,children:[P.jsx("input",{type:"checkbox",checked:ht(ee.channelId,"stream_start"),onChange:()=>Ke(ee.channelId,ee.channelName,ee.guildId,ee.guildName,"stream_start")}),"🔴"," Stream Start"]}),P.jsxs("label",{className:`ap-toggle ${ht(ee.channelId,"stream_end")?"active":""}`,children:[P.jsx("input",{type:"checkbox",checked:ht(ee.channelId,"stream_end"),onChange:()=>Ke(ee.channelId,ee.channelName,ee.guildId,ee.guildName,"stream_end")}),"⏹️"," Stream Ende"]})]})]},ee.channelId))}),P.jsx("div",{className:"ap-save-row",children:P.jsx("button",{className:"ap-btn ap-btn-primary",onClick:fe,disabled:Fe,children:Fe?"Speichern...":"💾 Speichern"})})]})]}),t==="game-library"&&P.jsxs("div",{className:"ap-tab-content",children:[P.jsxs("div",{className:"ap-toolbar",children:[P.jsxs("span",{className:"ap-status-badge",children:[P.jsx("span",{className:"ap-status-dot online"}),"Eingeloggt als Admin"]}),P.jsxs("button",{className:"ap-btn ap-btn-outline",onClick:()=>{Ht()},disabled:Gt,children:["↻"," Aktualisieren"]})]}),Gt?P.jsx("div",{className:"ap-empty",children:"Lade Profile..."}):$t.length===0?P.jsx("div",{className:"ap-empty",children:"Keine Profile vorhanden."}):P.jsx("div",{className:"ap-profile-list",children:$t.map(ee=>P.jsxs("div",{className:"ap-profile-row",children:[P.jsx("img",{className:"ap-profile-avatar",src:ee.avatarUrl,alt:ee.displayName}),P.jsxs("div",{className:"ap-profile-info",children:[P.jsx("span",{className:"ap-profile-name",children:ee.displayName}),P.jsxs("span",{className:"ap-profile-details",children:[ee.steamName&&P.jsxs("span",{className:"ap-platform-badge steam",children:["Steam: ",ee.steamGames]}),ee.gogName&&P.jsxs("span",{className:"ap-platform-badge gog",children:["GOG: ",ee.gogGames]}),P.jsxs("span",{className:"ap-profile-total",children:[ee.totalGames," Spiele"]})]})]}),P.jsxs("button",{className:"ap-btn ap-btn-danger ap-btn-sm",onClick:()=>k(ee.id,ee.displayName),children:["🗑️"," Entfernen"]})]},ee.id))})]})]})]}),r&&P.jsxs("div",{className:`ap-toast ${r.type}`,children:[r.type==="error"?"❌":"✅"," ",r.msg]})]})})}const M7={radio:MAe,soundboard:jAe,lolstats:YAe,streaming:QAe,"watch-together":ZAe,"game-library":e0e};function a0e(){var Z;const[i,e]=se.useState(!1),[t,n]=se.useState([]),[r,s]=se.useState(()=>localStorage.getItem("hub_activeTab")??""),a=ne=>{s(ne),localStorage.setItem("hub_activeTab",ne)},[l,u]=se.useState(!1),[h,m]=se.useState({}),[v,x]=se.useState(!1),[S,T]=se.useState(!1),[N,C]=se.useState(!1),[E,O]=se.useState(""),[U,I]=se.useState(""),j=!!((Z=window.electronAPI)!=null&&Z.isElectron),z=j?window.electronAPI.version:null,[G,H]=se.useState("idle"),[q,V]=se.useState(""),Q=se.useRef(null);se.useEffect(()=>{"Notification"in window&&Notification.permission==="default"&&Notification.requestPermission()},[]),se.useEffect(()=>{fetch("/api/soundboard/admin/status",{credentials:"include"}).then(ne=>ne.json()).then(ne=>x(!!ne.authenticated)).catch(()=>{})},[]),se.useEffect(()=>{if(!S)return;const ne=de=>{de.key==="Escape"&&T(!1)};return window.addEventListener("keydown",ne),()=>window.removeEventListener("keydown",ne)},[S]);async function J(){I("");try{(await fetch("/api/soundboard/admin/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:E}),credentials:"include"})).ok?(x(!0),O(""),T(!1)):I("Falsches Passwort")}catch{I("Verbindung fehlgeschlagen")}}async function ie(){await fetch("/api/soundboard/admin/logout",{method:"POST",credentials:"include"}),x(!1)}se.useEffect(()=>{var be;if(!j)return;const ne=window.electronAPI;ne.onUpdateAvailable(()=>H("downloading")),ne.onUpdateReady(()=>H("ready")),ne.onUpdateNotAvailable(()=>H("upToDate")),ne.onUpdateError(Te=>{H("error"),V(Te||"Unbekannter Fehler")});const de=(be=ne.getUpdateStatus)==null?void 0:be.call(ne);de==="downloading"?H("downloading"):de==="ready"?H("ready"):de==="checking"&&H("checking")},[j]),se.useEffect(()=>{fetch("/api/plugins").then(ne=>ne.json()).then(ne=>{if(n(ne),new URLSearchParams(location.search).has("viewStream")&&ne.some(ae=>ae.name==="streaming")){a("streaming");return}const be=localStorage.getItem("hub_activeTab"),Te=ne.some(ae=>ae.name===be);ne.length>0&&!Te&&a(ne[0].name)}).catch(()=>{})},[]),se.useEffect(()=>{let ne=null,de;function be(){ne=new EventSource("/api/events"),Q.current=ne,ne.onopen=()=>e(!0),ne.onmessage=Te=>{try{const ae=JSON.parse(Te.data);ae.type==="snapshot"?m(Me=>({...Me,...ae})):ae.plugin&&m(Me=>({...Me,[ae.plugin]:{...Me[ae.plugin]||{},...ae}}))}catch{}},ne.onerror=()=>{e(!1),ne==null||ne.close(),de=setTimeout(be,3e3)}}return be(),()=>{ne==null||ne.close(),clearTimeout(de)}},[]);const le="1.0.0-dev";se.useEffect(()=>{if(!l)return;const ne=de=>{de.key==="Escape"&&u(!1)};return window.addEventListener("keydown",ne),()=>window.removeEventListener("keydown",ne)},[l]);const re={radio:"🌍",soundboard:"🎵",lolstats:"⚔️",stats:"📊",events:"📅",games:"🎲",gamevote:"🎮",streaming:"📺","watch-together":"🎬","game-library":"🎮"};return P.jsxs("div",{className:"hub-app",children:[P.jsxs("header",{className:"hub-header",children:[P.jsxs("div",{className:"hub-header-left",children:[P.jsx("span",{className:"hub-logo",children:"🎮"}),P.jsx("span",{className:"hub-title",children:"Gaming Hub"}),P.jsx("span",{className:`hub-conn-dot ${i?"online":""}`})]}),P.jsx("nav",{className:"hub-tabs",children:t.filter(ne=>ne.name in M7).map(ne=>P.jsxs("button",{className:`hub-tab ${r===ne.name?"active":""}`,onClick:()=>a(ne.name),title:ne.description,children:[P.jsx("span",{className:"hub-tab-icon",children:re[ne.name]??"📦"}),P.jsx("span",{className:"hub-tab-label",children:ne.name})]},ne.name))}),P.jsxs("div",{className:"hub-header-right",children:[!window.electronAPI&&P.jsxs("a",{className:"hub-download-btn",href:"/downloads/GamingHub-Setup.exe",download:!0,title:"Desktop App herunterladen",children:[P.jsx("span",{className:"hub-download-icon",children:"⬇️"}),P.jsx("span",{className:"hub-download-label",children:"Desktop App"})]}),P.jsx("button",{className:`hub-admin-btn ${v?"active":""}`,onClick:()=>v?C(!0):T(!0),onContextMenu:ne=>{v&&(ne.preventDefault(),ie())},title:v?"Admin Panel (Rechtsklick = Abmelden)":"Admin Login",children:v?"🔓":"🔒"}),P.jsx("button",{className:"hub-refresh-btn",onClick:()=>window.location.reload(),title:"Seite neu laden",children:"🔄"}),P.jsxs("span",{className:"hub-version hub-version-clickable",onClick:()=>{var ne;if(j){const de=window.electronAPI,be=(ne=de.getUpdateStatus)==null?void 0:ne.call(de);be==="downloading"?H("downloading"):be==="ready"?H("ready"):be==="checking"&&H("checking")}u(!0)},title:"Versionsinformationen",children:["v",le]})]})]}),l&&P.jsx("div",{className:"hub-version-overlay",onClick:()=>u(!1),children:P.jsxs("div",{className:"hub-version-modal",onClick:ne=>ne.stopPropagation(),children:[P.jsxs("div",{className:"hub-version-modal-header",children:[P.jsx("span",{children:"Versionsinformationen"}),P.jsx("button",{className:"hub-version-modal-close",onClick:()=>u(!1),children:"✕"})]}),P.jsxs("div",{className:"hub-version-modal-body",children:[P.jsxs("div",{className:"hub-version-modal-row",children:[P.jsx("span",{className:"hub-version-modal-label",children:"Hub-Version"}),P.jsxs("span",{className:"hub-version-modal-value",children:["v",le]})]}),j&&P.jsxs("div",{className:"hub-version-modal-row",children:[P.jsx("span",{className:"hub-version-modal-label",children:"Desktop-App"}),P.jsxs("span",{className:"hub-version-modal-value",children:["v",z]})]}),P.jsxs("div",{className:"hub-version-modal-row",children:[P.jsx("span",{className:"hub-version-modal-label",children:"Server"}),P.jsxs("span",{className:"hub-version-modal-value",children:[P.jsx("span",{className:`hub-version-modal-dot ${i?"online":""}`}),i?"Verbunden":"Getrennt"]})]}),j&&P.jsxs("div",{className:"hub-version-modal-update",children:[G==="idle"&&P.jsxs("button",{className:"hub-version-modal-update-btn",onClick:()=>{H("checking"),V(""),window.electronAPI.checkForUpdates()},children:["🔄"," Nach Updates suchen"]}),G==="checking"&&P.jsxs("div",{className:"hub-version-modal-update-status",children:[P.jsx("span",{className:"hub-update-spinner"}),"Suche nach Updates…"]}),G==="downloading"&&P.jsxs("div",{className:"hub-version-modal-update-status",children:[P.jsx("span",{className:"hub-update-spinner"}),"Update wird heruntergeladen…"]}),G==="ready"&&P.jsxs("button",{className:"hub-version-modal-update-btn ready",onClick:()=>window.electronAPI.installUpdate(),children:["✅"," Jetzt installieren & neu starten"]}),G==="upToDate"&&P.jsxs("div",{className:"hub-version-modal-update-status success",children:["✅"," App ist aktuell",P.jsx("button",{className:"hub-version-modal-update-retry",onClick:()=>H("idle"),children:"Erneut prüfen"})]}),G==="error"&&P.jsxs("div",{className:"hub-version-modal-update-status error",children:["❌"," ",q,P.jsx("button",{className:"hub-version-modal-update-retry",onClick:()=>H("idle"),children:"Erneut versuchen"})]})]})]})]})}),S&&P.jsx("div",{className:"hub-admin-overlay",onClick:()=>T(!1),children:P.jsxs("div",{className:"hub-admin-modal",onClick:ne=>ne.stopPropagation(),children:[P.jsxs("div",{className:"hub-admin-modal-header",children:[P.jsxs("span",{children:["🔒"," Admin Login"]}),P.jsx("button",{className:"hub-admin-modal-close",onClick:()=>T(!1),children:"✕"})]}),P.jsxs("div",{className:"hub-admin-modal-body",children:[P.jsx("input",{type:"password",className:"hub-admin-input",placeholder:"Admin-Passwort...",value:E,onChange:ne=>O(ne.target.value),onKeyDown:ne=>ne.key==="Enter"&&J(),autoFocus:!0}),U&&P.jsx("p",{className:"hub-admin-error",children:U}),P.jsx("button",{className:"hub-admin-submit",onClick:J,children:"Login"})]})]})}),N&&v&&P.jsx(s0e,{onClose:()=>C(!1),onLogout:()=>{ie(),C(!1)}}),P.jsx("main",{className:"hub-content",children:t.length===0?P.jsxs("div",{className:"hub-empty",children:[P.jsx("span",{className:"hub-empty-icon",children:"📦"}),P.jsx("h2",{children:"Keine Plugins geladen"}),P.jsx("p",{children:"Plugins werden im Server konfiguriert."})]}):t.map(ne=>{const de=M7[ne.name];if(!de)return null;const be=r===ne.name;return P.jsx("div",{className:`hub-tab-panel ${be?"active":""}`,style:be?{display:"flex",flexDirection:"column",width:"100%",height:"100%"}:{display:"none"},children:P.jsx(de,{data:h[ne.name]||{},isAdmin:v})},ne.name)})})]})}IF.createRoot(document.getElementById("root")).render(P.jsx(a0e,{})); +In order to be iterable, non-array objects must have a [Symbol.iterator]() method.`)}function m7(i,e){var t=Object.keys(i);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(i);e&&(n=n.filter(function(r){return Object.getOwnPropertyDescriptor(i,r).enumerable})),t.push.apply(t,n)}return t}function zf(i){for(var e=1;e1?l-1:0),h=1;h1&&arguments[1]!==void 0?arguments[1]:{},n=arguments.length>2&&arguments[2]!==void 0?arguments[2]:0,r=a();if(t.lat===void 0&&t.lng===void 0&&t.altitude===void 0)return r;var s=Object.assign({},r,t);if(["lat","lng","altitude"].forEach(function(u){return s[u]=+s[u]}),!n)l(s);else{for(;r.lng-s.lng>180;)r.lng-=360;for(;r.lng-s.lng<-180;)r.lng+=360;e.tweenGroup.add(new la(r).to(s,n).easing(os.Cubic.InOut).onUpdate(l).start())}return this;function a(){return e.globe.toGeoCoords(e.renderObjs.cameraPosition())}function l(u){var h=u.lat,m=u.lng,v=u.altitude;e.renderObjs.cameraPosition(e.globe.getCoords(h,m,v)),e.globe.setPointOfView(e.renderObjs.camera())}},getScreenCoords:function(e){for(var t,n=arguments.length,r=new Array(n>1?n-1:0),s=1;slocalStorage.getItem("radio-theme")||"default"),[a,l]=se.useState([]),[u,h]=se.useState(null),[m,v]=se.useState([]),[x,S]=se.useState(!1),[T,N]=se.useState({}),[C,E]=se.useState([]),[O,U]=se.useState(""),[I,j]=se.useState(""),[z,G]=se.useState(""),[H,q]=se.useState([]),[V,Q]=se.useState(!1),[J,ie]=se.useState([]),[le,re]=se.useState(!1),[Z,ne]=se.useState(!1),[de,be]=se.useState(.5),[Te,ae]=se.useState(null),[Me,Ve]=se.useState(!1),[Ce,Fe]=se.useState(!1),tt=se.useRef(void 0),je=se.useRef(void 0),Rt=se.useRef(O);se.useEffect(()=>{fetch("/api/radio/places").then(k=>k.json()).then(l).catch(console.error),fetch("/api/radio/guilds").then(k=>k.json()).then(k=>{if(E(k),k.length>0){U(k[0].id);const xe=k[0].voiceChannels.find(Oe=>Oe.members>0)??k[0].voiceChannels[0];xe&&j(xe.id)}}).catch(console.error),fetch("/api/radio/favorites").then(k=>k.json()).then(ie).catch(console.error)},[]),se.useEffect(()=>{Rt.current=O},[O]),se.useEffect(()=>{i!=null&&i.guildId&&"playing"in i&&i.type!=="radio_voicestats"?N(k=>{if(i.playing)return{...k,[i.guildId]:i.playing};const xe={...k};return delete xe[i.guildId],xe}):i!=null&&i.playing&&!(i!=null&&i.guildId)&&N(i.playing),i!=null&&i.favorites&&ie(i.favorites),i!=null&&i.volumes&&O&&i.volumes[O]!=null&&be(i.volumes[O]),(i==null?void 0:i.volume)!=null&&(i==null?void 0:i.guildId)===O&&be(i.volume),(i==null?void 0:i.type)==="radio_voicestats"&&i.guildId===Rt.current&&ae({voicePing:i.voicePing,gatewayPing:i.gatewayPing,status:i.status,channelName:i.channelName,connectedSince:i.connectedSince})},[i,O]),se.useEffect(()=>{if(localStorage.setItem("radio-theme",r),t.current&&e.current){const xe=getComputedStyle(e.current.parentElement).getPropertyValue("--accent-rgb").trim();t.current.pointColor(()=>`rgba(${xe}, 0.85)`).atmosphereColor(`rgba(${xe}, 0.25)`)}},[r]);const Et=se.useRef(u);Et.current=u;const Ft=se.useRef(le);Ft.current=le;const Ut=se.useCallback(()=>{var xe;const k=(xe=t.current)==null?void 0:xe.controls();k&&(k.autoRotate=!1),n.current&&clearTimeout(n.current),n.current=setTimeout(()=>{var Ue;if(Et.current||Ft.current)return;const Oe=(Ue=t.current)==null?void 0:Ue.controls();Oe&&(Oe.autoRotate=!0)},5e3)},[]);se.useEffect(()=>{var xe;const k=(xe=t.current)==null?void 0:xe.controls();k&&(u||le?(k.autoRotate=!1,n.current&&clearTimeout(n.current)):k.autoRotate=!0)},[u,le]);const Ke=se.useRef(void 0);Ke.current=k=>{h(k),re(!1),S(!0),v([]),Ut(),t.current&&t.current.pointOfView({lat:k.geo[1],lng:k.geo[0],altitude:.4},800),fetch(`/api/radio/place/${k.id}/channels`).then(xe=>xe.json()).then(xe=>{v(xe),S(!1)}).catch(()=>S(!1))},se.useEffect(()=>{const k=e.current;if(!k)return;k.clientWidth>0&&k.clientHeight>0&&Fe(!0);const xe=new ResizeObserver(Oe=>{for(const Ue of Oe){const{width:ee,height:we}=Ue.contentRect;ee>0&&we>0&&Fe(!0)}});return xe.observe(k),()=>xe.disconnect()},[]),se.useEffect(()=>{if(!e.current||a.length===0)return;const k=e.current.clientWidth,xe=e.current.clientHeight;if(t.current){t.current.pointsData(a),k>0&&xe>0&&t.current.width(k).height(xe);return}if(k===0||xe===0)return;const Ue=getComputedStyle(e.current.parentElement).getPropertyValue("--accent-rgb").trim()||"230, 126, 34",ee=new wAe(e.current).backgroundColor("rgba(0,0,0,0)").atmosphereColor(`rgba(${Ue}, 0.25)`).atmosphereAltitude(.12).globeImageUrl("/nasa-blue-marble.jpg").pointsData(a).pointLat(It=>It.geo[1]).pointLng(It=>It.geo[0]).pointColor(()=>`rgba(${Ue}, 0.85)`).pointRadius(It=>Math.max(.12,Math.min(.45,.06+(It.size??1)*.005))).pointAltitude(.001).pointResolution(24).pointLabel(It=>`
${It.title}
${It.country}
`).onPointClick(It=>{var lt;return(lt=Ke.current)==null?void 0:lt.call(Ke,It)}).width(e.current.clientWidth).height(e.current.clientHeight);ee.renderer().setPixelRatio(window.devicePixelRatio),ee.pointOfView({lat:48,lng:10,altitude:qS});const we=ee.controls();we&&(we.autoRotate=!0,we.autoRotateSpeed=.3);let Re=qS;const We=()=>{const lt=ee.pointOfView().altitude;if(Math.abs(lt-Re)/Re<.05)return;Re=lt;const jt=Math.sqrt(lt/qS);ee.pointRadius(Jt=>Math.max(.12,Math.min(.45,.06+(Jt.size??1)*.005))*Math.max(.15,Math.min(2.5,jt)))};we.addEventListener("change",We),t.current=ee;const Se=e.current,Le=()=>Ut();Se.addEventListener("mousedown",Le),Se.addEventListener("touchstart",Le),Se.addEventListener("wheel",Le);const ct=()=>{if(e.current&&t.current){const It=e.current.clientWidth,lt=e.current.clientHeight;It>0&<>0&&t.current.width(It).height(lt)}};window.addEventListener("resize",ct);const Dt=new ResizeObserver(()=>ct());return Dt.observe(Se),()=>{we.removeEventListener("change",We),Se.removeEventListener("mousedown",Le),Se.removeEventListener("touchstart",Le),Se.removeEventListener("wheel",Le),window.removeEventListener("resize",ct),Dt.disconnect()}},[a,Ut,Ce]);const ht=se.useCallback(async(k,xe,Oe,Ue)=>{if(!(!O||!I)){ne(!0);try{(await(await fetch("/api/radio/play",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:O,voiceChannelId:I,stationId:k,stationName:xe,placeName:Oe??(u==null?void 0:u.title)??"",country:Ue??(u==null?void 0:u.country)??""})})).json()).ok&&(N(Re=>{var We,Se;return{...Re,[O]:{stationId:k,stationName:xe,placeName:Oe??(u==null?void 0:u.title)??"",country:Ue??(u==null?void 0:u.country)??"",startedAt:new Date().toISOString(),channelName:((Se=(We=C.find(Le=>Le.id===O))==null?void 0:We.voiceChannels.find(Le=>Le.id===I))==null?void 0:Se.name)??""}}}),Ut())}catch(ee){console.error(ee)}ne(!1)}},[O,I,u,C]),fe=se.useCallback(async()=>{O&&(await fetch("/api/radio/stop",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:O})}),N(k=>{const xe={...k};return delete xe[O],xe}))},[O]),$t=se.useCallback(k=>{if(G(k),tt.current&&clearTimeout(tt.current),!k.trim()){q([]),Q(!1);return}tt.current=setTimeout(async()=>{try{const Oe=await(await fetch(`/api/radio/search?q=${encodeURIComponent(k)}`)).json();q(Oe),Q(!0)}catch{q([])}},350)},[]),_t=se.useCallback(k=>{var xe,Oe,Ue;if(Q(!1),G(""),q([]),k.type==="channel"){const ee=(xe=k.url.match(/\/listen\/[^/]+\/([^/]+)/))==null?void 0:xe[1];ee&&ht(ee,k.title,k.subtitle,"")}else if(k.type==="place"){const ee=(Oe=k.url.match(/\/visit\/[^/]+\/([^/]+)/))==null?void 0:Oe[1],we=a.find(Re=>Re.id===ee);we&&((Ue=Ke.current)==null||Ue.call(Ke,we))}},[a,ht]),Gt=se.useCallback(async(k,xe)=>{try{const Ue=await(await fetch("/api/radio/favorites",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({stationId:k,stationName:xe,placeName:(u==null?void 0:u.title)??"",country:(u==null?void 0:u.country)??"",placeId:(u==null?void 0:u.id)??""})})).json();Ue.favorites&&ie(Ue.favorites)}catch{}},[u]),yt=se.useCallback(k=>{be(k),O&&(je.current&&clearTimeout(je.current),je.current=setTimeout(()=>{fetch("/api/radio/volume",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:O,volume:k})}).catch(console.error)},100))},[O]),Ht=k=>J.some(xe=>xe.stationId===k),pt=O?T[O]:null,Ae=C.find(k=>k.id===O);return P.jsxs("div",{className:"radio-container","data-theme":r,children:[P.jsxs("header",{className:"radio-topbar",children:[P.jsxs("div",{className:"radio-topbar-left",children:[P.jsx("span",{className:"radio-topbar-logo",children:"🌍"}),P.jsx("span",{className:"radio-topbar-title",children:"World Radio"}),C.length>1&&P.jsx("select",{className:"radio-sel",value:O,onChange:k=>{U(k.target.value);const xe=C.find(Ue=>Ue.id===k.target.value),Oe=(xe==null?void 0:xe.voiceChannels.find(Ue=>Ue.members>0))??(xe==null?void 0:xe.voiceChannels[0]);j((Oe==null?void 0:Oe.id)??"")},children:C.map(k=>P.jsx("option",{value:k.id,children:k.name},k.id))}),P.jsxs("select",{className:"radio-sel",value:I,onChange:k=>j(k.target.value),children:[P.jsx("option",{value:"",children:"Voice Channel..."}),Ae==null?void 0:Ae.voiceChannels.map(k=>P.jsxs("option",{value:k.id,children:["🔊"," ",k.name,k.members>0?` (${k.members})`:""]},k.id))]})]}),pt&&P.jsxs("div",{className:"radio-topbar-np",children:[P.jsxs("div",{className:"radio-eq radio-eq-np",children:[P.jsx("span",{}),P.jsx("span",{}),P.jsx("span",{})]}),P.jsxs("div",{className:"radio-np-info",children:[P.jsx("span",{className:"radio-np-name",children:pt.stationName}),P.jsxs("span",{className:"radio-np-loc",children:[pt.placeName,pt.country?`, ${pt.country}`:""]})]})]}),P.jsxs("div",{className:"radio-topbar-right",children:[pt&&P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"radio-volume",children:[P.jsx("span",{className:"radio-volume-icon",children:de===0?"🔇":de<.4?"🔉":"🔊"}),P.jsx("input",{type:"range",className:"radio-volume-slider",min:0,max:1,step:.01,value:de,onChange:k=>yt(Number(k.target.value))}),P.jsxs("span",{className:"radio-volume-val",children:[Math.round(de*100),"%"]})]}),P.jsxs("div",{className:"radio-conn",onClick:()=>Ve(!0),title:"Verbindungsdetails",children:[P.jsx("span",{className:"radio-conn-dot"}),"Verbunden",(Te==null?void 0:Te.voicePing)!=null&&P.jsxs("span",{className:"radio-conn-ping",children:[Te.voicePing,"ms"]})]}),P.jsxs("button",{className:"radio-topbar-stop",onClick:fe,children:["⏹"," Stop"]})]}),P.jsx("div",{className:"radio-theme-inline",children:TAe.map(k=>P.jsx("div",{className:`radio-theme-dot ${r===k.id?"active":""}`,style:{background:k.color},title:k.label,onClick:()=>s(k.id)},k.id))})]})]}),P.jsxs("div",{className:"radio-globe-wrap",children:[P.jsx("div",{className:"radio-globe",ref:e}),P.jsxs("div",{className:"radio-search",children:[P.jsxs("div",{className:"radio-search-wrap",children:[P.jsx("span",{className:"radio-search-icon",children:"🔍"}),P.jsx("input",{className:"radio-search-input",type:"text",placeholder:"Sender oder Stadt suchen...",value:z,onChange:k=>$t(k.target.value),onFocus:()=>{H.length&&Q(!0)}}),z&&P.jsx("button",{className:"radio-search-clear",onClick:()=>{G(""),q([]),Q(!1)},children:"✕"})]}),V&&H.length>0&&P.jsx("div",{className:"radio-search-results",children:H.slice(0,12).map(k=>P.jsxs("button",{className:"radio-search-result",onClick:()=>_t(k),children:[P.jsx("span",{className:"radio-search-result-icon",children:k.type==="channel"?"📻":k.type==="place"?"📍":"🌍"}),P.jsxs("div",{className:"radio-search-result-text",children:[P.jsx("span",{className:"radio-search-result-title",children:k.title}),P.jsx("span",{className:"radio-search-result-sub",children:k.subtitle})]})]},k.id+k.url))})]}),!u&&!le&&P.jsxs("button",{className:"radio-fab",onClick:()=>{re(!0),h(null)},title:"Favoriten",children:["⭐",J.length>0&&P.jsx("span",{className:"radio-fab-badge",children:J.length})]}),le&&P.jsxs("div",{className:"radio-panel open",children:[P.jsxs("div",{className:"radio-panel-header",children:[P.jsxs("h3",{children:["⭐"," Favoriten"]}),P.jsx("button",{className:"radio-panel-close",onClick:()=>re(!1),children:"✕"})]}),P.jsx("div",{className:"radio-panel-body",children:J.length===0?P.jsx("div",{className:"radio-panel-empty",children:"Noch keine Favoriten"}):J.map(k=>P.jsxs("div",{className:`radio-station ${(pt==null?void 0:pt.stationId)===k.stationId?"playing":""}`,children:[P.jsxs("div",{className:"radio-station-info",children:[P.jsx("span",{className:"radio-station-name",children:k.stationName}),P.jsxs("span",{className:"radio-station-loc",children:[k.placeName,", ",k.country]})]}),P.jsxs("div",{className:"radio-station-btns",children:[P.jsx("button",{className:"radio-btn-play",onClick:()=>ht(k.stationId,k.stationName,k.placeName,k.country),disabled:!I||Z,children:"▶"}),P.jsx("button",{className:"radio-btn-fav active",onClick:()=>Gt(k.stationId,k.stationName),children:"★"})]})]},k.stationId))})]}),u&&!le&&P.jsxs("div",{className:"radio-panel open",children:[P.jsxs("div",{className:"radio-panel-header",children:[P.jsxs("div",{children:[P.jsx("h3",{children:u.title}),P.jsx("span",{className:"radio-panel-sub",children:u.country})]}),P.jsx("button",{className:"radio-panel-close",onClick:()=>h(null),children:"✕"})]}),P.jsx("div",{className:"radio-panel-body",children:x?P.jsxs("div",{className:"radio-panel-loading",children:[P.jsx("div",{className:"radio-spinner"}),"Sender werden geladen..."]}):m.length===0?P.jsx("div",{className:"radio-panel-empty",children:"Keine Sender gefunden"}):m.map(k=>P.jsxs("div",{className:`radio-station ${(pt==null?void 0:pt.stationId)===k.id?"playing":""}`,children:[P.jsxs("div",{className:"radio-station-info",children:[P.jsx("span",{className:"radio-station-name",children:k.title}),(pt==null?void 0:pt.stationId)===k.id&&P.jsxs("span",{className:"radio-station-live",children:[P.jsxs("span",{className:"radio-eq",children:[P.jsx("span",{}),P.jsx("span",{}),P.jsx("span",{})]}),"Live"]})]}),P.jsxs("div",{className:"radio-station-btns",children:[(pt==null?void 0:pt.stationId)===k.id?P.jsx("button",{className:"radio-btn-stop",onClick:fe,children:"⏹"}):P.jsx("button",{className:"radio-btn-play",onClick:()=>ht(k.id,k.title),disabled:!I||Z,children:"▶"}),P.jsx("button",{className:`radio-btn-fav ${Ht(k.id)?"active":""}`,onClick:()=>Gt(k.id,k.title),children:Ht(k.id)?"★":"☆"})]})]},k.id))})]}),P.jsxs("div",{className:"radio-counter",children:["📻"," ",a.length.toLocaleString("de-DE")," Sender weltweit"]}),P.jsx("a",{className:"radio-attribution",href:"https://science.nasa.gov/earth/earth-observatory/blue-marble-next-generation/",target:"_blank",rel:"noreferrer",children:"Imagery © NASA Blue Marble"})]}),Me&&(()=>{const k=Te!=null&&Te.connectedSince?Math.floor((Date.now()-new Date(Te.connectedSince).getTime())/1e3):0,xe=Math.floor(k/3600),Oe=Math.floor(k%3600/60),Ue=k%60,ee=xe>0?`${xe}h ${String(Oe).padStart(2,"0")}m ${String(Ue).padStart(2,"0")}s`:Oe>0?`${Oe}m ${String(Ue).padStart(2,"0")}s`:`${Ue}s`,we=Re=>Re==null?"var(--text-faint)":Re<80?"var(--success)":Re<150?"#f0a830":"#e04040";return P.jsx("div",{className:"radio-modal-overlay",onClick:()=>Ve(!1),children:P.jsxs("div",{className:"radio-modal",onClick:Re=>Re.stopPropagation(),children:[P.jsxs("div",{className:"radio-modal-header",children:[P.jsx("span",{children:"📡"}),P.jsx("span",{children:"Verbindungsdetails"}),P.jsx("button",{className:"radio-modal-close",onClick:()=>Ve(!1),children:"✕"})]}),P.jsxs("div",{className:"radio-modal-body",children:[P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Voice Ping"}),P.jsxs("span",{className:"radio-modal-value",children:[P.jsx("span",{className:"radio-modal-dot",style:{background:we((Te==null?void 0:Te.voicePing)??null)}}),(Te==null?void 0:Te.voicePing)!=null?`${Te.voicePing} ms`:"---"]})]}),P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Gateway Ping"}),P.jsxs("span",{className:"radio-modal-value",children:[P.jsx("span",{className:"radio-modal-dot",style:{background:we((Te==null?void 0:Te.gatewayPing)??null)}}),Te&&Te.gatewayPing>=0?`${Te.gatewayPing} ms`:"---"]})]}),P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Status"}),P.jsx("span",{className:"radio-modal-value",style:{color:(Te==null?void 0:Te.status)==="ready"?"var(--success)":"#f0a830"},children:(Te==null?void 0:Te.status)==="ready"?"Verbunden":(Te==null?void 0:Te.status)??"Warte auf Verbindung"})]}),P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Kanal"}),P.jsx("span",{className:"radio-modal-value",children:(Te==null?void 0:Te.channelName)||"---"})]}),P.jsxs("div",{className:"radio-modal-stat",children:[P.jsx("span",{className:"radio-modal-label",children:"Verbunden seit"}),P.jsx("span",{className:"radio-modal-value",children:ee||"---"})]})]})]})})})()]})}function EAe(i,e,t=365){const n=new Date(Date.now()+t*24*60*60*1e3).toUTCString();document.cookie=`${encodeURIComponent(i)}=${encodeURIComponent(e)}; expires=${n}; path=/; SameSite=Lax`}function CAe(i){const e=`${encodeURIComponent(i)}=`,t=document.cookie.split(";");for(const n of t){const r=n.trim();if(r.startsWith(e))return decodeURIComponent(r.slice(e.length))}return null}const ca="/api/soundboard";async function NAe(i,e,t,n){const r=new URL(`${ca}/sounds`,window.location.origin);i&&r.searchParams.set("q",i),e!==void 0&&r.searchParams.set("folder",e),r.searchParams.set("fuzzy","0");const s=await fetch(r.toString());if(!s.ok)throw new Error("Fehler beim Laden der Sounds");return s.json()}async function RAe(){const i=await fetch(`${ca}/analytics`);if(!i.ok)throw new Error("Fehler beim Laden der Analytics");return i.json()}async function DAe(){const i=await fetch(`${ca}/categories`,{credentials:"include"});if(!i.ok)throw new Error("Fehler beim Laden der Kategorien");return i.json()}async function PAe(){const i=await fetch(`${ca}/channels`);if(!i.ok)throw new Error("Fehler beim Laden der Channels");return i.json()}async function LAe(){const i=await fetch(`${ca}/selected-channels`);if(!i.ok)throw new Error("Fehler beim Laden der Channel-Auswahl");const e=await i.json();return(e==null?void 0:e.selected)||{}}async function UAe(i,e){if(!(await fetch(`${ca}/selected-channel`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:i,channelId:e})})).ok)throw new Error("Channel-Auswahl setzen fehlgeschlagen")}async function BAe(i,e,t,n,r){const s=await fetch(`${ca}/play`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({soundName:i,guildId:e,channelId:t,volume:n,relativePath:r})});if(!s.ok){const a=await s.json().catch(()=>({}));throw new Error((a==null?void 0:a.error)||"Play fehlgeschlagen")}}async function OAe(i,e,t,n,r){const s=await fetch(`${ca}/play-url`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:i,guildId:e,channelId:t,volume:n,filename:r})}),a=await s.json().catch(()=>({}));if(!s.ok)throw new Error((a==null?void 0:a.error)||"Play-URL fehlgeschlagen");return a}async function IAe(i,e){const t=await fetch(`${ca}/download-url`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({url:i,filename:e})}),n=await t.json().catch(()=>({}));if(!t.ok)throw new Error((n==null?void 0:n.error)||"Download fehlgeschlagen");return n}async function FAe(i,e){if(!(await fetch(`${ca}/party/start`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:i,channelId:e})})).ok)throw new Error("Partymode Start fehlgeschlagen")}async function kAe(i){if(!(await fetch(`${ca}/party/stop`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:i})})).ok)throw new Error("Partymode Stop fehlgeschlagen")}async function g7(i,e){const t=await fetch(`${ca}/volume`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({guildId:i,volume:e})});if(!t.ok){const n=await t.json().catch(()=>({}));throw new Error((n==null?void 0:n.error)||"Volume aendern fehlgeschlagen")}}async function zAe(i){const e=new URL(`${ca}/volume`,window.location.origin);e.searchParams.set("guildId",i);const t=await fetch(e.toString());if(!t.ok)throw new Error("Fehler beim Laden der Lautstaerke");const n=await t.json();return typeof(n==null?void 0:n.volume)=="number"?n.volume:1}async function GAe(i){if(!(await fetch(`${ca}/admin/sounds/delete`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({paths:i})})).ok)throw new Error("Loeschen fehlgeschlagen")}function qAe(i,e,t){return new Promise((n,r)=>{const s=new FormData;s.append("files",i),e&&s.append("customName",e);const a=new XMLHttpRequest;a.open("POST",`${ca}/upload`),a.upload.onprogress=l=>{l.lengthComputable&&t(Math.round(l.loaded/l.total*100))},a.onload=()=>{var l,u;if(a.status===200)try{const h=JSON.parse(a.responseText);n(((u=(l=h.files)==null?void 0:l[0])==null?void 0:u.name)??i.name)}catch{n(i.name)}else try{r(new Error(JSON.parse(a.responseText).error))}catch{r(new Error(`HTTP ${a.status}`))}},a.onerror=()=>r(new Error("Netzwerkfehler")),a.send(s)})}const VAe=[{id:"default",color:"#5865f2",label:"Discord"},{id:"purple",color:"#9b59b6",label:"Midnight"},{id:"forest",color:"#2ecc71",label:"Forest"},{id:"sunset",color:"#e67e22",label:"Sunset"},{id:"ocean",color:"#3498db",label:"Ocean"}],v7=["#3b82f6","#f59e0b","#8b5cf6","#ec4899","#14b8a6","#f97316","#06b6d4","#ef4444","#a855f7","#84cc16","#d946ef","#0ea5e9","#f43f5e","#10b981"];function jAe({data:i,isAdmin:e}){var qe,qt,Qt;const[t,n]=se.useState([]),[r,s]=se.useState(0),[a,l]=se.useState([]),[u,h]=se.useState([]),[m,v]=se.useState({totalSounds:0,totalPlays:0,mostPlayed:[]}),[x,S]=se.useState("all"),[T,N]=se.useState(""),[C,E]=se.useState(""),[O,U]=se.useState(""),[I,j]=se.useState(!1),[z,G]=se.useState(null),[H,q]=se.useState([]),[V,Q]=se.useState(""),J=se.useRef(""),[ie,le]=se.useState(!1),[re,Z]=se.useState(1),[ne,de]=se.useState(""),[be,Te]=se.useState({}),[ae,Me]=se.useState(()=>localStorage.getItem("jb-theme")||"default"),[Ve,Ce]=se.useState(()=>parseInt(localStorage.getItem("jb-card-size")||"110")),[Fe,tt]=se.useState(!1),[je,Rt]=se.useState([]),Et=se.useRef(!1),Ft=se.useRef(void 0),Ut=e??!1,[Ke,ht]=se.useState(!1),[fe,$t]=se.useState([]),[_t,Gt]=se.useState(!1),yt=se.useRef(0);se.useRef(void 0);const[Ht,pt]=se.useState([]),[Ae,k]=se.useState(0),[xe,Oe]=se.useState(""),[Ue,ee]=se.useState("naming"),[we,Re]=se.useState(0),[We,Se]=se.useState(null),[Le,ct]=se.useState(!1),[Dt,It]=se.useState(null),[lt,jt]=se.useState(""),[Jt,In]=se.useState(null),[me,Bt]=se.useState(0);se.useEffect(()=>{Et.current=Fe},[Fe]),se.useEffect(()=>{J.current=V},[V]),se.useEffect(()=>{const he=sn=>{var Tn;Array.from(((Tn=sn.dataTransfer)==null?void 0:Tn.items)??[]).some(Rn=>Rn.kind==="file")&&(yt.current++,ht(!0))},X=()=>{yt.current=Math.max(0,yt.current-1),yt.current===0&&ht(!1)},et=sn=>sn.preventDefault(),en=sn=>{var Rn;sn.preventDefault(),yt.current=0,ht(!1);const Tn=Array.from(((Rn=sn.dataTransfer)==null?void 0:Rn.files)??[]).filter(xi=>/\.(mp3|wav)$/i.test(xi.name));Tn.length&&xt(Tn)};return window.addEventListener("dragenter",he),window.addEventListener("dragleave",X),window.addEventListener("dragover",et),window.addEventListener("drop",en),()=>{window.removeEventListener("dragenter",he),window.removeEventListener("dragleave",X),window.removeEventListener("dragover",et),window.removeEventListener("drop",en)}},[Ut]);const ot=se.useCallback((he,X="info")=>{It({msg:he,type:X}),setTimeout(()=>It(null),3e3)},[]);se.useCallback(he=>he.relativePath??he.fileName,[]);const Tt=["youtube.com","www.youtube.com","m.youtube.com","youtu.be","music.youtube.com","instagram.com","www.instagram.com"],Wt=se.useCallback(he=>{const X=he.trim();return!X||/^https?:\/\//i.test(X)?X:"https://"+X},[]),Yt=se.useCallback(he=>{try{const X=new URL(Wt(he)),et=X.hostname.toLowerCase();return!!(X.pathname.toLowerCase().endsWith(".mp3")||Tt.some(en=>et===en||et.endsWith("."+en)))}catch{return!1}},[Wt]),pn=se.useCallback(he=>{try{const X=new URL(Wt(he)),et=X.hostname.toLowerCase();return et.includes("youtube")||et==="youtu.be"?"youtube":et.includes("instagram")?"instagram":X.pathname.toLowerCase().endsWith(".mp3")?"mp3":null}catch{return null}},[Wt]),$e=V?V.split(":")[0]:"",St=V?V.split(":")[1]:"",Kt=se.useMemo(()=>H.find(he=>`${he.guildId}:${he.channelId}`===V),[H,V]);se.useEffect(()=>{const he=()=>{const et=new Date,en=String(et.getHours()).padStart(2,"0"),sn=String(et.getMinutes()).padStart(2,"0"),Tn=String(et.getSeconds()).padStart(2,"0");jt(`${en}:${sn}:${Tn}`)};he();const X=setInterval(he,1e3);return()=>clearInterval(X)},[]),se.useEffect(()=>{(async()=>{try{const[he,X]=await Promise.all([PAe(),LAe()]);if(q(he),he.length){const et=he[0].guildId,en=X[et],sn=en&&he.find(Tn=>Tn.guildId===et&&Tn.channelId===en);Q(sn?`${et}:${en}`:`${he[0].guildId}:${he[0].channelId}`)}}catch(he){ot((he==null?void 0:he.message)||"Channel-Fehler","error")}try{const he=await DAe();h(he.categories||[])}catch{}})()},[]),se.useEffect(()=>{localStorage.setItem("jb-theme",ae)},[ae]);const wn=se.useRef(null);se.useEffect(()=>{const he=wn.current;if(!he)return;he.style.setProperty("--card-size",Ve+"px");const X=Ve/110;he.style.setProperty("--card-emoji",Math.round(28*X)+"px"),he.style.setProperty("--card-font",Math.max(9,Math.round(11*X))+"px"),localStorage.setItem("jb-card-size",String(Ve))},[Ve]),se.useEffect(()=>{var he,X,et,en,sn,Tn,Rn,xi;if(i){if(i.soundboard){const K=i.soundboard;Array.isArray(K.party)&&Rt(K.party);try{const hn=K.selected||{},Zt=(he=J.current)==null?void 0:he.split(":")[0];Zt&&hn[Zt]&&Q(`${Zt}:${hn[Zt]}`)}catch{}try{const hn=K.volumes||{},Zt=(X=J.current)==null?void 0:X.split(":")[0];Zt&&typeof hn[Zt]=="number"&&Z(hn[Zt])}catch{}try{const hn=K.nowplaying||{},Zt=(et=J.current)==null?void 0:et.split(":")[0];Zt&&typeof hn[Zt]=="string"&&de(hn[Zt])}catch{}try{const hn=K.voicestats||{},Zt=(en=J.current)==null?void 0:en.split(":")[0];Zt&&hn[Zt]&&Se(hn[Zt])}catch{}}if(i.type==="soundboard_party")Rt(K=>{const hn=new Set(K);return i.active?hn.add(i.guildId):hn.delete(i.guildId),Array.from(hn)});else if(i.type==="soundboard_channel"){const K=(sn=J.current)==null?void 0:sn.split(":")[0];i.guildId===K&&Q(`${i.guildId}:${i.channelId}`)}else if(i.type==="soundboard_volume"){const K=(Tn=J.current)==null?void 0:Tn.split(":")[0];i.guildId===K&&typeof i.volume=="number"&&Z(i.volume)}else if(i.type==="soundboard_nowplaying"){const K=(Rn=J.current)==null?void 0:Rn.split(":")[0];i.guildId===K&&de(i.name||"")}else if(i.type==="soundboard_voicestats"){const K=(xi=J.current)==null?void 0:xi.split(":")[0];i.guildId===K&&Se({voicePing:i.voicePing,gatewayPing:i.gatewayPing,status:i.status,channelName:i.channelName,connectedSince:i.connectedSince})}}},[i]),se.useEffect(()=>{tt($e?je.includes($e):!1)},[V,je,$e]),se.useEffect(()=>{(async()=>{try{let he="__all__";x==="recent"?he="__recent__":T&&(he=T);const X=await NAe(C,he,void 0,!1);n(X.items),s(X.total),l(X.folders)}catch(he){ot((he==null?void 0:he.message)||"Sounds-Fehler","error")}})()},[x,T,C,me,ot]),se.useEffect(()=>{qn()},[me]),se.useEffect(()=>{const he=CAe("favs");if(he)try{Te(JSON.parse(he))}catch{}},[]),se.useEffect(()=>{try{EAe("favs",JSON.stringify(be))}catch{}},[be]),se.useEffect(()=>{V&&(async()=>{try{const he=await zAe($e);Z(he)}catch{}})()},[V]),se.useEffect(()=>{const he=()=>{le(!1),In(null)};return document.addEventListener("click",he),()=>document.removeEventListener("click",he)},[]);async function qn(){try{const he=await RAe();v(he)}catch{}}async function Je(he){if(!V)return ot("Bitte einen Voice-Channel auswaehlen","error");try{await BAe(he.name,$e,St,re,he.relativePath),de(he.name),qn()}catch(X){ot((X==null?void 0:X.message)||"Play fehlgeschlagen","error")}}function dt(){var en;const he=Wt(O);if(!he)return ot("Bitte einen Link eingeben","error");if(!Yt(he))return ot("Nur YouTube, Instagram oder direkte MP3-Links","error");const X=pn(he);let et="";if(X==="mp3")try{et=((en=new URL(he).pathname.split("/").pop())==null?void 0:en.replace(/\.mp3$/i,""))??""}catch{}G({url:he,type:X,filename:et,phase:"input"})}async function Vt(){if(z){G(he=>he?{...he,phase:"downloading"}:null);try{let he;const X=z.filename.trim()||void 0;V&&$e&&St?he=(await OAe(z.url,$e,St,re,X)).saved:he=(await IAe(z.url,X)).saved,G(et=>et?{...et,phase:"done",savedName:he}:null),U(""),Bt(et=>et+1),qn(),setTimeout(()=>G(null),2500)}catch(he){G(X=>X?{...X,phase:"error",error:(he==null?void 0:he.message)||"Fehler"}:null)}}}async function xt(he){if(!Ut){ot("Admin-Login erforderlich zum Hochladen","error");return}if(he.length===0)return;pt(he),k(0);const X=he[0].name.replace(/\.(mp3|wav)$/i,"");Oe(X),ee("naming"),Re(0)}async function A(){if(Ht.length===0)return;const he=Ht[Ae],X=xe.trim()||he.name.replace(/\.(mp3|wav)$/i,"");ee("uploading"),Re(0);try{await qAe(he,X,et=>Re(et)),ee("done"),setTimeout(()=>{const et=Ae+1;if(eten+1),qn(),ot(`${Ht.length} Sound${Ht.length>1?"s":""} hochgeladen`,"info")},800)}catch(et){ot((et==null?void 0:et.message)||"Upload fehlgeschlagen","error"),pt([])}}function te(){const he=Ae+1;if(he0&&(Bt(X=>X+1),qn())}async function Vn(){if(V){de("");try{await fetch(`${ca}/stop?guildId=${encodeURIComponent($e)}`,{method:"POST"})}catch{}}}async function Wn(){if(!lr.length||!V)return;const he=lr[Math.floor(Math.random()*lr.length)];Je(he)}async function $n(){if(Fe){await Vn();try{await kAe($e)}catch{}}else{if(!V)return ot("Bitte einen Channel auswaehlen","error");try{await FAe($e,St)}catch{}}}async function dn(he){const X=`${he.guildId}:${he.channelId}`;Q(X),le(!1);try{await UAe(he.guildId,he.channelId)}catch{}}function Fn(he){Te(X=>({...X,[he]:!X[he]}))}const lr=se.useMemo(()=>x==="favorites"?t.filter(he=>be[he.relativePath??he.fileName]):t,[t,x,be]),an=se.useMemo(()=>Object.values(be).filter(Boolean).length,[be]),mn=se.useMemo(()=>a.filter(he=>!["__all__","__recent__","__top3__"].includes(he.key)),[a]),Er=se.useMemo(()=>{const he={};return mn.forEach((X,et)=>{he[X.key]=v7[et%v7.length]}),he},[mn]),Wi=se.useMemo(()=>{const he=new Set,X=new Set;return lr.forEach((et,en)=>{const sn=et.name.charAt(0).toUpperCase();he.has(sn)||(he.add(sn),X.add(en))}),X},[lr]),No=se.useMemo(()=>{const he={};return H.forEach(X=>{he[X.guildName]||(he[X.guildName]=[]),he[X.guildName].push(X)}),he},[H]),ce=m.mostPlayed.slice(0,10),Ge=m.totalSounds||r,rt=lt.slice(0,5),it=lt.slice(5);return P.jsxs("div",{className:"sb-app","data-theme":ae,ref:wn,children:[Fe&&P.jsx("div",{className:"party-overlay active"}),P.jsxs("header",{className:"topbar",children:[P.jsxs("div",{className:"topbar-left",children:[P.jsx("div",{className:"sb-app-logo",children:P.jsx("span",{className:"material-icons",style:{fontSize:16,color:"white"},children:"music_note"})}),P.jsx("span",{className:"sb-app-title",children:"Soundboard"}),P.jsxs("div",{className:"channel-dropdown",onClick:he=>he.stopPropagation(),children:[P.jsxs("button",{className:`channel-btn ${ie?"open":""}`,onClick:()=>le(!ie),children:[P.jsx("span",{className:"material-icons cb-icon",children:"headset"}),V&&P.jsx("span",{className:"channel-status"}),P.jsx("span",{className:"channel-label",children:Kt?`${Kt.channelName}${Kt.members?` (${Kt.members})`:""}`:"Channel..."}),P.jsx("span",{className:"material-icons chevron",children:"expand_more"})]}),ie&&P.jsxs("div",{className:"channel-menu visible",children:[Object.entries(No).map(([he,X])=>P.jsxs(FF.Fragment,{children:[P.jsx("div",{className:"channel-menu-header",children:he}),X.map(et=>P.jsxs("div",{className:`channel-option ${`${et.guildId}:${et.channelId}`===V?"active":""}`,onClick:()=>dn(et),children:[P.jsx("span",{className:"material-icons co-icon",children:"volume_up"}),et.channelName,et.members?` (${et.members})`:""]},`${et.guildId}:${et.channelId}`))]},he)),H.length===0&&P.jsx("div",{className:"channel-option",style:{color:"var(--text-faint)",cursor:"default"},children:"Keine Channels verfuegbar"})]})]})]}),P.jsx("div",{className:"clock-wrap",children:P.jsxs("div",{className:"clock",children:[rt,P.jsx("span",{className:"clock-seconds",children:it})]})}),P.jsxs("div",{className:"topbar-right",children:[ne&&P.jsxs("div",{className:"now-playing",children:[P.jsxs("div",{className:"np-waves active",children:[P.jsx("div",{className:"np-wave-bar"}),P.jsx("div",{className:"np-wave-bar"}),P.jsx("div",{className:"np-wave-bar"}),P.jsx("div",{className:"np-wave-bar"})]}),P.jsx("span",{className:"np-label",children:"Last Played:"})," ",P.jsx("span",{className:"np-name",children:ne})]}),V&&P.jsxs("div",{className:"connection",onClick:()=>ct(!0),style:{cursor:"pointer"},title:"Verbindungsdetails",children:[P.jsx("span",{className:"conn-dot"}),"Verbunden",(We==null?void 0:We.voicePing)!=null&&P.jsxs("span",{className:"conn-ping",children:[We.voicePing,"ms"]})]})]})]}),P.jsxs("div",{className:"toolbar",children:[P.jsxs("div",{className:"cat-tabs",children:[P.jsxs("button",{className:`cat-tab ${x==="all"?"active":""}`,onClick:()=>{S("all"),N("")},children:["Alle",P.jsx("span",{className:"tab-count",children:r})]}),P.jsx("button",{className:`cat-tab ${x==="recent"?"active":""}`,onClick:()=>{S("recent"),N("")},children:"Neu hinzugefuegt"}),P.jsxs("button",{className:`cat-tab ${x==="favorites"?"active":""}`,onClick:()=>{S("favorites"),N("")},children:["Favoriten",an>0&&P.jsx("span",{className:"tab-count",children:an})]})]}),P.jsxs("div",{className:"search-wrap",children:[P.jsx("span",{className:"material-icons search-icon",children:"search"}),P.jsx("input",{className:"search-input",type:"text",placeholder:"Suchen...",value:C,onChange:he=>E(he.target.value)}),C&&P.jsx("button",{className:"search-clear",onClick:()=>E(""),children:P.jsx("span",{className:"material-icons",style:{fontSize:14},children:"close"})})]}),P.jsxs("div",{className:"url-import-wrap",children:[P.jsx("span",{className:"material-icons url-import-icon",children:pn(O)==="youtube"?"smart_display":pn(O)==="instagram"?"photo_camera":"link"}),P.jsx("input",{className:"url-import-input",type:"text",placeholder:"YouTube / Instagram / MP3-Link...",value:O,onChange:he=>U(he.target.value),onKeyDown:he=>{he.key==="Enter"&&dt()}}),O&&P.jsx("span",{className:`url-import-tag ${Yt(O)?"valid":"invalid"}`,children:pn(O)==="youtube"?"YT":pn(O)==="instagram"?"IG":pn(O)==="mp3"?"MP3":"?"}),P.jsx("button",{className:"url-import-btn",onClick:()=>{dt()},disabled:I||!!O&&!Yt(O),title:"Sound herunterladen",children:I?"Laedt...":"Download"})]}),P.jsx("div",{className:"toolbar-spacer"}),P.jsxs("div",{className:"volume-control",children:[P.jsx("span",{className:"material-icons vol-icon",onClick:()=>{const he=re>0?0:.5;Z(he),$e&&g7($e,he).catch(()=>{})},children:re===0?"volume_off":re<.5?"volume_down":"volume_up"}),P.jsx("input",{type:"range",className:"vol-slider",min:0,max:1,step:.01,value:re,onChange:he=>{const X=parseFloat(he.target.value);Z(X),$e&&(Ft.current&&clearTimeout(Ft.current),Ft.current=setTimeout(()=>{g7($e,X).catch(()=>{})},50))},style:{"--vol":`${Math.round(re*100)}%`}}),P.jsxs("span",{className:"vol-pct",children:[Math.round(re*100),"%"]})]}),P.jsxs("button",{className:"tb-btn random",onClick:Wn,title:"Zufaelliger Sound",children:[P.jsx("span",{className:"material-icons tb-icon",children:"shuffle"}),"Random"]}),P.jsxs("button",{className:`tb-btn party ${Fe?"active":""}`,onClick:$n,title:"Party Mode",children:[P.jsx("span",{className:"material-icons tb-icon",children:Fe?"celebration":"auto_awesome"}),Fe?"Party!":"Party"]}),P.jsxs("button",{className:"tb-btn stop",onClick:Vn,title:"Alle stoppen",children:[P.jsx("span",{className:"material-icons tb-icon",children:"stop"}),"Stop"]}),P.jsxs("div",{className:"size-control",title:"Button-Groesse",children:[P.jsx("span",{className:"material-icons sc-icon",children:"grid_view"}),P.jsx("input",{type:"range",className:"size-slider",min:80,max:160,value:Ve,onChange:he=>Ce(parseInt(he.target.value))})]}),P.jsx("div",{className:"theme-selector",children:VAe.map(he=>P.jsx("div",{className:`theme-dot ${ae===he.id?"active":""}`,style:{background:he.color},title:he.label,onClick:()=>Me(he.id)},he.id))})]}),P.jsxs("div",{className:"analytics-strip",children:[P.jsxs("div",{className:"analytics-card",children:[P.jsx("span",{className:"material-icons analytics-icon",children:"library_music"}),P.jsxs("div",{className:"analytics-copy",children:[P.jsx("span",{className:"analytics-label",children:"Sounds gesamt"}),P.jsx("strong",{className:"analytics-value",children:Ge})]})]}),P.jsxs("div",{className:"analytics-card analytics-wide",children:[P.jsx("span",{className:"material-icons analytics-icon",children:"leaderboard"}),P.jsxs("div",{className:"analytics-copy",children:[P.jsx("span",{className:"analytics-label",children:"Most Played"}),P.jsx("div",{className:"analytics-top-list",children:ce.length===0?P.jsx("span",{className:"analytics-muted",children:"Noch keine Plays"}):ce.map((he,X)=>P.jsxs("span",{className:"analytics-chip",children:[X+1,". ",he.name," (",he.count,")"]},he.relativePath))})]})]})]}),x==="all"&&mn.length>0&&P.jsx("div",{className:"category-strip",children:mn.map(he=>{const X=Er[he.key]||"#888",et=T===he.key;return P.jsxs("button",{className:`cat-chip ${et?"active":""}`,onClick:()=>N(et?"":he.key),style:et?{borderColor:X,color:X}:void 0,children:[P.jsx("span",{className:"cat-dot",style:{background:X}}),he.name.replace(/\s*\(\d+\)\s*$/,""),P.jsx("span",{className:"cat-count",children:he.count})]},he.key)})}),P.jsx("main",{className:"main",children:lr.length===0?P.jsxs("div",{className:"empty-state visible",children:[P.jsx("div",{className:"empty-emoji",children:x==="favorites"?"⭐":"🔇"}),P.jsx("div",{className:"empty-title",children:x==="favorites"?"Noch keine Favoriten":C?`Kein Sound fuer "${C}" gefunden`:"Keine Sounds vorhanden"}),P.jsx("div",{className:"empty-desc",children:x==="favorites"?"Klick den Stern auf einem Sound!":"Hier gibt's noch nichts zu hoeren."})]}):P.jsx("div",{className:"sound-grid",children:lr.map((he,X)=>{var hn;const et=he.relativePath??he.fileName,en=!!be[et],sn=ne===he.name,Tn=he.isRecent||((hn=he.badges)==null?void 0:hn.includes("new")),Rn=he.name.charAt(0).toUpperCase(),xi=Wi.has(X),K=he.folder&&Er[he.folder]||"var(--accent)";return P.jsxs("div",{className:`sound-card ${sn?"playing":""} ${xi?"has-initial":""}`,style:{animationDelay:`${Math.min(X*20,400)}ms`},onClick:Zt=>{const gr=Zt.currentTarget,ui=gr.getBoundingClientRect(),vr=document.createElement("div");vr.className="ripple";const Ps=Math.max(ui.width,ui.height);vr.style.width=vr.style.height=Ps+"px",vr.style.left=Zt.clientX-ui.left-Ps/2+"px",vr.style.top=Zt.clientY-ui.top-Ps/2+"px",gr.appendChild(vr),setTimeout(()=>vr.remove(),500),Je(he)},onContextMenu:Zt=>{Zt.preventDefault(),Zt.stopPropagation(),In({x:Math.min(Zt.clientX,window.innerWidth-170),y:Math.min(Zt.clientY,window.innerHeight-140),sound:he})},title:`${he.name}${he.folder?` (${he.folder})`:""}`,children:[Tn&&P.jsx("span",{className:"new-badge",children:"NEU"}),P.jsx("span",{className:`fav-star ${en?"active":""}`,onClick:Zt=>{Zt.stopPropagation(),Fn(et)},children:P.jsx("span",{className:"material-icons fav-icon",children:en?"star":"star_border"})}),xi&&P.jsx("span",{className:"sound-emoji",style:{color:K},children:Rn}),P.jsx("span",{className:"sound-name",children:he.name}),he.folder&&P.jsx("span",{className:"sound-duration",children:he.folder}),P.jsxs("div",{className:"playing-indicator",children:[P.jsx("div",{className:"wave-bar"}),P.jsx("div",{className:"wave-bar"}),P.jsx("div",{className:"wave-bar"}),P.jsx("div",{className:"wave-bar"})]})]},et)})})}),Jt&&P.jsxs("div",{className:"ctx-menu visible",style:{left:Jt.x,top:Jt.y},onClick:he=>he.stopPropagation(),children:[P.jsxs("div",{className:"ctx-item",onClick:()=>{Je(Jt.sound),In(null)},children:[P.jsx("span",{className:"material-icons ctx-icon",children:"play_arrow"}),"Abspielen"]}),P.jsxs("div",{className:"ctx-item",onClick:()=>{Fn(Jt.sound.relativePath??Jt.sound.fileName),In(null)},children:[P.jsx("span",{className:"material-icons ctx-icon",children:be[Jt.sound.relativePath??Jt.sound.fileName]?"star":"star_border"}),"Favorit"]}),Ut&&P.jsxs(P.Fragment,{children:[P.jsx("div",{className:"ctx-sep"}),P.jsxs("div",{className:"ctx-item danger",onClick:async()=>{const he=Jt.sound.relativePath??Jt.sound.fileName;if(!window.confirm(`Sound "${Jt.sound.name}" loeschen?`)){In(null);return}try{await GAe([he]),ot("Sound geloescht"),Bt(X=>X+1)}catch(X){ot((X==null?void 0:X.message)||"Loeschen fehlgeschlagen","error")}In(null)},children:[P.jsx("span",{className:"material-icons ctx-icon",children:"delete"}),"Loeschen"]})]})]}),Le&&(()=>{const he=We!=null&&We.connectedSince?Math.floor((Date.now()-new Date(We.connectedSince).getTime())/1e3):0,X=Math.floor(he/3600),et=Math.floor(he%3600/60),en=he%60,sn=X>0?`${X}h ${String(et).padStart(2,"0")}m ${String(en).padStart(2,"0")}s`:et>0?`${et}m ${String(en).padStart(2,"0")}s`:`${en}s`,Tn=Rn=>Rn==null?"var(--muted)":Rn<80?"var(--green)":Rn<150?"#f0a830":"#e04040";return P.jsx("div",{className:"conn-modal-overlay",onClick:()=>ct(!1),children:P.jsxs("div",{className:"conn-modal",onClick:Rn=>Rn.stopPropagation(),children:[P.jsxs("div",{className:"conn-modal-header",children:[P.jsx("span",{className:"material-icons",style:{fontSize:20,color:"var(--green)"},children:"cell_tower"}),P.jsx("span",{children:"Verbindungsdetails"}),P.jsx("button",{className:"conn-modal-close",onClick:()=>ct(!1),children:P.jsx("span",{className:"material-icons",children:"close"})})]}),P.jsxs("div",{className:"conn-modal-body",children:[P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Voice Ping"}),P.jsxs("span",{className:"conn-stat-value",children:[P.jsx("span",{className:"conn-ping-dot",style:{background:Tn((We==null?void 0:We.voicePing)??null)}}),(We==null?void 0:We.voicePing)!=null?`${We.voicePing} ms`:"---"]})]}),P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Gateway Ping"}),P.jsxs("span",{className:"conn-stat-value",children:[P.jsx("span",{className:"conn-ping-dot",style:{background:Tn((We==null?void 0:We.gatewayPing)??null)}}),We&&We.gatewayPing>=0?`${We.gatewayPing} ms`:"---"]})]}),P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Status"}),P.jsx("span",{className:"conn-stat-value",style:{color:(We==null?void 0:We.status)==="ready"?"var(--green)":"#f0a830"},children:(We==null?void 0:We.status)==="ready"?"Verbunden":(We==null?void 0:We.status)??"Warte auf Verbindung"})]}),P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Kanal"}),P.jsx("span",{className:"conn-stat-value",children:(We==null?void 0:We.channelName)||"---"})]}),P.jsxs("div",{className:"conn-stat",children:[P.jsx("span",{className:"conn-stat-label",children:"Verbunden seit"}),P.jsx("span",{className:"conn-stat-value",children:sn||"---"})]})]})]})})})(),Dt&&P.jsxs("div",{className:`toast ${Dt.type}`,children:[P.jsx("span",{className:"material-icons toast-icon",children:Dt.type==="error"?"error_outline":"check_circle"}),Dt.msg]}),Ke&&P.jsx("div",{className:"drop-overlay",children:P.jsxs("div",{className:"drop-zone",children:[P.jsx("span",{className:"material-icons drop-icon",children:"cloud_upload"}),P.jsx("div",{className:"drop-title",children:"MP3 & WAV hier ablegen"}),P.jsx("div",{className:"drop-sub",children:"Mehrere Dateien gleichzeitig moeglich"})]})}),_t&&fe.length>0&&P.jsxs("div",{className:"upload-queue",children:[P.jsxs("div",{className:"uq-header",children:[P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"upload"}),P.jsx("span",{children:fe.every(he=>he.status==="done"||he.status==="error")?`${fe.filter(he=>he.status==="done").length} von ${fe.length} hochgeladen`:`Lade hoch… (${fe.filter(he=>he.status==="done").length}/${fe.length})`}),P.jsx("button",{className:"uq-close",onClick:()=>{Gt(!1),$t([])},children:P.jsx("span",{className:"material-icons",style:{fontSize:14},children:"close"})})]}),P.jsx("div",{className:"uq-list",children:fe.map(he=>P.jsxs("div",{className:`uq-item uq-${he.status}`,children:[P.jsx("span",{className:"material-icons uq-file-icon",children:"audio_file"}),P.jsxs("div",{className:"uq-info",children:[P.jsx("div",{className:"uq-name",title:he.savedName??he.file.name,children:he.savedName??he.file.name}),P.jsxs("div",{className:"uq-size",children:[(he.file.size/1024).toFixed(0)," KB"]})]}),(he.status==="waiting"||he.status==="uploading")&&P.jsx("div",{className:"uq-progress-wrap",children:P.jsx("div",{className:"uq-progress-bar",style:{width:`${he.progress}%`}})}),P.jsx("span",{className:`material-icons uq-status-icon uq-status-${he.status}`,children:he.status==="done"?"check_circle":he.status==="error"?"error":he.status==="uploading"?"sync":"schedule"}),he.status==="error"&&P.jsx("div",{className:"uq-error",children:he.error})]},he.id))})]}),Ht.length>0&&P.jsx("div",{className:"dl-modal-overlay",onClick:()=>Ue==="naming"&&te(),children:P.jsxs("div",{className:"dl-modal",onClick:he=>he.stopPropagation(),children:[P.jsxs("div",{className:"dl-modal-header",children:[P.jsx("span",{className:"material-icons",style:{fontSize:20},children:"upload_file"}),P.jsxs("span",{children:[Ue==="naming"?"Sound benennen":Ue==="uploading"?"Wird hochgeladen...":"Gespeichert!",Ht.length>1&&` (${Ae+1}/${Ht.length})`]}),Ue==="naming"&&P.jsx("button",{className:"dl-modal-close",onClick:te,children:P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"close"})})]}),P.jsxs("div",{className:"dl-modal-body",children:[P.jsxs("div",{className:"dl-modal-url",children:[P.jsx("span",{className:"dl-modal-tag mp3",children:"Datei"}),P.jsx("span",{className:"dl-modal-url-text",title:(qe=Ht[Ae])==null?void 0:qe.name,children:(qt=Ht[Ae])==null?void 0:qt.name}),P.jsxs("span",{style:{marginLeft:"auto",opacity:.5,fontSize:12},children:[((((Qt=Ht[Ae])==null?void 0:Qt.size)??0)/1024).toFixed(0)," KB"]})]}),Ue==="naming"&&P.jsxs("div",{className:"dl-modal-field",children:[P.jsx("label",{className:"dl-modal-label",children:"Dateiname"}),P.jsxs("div",{className:"dl-modal-input-wrap",children:[P.jsx("input",{className:"dl-modal-input",type:"text",placeholder:"Dateiname eingeben...",value:xe,onChange:he=>Oe(he.target.value),onKeyDown:he=>{he.key==="Enter"&&A()},autoFocus:!0}),P.jsx("span",{className:"dl-modal-ext",children:".mp3"})]})]}),Ue==="uploading"&&P.jsxs("div",{className:"dl-modal-progress",children:[P.jsx("div",{className:"dl-modal-spinner"}),P.jsxs("span",{children:["Upload: ",we,"%"]})]}),Ue==="done"&&P.jsxs("div",{className:"dl-modal-success",children:[P.jsx("span",{className:"material-icons dl-modal-check",children:"check_circle"}),P.jsx("span",{children:"Erfolgreich hochgeladen!"})]})]}),Ue==="naming"&&P.jsxs("div",{className:"dl-modal-actions",children:[P.jsx("button",{className:"dl-modal-cancel",onClick:te,children:Ht.length>1?"Überspringen":"Abbrechen"}),P.jsxs("button",{className:"dl-modal-submit",onClick:()=>void A(),children:[P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"upload"}),"Hochladen"]})]})]})}),z&&P.jsx("div",{className:"dl-modal-overlay",onClick:()=>z.phase!=="downloading"&&G(null),children:P.jsxs("div",{className:"dl-modal",onClick:he=>he.stopPropagation(),children:[P.jsxs("div",{className:"dl-modal-header",children:[P.jsx("span",{className:"material-icons",style:{fontSize:20},children:z.type==="youtube"?"smart_display":z.type==="instagram"?"photo_camera":"audio_file"}),P.jsx("span",{children:z.phase==="input"?"Sound herunterladen":z.phase==="downloading"?"Wird heruntergeladen...":z.phase==="done"?"Fertig!":"Fehler"}),z.phase!=="downloading"&&P.jsx("button",{className:"dl-modal-close",onClick:()=>G(null),children:P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"close"})})]}),P.jsxs("div",{className:"dl-modal-body",children:[P.jsxs("div",{className:"dl-modal-url",children:[P.jsx("span",{className:`dl-modal-tag ${z.type??""}`,children:z.type==="youtube"?"YouTube":z.type==="instagram"?"Instagram":"MP3"}),P.jsx("span",{className:"dl-modal-url-text",title:z.url,children:z.url.length>60?z.url.slice(0,57)+"...":z.url})]}),z.phase==="input"&&P.jsxs("div",{className:"dl-modal-field",children:[P.jsx("label",{className:"dl-modal-label",children:"Dateiname"}),P.jsxs("div",{className:"dl-modal-input-wrap",children:[P.jsx("input",{className:"dl-modal-input",type:"text",placeholder:z.type==="mp3"?"Dateiname...":"Wird automatisch erkannt...",value:z.filename,onChange:he=>G(X=>X?{...X,filename:he.target.value}:null),onKeyDown:he=>{he.key==="Enter"&&Vt()},autoFocus:!0}),P.jsx("span",{className:"dl-modal-ext",children:".mp3"})]}),P.jsx("span",{className:"dl-modal-hint",children:"Leer lassen = automatischer Name"})]}),z.phase==="downloading"&&P.jsxs("div",{className:"dl-modal-progress",children:[P.jsx("div",{className:"dl-modal-spinner"}),P.jsx("span",{children:z.type==="youtube"||z.type==="instagram"?"Audio wird extrahiert...":"MP3 wird heruntergeladen..."})]}),z.phase==="done"&&P.jsxs("div",{className:"dl-modal-success",children:[P.jsx("span",{className:"material-icons dl-modal-check",children:"check_circle"}),P.jsxs("span",{children:["Gespeichert als ",P.jsx("b",{children:z.savedName})]})]}),z.phase==="error"&&P.jsxs("div",{className:"dl-modal-error",children:[P.jsx("span",{className:"material-icons",style:{color:"#e74c3c"},children:"error"}),P.jsx("span",{children:z.error})]})]}),z.phase==="input"&&P.jsxs("div",{className:"dl-modal-actions",children:[P.jsx("button",{className:"dl-modal-cancel",onClick:()=>G(null),children:"Abbrechen"}),P.jsxs("button",{className:"dl-modal-submit",onClick:()=>void Vt(),children:[P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"download"}),"Herunterladen"]})]}),z.phase==="error"&&P.jsxs("div",{className:"dl-modal-actions",children:[P.jsx("button",{className:"dl-modal-cancel",onClick:()=>G(null),children:"Schliessen"}),P.jsxs("button",{className:"dl-modal-submit",onClick:()=>G(he=>he?{...he,phase:"input",error:void 0}:null),children:[P.jsx("span",{className:"material-icons",style:{fontSize:16},children:"refresh"}),"Nochmal"]})]})]})})]})}const _7={IRON:"#6b6b6b",BRONZE:"#8c6239",SILVER:"#8c8c8c",GOLD:"#d4a017",PLATINUM:"#28b29e",EMERALD:"#1e9e5e",DIAMOND:"#576cce",MASTER:"#9d48e0",GRANDMASTER:"#e44c3e",CHALLENGER:"#f4c874"},HAe={SOLORANKED:"Ranked Solo",FLEXRANKED:"Ranked Flex",NORMAL:"Normal",ARAM:"ARAM",ARENA:"Arena",URF:"URF",BOT:"Co-op vs AI"},WAe="https://ddragon.leagueoflegends.com/cdn/15.5.1/img";function mm(i){return`${WAe}/champion/${i}.png`}function y7(i){const e=Math.floor((Date.now()-new Date(i).getTime())/1e3);return e<60?`${e}s`:e<3600?`${Math.floor(e/60)}m`:e<86400?`${Math.floor(e/3600)}h`:`${Math.floor(e/86400)}d`}function $Ae(i){const e=Math.floor(i/60),t=i%60;return`${e}:${String(t).padStart(2,"0")}`}function x7(i,e,t){return e===0?"Perfect":((i+t)/e).toFixed(2)}function b7(i,e){const t=i+e;return t>0?Math.round(i/t*100):0}function XAe(i,e){if(!i)return"Unranked";const t=["","I","II","III","IV"];return`${i.charAt(0)}${i.slice(1).toLowerCase()}${e?" "+(t[e]??e):""}`}function YAe({data:i}){var yt,Ht,pt,Ae;const[e,t]=se.useState(""),[n,r]=se.useState("EUW"),[s,a]=se.useState([]),[l,u]=se.useState(null),[h,m]=se.useState([]),[v,x]=se.useState(!1),[S,T]=se.useState(null),[N,C]=se.useState([]),[E,O]=se.useState(null),[U,I]=se.useState({}),[j,z]=se.useState(!1),[G,H]=se.useState(!1),[q,V]=se.useState(null),[Q,J]=se.useState("aram"),[ie,le]=se.useState("EUW"),[re,Z]=se.useState([]),[ne,de]=se.useState(!1),[be,Te]=se.useState(null),[ae,Me]=se.useState([]),[Ve,Ce]=se.useState(""),[Fe,tt]=se.useState(!1),je=se.useRef(null),Rt=se.useRef(null);se.useEffect(()=>{fetch("/api/lolstats/regions").then(k=>k.json()).then(a).catch(()=>{}),fetch("/api/lolstats/recent").then(k=>k.json()).then(C).catch(()=>{}),fetch("/api/lolstats/modes").then(k=>k.json()).then(Me).catch(()=>{})},[]),se.useEffect(()=>{Q&&(de(!0),Te(null),tt(!1),fetch(`/api/lolstats/tierlist?mode=${Q}®ion=${ie}`).then(k=>{if(!k.ok)throw new Error(`HTTP ${k.status}`);return k.json()}).then(k=>Z(k.champions??[])).catch(k=>Te(k.message)).finally(()=>de(!1)))},[Q,ie]),se.useEffect(()=>{i&&(i.recentSearches&&C(i.recentSearches),i.regions&&!s.length&&a(i.regions))},[i]);const Et=se.useCallback(async(k,xe,Oe)=>{H(!0);try{const Ue=`gameName=${encodeURIComponent(k)}&tagLine=${encodeURIComponent(xe)}®ion=${Oe}`,ee=await fetch(`/api/lolstats/renew?${Ue}`,{method:"POST"});if(ee.ok){const we=await ee.json();return we.last_updated_at&&V(we.last_updated_at),we.renewed??!1}}catch{}return H(!1),!1},[]),Ft=se.useCallback(async(k,xe,Oe,Ue=!1)=>{var We,Se;let ee=k??"",we=xe??"";const Re=Oe??n;if(!ee){const Le=e.split("#");ee=((We=Le[0])==null?void 0:We.trim())??"",we=((Se=Le[1])==null?void 0:Se.trim())??""}if(!ee||!we){T("Bitte im Format Name#Tag eingeben");return}x(!0),T(null),u(null),m([]),O(null),I({}),Rt.current={gameName:ee,tagLine:we,region:Re},Ue||Et(ee,we,Re).finally(()=>H(!1));try{const Le=`gameName=${encodeURIComponent(ee)}&tagLine=${encodeURIComponent(we)}®ion=${Re}`,[ct,Dt]=await Promise.all([fetch(`/api/lolstats/profile?${Le}`),fetch(`/api/lolstats/matches?${Le}&limit=10`)]);if(!ct.ok){const lt=await ct.json();throw new Error(lt.error??`Fehler ${ct.status}`)}const It=await ct.json();if(u(It),It.updated_at&&V(It.updated_at),Dt.ok){const lt=await Dt.json();m(Array.isArray(lt)?lt:[])}}catch(Le){T(Le.message)}x(!1)},[e,n,Et]),Ut=se.useCallback(async()=>{const k=Rt.current;if(!(!k||G)){H(!0);try{await Et(k.gameName,k.tagLine,k.region),await new Promise(xe=>setTimeout(xe,1500)),await Ft(k.gameName,k.tagLine,k.region,!0)}finally{H(!1)}}},[Et,Ft,G]),Ke=se.useCallback(async()=>{if(!(!l||j)){z(!0);try{const k=`gameName=${encodeURIComponent(l.game_name)}&tagLine=${encodeURIComponent(l.tagline)}®ion=${n}&limit=20`,xe=await fetch(`/api/lolstats/matches?${k}`);if(xe.ok){const Oe=await xe.json();m(Array.isArray(Oe)?Oe:[])}}catch{}z(!1)}},[l,n,j]),ht=se.useCallback(async k=>{var xe;if(E===k.id){O(null);return}if(O(k.id),!(((xe=k.participants)==null?void 0:xe.length)>=10||U[k.id]))try{const Oe=`region=${n}&createdAt=${encodeURIComponent(k.created_at)}`,Ue=await fetch(`/api/lolstats/match/${encodeURIComponent(k.id)}?${Oe}`);if(Ue.ok){const ee=await Ue.json();I(we=>({...we,[k.id]:ee}))}}catch{}},[E,U,n]),fe=se.useCallback(k=>{t(`${k.game_name}#${k.tag_line}`),r(k.region),Ft(k.game_name,k.tag_line,k.region)},[Ft]),$t=se.useCallback(k=>{var Oe,Ue,ee;if(!l)return((Oe=k.participants)==null?void 0:Oe[0])??null;const xe=l.game_name.toLowerCase();return((Ue=k.participants)==null?void 0:Ue.find(we=>{var Re,We;return((We=(Re=we.summoner)==null?void 0:Re.game_name)==null?void 0:We.toLowerCase())===xe}))??((ee=k.participants)==null?void 0:ee[0])??null},[l]),_t=k=>{var Se,Le,ct;const xe=$t(k);if(!xe)return null;const Oe=((Se=xe.stats)==null?void 0:Se.result)==="WIN",Ue=x7(xe.stats.kill,xe.stats.death,xe.stats.assist),ee=(xe.stats.minion_kill??0)+(xe.stats.neutral_minion_kill??0),we=k.game_length_second>0?(ee/(k.game_length_second/60)).toFixed(1):"0",Re=E===k.id,We=U[k.id]??(((Le=k.participants)==null?void 0:Le.length)>=10?k:null);return P.jsxs("div",{children:[P.jsxs("div",{className:`lol-match ${Oe?"win":"loss"}`,onClick:()=>ht(k),children:[P.jsx("div",{className:"lol-match-result",children:Oe?"W":"L"}),P.jsxs("div",{className:"lol-match-champ",children:[P.jsx("img",{src:mm(xe.champion_name),alt:xe.champion_name,title:xe.champion_name}),P.jsx("span",{className:"lol-match-champ-level",children:xe.stats.champion_level})]}),P.jsxs("div",{className:"lol-match-kda",children:[P.jsxs("div",{className:"lol-match-kda-nums",children:[xe.stats.kill,"/",xe.stats.death,"/",xe.stats.assist]}),P.jsxs("div",{className:`lol-match-kda-ratio ${Ue==="Perfect"?"perfect":Number(Ue)>=4?"great":""}`,children:[Ue," KDA"]})]}),P.jsxs("div",{className:"lol-match-stats",children:[P.jsxs("span",{children:[ee," CS (",we,"/m)"]}),P.jsxs("span",{children:[xe.stats.ward_place," wards"]})]}),P.jsx("div",{className:"lol-match-items",children:(xe.items_names??[]).slice(0,7).map((Dt,It)=>Dt?P.jsx("img",{src:mm("Aatrox"),alt:Dt,title:Dt,style:{background:"var(--bg-deep)"},onError:lt=>{lt.target.style.display="none"}},It):P.jsx("div",{className:"lol-match-item-empty"},It))}),P.jsxs("div",{className:"lol-match-meta",children:[P.jsx("div",{className:"lol-match-duration",children:$Ae(k.game_length_second)}),P.jsx("div",{className:"lol-match-queue",children:HAe[k.game_type]??k.game_type}),P.jsxs("div",{className:"lol-match-ago",children:[y7(k.created_at)," ago"]})]})]}),Re&&We&&P.jsx("div",{className:"lol-match-detail",children:Gt(We,(ct=xe.summoner)==null?void 0:ct.game_name)})]},k.id)},Gt=(k,xe)=>{var Re,We,Se,Le,ct;const Oe=((Re=k.participants)==null?void 0:Re.filter(Dt=>Dt.team_key==="BLUE"))??[],Ue=((We=k.participants)==null?void 0:We.filter(Dt=>Dt.team_key==="RED"))??[],ee=(ct=(Le=(Se=k.teams)==null?void 0:Se.find(Dt=>Dt.key==="BLUE"))==null?void 0:Le.game_stat)==null?void 0:ct.is_win,we=(Dt,It,lt)=>P.jsxs("div",{className:"lol-match-detail-team",children:[P.jsxs("div",{className:`lol-match-detail-team-header ${It?"win":"loss"}`,children:[lt," — ",It?"Victory":"Defeat"]}),Dt.map((jt,Jt)=>{var Bt,ot,Tt,Wt,Yt,pn,$e,St,Kt,wn,qn,Je;const In=((ot=(Bt=jt.summoner)==null?void 0:Bt.game_name)==null?void 0:ot.toLowerCase())===(xe==null?void 0:xe.toLowerCase()),me=(((Tt=jt.stats)==null?void 0:Tt.minion_kill)??0)+(((Wt=jt.stats)==null?void 0:Wt.neutral_minion_kill)??0);return P.jsxs("div",{className:`lol-detail-row ${In?"me":""}`,children:[P.jsx("img",{className:"lol-detail-champ",src:mm(jt.champion_name),alt:jt.champion_name}),P.jsx("span",{className:"lol-detail-name",title:`${(Yt=jt.summoner)==null?void 0:Yt.game_name}#${(pn=jt.summoner)==null?void 0:pn.tagline}`,children:(($e=jt.summoner)==null?void 0:$e.game_name)??jt.champion_name}),P.jsxs("span",{className:"lol-detail-kda",children:[(St=jt.stats)==null?void 0:St.kill,"/",(Kt=jt.stats)==null?void 0:Kt.death,"/",(wn=jt.stats)==null?void 0:wn.assist]}),P.jsxs("span",{className:"lol-detail-cs",children:[me," CS"]}),P.jsxs("span",{className:"lol-detail-dmg",children:[((((qn=jt.stats)==null?void 0:qn.total_damage_dealt_to_champions)??0)/1e3).toFixed(1),"k"]}),P.jsxs("span",{className:"lol-detail-gold",children:[((((Je=jt.stats)==null?void 0:Je.gold_earned)??0)/1e3).toFixed(1),"k"]})]},Jt)})]});return P.jsxs(P.Fragment,{children:[we(Oe,ee,"Blue Team"),we(Ue,ee===void 0?void 0:!ee,"Red Team")]})};return P.jsxs("div",{className:"lol-container",children:[P.jsxs("div",{className:"lol-search",children:[P.jsx("input",{ref:je,className:"lol-search-input",placeholder:"Summoner Name#Tag",value:e,onChange:k=>t(k.target.value),onKeyDown:k=>k.key==="Enter"&&Ft()}),P.jsx("select",{className:"lol-search-region",value:n,onChange:k=>r(k.target.value),children:s.map(k=>P.jsx("option",{value:k.code,children:k.code},k.code))}),P.jsx("button",{className:"lol-search-btn",onClick:()=>Ft(),disabled:v,children:v?"...":"Search"})]}),N.length>0&&P.jsx("div",{className:"lol-recent",children:N.map((k,xe)=>P.jsxs("button",{className:"lol-recent-chip",onClick:()=>fe(k),children:[k.profile_image_url&&P.jsx("img",{src:k.profile_image_url,alt:""}),k.game_name,"#",k.tag_line,k.tier&&P.jsx("span",{className:"lol-recent-tier",style:{color:_7[k.tier]},children:k.tier})]},xe))}),S&&P.jsx("div",{className:"lol-error",children:S}),v&&P.jsxs("div",{className:"lol-loading",children:[P.jsx("div",{className:"lol-spinner"}),"Lade Profil..."]}),l&&!v&&P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"lol-profile",children:[P.jsx("img",{className:"lol-profile-icon",src:l.profile_image_url,alt:""}),P.jsxs("div",{className:"lol-profile-info",children:[P.jsxs("h2",{children:[l.game_name,P.jsxs("span",{children:["#",l.tagline]})]}),P.jsxs("div",{className:"lol-profile-level",children:["Level ",l.level]}),((yt=l.ladder_rank)==null?void 0:yt.rank)&&P.jsxs("div",{className:"lol-profile-ladder",children:["Ladder Rank #",l.ladder_rank.rank.toLocaleString()," / ",(Ht=l.ladder_rank.total)==null?void 0:Ht.toLocaleString()]}),q&&P.jsxs("div",{className:"lol-profile-updated",children:["Updated ",y7(q)," ago"]})]}),P.jsxs("button",{className:`lol-update-btn ${G?"renewing":""}`,onClick:Ut,disabled:G,title:"Refresh data from Riot servers",children:[P.jsx("span",{className:"lol-update-icon",children:G?"⟳":"↻"}),G?"Updating...":"Update"]})]}),P.jsx("div",{className:"lol-ranked-row",children:(l.league_stats??[]).filter(k=>k.game_type==="SOLORANKED"||k.game_type==="FLEXRANKED").map(k=>{const xe=k.tier_info,Oe=!!(xe!=null&&xe.tier),Ue=_7[(xe==null?void 0:xe.tier)??""]??"var(--text-normal)";return P.jsxs("div",{className:`lol-ranked-card ${Oe?"has-rank":""}`,style:{"--tier-color":Ue},children:[P.jsx("div",{className:"lol-ranked-type",children:k.game_type==="SOLORANKED"?"Ranked Solo/Duo":"Ranked Flex"}),Oe?P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"lol-ranked-tier",style:{color:Ue},children:[XAe(xe.tier,xe.division),P.jsxs("span",{className:"lol-ranked-lp",children:[xe.lp," LP"]})]}),P.jsxs("div",{className:"lol-ranked-record",children:[k.win,"W ",k.lose,"L",P.jsxs("span",{className:"lol-ranked-wr",children:["(",b7(k.win??0,k.lose??0),"%)"]}),k.is_hot_streak&&P.jsx("span",{className:"lol-ranked-streak",children:"🔥"})]})]}):P.jsx("div",{className:"lol-ranked-tier",children:"Unranked"})]},k.game_type)})}),((Ae=(pt=l.most_champions)==null?void 0:pt.champion_stats)==null?void 0:Ae.length)>0&&P.jsxs(P.Fragment,{children:[P.jsx("div",{className:"lol-section-title",children:"Top Champions"}),P.jsx("div",{className:"lol-champs",children:l.most_champions.champion_stats.slice(0,7).map(k=>{const xe=b7(k.win,k.lose),Oe=k.play>0?x7(k.kill/k.play,k.death/k.play,k.assist/k.play):"0";return P.jsxs("div",{className:"lol-champ-card",children:[P.jsx("img",{className:"lol-champ-icon",src:mm(k.champion_name),alt:k.champion_name}),P.jsxs("div",{children:[P.jsx("div",{className:"lol-champ-name",children:k.champion_name}),P.jsxs("div",{className:"lol-champ-stats",children:[k.play," games · ",xe,"% WR"]}),P.jsxs("div",{className:"lol-champ-kda",children:[Oe," KDA"]})]})]},k.champion_name)})})]}),h.length>0&&P.jsxs(P.Fragment,{children:[P.jsx("div",{className:"lol-section-title",children:"Match History"}),P.jsx("div",{className:"lol-matches",children:h.map(k=>_t(k))}),h.length<20&&P.jsx("button",{className:"lol-load-more",onClick:Ke,disabled:j,children:j?"Laden...":"Mehr laden"})]})]}),!l&&!v&&!S&&P.jsxs("div",{className:"lol-empty",children:[P.jsx("div",{className:"lol-empty-icon",children:"⚔️"}),P.jsx("h3",{children:"League of Legends Stats"}),P.jsx("p",{children:"Gib einen Summoner Name#Tag ein und wähle die Region"})]}),P.jsxs("div",{className:"lol-tier-section",children:[P.jsx("div",{className:"lol-section-title",children:"Champion Tier List"}),P.jsxs("div",{className:"lol-tier-controls",children:[P.jsx("div",{className:"lol-tier-modes",children:ae.map(k=>P.jsx("button",{className:`lol-tier-mode-btn ${Q===k.key?"active":""}`,onClick:()=>J(k.key),children:k.label},k.key))}),P.jsx("select",{className:"lol-search-region",value:ie,onChange:k=>le(k.target.value),children:s.map(k=>P.jsx("option",{value:k.code,children:k.code},k.code))}),P.jsx("input",{className:"lol-tier-filter",placeholder:"Filter champion...",value:Ve,onChange:k=>Ce(k.target.value)})]}),ne&&P.jsxs("div",{className:"lol-loading",children:[P.jsx("div",{className:"lol-spinner"}),"Lade Tier List..."]}),be&&P.jsx("div",{className:"lol-error",children:be}),!ne&&!be&&re.length>0&&P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"lol-tier-table",children:[P.jsxs("div",{className:"lol-tier-header",children:[P.jsx("span",{className:"lol-tier-col-rank",children:"#"}),P.jsx("span",{className:"lol-tier-col-champ",children:"Champion"}),P.jsx("span",{className:"lol-tier-col-tier",children:"Tier"}),P.jsx("span",{className:"lol-tier-col-wr",children:Q==="arena"?"Win":"Win %"}),P.jsx("span",{className:"lol-tier-col-pr",children:"Pick %"}),Q!=="arena"&&P.jsx("span",{className:"lol-tier-col-br",children:"Ban %"}),P.jsx("span",{className:"lol-tier-col-kda",children:Q==="arena"?"Avg Place":"KDA"})]}),re.filter(k=>!Ve||k.champion_name.toLowerCase().includes(Ve.toLowerCase())).slice(0,Fe?void 0:50).map(k=>{var Oe,Ue;const xe=["OP","1","2","3","4","5"];return P.jsxs("div",{className:`lol-tier-row tier-${k.tier}`,children:[P.jsx("span",{className:"lol-tier-col-rank",children:k.rank}),P.jsxs("span",{className:"lol-tier-col-champ",children:[P.jsx("img",{src:mm(k.champion_name),alt:k.champion_name}),k.champion_name]}),P.jsx("span",{className:`lol-tier-col-tier tier-badge-${k.tier}`,children:xe[k.tier]??k.tier}),P.jsx("span",{className:"lol-tier-col-wr",children:k.win_rate!=null?`${(k.win_rate*100).toFixed(1)}%`:"-"}),P.jsxs("span",{className:"lol-tier-col-pr",children:[(k.pick_rate*100).toFixed(1),"%"]}),Q!=="arena"&&P.jsx("span",{className:"lol-tier-col-br",children:k.ban_rate!=null?`${(k.ban_rate*100).toFixed(1)}%`:"-"}),P.jsx("span",{className:"lol-tier-col-kda",children:Q==="arena"?((Oe=k.average_placement)==null?void 0:Oe.toFixed(1))??"-":((Ue=k.kda)==null?void 0:Ue.toFixed(2))??"-"})]},k.champion_id)})]}),!Fe&&re.length>50&&P.jsxs("button",{className:"lol-load-more",onClick:()=>tt(!0),children:["Alle ",re.length," Champions anzeigen"]})]})]})]})}const S7={iceServers:[{urls:"stun:stun.l.google.com:19302"},{urls:"stun:stun1.l.google.com:19302"}]};function VS(i){const e=Math.max(0,Math.floor((Date.now()-new Date(i).getTime())/1e3)),t=Math.floor(e/3600),n=Math.floor(e%3600/60),r=e%60;return t>0?`${t}:${String(n).padStart(2,"0")}:${String(r).padStart(2,"0")}`:`${n}:${String(r).padStart(2,"0")}`}const jS=[{label:"Niedrig · 4 Mbit · 60fps",fps:60,bitrate:4e6},{label:"Mittel · 8 Mbit · 60fps",fps:60,bitrate:8e6},{label:"Hoch · 14 Mbit · 60fps",fps:60,bitrate:14e6},{label:"Ultra · 25 Mbit · 60fps",fps:60,bitrate:25e6},{label:"Max · 50 Mbit · 165fps",fps:165,bitrate:5e7}];function QAe({data:i,isAdmin:e}){var Re,We;const[t,n]=se.useState([]),[r,s]=se.useState(()=>localStorage.getItem("streaming_name")||""),[a,l]=se.useState("Screen Share"),[u,h]=se.useState(""),[m,v]=se.useState(1),[x,S]=se.useState(null),[T,N]=se.useState(null),[C,E]=se.useState(null),[O,U]=se.useState(!1),[I,j]=se.useState(!1),[z,G]=se.useState(null),[,H]=se.useState(0),[q,V]=se.useState(null),[Q,J]=se.useState(null),ie=se.useRef(null),le=se.useRef(""),re=se.useRef(null),Z=se.useRef(null),ne=se.useRef(null),de=se.useRef(new Map),be=se.useRef(null),Te=se.useRef(null),ae=se.useRef(new Map),Me=se.useRef(null),Ve=se.useRef(1e3),Ce=se.useRef(!1),Fe=se.useRef(null),tt=se.useRef(jS[1]);se.useEffect(()=>{Ce.current=O},[O]),se.useEffect(()=>{Fe.current=z},[z]),se.useEffect(()=>{tt.current=jS[m]},[m]),se.useEffect(()=>{var Se,Le;(Le=(Se=window.electronAPI)==null?void 0:Se.setStreaming)==null||Le.call(Se,O||z!==null)},[O,z]),se.useEffect(()=>{if(!(t.length>0||O))return;const Le=setInterval(()=>H(ct=>ct+1),1e3);return()=>clearInterval(Le)},[t.length,O]),se.useEffect(()=>{i!=null&&i.streams&&n(i.streams)},[i]),se.useEffect(()=>{r&&localStorage.setItem("streaming_name",r)},[r]),se.useEffect(()=>{if(!q)return;const Se=()=>V(null);return document.addEventListener("click",Se),()=>document.removeEventListener("click",Se)},[q]);const je=se.useCallback(Se=>{var Le;((Le=ie.current)==null?void 0:Le.readyState)===WebSocket.OPEN&&ie.current.send(JSON.stringify(Se))},[]),Rt=se.useCallback((Se,Le,ct)=>{if(Se.remoteDescription)Se.addIceCandidate(new RTCIceCandidate(ct)).catch(()=>{});else{let Dt=ae.current.get(Le);Dt||(Dt=[],ae.current.set(Le,Dt)),Dt.push(ct)}},[]),Et=se.useCallback((Se,Le)=>{const ct=ae.current.get(Le);if(ct){for(const Dt of ct)Se.addIceCandidate(new RTCIceCandidate(Dt)).catch(()=>{});ae.current.delete(Le)}},[]),Ft=se.useCallback((Se,Le)=>{Se.srcObject=Le;const ct=Se.play();ct&&ct.catch(()=>{Se.muted=!0,Se.play().catch(()=>{})})},[]),Ut=se.useCallback(()=>{document.fullscreenElement&&document.exitFullscreen().catch(()=>{}),be.current&&(be.current.close(),be.current=null),Te.current=null,ne.current&&(ne.current.srcObject=null)},[]),Ke=se.useRef(()=>{});Ke.current=Se=>{var Le,ct,Dt;switch(Se.type){case"welcome":le.current=Se.clientId,Se.streams&&n(Se.streams);break;case"broadcast_started":E(Se.streamId),U(!0),Ce.current=!0,j(!1),(Le=window.electronAPI)!=null&&Le.showNotification&&window.electronAPI.showNotification("Stream gestartet","Dein Stream ist jetzt live!");break;case"stream_available":n(lt=>lt.some(jt=>jt.id===Se.streamId)?lt:[...lt,{id:Se.streamId,broadcasterName:Se.broadcasterName,title:Se.title,startedAt:new Date().toISOString(),viewerCount:0,hasPassword:!!Se.hasPassword}]);const It=`${Se.broadcasterName} streamt: ${Se.title}`;(ct=window.electronAPI)!=null&&ct.showNotification?window.electronAPI.showNotification("Neuer Stream",It):Notification.permission==="granted"&&new Notification("Neuer Stream",{body:It,icon:"/assets/icon.png"});break;case"stream_ended":n(lt=>lt.filter(jt=>jt.id!==Se.streamId)),((Dt=Fe.current)==null?void 0:Dt.streamId)===Se.streamId&&(Ut(),G(null));break;case"viewer_joined":{const lt=Se.viewerId,jt=de.current.get(lt);jt&&(jt.close(),de.current.delete(lt)),ae.current.delete(lt);const Jt=new RTCPeerConnection(S7);de.current.set(lt,Jt);const In=re.current;if(In)for(const Bt of In.getTracks())Jt.addTrack(Bt,In);Jt.onicecandidate=Bt=>{Bt.candidate&&je({type:"ice_candidate",targetId:lt,candidate:Bt.candidate.toJSON()})};const me=Jt.getSenders().find(Bt=>{var ot;return((ot=Bt.track)==null?void 0:ot.kind)==="video"});if(me){const Bt=me.getParameters();(!Bt.encodings||Bt.encodings.length===0)&&(Bt.encodings=[{}]),Bt.encodings[0].maxFramerate=tt.current.fps,Bt.encodings[0].maxBitrate=tt.current.bitrate,me.setParameters(Bt).catch(()=>{})}Jt.createOffer().then(Bt=>Jt.setLocalDescription(Bt)).then(()=>je({type:"offer",targetId:lt,sdp:Jt.localDescription})).catch(console.error);break}case"viewer_left":{const lt=de.current.get(Se.viewerId);lt&&(lt.close(),de.current.delete(Se.viewerId)),ae.current.delete(Se.viewerId);break}case"offer":{const lt=Se.fromId;be.current&&(be.current.close(),be.current=null),ae.current.delete(lt);const jt=new RTCPeerConnection(S7);be.current=jt,jt.ontrack=Jt=>{const In=Jt.streams[0];if(!In)return;Te.current=In;const me=ne.current;me&&Ft(me,In),G(Bt=>Bt&&{...Bt,phase:"connected"})},jt.onicecandidate=Jt=>{Jt.candidate&&je({type:"ice_candidate",targetId:lt,candidate:Jt.candidate.toJSON()})},jt.oniceconnectionstatechange=()=>{(jt.iceConnectionState==="failed"||jt.iceConnectionState==="disconnected")&&G(Jt=>Jt&&{...Jt,phase:"error",error:"Verbindung verloren"})},jt.setRemoteDescription(new RTCSessionDescription(Se.sdp)).then(()=>(Et(jt,lt),jt.createAnswer())).then(Jt=>jt.setLocalDescription(Jt)).then(()=>je({type:"answer",targetId:lt,sdp:jt.localDescription})).catch(console.error);break}case"answer":{const lt=de.current.get(Se.fromId);lt&<.setRemoteDescription(new RTCSessionDescription(Se.sdp)).then(()=>Et(lt,Se.fromId)).catch(console.error);break}case"ice_candidate":{if(!Se.candidate)break;const lt=de.current.get(Se.fromId);lt?Rt(lt,Se.fromId,Se.candidate):be.current&&Rt(be.current,Se.fromId,Se.candidate);break}case"error":Se.code==="WRONG_PASSWORD"?N(lt=>lt&&{...lt,error:Se.message}):S(Se.message),j(!1);break}};const ht=se.useCallback(()=>{if(ie.current&&ie.current.readyState===WebSocket.OPEN)return;const Se=location.protocol==="https:"?"wss":"ws",Le=new WebSocket(`${Se}://${location.host}/ws/streaming`);ie.current=Le,Le.onopen=()=>{Ve.current=1e3},Le.onmessage=ct=>{let Dt;try{Dt=JSON.parse(ct.data)}catch{return}Ke.current(Dt)},Le.onclose=()=>{ie.current=null,Me.current=setTimeout(()=>{Ve.current=Math.min(Ve.current*2,1e4),ht()},Ve.current)},Le.onerror=()=>{Le.close()}},[]);se.useEffect(()=>(ht(),()=>{Me.current&&clearTimeout(Me.current)}),[ht]);const fe=se.useCallback(async()=>{var Se,Le;if(!r.trim()){S("Bitte gib einen Namen ein.");return}if(!((Se=navigator.mediaDevices)!=null&&Se.getDisplayMedia)){S("Dein Browser unterstützt keine Bildschirmfreigabe.");return}S(null),j(!0);try{const ct=tt.current,Dt=await navigator.mediaDevices.getDisplayMedia({video:{frameRate:{ideal:ct.fps}},audio:!0});re.current=Dt,Z.current&&(Z.current.srcObject=Dt),(Le=Dt.getVideoTracks()[0])==null||Le.addEventListener("ended",()=>{$t()}),ht();const It=()=>{var lt;((lt=ie.current)==null?void 0:lt.readyState)===WebSocket.OPEN?je({type:"start_broadcast",name:r.trim(),title:a.trim()||"Screen Share",password:u.trim()||void 0}):setTimeout(It,100)};It()}catch(ct){j(!1),ct.name==="NotAllowedError"?S("Bildschirmfreigabe wurde abgelehnt."):S(`Fehler: ${ct.message}`)}},[r,a,u,ht,je]),$t=se.useCallback(()=>{var Se;je({type:"stop_broadcast"}),(Se=re.current)==null||Se.getTracks().forEach(Le=>Le.stop()),re.current=null,Z.current&&(Z.current.srcObject=null);for(const Le of de.current.values())Le.close();de.current.clear(),U(!1),Ce.current=!1,E(null),h("")},[je]),_t=se.useCallback(Se=>{S(null),G({streamId:Se,phase:"connecting"}),ht();const Le=()=>{var ct;((ct=ie.current)==null?void 0:ct.readyState)===WebSocket.OPEN?je({type:"join_viewer",name:r.trim()||"Viewer",streamId:Se}):setTimeout(Le,100)};Le()},[r,ht,je]),Gt=se.useCallback(Se=>{Se.hasPassword?N({streamId:Se.id,streamTitle:Se.title,broadcasterName:Se.broadcasterName,password:"",error:null}):_t(Se.id)},[_t]),yt=se.useCallback(()=>{if(!T)return;if(!T.password.trim()){N(Dt=>Dt&&{...Dt,error:"Passwort eingeben."});return}const{streamId:Se,password:Le}=T;N(null),S(null),G({streamId:Se,phase:"connecting"}),ht();const ct=()=>{var Dt;((Dt=ie.current)==null?void 0:Dt.readyState)===WebSocket.OPEN?je({type:"join_viewer",name:r.trim()||"Viewer",streamId:Se,password:Le.trim()}):setTimeout(ct,100)};ct()},[T,r,ht,je]),Ht=se.useCallback(()=>{je({type:"leave_viewer"}),Ut(),G(null)},[Ut,je]);se.useEffect(()=>{const Se=ct=>{(Ce.current||Fe.current)&&ct.preventDefault()},Le=()=>{le.current&&navigator.sendBeacon("/api/streaming/disconnect",JSON.stringify({clientId:le.current}))};return window.addEventListener("beforeunload",Se),window.addEventListener("pagehide",Le),()=>{window.removeEventListener("beforeunload",Se),window.removeEventListener("pagehide",Le)}},[]);const pt=se.useRef(null),[Ae,k]=se.useState(!1),xe=se.useCallback(()=>{const Se=pt.current;Se&&(document.fullscreenElement?document.exitFullscreen().catch(()=>{}):Se.requestFullscreen().catch(()=>{}))},[]);se.useEffect(()=>{const Se=()=>k(!!document.fullscreenElement);return document.addEventListener("fullscreenchange",Se),()=>document.removeEventListener("fullscreenchange",Se)},[]),se.useEffect(()=>()=>{var Se;(Se=re.current)==null||Se.getTracks().forEach(Le=>Le.stop());for(const Le of de.current.values())Le.close();be.current&&be.current.close(),ie.current&&ie.current.close(),Me.current&&clearTimeout(Me.current)},[]),se.useEffect(()=>{z&&Te.current&&ne.current&&!ne.current.srcObject&&Ft(ne.current,Te.current)},[z,Ft]);const Oe=se.useRef(null);se.useEffect(()=>{const Le=new URLSearchParams(location.search).get("viewStream");if(Le){Oe.current=Le;const ct=new URL(location.href);ct.searchParams.delete("viewStream"),window.history.replaceState({},"",ct.toString())}},[]),se.useEffect(()=>{const Se=Oe.current;if(!Se||t.length===0)return;const Le=t.find(ct=>ct.id===Se);Le&&(Oe.current=null,Gt(Le))},[t,Gt]);const Ue=se.useCallback(Se=>{const Le=new URL(location.href);return Le.searchParams.set("viewStream",Se),Le.hash="",Le.toString()},[]),ee=se.useCallback(Se=>{navigator.clipboard.writeText(Ue(Se)).then(()=>{J(Se),setTimeout(()=>J(null),2e3)}).catch(()=>{})},[Ue]),we=se.useCallback(Se=>{window.open(Ue(Se),"_blank","noopener"),V(null)},[Ue]);if(z){const Se=t.find(Le=>Le.id===z.streamId);return P.jsxs("div",{className:"stream-viewer-overlay",ref:pt,children:[P.jsxs("div",{className:"stream-viewer-header",children:[P.jsxs("div",{className:"stream-viewer-header-left",children:[P.jsxs("span",{className:"stream-live-badge",children:[P.jsx("span",{className:"stream-live-dot"})," LIVE"]}),P.jsxs("div",{children:[P.jsx("div",{className:"stream-viewer-title",children:(Se==null?void 0:Se.title)||"Stream"}),P.jsxs("div",{className:"stream-viewer-subtitle",children:[(Se==null?void 0:Se.broadcasterName)||"..."," ",Se?` · ${Se.viewerCount} Zuschauer`:""]})]})]}),P.jsxs("div",{className:"stream-viewer-header-right",children:[P.jsx("button",{className:"stream-viewer-fullscreen",onClick:xe,title:Ae?"Vollbild verlassen":"Vollbild",children:Ae?"✖":"⛶"}),P.jsx("button",{className:"stream-viewer-close",onClick:Ht,children:"Verlassen"})]})]}),P.jsxs("div",{className:"stream-viewer-video",children:[z.phase==="connecting"?P.jsxs("div",{className:"stream-viewer-connecting",children:[P.jsx("div",{className:"stream-viewer-spinner"}),"Verbindung wird hergestellt..."]}):z.phase==="error"?P.jsxs("div",{className:"stream-viewer-connecting",children:[z.error||"Verbindungsfehler",P.jsx("button",{className:"stream-btn",onClick:Ht,children:"Zurück"})]}):null,P.jsx("video",{ref:ne,autoPlay:!0,playsInline:!0,style:z.phase==="connected"?{}:{display:"none"}})]})]})}return P.jsxs("div",{className:"stream-container",children:[x&&P.jsxs("div",{className:"stream-error",children:[x,P.jsx("button",{className:"stream-error-dismiss",onClick:()=>S(null),children:"×"})]}),P.jsxs("div",{className:"stream-topbar",children:[P.jsxs("label",{className:"stream-field",children:[P.jsx("span",{className:"stream-field-label",children:"Name"}),P.jsx("input",{className:"stream-input stream-input-name",placeholder:"Dein Name",value:r,onChange:Se=>s(Se.target.value),disabled:O})]}),P.jsxs("label",{className:"stream-field stream-field-grow",children:[P.jsx("span",{className:"stream-field-label",children:"Titel"}),P.jsx("input",{className:"stream-input stream-input-title",placeholder:"Stream-Titel",value:a,onChange:Se=>l(Se.target.value),disabled:O})]}),P.jsxs("label",{className:"stream-field",children:[P.jsx("span",{className:"stream-field-label",children:"Passwort"}),P.jsx("input",{className:"stream-input stream-input-password",type:"password",placeholder:"optional",value:u,onChange:Se=>h(Se.target.value),disabled:O})]}),P.jsxs("label",{className:"stream-field",children:[P.jsxs("span",{className:"stream-field-label",children:["Qualit","ä","t"]}),P.jsx("select",{className:"stream-select-quality",value:m,onChange:Se=>v(Number(Se.target.value)),disabled:O,children:jS.map((Se,Le)=>P.jsx("option",{value:Le,children:Se.label},Se.label))})]}),O?P.jsxs("button",{className:"stream-btn stream-btn-stop",onClick:$t,children:["⏹"," Stream beenden"]}):P.jsx("button",{className:"stream-btn",onClick:fe,disabled:I,children:I?"Starte...":"🖥️ Stream starten"})]}),t.length===0&&!O?P.jsxs("div",{className:"stream-empty",children:[P.jsx("div",{className:"stream-empty-icon",children:"📺"}),P.jsx("h3",{children:"Keine aktiven Streams"}),P.jsx("p",{children:"Starte einen Stream, um deinen Bildschirm zu teilen."})]}):P.jsxs("div",{className:"stream-grid",children:[O&&P.jsxs("div",{className:"stream-tile own broadcasting",children:[P.jsxs("div",{className:"stream-tile-preview",children:[P.jsx("video",{ref:Z,autoPlay:!0,playsInline:!0,muted:!0}),P.jsxs("span",{className:"stream-live-badge",children:[P.jsx("span",{className:"stream-live-dot"})," LIVE"]}),P.jsxs("span",{className:"stream-tile-viewers",children:["👥"," ",((Re=t.find(Se=>Se.id===C))==null?void 0:Re.viewerCount)??0]})]}),P.jsxs("div",{className:"stream-tile-info",children:[P.jsxs("div",{className:"stream-tile-meta",children:[P.jsxs("div",{className:"stream-tile-name",children:[r," (Du)"]}),P.jsx("div",{className:"stream-tile-title",children:a})]}),P.jsx("span",{className:"stream-tile-time",children:C&&((We=t.find(Se=>Se.id===C))!=null&&We.startedAt)?VS(t.find(Se=>Se.id===C).startedAt):"0:00"})]})]}),t.filter(Se=>Se.id!==C).map(Se=>P.jsxs("div",{className:"stream-tile",onClick:()=>Gt(Se),children:[P.jsxs("div",{className:"stream-tile-preview",children:[P.jsx("span",{className:"stream-tile-icon",children:"🖥️"}),P.jsxs("span",{className:"stream-live-badge",children:[P.jsx("span",{className:"stream-live-dot"})," LIVE"]}),P.jsxs("span",{className:"stream-tile-viewers",children:["👥"," ",Se.viewerCount]}),Se.hasPassword&&P.jsx("span",{className:"stream-tile-lock",children:"🔒"})]}),P.jsxs("div",{className:"stream-tile-info",children:[P.jsxs("div",{className:"stream-tile-meta",children:[P.jsx("div",{className:"stream-tile-name",children:Se.broadcasterName}),P.jsx("div",{className:"stream-tile-title",children:Se.title})]}),P.jsx("span",{className:"stream-tile-time",children:VS(Se.startedAt)}),P.jsxs("div",{className:"stream-tile-menu-wrap",children:[P.jsx("button",{className:"stream-tile-menu",onClick:Le=>{Le.stopPropagation(),V(q===Se.id?null:Se.id)},children:"⋮"}),q===Se.id&&P.jsxs("div",{className:"stream-tile-dropdown",onClick:Le=>Le.stopPropagation(),children:[P.jsxs("div",{className:"stream-tile-dropdown-header",children:[P.jsx("div",{className:"stream-tile-dropdown-name",children:Se.broadcasterName}),P.jsx("div",{className:"stream-tile-dropdown-title",children:Se.title}),P.jsxs("div",{className:"stream-tile-dropdown-detail",children:["👥"," ",Se.viewerCount," Zuschauer · ",VS(Se.startedAt)]})]}),P.jsx("div",{className:"stream-tile-dropdown-divider"}),P.jsxs("button",{className:"stream-tile-dropdown-item",onClick:()=>we(Se.id),children:["🗗"," In neuem Fenster öffnen"]}),P.jsx("button",{className:"stream-tile-dropdown-item",onClick:()=>{ee(Se.id),V(null)},children:Q===Se.id?"✅ Kopiert!":"🔗 Link teilen"})]})]})]})]},Se.id))]}),T&&P.jsx("div",{className:"stream-pw-overlay",onClick:()=>N(null),children:P.jsxs("div",{className:"stream-pw-modal",onClick:Se=>Se.stopPropagation(),children:[P.jsx("h3",{children:T.broadcasterName}),P.jsx("p",{children:T.streamTitle}),T.error&&P.jsx("div",{className:"stream-pw-modal-error",children:T.error}),P.jsx("input",{className:"stream-input",type:"password",placeholder:"Stream-Passwort",value:T.password,onChange:Se=>N(Le=>Le&&{...Le,password:Se.target.value,error:null}),onKeyDown:Se=>{Se.key==="Enter"&&yt()},autoFocus:!0}),P.jsxs("div",{className:"stream-pw-actions",children:[P.jsx("button",{className:"stream-pw-cancel",onClick:()=>N(null),children:"Abbrechen"}),P.jsx("button",{className:"stream-btn",onClick:yt,children:"Beitreten"})]})]})})]})}function w7(i){const e=Math.floor(i),t=Math.floor(e/3600),n=Math.floor(e%3600/60),r=e%60;return t>0?`${t}:${String(n).padStart(2,"0")}:${String(r).padStart(2,"0")}`:`${n}:${String(r).padStart(2,"0")}`}function KAe(i){const e=i.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/);if(e)return{type:"youtube",videoId:e[1]};const t=i.match(/(?:dailymotion\.com\/video\/|dai\.ly\/)([a-zA-Z0-9]+)/);return t?{type:"dailymotion",videoId:t[1]}:/\.(mp4|webm|ogg)(\?|$)/i.test(i)||i.startsWith("http")?{type:"direct",url:i}:null}function ZAe({data:i}){var pn;const[e,t]=se.useState([]),[n,r]=se.useState(()=>localStorage.getItem("wt_name")||""),[s,a]=se.useState(""),[l,u]=se.useState(""),[h,m]=se.useState(null),[v,x]=se.useState(null),[S,T]=se.useState(null),[N,C]=se.useState(""),[E,O]=se.useState(()=>{const $e=localStorage.getItem("wt_volume");return $e?parseFloat($e):1}),[U,I]=se.useState(!1),[j,z]=se.useState(0),[G,H]=se.useState(0),[q,V]=se.useState(null),[Q,J]=se.useState(!1),[ie,le]=se.useState([]),[re,Z]=se.useState(""),[ne,de]=se.useState(null),[be,Te]=se.useState("synced"),[ae,Me]=se.useState(!0),[Ve,Ce]=se.useState(()=>localStorage.getItem("wt_yt_quality")||"hd1080"),Fe=se.useRef(null),tt=se.useRef(""),je=se.useRef(null),Rt=se.useRef(1e3),Et=se.useRef(null),Ft=se.useRef(null),Ut=se.useRef(null),Ke=se.useRef(null),ht=se.useRef(null),fe=se.useRef(null),$t=se.useRef(!1),_t=se.useRef(!1),Gt=se.useRef(null),yt=se.useRef(null),Ht=se.useRef(Ve),pt=se.useRef(null),Ae=se.useRef(!1),k=se.useRef(0),xe=se.useRef(0);se.useEffect(()=>{Et.current=h},[h]);const Oe=h!=null&&tt.current===h.hostId;se.useEffect(()=>{Ht.current=Ve,localStorage.setItem("wt_yt_quality",Ve),Ut.current&&typeof Ut.current.setPlaybackQuality=="function"&&Ut.current.setPlaybackQuality(Ve)},[Ve]),se.useEffect(()=>{i!=null&&i.rooms&&t(i.rooms)},[i]),se.useEffect(()=>{var $e;($e=yt.current)==null||$e.scrollIntoView({behavior:"smooth"})},[ie]),se.useEffect(()=>{const St=new URLSearchParams(window.location.search).get("wt");if(St&&n.trim()){const Kt=setTimeout(()=>ct(St),1500);return()=>clearTimeout(Kt)}},[]),se.useEffect(()=>{n&&localStorage.setItem("wt_name",n)},[n]),se.useEffect(()=>{var $e;localStorage.setItem("wt_volume",String(E)),Ut.current&&typeof Ut.current.setVolume=="function"&&Ut.current.setVolume(E*100),Ke.current&&(Ke.current.volume=E),($e=pt.current)!=null&&$e.contentWindow&&fe.current==="dailymotion"&&pt.current.contentWindow.postMessage(`volume?volume=${E}`,"https://www.dailymotion.com")},[E]),se.useEffect(()=>{if(window.YT){$t.current=!0;return}const $e=document.createElement("script");$e.src="https://www.youtube.com/iframe_api",document.head.appendChild($e);const St=window.onYouTubeIframeAPIReady;window.onYouTubeIframeAPIReady=()=>{$t.current=!0,St&&St()}},[]);const Ue=se.useCallback($e=>{var St;((St=Fe.current)==null?void 0:St.readyState)===WebSocket.OPEN&&Fe.current.send(JSON.stringify($e))},[]),ee=se.useCallback(()=>fe.current==="youtube"&&Ut.current&&typeof Ut.current.getCurrentTime=="function"?Ut.current.getCurrentTime():fe.current==="direct"&&Ke.current?Ke.current.currentTime:fe.current==="dailymotion"?k.current:null,[]);se.useCallback(()=>fe.current==="youtube"&&Ut.current&&typeof Ut.current.getDuration=="function"?Ut.current.getDuration()||0:fe.current==="direct"&&Ke.current?Ke.current.duration||0:fe.current==="dailymotion"?xe.current:0,[]);const we=se.useCallback(()=>{if(Ut.current){try{Ut.current.destroy()}catch{}Ut.current=null}Ke.current&&(Ke.current.pause(),Ke.current.removeAttribute("src"),Ke.current.load()),pt.current&&(pt.current.src="",Ae.current=!1,k.current=0,xe.current=0),fe.current=null,Gt.current&&(clearInterval(Gt.current),Gt.current=null)},[]),Re=se.useCallback($e=>{we(),V(null);const St=KAe($e);if(St)if(St.type==="youtube"){if(fe.current="youtube",!$t.current||!ht.current)return;const Kt=ht.current,wn=document.createElement("div");wn.id="wt-yt-player-"+Date.now(),Kt.innerHTML="",Kt.appendChild(wn),Ut.current=new window.YT.Player(wn.id,{videoId:St.videoId,playerVars:{autoplay:1,controls:0,modestbranding:1,rel:0},events:{onReady:qn=>{qn.target.setVolume(E*100),qn.target.setPlaybackQuality(Ht.current),z(qn.target.getDuration()||0),Gt.current=setInterval(()=>{Ut.current&&typeof Ut.current.getCurrentTime=="function"&&(H(Ut.current.getCurrentTime()),z(Ut.current.getDuration()||0))},500)},onStateChange:qn=>{if(qn.data===window.YT.PlayerState.ENDED){const Je=Et.current;Je&&tt.current===Je.hostId&&Ue({type:"skip"})}},onError:qn=>{const Je=qn.data;V(Je===101||Je===150?"Embedding deaktiviert — Video kann nur auf YouTube angesehen werden.":Je===100?"Video nicht gefunden oder entfernt.":"Wiedergabefehler — Video wird übersprungen."),setTimeout(()=>{const dt=Et.current;dt&&tt.current===dt.hostId&&Ue({type:"skip"})},3e3)}}})}else St.type==="dailymotion"?(fe.current="dailymotion",pt.current&&(pt.current.src=`https://www.dailymotion.com/embed/video/${St.videoId}?api=postMessage&autoplay=1&controls=0&mute=0&queue-enable=0`)):(fe.current="direct",Ke.current&&(Ke.current.src=St.url,Ke.current.volume=E,Ke.current.play().catch(()=>{})))},[we,E,Ue]);se.useEffect(()=>{const $e=Ke.current;if(!$e)return;const St=()=>{const wn=Et.current;wn&&tt.current===wn.hostId&&Ue({type:"skip"})},Kt=()=>{H($e.currentTime),z($e.duration||0)};return $e.addEventListener("ended",St),$e.addEventListener("timeupdate",Kt),()=>{$e.removeEventListener("ended",St),$e.removeEventListener("timeupdate",Kt)}},[Ue]),se.useEffect(()=>{const $e=St=>{var Je;if(St.origin!=="https://www.dailymotion.com"||typeof St.data!="string")return;const Kt=new URLSearchParams(St.data),wn=Kt.get("method"),qn=Kt.get("value");if(wn==="timeupdate"&&qn){const dt=parseFloat(qn);k.current=dt,H(dt)}else if(wn==="durationchange"&&qn){const dt=parseFloat(qn);xe.current=dt,z(dt)}else if(wn==="ended"){const dt=Et.current;dt&&tt.current===dt.hostId&&Ue({type:"skip"})}else wn==="apiready"&&(Ae.current=!0,(Je=pt.current)!=null&&Je.contentWindow&&pt.current.contentWindow.postMessage(`volume?volume=${E}`,"https://www.dailymotion.com"))};return window.addEventListener("message",$e),()=>window.removeEventListener("message",$e)},[Ue,E]);const We=se.useRef(()=>{});We.current=$e=>{var St,Kt,wn,qn,Je,dt,Vt,xt,A,te,Vn,Wn,$n,dn,Fn,lr;switch($e.type){case"welcome":tt.current=$e.clientId,$e.rooms&&t($e.rooms);break;case"room_created":{const an=$e.room;m({id:an.id,name:an.name,hostId:an.hostId,members:an.members||[],currentVideo:an.currentVideo||null,playing:an.playing||!1,currentTime:an.currentTime||0,queue:an.queue||[]});break}case"room_joined":{const an=$e.room;m({id:an.id,name:an.name,hostId:an.hostId,members:an.members||[],currentVideo:an.currentVideo||null,playing:an.playing||!1,currentTime:an.currentTime||0,queue:an.queue||[]}),(St=an.currentVideo)!=null&&St.url&&setTimeout(()=>Re(an.currentVideo.url),100);break}case"playback_state":{const an=Et.current;if(!an)break;const mn=$e.currentVideo,Er=(Kt=an.currentVideo)==null?void 0:Kt.url;if(mn!=null&&mn.url&&mn.url!==Er?Re(mn.url):!mn&&Er&&we(),fe.current==="youtube"&&Ut.current){const Wi=(qn=(wn=Ut.current).getPlayerState)==null?void 0:qn.call(wn);$e.playing&&Wi!==((dt=(Je=window.YT)==null?void 0:Je.PlayerState)==null?void 0:dt.PLAYING)?(xt=(Vt=Ut.current).playVideo)==null||xt.call(Vt):!$e.playing&&Wi===((te=(A=window.YT)==null?void 0:A.PlayerState)==null?void 0:te.PLAYING)&&((Wn=(Vn=Ut.current).pauseVideo)==null||Wn.call(Vn))}else fe.current==="direct"&&Ke.current?$e.playing&&Ke.current.paused?Ke.current.play().catch(()=>{}):!$e.playing&&!Ke.current.paused&&Ke.current.pause():fe.current==="dailymotion"&&(($n=pt.current)!=null&&$n.contentWindow)&&($e.playing?pt.current.contentWindow.postMessage("play","https://www.dailymotion.com"):pt.current.contentWindow.postMessage("pause","https://www.dailymotion.com"));if($e.currentTime!==void 0&&!_t.current){const Wi=ee();Wi!==null&&Math.abs(Wi-$e.currentTime)>2&&(fe.current==="youtube"&&Ut.current?(Fn=(dn=Ut.current).seekTo)==null||Fn.call(dn,$e.currentTime,!0):fe.current==="direct"&&Ke.current?Ke.current.currentTime=$e.currentTime:fe.current==="dailymotion"&&((lr=pt.current)!=null&&lr.contentWindow)&&pt.current.contentWindow.postMessage(`seek?to=${$e.currentTime}`,"https://www.dailymotion.com"))}if($e.currentTime!==void 0){const Wi=ee();if(Wi!==null){const No=Math.abs(Wi-$e.currentTime);No<1.5?Te("synced"):No<5?Te("drifting"):Te("desynced")}}m(Wi=>Wi&&{...Wi,currentVideo:mn||null,playing:$e.playing,currentTime:$e.currentTime??Wi.currentTime});break}case"queue_updated":m(an=>an&&{...an,queue:$e.queue});break;case"members_updated":m(an=>an&&{...an,members:$e.members,hostId:$e.hostId});break;case"vote_updated":de($e.votes);break;case"chat":le(an=>{const mn=[...an,{sender:$e.sender,text:$e.text,timestamp:$e.timestamp}];return mn.length>100?mn.slice(-100):mn});break;case"chat_history":le($e.messages||[]);break;case"error":$e.code==="WRONG_PASSWORD"?x(an=>an&&{...an,error:$e.message}):T($e.message);break}};const Se=se.useCallback(()=>{if(Fe.current&&(Fe.current.readyState===WebSocket.OPEN||Fe.current.readyState===WebSocket.CONNECTING))return;const $e=location.protocol==="https:"?"wss":"ws",St=new WebSocket(`${$e}://${location.host}/ws/watch-together`);Fe.current=St,St.onopen=()=>{Rt.current=1e3},St.onmessage=Kt=>{let wn;try{wn=JSON.parse(Kt.data)}catch{return}We.current(wn)},St.onclose=()=>{Fe.current===St&&(Fe.current=null),Et.current&&(je.current=setTimeout(()=>{Rt.current=Math.min(Rt.current*2,1e4),Se()},Rt.current))},St.onerror=()=>{St.close()}},[]),Le=se.useCallback(()=>{if(!n.trim()){T("Bitte gib einen Namen ein.");return}if(!s.trim()){T("Bitte gib einen Raumnamen ein.");return}T(null),Se();const $e=Date.now(),St=()=>{var Kt;((Kt=Fe.current)==null?void 0:Kt.readyState)===WebSocket.OPEN?Ue({type:"create_room",name:s.trim(),userName:n.trim(),password:l.trim()||void 0}):Date.now()-$e>1e4?T("Verbindung zum Server fehlgeschlagen."):setTimeout(St,100)};St()},[n,s,l,Se,Ue]),ct=se.useCallback(($e,St)=>{if(!n.trim()){T("Bitte gib einen Namen ein.");return}T(null),Se();const Kt=Date.now(),wn=()=>{var qn;((qn=Fe.current)==null?void 0:qn.readyState)===WebSocket.OPEN?Ue({type:"join_room",userName:n.trim(),roomId:$e,password:(St==null?void 0:St.trim())||void 0}):Date.now()-Kt>1e4?T("Verbindung zum Server fehlgeschlagen."):setTimeout(wn,100)};wn()},[n,Se,Ue]),Dt=se.useCallback(()=>{Ue({type:"leave_room"}),we(),m(null),C(""),z(0),H(0),le([]),de(null),Te("synced")},[Ue,we]),It=se.useCallback(async()=>{const $e=N.trim();if(!$e)return;C(""),J(!0);let St="";try{const Kt=await fetch(`/api/watch-together/video-info?url=${encodeURIComponent($e)}`);Kt.ok&&(St=(await Kt.json()).title||"")}catch{}Ue({type:"add_to_queue",url:$e,title:St||void 0}),J(!1)},[N,Ue]),lt=se.useCallback(()=>{const $e=re.trim();$e&&(Z(""),Ue({type:"chat_message",text:$e}))},[re,Ue]);se.useCallback(()=>{Ue({type:"vote_skip"})},[Ue]),se.useCallback(()=>{Ue({type:"vote_pause"})},[Ue]);const jt=se.useCallback(()=>{Ue({type:"clear_watched"})},[Ue]),Jt=se.useCallback(()=>{if(!h)return;const $e=`${window.location.origin}${window.location.pathname}?wt=${h.id}`;navigator.clipboard.writeText($e).catch(()=>{})},[h]),In=se.useCallback($e=>{Ue({type:"remove_from_queue",index:$e})},[Ue]),me=se.useCallback(()=>{const $e=Et.current;$e&&Ue({type:$e.playing?"pause":"resume"})},[Ue]),Bt=se.useCallback(()=>{Ue({type:"skip"})},[Ue]),ot=se.useCallback($e=>{var St,Kt,wn;_t.current=!0,Ue({type:"seek",time:$e}),fe.current==="youtube"&&Ut.current?(Kt=(St=Ut.current).seekTo)==null||Kt.call(St,$e,!0):fe.current==="direct"&&Ke.current?Ke.current.currentTime=$e:fe.current==="dailymotion"&&((wn=pt.current)!=null&&wn.contentWindow)&&pt.current.contentWindow.postMessage(`seek?to=${$e}`,"https://www.dailymotion.com"),H($e),setTimeout(()=>{_t.current=!1},3e3)},[Ue]);se.useEffect(()=>{if(!Oe||!(h!=null&&h.playing))return;const $e=setInterval(()=>{const St=ee();St!==null&&Ue({type:"report_time",time:St})},2e3);return()=>clearInterval($e)},[Oe,h==null?void 0:h.playing,Ue,ee]);const Tt=se.useCallback(()=>{const $e=Ft.current;$e&&(document.fullscreenElement?document.exitFullscreen().catch(()=>{}):$e.requestFullscreen().catch(()=>{}))},[]);se.useEffect(()=>{const $e=()=>I(!!document.fullscreenElement);return document.addEventListener("fullscreenchange",$e),()=>document.removeEventListener("fullscreenchange",$e)},[]),se.useEffect(()=>{const $e=Kt=>{Et.current&&Kt.preventDefault()},St=()=>{tt.current&&navigator.sendBeacon("/api/watch-together/disconnect",JSON.stringify({clientId:tt.current}))};return window.addEventListener("beforeunload",$e),window.addEventListener("pagehide",St),()=>{window.removeEventListener("beforeunload",$e),window.removeEventListener("pagehide",St)}},[]),se.useEffect(()=>()=>{we(),Fe.current&&Fe.current.close(),je.current&&clearTimeout(je.current)},[we]);const Wt=se.useCallback(()=>{if(!v)return;if(!v.password.trim()){x(Kt=>Kt&&{...Kt,error:"Passwort eingeben."});return}const{roomId:$e,password:St}=v;x(null),ct($e,St)},[v,ct]),Yt=se.useCallback($e=>{$e.hasPassword?x({roomId:$e.id,roomName:$e.name,password:"",error:null}):ct($e.id)},[ct]);if(h){const $e=h.members.find(St=>St.id===h.hostId);return P.jsxs("div",{className:"wt-room-overlay",ref:Ft,children:[P.jsxs("div",{className:"wt-room-header",children:[P.jsxs("div",{className:"wt-room-header-left",children:[P.jsx("span",{className:"wt-room-name",children:h.name}),P.jsxs("span",{className:"wt-room-members",children:[h.members.length," Mitglieder"]}),$e&&P.jsxs("span",{className:"wt-host-badge",children:["Host: ",$e.name]})]}),P.jsxs("div",{className:"wt-room-header-right",children:[P.jsx("div",{className:`wt-sync-dot wt-sync-${be}`,title:be==="synced"?"Synchron":be==="drifting"?"Leichte Verzögerung":"Nicht synchron"}),P.jsx("button",{className:"wt-header-btn",onClick:Jt,title:"Link kopieren",children:"Link"}),P.jsx("button",{className:"wt-header-btn",onClick:()=>Me(St=>!St),title:ae?"Chat ausblenden":"Chat einblenden",children:"Chat"}),P.jsx("button",{className:"wt-fullscreen-btn",onClick:Tt,title:U?"Vollbild verlassen":"Vollbild",children:U?"✖":"⛶"}),P.jsx("button",{className:"wt-leave-btn",onClick:Dt,children:"Verlassen"})]})]}),P.jsxs("div",{className:"wt-room-body",children:[P.jsxs("div",{className:"wt-player-section",children:[P.jsxs("div",{className:"wt-player-wrap",children:[P.jsx("div",{ref:ht,className:"wt-yt-container",style:fe.current==="youtube"?{}:{display:"none"}}),P.jsx("video",{ref:Ke,className:"wt-video-element",style:fe.current==="direct"?{}:{display:"none"},playsInline:!0}),P.jsx("iframe",{ref:pt,className:"wt-dm-container",style:fe.current==="dailymotion"?{}:{display:"none"},allow:"autoplay; fullscreen",allowFullScreen:!0}),q&&P.jsxs("div",{className:"wt-player-error",children:[P.jsx("div",{className:"wt-error-icon",children:"⚠️"}),P.jsx("p",{children:q}),((pn=h.currentVideo)==null?void 0:pn.url)&&P.jsx("a",{className:"wt-yt-link",href:h.currentVideo.url,target:"_blank",rel:"noopener noreferrer",children:"Auf YouTube öffnen ↗"}),P.jsx("p",{className:"wt-skip-info",children:"Wird in 3 Sekunden übersprungen..."})]}),!h.currentVideo&&P.jsxs("div",{className:"wt-player-placeholder",children:[P.jsx("div",{className:"wt-placeholder-icon",children:"🎬"}),P.jsx("p",{children:"Fuege ein Video zur Warteschlange hinzu"})]})]}),P.jsxs("div",{className:"wt-controls",children:[P.jsx("button",{className:"wt-ctrl-btn",onClick:me,disabled:!h.currentVideo,title:h.playing?"Pause":"Abspielen",children:h.playing?"⏸":"▶"}),P.jsxs("button",{className:"wt-ctrl-btn wt-next-btn",onClick:Bt,disabled:!h.currentVideo&&h.queue.length===0,title:"Nächstes Video",children:["⏭"," Weiter"]}),P.jsx("input",{className:"wt-seek",type:"range",min:0,max:j||0,step:.5,value:G,onChange:St=>ot(parseFloat(St.target.value)),disabled:!h.currentVideo}),P.jsxs("span",{className:"wt-time",children:[w7(G)," / ",w7(j)]}),P.jsxs("div",{className:"wt-volume",children:[P.jsx("span",{className:"wt-volume-icon",children:E===0?"🔇":E<.5?"🔉":"🔊"}),P.jsx("input",{className:"wt-volume-slider",type:"range",min:0,max:1,step:.01,value:E,onChange:St=>O(parseFloat(St.target.value))})]}),fe.current==="youtube"&&P.jsxs("select",{className:"wt-quality-select",value:Ve,onChange:St=>Ce(St.target.value),title:"Videoqualität",children:[P.jsx("option",{value:"highres",children:"4K+"}),P.jsx("option",{value:"hd2160",children:"2160p"}),P.jsx("option",{value:"hd1440",children:"1440p"}),P.jsx("option",{value:"hd1080",children:"1080p"}),P.jsx("option",{value:"hd720",children:"720p"}),P.jsx("option",{value:"large",children:"480p"}),P.jsx("option",{value:"medium",children:"360p"}),P.jsx("option",{value:"small",children:"240p"})]})]})]}),P.jsxs("div",{className:"wt-queue-panel",children:[P.jsxs("div",{className:"wt-queue-header",children:[P.jsxs("span",{children:["Warteschlange (",h.queue.length,")"]}),h.queue.some(St=>St.watched)&&P.jsx("button",{className:"wt-queue-clear-btn",onClick:jt,title:"Gesehene entfernen",children:"Gesehene entfernen"})]}),P.jsx("div",{className:"wt-queue-list",children:h.queue.length===0?P.jsx("div",{className:"wt-queue-empty",children:"Keine Videos in der Warteschlange"}):h.queue.map((St,Kt)=>{var qn,Je;const wn=((qn=h.currentVideo)==null?void 0:qn.url)===St.url;return P.jsxs("div",{className:`wt-queue-item${wn?" playing":""}${St.watched&&!wn?" watched":""} clickable`,onClick:()=>Ue({type:"play_video",index:Kt}),title:"Klicken zum Abspielen",children:[P.jsxs("div",{className:"wt-queue-item-info",children:[St.watched&&!wn&&P.jsx("span",{className:"wt-queue-item-check",children:"✓"}),St.url.match(/youtu/)&&P.jsx("img",{className:"wt-queue-thumb",src:`https://img.youtube.com/vi/${(Je=St.url.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|shorts\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/))==null?void 0:Je[1]}/default.jpg`,alt:""}),P.jsxs("div",{className:"wt-queue-item-text",children:[P.jsx("div",{className:"wt-queue-item-title",children:St.title||St.url}),P.jsx("div",{className:"wt-queue-item-by",children:St.addedBy})]})]}),Oe&&P.jsx("button",{className:"wt-queue-item-remove",onClick:dt=>{dt.stopPropagation(),In(Kt)},title:"Entfernen",children:"×"})]},Kt)})}),P.jsxs("div",{className:"wt-queue-add",children:[P.jsx("input",{className:"wt-input wt-queue-input",placeholder:"Video-URL eingeben",value:N,onChange:St=>C(St.target.value),onKeyDown:St=>{St.key==="Enter"&&It()}}),P.jsx("button",{className:"wt-btn wt-queue-add-btn",onClick:It,disabled:Q,children:Q?"Laden...":"Hinzufuegen"})]})]}),ae&&P.jsxs("div",{className:"wt-chat-panel",children:[P.jsx("div",{className:"wt-chat-header",children:"Chat"}),P.jsxs("div",{className:"wt-chat-messages",children:[ie.length===0?P.jsx("div",{className:"wt-chat-empty",children:"Noch keine Nachrichten"}):ie.map((St,Kt)=>P.jsxs("div",{className:"wt-chat-msg",children:[P.jsx("span",{className:"wt-chat-sender",children:St.sender}),P.jsx("span",{className:"wt-chat-text",children:St.text})]},Kt)),P.jsx("div",{ref:yt})]}),P.jsxs("div",{className:"wt-chat-input-row",children:[P.jsx("input",{className:"wt-input wt-chat-input",placeholder:"Nachricht...",value:re,onChange:St=>Z(St.target.value),onKeyDown:St=>{St.key==="Enter"&<()},maxLength:500}),P.jsx("button",{className:"wt-btn wt-chat-send-btn",onClick:lt,children:"Senden"})]})]})]})]})}return P.jsxs("div",{className:"wt-container",children:[S&&P.jsxs("div",{className:"wt-error",children:[S,P.jsx("button",{className:"wt-error-dismiss",onClick:()=>T(null),children:"×"})]}),P.jsxs("div",{className:"wt-topbar",children:[P.jsx("input",{className:"wt-input wt-input-name",placeholder:"Dein Name",value:n,onChange:$e=>r($e.target.value)}),P.jsx("input",{className:"wt-input wt-input-room",placeholder:"Raumname",value:s,onChange:$e=>a($e.target.value)}),P.jsx("input",{className:"wt-input wt-input-password",type:"password",placeholder:"Passwort (optional)",value:l,onChange:$e=>u($e.target.value)}),P.jsx("button",{className:"wt-btn",onClick:Le,children:"Raum erstellen"})]}),e.length===0?P.jsxs("div",{className:"wt-empty",children:[P.jsx("div",{className:"wt-empty-icon",children:"🎬"}),P.jsx("h3",{children:"Keine aktiven Raeume"}),P.jsx("p",{children:"Erstelle einen Raum, um gemeinsam Videos zu schauen."})]}):P.jsx("div",{className:"wt-grid",children:e.map($e=>P.jsxs("div",{className:"wt-tile",onClick:()=>Yt($e),children:[P.jsxs("div",{className:"wt-tile-preview",children:[P.jsx("span",{className:"wt-tile-icon",children:"🎬"}),P.jsxs("span",{className:"wt-tile-members",children:["👥"," ",$e.memberCount]}),$e.hasPassword&&P.jsx("span",{className:"wt-tile-lock",children:"🔒"}),$e.playing&&P.jsx("span",{className:"wt-tile-playing",children:"▶"})]}),P.jsxs("div",{className:"wt-tile-info",children:[P.jsxs("div",{className:"wt-tile-meta",children:[P.jsx("div",{className:"wt-tile-name",children:$e.name}),P.jsx("div",{className:"wt-tile-host",children:$e.hostName})]}),$e.memberNames&&$e.memberNames.length>0&&P.jsxs("div",{className:"wt-tile-members-list",children:[$e.memberNames.slice(0,5).join(", "),$e.memberNames.length>5&&` +${$e.memberNames.length-5}`]})]})]},$e.id))}),v&&P.jsx("div",{className:"wt-modal-overlay",onClick:()=>x(null),children:P.jsxs("div",{className:"wt-modal",onClick:$e=>$e.stopPropagation(),children:[P.jsx("h3",{children:v.roomName}),P.jsx("p",{children:"Raum-Passwort"}),v.error&&P.jsx("div",{className:"wt-modal-error",children:v.error}),P.jsx("input",{className:"wt-input",type:"password",placeholder:"Passwort",value:v.password,onChange:$e=>x(St=>St&&{...St,password:$e.target.value,error:null}),onKeyDown:$e=>{$e.key==="Enter"&&Wt()},autoFocus:!0}),P.jsxs("div",{className:"wt-modal-actions",children:[P.jsx("button",{className:"wt-modal-cancel",onClick:()=>x(null),children:"Abbrechen"}),P.jsx("button",{className:"wt-btn",onClick:Wt,children:"Beitreten"})]})]})})]})}function HS(i,e){return`https://media.steampowered.com/steamcommunity/public/images/apps/${i}/${e}.jpg`}function T7(i){if(i==null||i===0)return"—";if(i<60)return`${i} Min`;const e=Math.floor(i/60),t=i%60;return t>0?`${e}h ${t}m`:`${e}h`}function JAe(i){try{return new Date(i).toLocaleDateString("de-DE",{day:"2-digit",month:"2-digit",year:"numeric",hour:"2-digit",minute:"2-digit"})}catch{return i}}function e0e({data:i,isAdmin:e}){const[t,n]=se.useState([]),[r,s]=se.useState("overview"),[a,l]=se.useState(null),[u,h]=se.useState(new Set),[m,v]=se.useState(null),[x,S]=se.useState(null),[T,N]=se.useState(""),[C,E]=se.useState(null),[O,U]=se.useState(!1),[I,j]=se.useState(null),[z,G]=se.useState(new Set),[H,q]=se.useState("playtime"),V=se.useRef(null),Q=se.useRef(null),[J,ie]=se.useState("");se.useEffect(()=>{i!=null&&i.profiles&&n(i.profiles)},[i]);const le=se.useCallback(async()=>{try{const ee=await fetch("/api/game-library/profiles");if(ee.ok){const we=await ee.json();n(we.profiles||[])}}catch{}},[]),re=se.useCallback(()=>{const ee=window.open("/api/game-library/steam/login","_blank","width=800,height=600"),we=setInterval(()=>{ee&&ee.closed&&(clearInterval(we),setTimeout(le,1e3))},500)},[le]),Z=navigator.userAgent.includes("GamingHubDesktop"),[ne,de]=se.useState(!1),[be,Te]=se.useState(""),[ae,Me]=se.useState("idle"),[Ve,Ce]=se.useState(""),Fe=se.useCallback(()=>{const ee=a?`?linkTo=${a}`:"";if(Z){const we=window.open(`/api/game-library/gog/login${ee}`,"_blank","width=800,height=700"),Re=setInterval(()=>{we&&we.closed&&(clearInterval(Re),setTimeout(le,1e3))},500)}else window.open(`/api/game-library/gog/login${ee}`,"_blank","width=800,height=700"),Te(""),Me("idle"),Ce(""),de(!0)},[le,a,Z]),tt=se.useCallback(async()=>{let ee=be.trim();const we=ee.match(/[?&]code=([^&]+)/);if(we&&(ee=we[1]),!!ee){Me("loading"),Ce("Verbinde mit GOG...");try{const Re=await fetch("/api/game-library/gog/exchange",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:ee,linkTo:a||""})}),We=await Re.json();Re.ok&&We.ok?(Me("success"),Ce(`${We.profileName}: ${We.gameCount} Spiele geladen!`),le(),setTimeout(()=>de(!1),2e3)):(Me("error"),Ce(We.error||"Unbekannter Fehler"))}catch{Me("error"),Ce("Verbindung fehlgeschlagen.")}}},[be,a,le]);se.useEffect(()=>{const ee=()=>le();return window.addEventListener("gog-connected",ee),()=>window.removeEventListener("gog-connected",ee)},[le]),se.useEffect(()=>{const ee=()=>le();return window.addEventListener("focus",ee),()=>window.removeEventListener("focus",ee)},[le]);const je=se.useCallback(async ee=>{var we,Re;s("user"),l(ee),v(null),ie(""),U(!0);try{const We=await fetch(`/api/game-library/profile/${ee}/games`);if(We.ok){const Se=await We.json(),Le=Se.games||Se;v(Le);const ct=t.find(It=>It.id===ee),Dt=(Re=(we=ct==null?void 0:ct.platforms)==null?void 0:we.steam)==null?void 0:Re.steamId;Dt&&Le.filter(lt=>!lt.igdb).length>0&&(j(ee),fetch(`/api/game-library/igdb/enrich/${Dt}`).then(lt=>lt.ok?lt.json():null).then(()=>fetch(`/api/game-library/profile/${ee}/games`)).then(lt=>lt.ok?lt.json():null).then(lt=>{lt&&v(lt.games||lt)}).catch(()=>{}).finally(()=>j(null)))}}catch{}finally{U(!1)}},[t]),Rt=se.useCallback(async(ee,we)=>{var Se,Le;we&&we.stopPropagation();const Re=t.find(ct=>ct.id===ee),We=(Le=(Se=Re==null?void 0:Re.platforms)==null?void 0:Se.steam)==null?void 0:Le.steamId;try{We&&await fetch(`/api/game-library/user/${We}?refresh=true`),await le(),r==="user"&&a===ee&&je(ee)}catch{}},[le,r,a,je,t]),Et=se.useCallback(async ee=>{var We,Se;const we=t.find(Le=>Le.id===ee),Re=(Se=(We=we==null?void 0:we.platforms)==null?void 0:We.steam)==null?void 0:Se.steamId;if(Re){j(ee);try{(await fetch(`/api/game-library/igdb/enrich/${Re}`)).ok&&r==="user"&&a===ee&&je(ee)}catch{}finally{j(null)}}},[r,a,je,t]),Ft=se.useCallback(ee=>{h(we=>{const Re=new Set(we);return Re.has(ee)?Re.delete(ee):Re.add(ee),Re})},[]),Ut=se.useCallback(async()=>{if(!(u.size<2)){s("common"),S(null),U(!0);try{const ee=Array.from(u).join(","),we=await fetch(`/api/game-library/common-games?users=${ee}`);if(we.ok){const Re=await we.json();S(Re.games||Re)}else console.error("[GameLibrary] common-games error:",we.status,await we.text().catch(()=>"")),S([])}catch(ee){console.error("[GameLibrary] common-games fetch failed:",ee)}finally{U(!1)}}},[u]),Ke=se.useCallback(ee=>{if(N(ee),V.current&&clearTimeout(V.current),ee.length<2){E(null);return}V.current=setTimeout(async()=>{try{const we=await fetch(`/api/game-library/search?q=${encodeURIComponent(ee)}`);if(we.ok){const Re=await we.json();E(Re.results||Re)}}catch{}},300)},[]),ht=se.useCallback(ee=>{G(we=>{const Re=new Set(we);return Re.has(ee)?Re.delete(ee):Re.add(ee),Re})},[]),fe=se.useCallback(async(ee,we)=>{if(confirm(`${we==="steam"?"Steam":"GOG"}-Verknuepfung wirklich trennen?`))try{const Re=await fetch(`/api/game-library/profile/${ee}/${we}`,{method:"DELETE"});if(Re.ok&&(le(),(await Re.json()).ok)){const Se=t.find(ct=>ct.id===ee);(we==="steam"?Se==null?void 0:Se.platforms.gog:Se==null?void 0:Se.platforms.steam)||$t()}}catch{}},[le,t]);se.useCallback(async ee=>{const we=t.find(Re=>Re.id===ee);if(confirm(`Profil "${we==null?void 0:we.displayName}" wirklich komplett loeschen?`))try{(await fetch(`/api/game-library/profile/${ee}`,{method:"DELETE"})).ok&&(le(),$t())}catch{}},[le,t]);const $t=se.useCallback(()=>{s("overview"),l(null),v(null),S(null),ie(""),G(new Set),q("playtime")},[]),_t=$t,Gt=se.useCallback(ee=>t.find(we=>we.id===ee),[t]),yt=se.useCallback(ee=>typeof ee.playtime_forever=="number"?ee.playtime_forever:Array.isArray(ee.owners)?Math.max(...ee.owners.map(we=>we.playtime_forever||0)):0,[]),Ht=se.useCallback(ee=>[...ee].sort((we,Re)=>{var We,Se;if(H==="rating"){const Le=((We=we.igdb)==null?void 0:We.rating)??-1;return(((Se=Re.igdb)==null?void 0:Se.rating)??-1)-Le}return H==="name"?we.name.localeCompare(Re.name):yt(Re)-yt(we)}),[H,yt]),pt=se.useCallback(ee=>{var we,Re;return z.size===0?!0:(Re=(we=ee.igdb)==null?void 0:we.genres)!=null&&Re.length?ee.igdb.genres.some(We=>z.has(We)):!1},[z]),Ae=se.useCallback(ee=>{var Re;const we=new Map;for(const We of ee)if((Re=We.igdb)!=null&&Re.genres)for(const Se of We.igdb.genres)we.set(Se,(we.get(Se)||0)+1);return[...we.entries()].sort((We,Se)=>Se[1]-We[1]).map(([We])=>We)},[]),k=m?Ht(m.filter(ee=>!J||ee.name.toLowerCase().includes(J.toLowerCase())).filter(pt)):null,xe=m?Ae(m):[],Oe=x?Ae(x):[],Ue=x?Ht(x.filter(pt)):null;return P.jsxs("div",{className:"gl-container",children:[P.jsxs("div",{className:"gl-login-bar",children:[!a&&P.jsx("button",{className:"gl-connect-btn gl-steam-btn",onClick:re,children:"🎮 Steam verbinden"}),P.jsx("div",{className:"gl-login-bar-spacer"})]}),t.length>0&&P.jsx("div",{className:"gl-profile-chips",children:t.map(ee=>P.jsxs("div",{className:`gl-profile-chip${a===ee.id?" selected":""}`,onClick:()=>je(ee.id),children:[P.jsx("img",{className:"gl-profile-chip-avatar",src:ee.avatarUrl,alt:ee.displayName}),P.jsxs("div",{className:"gl-profile-chip-info",children:[P.jsx("span",{className:"gl-profile-chip-name",children:ee.displayName}),P.jsxs("span",{className:"gl-profile-chip-platforms",children:[ee.platforms.steam&&P.jsx("span",{className:"gl-platform-badge steam",title:`Steam: ${ee.platforms.steam.gameCount} Spiele`,children:"S"}),ee.platforms.gog&&P.jsx("span",{className:"gl-platform-badge gog",title:`GOG: ${ee.platforms.gog.gameCount} Spiele`,children:"G"})]})]}),P.jsxs("span",{className:"gl-profile-chip-count",children:["(",ee.totalGames,")"]})]},ee.id))}),r==="overview"&&P.jsx(P.Fragment,{children:t.length===0?P.jsxs("div",{className:"gl-empty",children:[P.jsx("div",{className:"gl-empty-icon",children:"🎮"}),P.jsx("h3",{children:"Keine Konten verbunden"}),P.jsx("p",{children:"Klicke oben auf “Steam verbinden” oder “GOG verbinden”, um deine Spielebibliothek hinzuzufuegen."})]}):P.jsxs(P.Fragment,{children:[P.jsx("p",{className:"gl-section-title",children:"Verbundene Spieler"}),P.jsx("div",{className:"gl-users-grid",children:t.map(ee=>P.jsxs("div",{className:"gl-user-card",onClick:()=>je(ee.id),children:[P.jsx("img",{className:"gl-user-card-avatar",src:ee.avatarUrl,alt:ee.displayName}),P.jsx("span",{className:"gl-user-card-name",children:ee.displayName}),P.jsxs("div",{className:"gl-profile-card-platforms",children:[ee.platforms.steam&&P.jsx("span",{className:"gl-platform-badge steam",title:"Steam",children:"S"}),ee.platforms.gog&&P.jsx("span",{className:"gl-platform-badge gog",title:"GOG",children:"G"})]}),P.jsxs("span",{className:"gl-user-card-games",children:[ee.totalGames," Spiele"]}),P.jsxs("span",{className:"gl-user-card-updated",children:["Aktualisiert: ",JAe(ee.lastUpdated)]})]},ee.id))}),t.length>=2&&P.jsxs("div",{className:"gl-common-finder",children:[P.jsx("h3",{children:"Gemeinsame Spiele finden"}),P.jsx("div",{className:"gl-common-users",children:t.map(ee=>P.jsxs("label",{className:`gl-common-check${u.has(ee.id)?" checked":""}`,children:[P.jsx("input",{type:"checkbox",checked:u.has(ee.id),onChange:()=>Ft(ee.id)}),P.jsx("img",{className:"gl-common-check-avatar",src:ee.avatarUrl,alt:ee.displayName}),ee.displayName,P.jsxs("span",{className:"gl-profile-chip-platforms",style:{marginLeft:4},children:[ee.platforms.steam&&P.jsx("span",{className:"gl-platform-badge steam",children:"S"}),ee.platforms.gog&&P.jsx("span",{className:"gl-platform-badge gog",children:"G"})]})]},ee.id))}),P.jsx("button",{className:"gl-common-find-btn",disabled:u.size<2,onClick:Ut,children:"Finden"})]}),P.jsx("div",{className:"gl-search",children:P.jsx("input",{className:"gl-search-input",type:"text",placeholder:"Spiel suchen...",value:T,onChange:ee=>Ke(ee.target.value)})}),C&&C.length>0&&P.jsxs(P.Fragment,{children:[P.jsxs("p",{className:"gl-search-results-title",children:[C.length," Ergebnis",C.length!==1?"se":""]}),P.jsx("div",{className:"gl-game-list",children:C.map(ee=>P.jsxs("div",{className:"gl-game-item",children:[ee.img_icon_url?P.jsx("img",{className:"gl-game-icon",src:HS(ee.appid,ee.img_icon_url),alt:""}):P.jsx("div",{className:"gl-game-icon"}),P.jsx("span",{className:"gl-game-name",children:ee.name}),P.jsx("div",{className:"gl-game-owners",children:ee.owners.map(we=>{const Re=t.find(We=>{var Se;return((Se=We.platforms.steam)==null?void 0:Se.steamId)===we.steamId});return Re?P.jsx("img",{className:"gl-game-owner-avatar",src:Re.avatarUrl,alt:we.personaName,title:we.personaName},we.steamId):null})})]},ee.appid))})]}),C&&C.length===0&&P.jsx("p",{className:"gl-search-results-title",children:"Keine Ergebnisse gefunden."})]})}),r==="user"&&(()=>{const ee=a?Gt(a):null;return P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"gl-detail-header",children:[P.jsx("button",{className:"gl-back-btn",onClick:_t,children:"← Zurueck"}),ee&&P.jsxs(P.Fragment,{children:[P.jsx("img",{className:"gl-detail-avatar",src:ee.avatarUrl,alt:ee.displayName}),P.jsxs("div",{className:"gl-detail-info",children:[P.jsxs("div",{className:"gl-detail-name",children:[ee.displayName,P.jsxs("span",{className:"gl-game-count",children:[ee.totalGames," Spiele"]})]}),P.jsxs("div",{className:"gl-detail-sub",children:[ee.platforms.steam&&P.jsxs("span",{className:"gl-platform-detail steam",children:[P.jsx("span",{className:"gl-platform-badge steam",children:"Steam ✓"}),P.jsx("button",{className:"gl-disconnect-btn",onClick:we=>{we.stopPropagation(),fe(ee.id,"steam")},title:"Steam trennen",children:"✕"})]}),ee.platforms.gog?P.jsxs("span",{className:"gl-platform-detail gog",children:[P.jsx("span",{className:"gl-platform-badge gog",children:"GOG ✓"}),P.jsx("button",{className:"gl-disconnect-btn",onClick:we=>{we.stopPropagation(),fe(ee.id,"gog")},title:"GOG trennen",children:"✕"})]}):P.jsx("button",{className:"gl-link-gog-btn",onClick:Fe,children:"🟣 GOG verknuepfen"})]})]}),P.jsx("button",{className:"gl-refresh-btn",onClick:()=>Rt(ee.id),title:"Aktualisieren",children:"↻"}),ee.platforms.steam&&P.jsxs("button",{className:`gl-enrich-btn ${I===a?"enriching":""}`,onClick:()=>Et(a),disabled:I===a,title:I===a?"IGDB-Daten werden geladen...":"Mit IGDB-Daten anreichern (erneut)",children:[I===a?"⏳":"🌐"," IGDB"]})]})]}),O?P.jsx("div",{className:"gl-loading",children:"Bibliothek wird geladen..."}):k?P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"gl-filter-bar",children:[P.jsx("input",{ref:Q,className:"gl-search-input",type:"text",placeholder:"Bibliothek durchsuchen...",value:J,onChange:we=>ie(we.target.value)}),P.jsxs("select",{className:"gl-sort-select",value:H,onChange:we=>q(we.target.value),children:[P.jsx("option",{value:"playtime",children:"Spielzeit"}),P.jsx("option",{value:"rating",children:"Bewertung"}),P.jsx("option",{value:"name",children:"Name"})]})]}),xe.length>0&&P.jsxs("div",{className:"gl-genre-filters",children:[z.size>0&&P.jsx("button",{className:"gl-genre-chip active clear",onClick:()=>G(new Set),children:"Alle"}),xe.map(we=>P.jsx("button",{className:`gl-genre-chip${z.has(we)?" active":""}`,onClick:()=>ht(we),children:we},we))]}),P.jsxs("p",{className:"gl-filter-count",children:[k.length," Spiele"]}),k.length===0?P.jsx("p",{className:"gl-search-results-title",children:"Keine Spiele gefunden."}):P.jsx("div",{className:"gl-game-list",children:k.map((we,Re)=>{var We,Se,Le;return P.jsxs("div",{className:`gl-game-item ${we.igdb?"enriched":""}`,children:[P.jsx("span",{className:`gl-game-platform-icon ${we.platform||"steam"}`,children:we.platform==="gog"?"G":"S"}),P.jsx("div",{className:"gl-game-visual",children:(We=we.igdb)!=null&&We.coverUrl?P.jsx("img",{className:"gl-game-cover",src:we.igdb.coverUrl,alt:""}):we.img_icon_url&&we.appid?P.jsx("img",{className:"gl-game-icon",src:HS(we.appid,we.img_icon_url),alt:""}):we.image?P.jsx("img",{className:"gl-game-icon",src:we.image,alt:""}):P.jsx("div",{className:"gl-game-icon"})}),P.jsxs("div",{className:"gl-game-info",children:[P.jsx("span",{className:"gl-game-name",children:we.name}),((Se=we.igdb)==null?void 0:Se.genres)&&we.igdb.genres.length>0&&P.jsx("div",{className:"gl-game-genres",children:we.igdb.genres.slice(0,3).map(ct=>P.jsx("span",{className:"gl-genre-tag",children:ct},ct))})]}),P.jsxs("div",{className:"gl-game-meta",children:[((Le=we.igdb)==null?void 0:Le.rating)!=null&&P.jsx("span",{className:`gl-game-rating ${we.igdb.rating>=75?"high":we.igdb.rating>=50?"mid":"low"}`,children:Math.round(we.igdb.rating)}),P.jsx("span",{className:"gl-game-playtime",children:T7(we.playtime_forever)})]})]},we.appid??we.gogId??Re)})})]}):null]})})(),r==="common"&&(()=>{const ee=Array.from(u).map(Re=>Gt(Re)).filter(Boolean),we=ee.map(Re=>Re.displayName).join(", ");return P.jsxs(P.Fragment,{children:[P.jsxs("div",{className:"gl-detail-header",children:[P.jsx("button",{className:"gl-back-btn",onClick:_t,children:"← Zurueck"}),P.jsx("div",{className:"gl-detail-avatars",children:ee.map(Re=>P.jsx("img",{src:Re.avatarUrl,alt:Re.displayName},Re.id))}),P.jsxs("div",{className:"gl-detail-info",children:[P.jsx("div",{className:"gl-detail-name",children:"Gemeinsame Spiele"}),P.jsxs("div",{className:"gl-detail-sub",children:["von ",we]})]})]}),O?P.jsx("div",{className:"gl-loading",children:"Gemeinsame Spiele werden gesucht..."}):x?x.length===0?P.jsxs("div",{className:"gl-empty",children:[P.jsx("div",{className:"gl-empty-icon",children:"😔"}),P.jsx("h3",{children:"Keine gemeinsamen Spiele"}),P.jsx("p",{children:"Die ausgewaehlten Spieler besitzen leider keine gemeinsamen Spiele."})]}):P.jsxs(P.Fragment,{children:[P.jsx("div",{className:"gl-filter-bar",children:P.jsxs("select",{className:"gl-sort-select",value:H,onChange:Re=>q(Re.target.value),children:[P.jsx("option",{value:"playtime",children:"Spielzeit"}),P.jsx("option",{value:"rating",children:"Bewertung"}),P.jsx("option",{value:"name",children:"Name"})]})}),Oe.length>0&&P.jsxs("div",{className:"gl-genre-filters",children:[z.size>0&&P.jsx("button",{className:"gl-genre-chip active clear",onClick:()=>G(new Set),children:"Alle"}),Oe.map(Re=>P.jsx("button",{className:`gl-genre-chip${z.has(Re)?" active":""}`,onClick:()=>ht(Re),children:Re},Re))]}),P.jsxs("p",{className:"gl-section-title",children:[Ue.length," gemeinsame",Ue.length!==1?" Spiele":"s Spiel",z.size>0?` (von ${x.length})`:""]}),P.jsx("div",{className:"gl-game-list",children:Ue.map(Re=>{var We,Se,Le;return P.jsxs("div",{className:`gl-game-item ${Re.igdb?"enriched":""}`,children:[P.jsx("div",{className:"gl-game-visual",children:(We=Re.igdb)!=null&&We.coverUrl?P.jsx("img",{className:"gl-game-cover",src:Re.igdb.coverUrl,alt:""}):Re.img_icon_url?P.jsx("img",{className:"gl-game-icon",src:HS(Re.appid,Re.img_icon_url),alt:""}):P.jsx("div",{className:"gl-game-icon"})}),P.jsxs("div",{className:"gl-game-info",children:[P.jsx("span",{className:"gl-game-name",children:Re.name}),((Se=Re.igdb)==null?void 0:Se.genres)&&Re.igdb.genres.length>0&&P.jsx("div",{className:"gl-game-genres",children:Re.igdb.genres.slice(0,3).map(ct=>P.jsx("span",{className:"gl-genre-tag",children:ct},ct))})]}),P.jsxs("div",{className:"gl-game-meta",children:[((Le=Re.igdb)==null?void 0:Le.rating)!=null&&P.jsx("span",{className:`gl-game-rating ${Re.igdb.rating>=75?"high":Re.igdb.rating>=50?"mid":"low"}`,children:Math.round(Re.igdb.rating)}),P.jsx("div",{className:"gl-common-playtimes",children:Re.owners.map(ct=>P.jsxs("span",{className:"gl-common-pt",children:[ct.personaName,": ",T7(ct.playtime_forever)]},ct.steamId))})]})]},Re.appid)})})]}):null]})})(),ne&&P.jsx("div",{className:"gl-dialog-overlay",onClick:()=>de(!1),children:P.jsxs("div",{className:"gl-dialog",onClick:ee=>ee.stopPropagation(),children:[P.jsx("h3",{children:"🟣 GOG verbinden"}),P.jsxs("p",{className:"gl-dialog-hint",children:["Nach dem GOG-Login wirst du auf eine Seite weitergeleitet. Kopiere die ",P.jsx("strong",{children:"komplette URL"})," aus der Adressleiste und füge sie hier ein:"]}),P.jsx("input",{className:"gl-dialog-input",type:"text",placeholder:"https://embed.gog.com/on_login_success?code=...",value:be,onChange:ee=>Te(ee.target.value),onKeyDown:ee=>{ee.key==="Enter"&&tt()},disabled:ae==="loading"||ae==="success",autoFocus:!0}),Ve&&P.jsx("p",{className:`gl-dialog-status ${ae}`,children:Ve}),P.jsxs("div",{className:"gl-dialog-actions",children:[P.jsx("button",{onClick:()=>de(!1),className:"gl-dialog-cancel",children:"Abbrechen"}),P.jsx("button",{onClick:tt,className:"gl-dialog-submit",disabled:!be.trim()||ae==="loading"||ae==="success",children:ae==="loading"?"Verbinde...":"Verbinden"})]})]})})]})}const lx="/api/soundboard";async function t0e(){const i=new URL(`${lx}/sounds`,window.location.origin);i.searchParams.set("folder","__all__"),i.searchParams.set("fuzzy","0");const e=await fetch(i.toString());if(!e.ok)throw new Error("Fehler beim Laden der Sounds");return e.json()}async function n0e(i){if(!(await fetch(`${lx}/admin/sounds/delete`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({paths:i})})).ok)throw new Error("Loeschen fehlgeschlagen")}async function i0e(i,e){const t=await fetch(`${lx}/admin/sounds/rename`,{method:"POST",headers:{"Content-Type":"application/json"},credentials:"include",body:JSON.stringify({from:i,to:e})});if(!t.ok)throw new Error("Umbenennen fehlgeschlagen");const n=await t.json();return n==null?void 0:n.to}function r0e(i,e){return new Promise((t,n)=>{const r=new FormData;r.append("files",i);const s=new XMLHttpRequest;s.open("POST",`${lx}/upload`),s.upload.onprogress=a=>{a.lengthComputable&&e(Math.round(a.loaded/a.total*100))},s.onload=()=>{var a,l;if(s.status===200)try{const u=JSON.parse(s.responseText);t(((l=(a=u.files)==null?void 0:a[0])==null?void 0:l.name)??i.name)}catch{t(i.name)}else try{n(new Error(JSON.parse(s.responseText).error))}catch{n(new Error(`HTTP ${s.status}`))}},s.onerror=()=>n(new Error("Netzwerkfehler")),s.send(r)})}function s0e({onClose:i,onLogout:e}){var Oe,Ue;const[t,n]=se.useState("soundboard"),[r,s]=se.useState(null),a=se.useCallback((ee,we="info")=>{s({msg:ee,type:we}),setTimeout(()=>s(null),3e3)},[]);se.useEffect(()=>{const ee=we=>{we.key==="Escape"&&i()};return window.addEventListener("keydown",ee),()=>window.removeEventListener("keydown",ee)},[i]);const[l,u]=se.useState([]),[h,m]=se.useState(!1),[v,x]=se.useState(""),[S,T]=se.useState({}),[N,C]=se.useState(""),[E,O]=se.useState(""),[U,I]=se.useState(null),j=se.useCallback(ee=>ee.relativePath??ee.fileName,[]),z=se.useCallback(async()=>{m(!0);try{const ee=await t0e();u(ee.items||[])}catch(ee){a((ee==null?void 0:ee.message)||"Sounds konnten nicht geladen werden","error")}finally{m(!1)}},[a]),[G,H]=se.useState(!1);se.useEffect(()=>{t==="soundboard"&&!G&&(H(!0),z())},[t,G,z]);const q=se.useMemo(()=>{const ee=v.trim().toLowerCase();return ee?l.filter(we=>{const Re=j(we).toLowerCase();return we.name.toLowerCase().includes(ee)||(we.folder||"").toLowerCase().includes(ee)||Re.includes(ee)}):l},[v,l,j]),V=se.useMemo(()=>Object.keys(S).filter(ee=>S[ee]),[S]),Q=se.useMemo(()=>q.filter(ee=>!!S[j(ee)]).length,[q,S,j]),J=q.length>0&&Q===q.length;function ie(ee){T(we=>({...we,[ee]:!we[ee]}))}function le(ee){C(j(ee)),O(ee.name)}function re(){C(""),O("")}async function Z(){if(!N)return;const ee=E.trim().replace(/\.(mp3|wav)$/i,"");if(!ee){a("Bitte einen gueltigen Namen eingeben","error");return}try{await i0e(N,ee),a("Sound umbenannt"),re(),await z()}catch(we){a((we==null?void 0:we.message)||"Umbenennen fehlgeschlagen","error")}}async function ne(ee){if(ee.length!==0)try{await n0e(ee),a(ee.length===1?"Sound geloescht":`${ee.length} Sounds geloescht`),T({}),re(),await z()}catch(we){a((we==null?void 0:we.message)||"Loeschen fehlgeschlagen","error")}}async function de(ee){I(0);try{await r0e(ee,we=>I(we)),a(`"${ee.name}" hochgeladen`),await z()}catch(we){a((we==null?void 0:we.message)||"Upload fehlgeschlagen","error")}finally{I(null)}}const[be,Te]=se.useState([]),[ae,Me]=se.useState([]),[Ve,Ce]=se.useState(!1),[Fe,tt]=se.useState(!1),[je,Rt]=se.useState({online:!1,botTag:null}),Et=se.useCallback(async()=>{Ce(!0);try{const[ee,we,Re]=await Promise.all([fetch("/api/notifications/status"),fetch("/api/notifications/channels",{credentials:"include"}),fetch("/api/notifications/config",{credentials:"include"})]);if(ee.ok){const We=await ee.json();Rt(We)}if(we.ok){const We=await we.json();Te(We.channels||[])}if(Re.ok){const We=await Re.json();Me(We.channels||[])}}catch{}finally{Ce(!1)}},[]),[Ft,Ut]=se.useState(!1);se.useEffect(()=>{t==="streaming"&&!Ft&&(Ut(!0),Et())},[t,Ft,Et]);const Ke=se.useCallback((ee,we,Re,We,Se)=>{Me(Le=>{const ct=Le.find(Dt=>Dt.channelId===ee);if(ct){const It=ct.events.includes(Se)?ct.events.filter(lt=>lt!==Se):[...ct.events,Se];return It.length===0?Le.filter(lt=>lt.channelId!==ee):Le.map(lt=>lt.channelId===ee?{...lt,events:It}:lt)}else return[...Le,{channelId:ee,channelName:we,guildId:Re,guildName:We,events:[Se]}]})},[]),ht=se.useCallback((ee,we)=>{const Re=ae.find(We=>We.channelId===ee);return(Re==null?void 0:Re.events.includes(we))??!1},[ae]),fe=se.useCallback(async()=>{tt(!0);try{await fetch("/api/notifications/config",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({channels:ae}),credentials:"include"}),a("Konfiguration gespeichert")}catch{a("Speichern fehlgeschlagen","error")}finally{tt(!1)}},[ae,a]),[$t,_t]=se.useState([]),[Gt,yt]=se.useState(!1),Ht=se.useCallback(async()=>{yt(!0);try{const ee=await fetch("/api/game-library/admin/profiles",{credentials:"include"});if(ee.ok){const we=await ee.json();_t(we.profiles||[])}}catch{}finally{yt(!1)}},[]),[pt,Ae]=se.useState(!1);se.useEffect(()=>{t==="game-library"&&!pt&&(Ae(!0),Ht())},[t,pt,Ht]);const k=se.useCallback(async(ee,we)=>{if(confirm(`Profil "${we}" wirklich komplett loeschen? (Alle verknuepften Daten werden entfernt)`))try{(await fetch(`/api/game-library/admin/profile/${ee}`,{method:"DELETE",credentials:"include"})).ok&&(a("Profil geloescht"),Ht())}catch{a("Loeschen fehlgeschlagen","error")}},[Ht,a]),xe=[{id:"soundboard",icon:"🎵",label:"Soundboard"},{id:"streaming",icon:"📺",label:"Streaming"},{id:"game-library",icon:"🎮",label:"Game Library"}];return P.jsx("div",{className:"ap-overlay",onClick:ee=>{ee.target===ee.currentTarget&&i()},children:P.jsxs("div",{className:"ap-modal",children:[P.jsxs("div",{className:"ap-sidebar",children:[P.jsxs("div",{className:"ap-sidebar-title",children:["⚙️"," Admin"]}),P.jsx("nav",{className:"ap-nav",children:xe.map(ee=>P.jsxs("button",{className:`ap-nav-item ${t===ee.id?"active":""}`,onClick:()=>n(ee.id),children:[P.jsx("span",{className:"ap-nav-icon",children:ee.icon}),P.jsx("span",{className:"ap-nav-label",children:ee.label})]},ee.id))}),P.jsxs("button",{className:"ap-logout-btn",onClick:e,children:["🔒"," Abmelden"]})]}),P.jsxs("div",{className:"ap-content",children:[P.jsxs("div",{className:"ap-header",children:[P.jsxs("h2",{className:"ap-title",children:[(Oe=xe.find(ee=>ee.id===t))==null?void 0:Oe.icon," ",(Ue=xe.find(ee=>ee.id===t))==null?void 0:Ue.label]}),P.jsx("button",{className:"ap-close",onClick:i,children:"✕"})]}),P.jsxs("div",{className:"ap-body",children:[t==="soundboard"&&P.jsxs("div",{className:"ap-tab-content",children:[P.jsxs("div",{className:"ap-toolbar",children:[P.jsx("input",{type:"text",className:"ap-search",value:v,onChange:ee=>x(ee.target.value),placeholder:"Nach Name, Ordner oder Pfad filtern..."}),P.jsxs("button",{className:"ap-btn ap-btn-outline",onClick:()=>{z()},disabled:h,children:["↻"," Aktualisieren"]})]}),P.jsxs("label",{className:"ap-upload-zone",children:[P.jsx("input",{type:"file",accept:".mp3,.wav",style:{display:"none"},onChange:ee=>{var Re;const we=(Re=ee.target.files)==null?void 0:Re[0];we&&de(we),ee.target.value=""}}),U!==null?P.jsxs("span",{className:"ap-upload-progress",children:["Upload: ",U,"%"]}):P.jsxs("span",{className:"ap-upload-text",children:["⬆️"," Datei hochladen (MP3 / WAV)"]})]}),P.jsxs("div",{className:"ap-bulk-row",children:[P.jsxs("label",{className:"ap-select-all",children:[P.jsx("input",{type:"checkbox",checked:J,onChange:ee=>{const we=ee.target.checked,Re={...S};q.forEach(We=>{Re[j(We)]=we}),T(Re)}}),P.jsxs("span",{children:["Alle sichtbaren (",Q,"/",q.length,")"]})]}),P.jsxs("button",{className:"ap-btn ap-btn-danger",disabled:V.length===0,onClick:async()=>{window.confirm(`Wirklich ${V.length} Sound(s) loeschen?`)&&await ne(V)},children:["🗑️"," Ausgewaehlte loeschen"]})]}),P.jsx("div",{className:"ap-list-wrap",children:h?P.jsx("div",{className:"ap-empty",children:"Lade Sounds..."}):q.length===0?P.jsx("div",{className:"ap-empty",children:"Keine Sounds gefunden."}):P.jsx("div",{className:"ap-list",children:q.map(ee=>{const we=j(ee),Re=N===we;return P.jsxs("div",{className:"ap-item",children:[P.jsx("label",{className:"ap-item-check",children:P.jsx("input",{type:"checkbox",checked:!!S[we],onChange:()=>ie(we)})}),P.jsxs("div",{className:"ap-item-main",children:[P.jsx("div",{className:"ap-item-name",children:ee.name}),P.jsxs("div",{className:"ap-item-meta",children:[ee.folder?`Ordner: ${ee.folder}`:"Root"," · ",we]}),Re&&P.jsxs("div",{className:"ap-rename-row",children:[P.jsx("input",{className:"ap-rename-input",value:E,onChange:We=>O(We.target.value),onKeyDown:We=>{We.key==="Enter"&&Z(),We.key==="Escape"&&re()},placeholder:"Neuer Name...",autoFocus:!0}),P.jsx("button",{className:"ap-btn ap-btn-primary ap-btn-sm",onClick:()=>{Z()},children:"Speichern"}),P.jsx("button",{className:"ap-btn ap-btn-outline ap-btn-sm",onClick:re,children:"Abbrechen"})]})]}),!Re&&P.jsxs("div",{className:"ap-item-actions",children:[P.jsx("button",{className:"ap-btn ap-btn-outline ap-btn-sm",onClick:()=>le(ee),children:"Umbenennen"}),P.jsx("button",{className:"ap-btn ap-btn-danger ap-btn-sm",onClick:async()=>{window.confirm(`Sound "${ee.name}" loeschen?`)&&await ne([we])},children:"Loeschen"})]})]},we)})})})]}),t==="streaming"&&P.jsxs("div",{className:"ap-tab-content",children:[P.jsxs("div",{className:"ap-toolbar",children:[P.jsxs("span",{className:"ap-status-badge",children:[P.jsx("span",{className:`ap-status-dot ${je.online?"online":""}`}),je.online?P.jsxs(P.Fragment,{children:["Bot online: ",P.jsx("b",{children:je.botTag})]}):P.jsx(P.Fragment,{children:"Bot offline"})]}),P.jsxs("button",{className:"ap-btn ap-btn-outline",onClick:()=>{Et()},disabled:Ve,children:["↻"," Aktualisieren"]})]}),Ve?P.jsx("div",{className:"ap-empty",children:"Lade Kanaele..."}):be.length===0?P.jsx("div",{className:"ap-empty",children:je.online?"Keine Text-Kanaele gefunden. Bot hat moeglicherweise keinen Zugriff.":"Bot ist nicht verbunden. Bitte DISCORD_TOKEN_NOTIFICATIONS konfigurieren."}):P.jsxs(P.Fragment,{children:[P.jsx("p",{className:"ap-hint",children:"Waehle die Kanaele, in die Benachrichtigungen gesendet werden sollen:"}),P.jsx("div",{className:"ap-channel-list",children:be.map(ee=>P.jsxs("div",{className:"ap-channel-row",children:[P.jsxs("div",{className:"ap-channel-info",children:[P.jsxs("span",{className:"ap-channel-name",children:["#",ee.channelName]}),P.jsx("span",{className:"ap-channel-guild",children:ee.guildName})]}),P.jsxs("div",{className:"ap-channel-toggles",children:[P.jsxs("label",{className:`ap-toggle ${ht(ee.channelId,"stream_start")?"active":""}`,children:[P.jsx("input",{type:"checkbox",checked:ht(ee.channelId,"stream_start"),onChange:()=>Ke(ee.channelId,ee.channelName,ee.guildId,ee.guildName,"stream_start")}),"🔴"," Stream Start"]}),P.jsxs("label",{className:`ap-toggle ${ht(ee.channelId,"stream_end")?"active":""}`,children:[P.jsx("input",{type:"checkbox",checked:ht(ee.channelId,"stream_end"),onChange:()=>Ke(ee.channelId,ee.channelName,ee.guildId,ee.guildName,"stream_end")}),"⏹️"," Stream Ende"]})]})]},ee.channelId))}),P.jsx("div",{className:"ap-save-row",children:P.jsx("button",{className:"ap-btn ap-btn-primary",onClick:fe,disabled:Fe,children:Fe?"Speichern...":"💾 Speichern"})})]})]}),t==="game-library"&&P.jsxs("div",{className:"ap-tab-content",children:[P.jsxs("div",{className:"ap-toolbar",children:[P.jsxs("span",{className:"ap-status-badge",children:[P.jsx("span",{className:"ap-status-dot online"}),"Eingeloggt als Admin"]}),P.jsxs("button",{className:"ap-btn ap-btn-outline",onClick:()=>{Ht()},disabled:Gt,children:["↻"," Aktualisieren"]})]}),Gt?P.jsx("div",{className:"ap-empty",children:"Lade Profile..."}):$t.length===0?P.jsx("div",{className:"ap-empty",children:"Keine Profile vorhanden."}):P.jsx("div",{className:"ap-profile-list",children:$t.map(ee=>P.jsxs("div",{className:"ap-profile-row",children:[P.jsx("img",{className:"ap-profile-avatar",src:ee.avatarUrl,alt:ee.displayName}),P.jsxs("div",{className:"ap-profile-info",children:[P.jsx("span",{className:"ap-profile-name",children:ee.displayName}),P.jsxs("span",{className:"ap-profile-details",children:[ee.steamName&&P.jsxs("span",{className:"ap-platform-badge steam",children:["Steam: ",ee.steamGames]}),ee.gogName&&P.jsxs("span",{className:"ap-platform-badge gog",children:["GOG: ",ee.gogGames]}),P.jsxs("span",{className:"ap-profile-total",children:[ee.totalGames," Spiele"]})]})]}),P.jsxs("button",{className:"ap-btn ap-btn-danger ap-btn-sm",onClick:()=>k(ee.id,ee.displayName),children:["🗑️"," Entfernen"]})]},ee.id))})]})]})]}),r&&P.jsxs("div",{className:`ap-toast ${r.type}`,children:[r.type==="error"?"❌":"✅"," ",r.msg]})]})})}const M7={radio:MAe,soundboard:jAe,lolstats:YAe,streaming:QAe,"watch-together":ZAe,"game-library":e0e};function a0e(){var Z;const[i,e]=se.useState(!1),[t,n]=se.useState([]),[r,s]=se.useState(()=>localStorage.getItem("hub_activeTab")??""),a=ne=>{s(ne),localStorage.setItem("hub_activeTab",ne)},[l,u]=se.useState(!1),[h,m]=se.useState({}),[v,x]=se.useState(!1),[S,T]=se.useState(!1),[N,C]=se.useState(!1),[E,O]=se.useState(""),[U,I]=se.useState(""),j=!!((Z=window.electronAPI)!=null&&Z.isElectron),z=j?window.electronAPI.version:null,[G,H]=se.useState("idle"),[q,V]=se.useState(""),Q=se.useRef(null);se.useEffect(()=>{"Notification"in window&&Notification.permission==="default"&&Notification.requestPermission()},[]),se.useEffect(()=>{fetch("/api/soundboard/admin/status",{credentials:"include"}).then(ne=>ne.json()).then(ne=>x(!!ne.authenticated)).catch(()=>{})},[]),se.useEffect(()=>{if(!S)return;const ne=de=>{de.key==="Escape"&&T(!1)};return window.addEventListener("keydown",ne),()=>window.removeEventListener("keydown",ne)},[S]);async function J(){I("");try{(await fetch("/api/soundboard/admin/login",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({password:E}),credentials:"include"})).ok?(x(!0),O(""),T(!1)):I("Falsches Passwort")}catch{I("Verbindung fehlgeschlagen")}}async function ie(){await fetch("/api/soundboard/admin/logout",{method:"POST",credentials:"include"}),x(!1)}se.useEffect(()=>{var be;if(!j)return;const ne=window.electronAPI;ne.onUpdateAvailable(()=>H("downloading")),ne.onUpdateReady(()=>H("ready")),ne.onUpdateNotAvailable(()=>H("upToDate")),ne.onUpdateError(Te=>{H("error"),V(Te||"Unbekannter Fehler")});const de=(be=ne.getUpdateStatus)==null?void 0:be.call(ne);de==="downloading"?H("downloading"):de==="ready"?H("ready"):de==="checking"&&H("checking")},[j]),se.useEffect(()=>{fetch("/api/plugins").then(ne=>ne.json()).then(ne=>{if(n(ne),new URLSearchParams(location.search).has("viewStream")&&ne.some(ae=>ae.name==="streaming")){a("streaming");return}const be=localStorage.getItem("hub_activeTab"),Te=ne.some(ae=>ae.name===be);ne.length>0&&!Te&&a(ne[0].name)}).catch(()=>{})},[]),se.useEffect(()=>{let ne=null,de;function be(){ne=new EventSource("/api/events"),Q.current=ne,ne.onopen=()=>e(!0),ne.onmessage=Te=>{try{const ae=JSON.parse(Te.data);ae.type==="snapshot"?m(Me=>({...Me,...ae})):ae.plugin&&m(Me=>({...Me,[ae.plugin]:{...Me[ae.plugin]||{},...ae}}))}catch{}},ne.onerror=()=>{e(!1),ne==null||ne.close(),de=setTimeout(be,3e3)}}return be(),()=>{ne==null||ne.close(),clearTimeout(de)}},[]);const le="1.0.0-dev";se.useEffect(()=>{if(!l)return;const ne=de=>{de.key==="Escape"&&u(!1)};return window.addEventListener("keydown",ne),()=>window.removeEventListener("keydown",ne)},[l]);const re={radio:"🌍",soundboard:"🎵",lolstats:"⚔️",stats:"📊",events:"📅",games:"🎲",gamevote:"🎮",streaming:"📺","watch-together":"🎬","game-library":"🎮"};return P.jsxs("div",{className:"hub-app",children:[P.jsxs("header",{className:"hub-header",children:[P.jsxs("div",{className:"hub-header-left",children:[P.jsx("span",{className:"hub-logo",children:"🎮"}),P.jsx("span",{className:"hub-title",children:"Gaming Hub"}),P.jsx("span",{className:`hub-conn-dot ${i?"online":""}`})]}),P.jsx("nav",{className:"hub-tabs",children:t.filter(ne=>ne.name in M7).map(ne=>P.jsxs("button",{className:`hub-tab ${r===ne.name?"active":""}`,onClick:()=>a(ne.name),title:ne.description,children:[P.jsx("span",{className:"hub-tab-icon",children:re[ne.name]??"📦"}),P.jsx("span",{className:"hub-tab-label",children:ne.name})]},ne.name))}),P.jsxs("div",{className:"hub-header-right",children:[!window.electronAPI&&P.jsxs("a",{className:"hub-download-btn",href:"/downloads/GamingHub-Setup.exe",download:!0,title:"Desktop App herunterladen",children:[P.jsx("span",{className:"hub-download-icon",children:"⬇️"}),P.jsx("span",{className:"hub-download-label",children:"Desktop App"})]}),P.jsx("button",{className:`hub-admin-btn ${v?"active":""}`,onClick:()=>v?C(!0):T(!0),onContextMenu:ne=>{v&&(ne.preventDefault(),ie())},title:v?"Admin Panel (Rechtsklick = Abmelden)":"Admin Login",children:v?"🔓":"🔒"}),P.jsx("button",{className:"hub-refresh-btn",onClick:()=>window.location.reload(),title:"Seite neu laden",children:"🔄"}),P.jsxs("span",{className:"hub-version hub-version-clickable",onClick:()=>{var ne;if(j){const de=window.electronAPI,be=(ne=de.getUpdateStatus)==null?void 0:ne.call(de);be==="downloading"?H("downloading"):be==="ready"?H("ready"):be==="checking"&&H("checking")}u(!0)},title:"Versionsinformationen",children:["v",le]})]})]}),l&&P.jsx("div",{className:"hub-version-overlay",onClick:()=>u(!1),children:P.jsxs("div",{className:"hub-version-modal",onClick:ne=>ne.stopPropagation(),children:[P.jsxs("div",{className:"hub-version-modal-header",children:[P.jsx("span",{children:"Versionsinformationen"}),P.jsx("button",{className:"hub-version-modal-close",onClick:()=>u(!1),children:"✕"})]}),P.jsxs("div",{className:"hub-version-modal-body",children:[P.jsxs("div",{className:"hub-version-modal-row",children:[P.jsx("span",{className:"hub-version-modal-label",children:"Hub-Version"}),P.jsxs("span",{className:"hub-version-modal-value",children:["v",le]})]}),j&&P.jsxs("div",{className:"hub-version-modal-row",children:[P.jsx("span",{className:"hub-version-modal-label",children:"Desktop-App"}),P.jsxs("span",{className:"hub-version-modal-value",children:["v",z]})]}),P.jsxs("div",{className:"hub-version-modal-row",children:[P.jsx("span",{className:"hub-version-modal-label",children:"Server"}),P.jsxs("span",{className:"hub-version-modal-value",children:[P.jsx("span",{className:`hub-version-modal-dot ${i?"online":""}`}),i?"Verbunden":"Getrennt"]})]}),j&&P.jsxs("div",{className:"hub-version-modal-update",children:[G==="idle"&&P.jsxs("button",{className:"hub-version-modal-update-btn",onClick:()=>{H("checking"),V(""),window.electronAPI.checkForUpdates()},children:["🔄"," Nach Updates suchen"]}),G==="checking"&&P.jsxs("div",{className:"hub-version-modal-update-status",children:[P.jsx("span",{className:"hub-update-spinner"}),"Suche nach Updates…"]}),G==="downloading"&&P.jsxs("div",{className:"hub-version-modal-update-status",children:[P.jsx("span",{className:"hub-update-spinner"}),"Update wird heruntergeladen…"]}),G==="ready"&&P.jsxs("button",{className:"hub-version-modal-update-btn ready",onClick:()=>window.electronAPI.installUpdate(),children:["✅"," Jetzt installieren & neu starten"]}),G==="upToDate"&&P.jsxs("div",{className:"hub-version-modal-update-status success",children:["✅"," App ist aktuell",P.jsx("button",{className:"hub-version-modal-update-retry",onClick:()=>H("idle"),children:"Erneut prüfen"})]}),G==="error"&&P.jsxs("div",{className:"hub-version-modal-update-status error",children:["❌"," ",q,P.jsx("button",{className:"hub-version-modal-update-retry",onClick:()=>H("idle"),children:"Erneut versuchen"})]})]})]})]})}),S&&P.jsx("div",{className:"hub-admin-overlay",onClick:()=>T(!1),children:P.jsxs("div",{className:"hub-admin-modal",onClick:ne=>ne.stopPropagation(),children:[P.jsxs("div",{className:"hub-admin-modal-header",children:[P.jsxs("span",{children:["🔒"," Admin Login"]}),P.jsx("button",{className:"hub-admin-modal-close",onClick:()=>T(!1),children:"✕"})]}),P.jsxs("div",{className:"hub-admin-modal-body",children:[P.jsx("input",{type:"password",className:"hub-admin-input",placeholder:"Admin-Passwort...",value:E,onChange:ne=>O(ne.target.value),onKeyDown:ne=>ne.key==="Enter"&&J(),autoFocus:!0}),U&&P.jsx("p",{className:"hub-admin-error",children:U}),P.jsx("button",{className:"hub-admin-submit",onClick:J,children:"Login"})]})]})}),N&&v&&P.jsx(s0e,{onClose:()=>C(!1),onLogout:()=>{ie(),C(!1)}}),P.jsx("main",{className:"hub-content",children:t.length===0?P.jsxs("div",{className:"hub-empty",children:[P.jsx("span",{className:"hub-empty-icon",children:"📦"}),P.jsx("h2",{children:"Keine Plugins geladen"}),P.jsx("p",{children:"Plugins werden im Server konfiguriert."})]}):t.map(ne=>{const de=M7[ne.name];if(!de)return null;const be=r===ne.name;return P.jsx("div",{className:`hub-tab-panel ${be?"active":""}`,style:be?{display:"flex",flexDirection:"column",width:"100%",height:"100%"}:{display:"none"},children:P.jsx(de,{data:h[ne.name]||{},isAdmin:v})},ne.name)})})]})}IF.createRoot(document.getElementById("root")).render(P.jsx(a0e,{})); diff --git a/web/dist/index.html b/web/dist/index.html index e6783aa..da68df3 100644 --- a/web/dist/index.html +++ b/web/dist/index.html @@ -5,7 +5,7 @@ Gaming Hub - + diff --git a/web/src/plugins/soundboard/SoundboardTab.tsx b/web/src/plugins/soundboard/SoundboardTab.tsx index bf1274d..a58c165 100644 --- a/web/src/plugins/soundboard/SoundboardTab.tsx +++ b/web/src/plugins/soundboard/SoundboardTab.tsx @@ -1009,7 +1009,7 @@ export default function SoundboardTab({ data, isAdmin: isAdminProp }: Soundboard if (volDebounceRef.current) clearTimeout(volDebounceRef.current); volDebounceRef.current = setTimeout(() => { apiSetVolumeLive(guildId, v).catch(() => {}); - }, 120); + }, 50); } }} style={{ '--vol': `${Math.round(volume * 100)}%` } as React.CSSProperties}