diff --git a/server/config.example.yaml b/server/config.example.yaml index 2486554b..fa343790 100644 --- a/server/config.example.yaml +++ b/server/config.example.yaml @@ -23,10 +23,12 @@ audioForward: enabled: true # Optional override; defaults to "ffmpeg" ffmpegBin: "ffmpeg" - # Optional test file path for admin-only first-pass playback - testAudioPath: "server/assets/test-audio.mp3" # Optional stream suffix for fallback URL generation streamSuffix: "-fwd" + # Max upload payload accepted via VIP forward upload + maxUploadBytes: 8388608 + # Maximum playback duration per upload (seconds) + maxUploadSeconds: 45 audioLevels: # Gains are multipliers (0.0 - 4.0) applied globally to all rovers. diff --git a/server/public/assets/index-C4govqUc.js b/server/public/assets/index-C4govqUc.js deleted file mode 100644 index 85708f59..00000000 --- a/server/public/assets/index-C4govqUc.js +++ /dev/null @@ -1,125 +0,0 @@ -(function(){const l=document.createElement("link").relList;if(l&&l.supports&&l.supports("modulepreload"))return;for(const f of document.querySelectorAll('link[rel="modulepreload"]'))o(f);new MutationObserver(f=>{for(const d of f)if(d.type==="childList")for(const h of d.addedNodes)h.tagName==="LINK"&&h.rel==="modulepreload"&&o(h)}).observe(document,{childList:!0,subtree:!0});function i(f){const d={};return f.integrity&&(d.integrity=f.integrity),f.referrerPolicy&&(d.referrerPolicy=f.referrerPolicy),f.crossOrigin==="use-credentials"?d.credentials="include":f.crossOrigin==="anonymous"?d.credentials="omit":d.credentials="same-origin",d}function o(f){if(f.ep)return;f.ep=!0;const d=i(f);fetch(f.href,d)}})();function Oy(a){return a&&a.__esModule&&Object.prototype.hasOwnProperty.call(a,"default")?a.default:a}var Eu={exports:{}},Qs={};var F0;function By(){if(F0)return Qs;F0=1;var a=Symbol.for("react.transitional.element"),l=Symbol.for("react.fragment");function i(o,f,d){var h=null;if(d!==void 0&&(h=""+d),f.key!==void 0&&(h=""+f.key),"key"in f){d={};for(var p in f)p!=="key"&&(d[p]=f[p])}else d=f;return f=d.ref,{$$typeof:a,type:o,key:h,ref:f!==void 0?f:null,props:d}}return Qs.Fragment=l,Qs.jsx=i,Qs.jsxs=i,Qs}var K0;function Ly(){return K0||(K0=1,Eu.exports=By()),Eu.exports}var r=Ly(),qu={exports:{}},be={};var Z0;function zy(){if(Z0)return be;Z0=1;var a=Symbol.for("react.transitional.element"),l=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),d=Symbol.for("react.consumer"),h=Symbol.for("react.context"),p=Symbol.for("react.forward_ref"),x=Symbol.for("react.suspense"),v=Symbol.for("react.memo"),b=Symbol.for("react.lazy"),y=Symbol.for("react.activity"),N=Symbol.iterator;function M(q){return q===null||typeof q!="object"?null:(q=N&&q[N]||q["@@iterator"],typeof q=="function"?q:null)}var E={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},w=Object.assign,j={};function k(q,H,ee){this.props=q,this.context=H,this.refs=j,this.updater=ee||E}k.prototype.isReactComponent={},k.prototype.setState=function(q,H){if(typeof q!="object"&&typeof q!="function"&&q!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,q,H,"setState")},k.prototype.forceUpdate=function(q){this.updater.enqueueForceUpdate(this,q,"forceUpdate")};function A(){}A.prototype=k.prototype;function C(q,H,ee){this.props=q,this.context=H,this.refs=j,this.updater=ee||E}var _=C.prototype=new A;_.constructor=C,w(_,k.prototype),_.isPureReactComponent=!0;var L=Array.isArray;function $(){}var O={H:null,A:null,T:null,S:null},Y=Object.prototype.hasOwnProperty;function z(q,H,ee){var ae=ee.ref;return{$$typeof:a,type:q,key:H,ref:ae!==void 0?ae:null,props:ee}}function G(q,H){return z(q.type,H,q.props)}function K(q){return typeof q=="object"&&q!==null&&q.$$typeof===a}function ne(q){var H={"=":"=0",":":"=2"};return"$"+q.replace(/[=:]/g,function(ee){return H[ee]})}var oe=/\/+/g;function me(q,H){return typeof q=="object"&&q!==null&&q.key!=null?ne(""+q.key):H.toString(36)}function X(q){switch(q.status){case"fulfilled":return q.value;case"rejected":throw q.reason;default:switch(typeof q.status=="string"?q.then($,$):(q.status="pending",q.then(function(H){q.status==="pending"&&(q.status="fulfilled",q.value=H)},function(H){q.status==="pending"&&(q.status="rejected",q.reason=H)})),q.status){case"fulfilled":return q.value;case"rejected":throw q.reason}}throw q}function R(q,H,ee,ae,se){var re=typeof q;(re==="undefined"||re==="boolean")&&(q=null);var fe=!1;if(q===null)fe=!0;else switch(re){case"bigint":case"string":case"number":fe=!0;break;case"object":switch(q.$$typeof){case a:case l:fe=!0;break;case b:return fe=q._init,R(fe(q._payload),H,ee,ae,se)}}if(fe)return se=se(q),fe=ae===""?"."+me(q,0):ae,L(se)?(ee="",fe!=null&&(ee=fe.replace(oe,"$&/")+"/"),R(se,H,ee,"",function(we){return we})):se!=null&&(K(se)&&(se=G(se,ee+(se.key==null||q&&q.key===se.key?"":(""+se.key).replace(oe,"$&/")+"/")+fe)),H.push(se)),1;fe=0;var ve=ae===""?".":ae+":";if(L(q))for(var pe=0;pe>>1,ue=R[le];if(0>>1;lef(ee,Z))aef(se,ee)?(R[le]=se,R[ae]=Z,le=ae):(R[le]=ee,R[H]=Z,le=H);else if(aef(se,Z))R[le]=se,R[ae]=Z,le=ae;else break e}}return F}function f(R,F){var Z=R.sortIndex-F.sortIndex;return Z!==0?Z:R.id-F.id}if(a.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var d=performance;a.unstable_now=function(){return d.now()}}else{var h=Date,p=h.now();a.unstable_now=function(){return h.now()-p}}var x=[],v=[],b=1,y=null,N=3,M=!1,E=!1,w=!1,j=!1,k=typeof setTimeout=="function"?setTimeout:null,A=typeof clearTimeout=="function"?clearTimeout:null,C=typeof setImmediate<"u"?setImmediate:null;function _(R){for(var F=i(v);F!==null;){if(F.callback===null)o(v);else if(F.startTime<=R)o(v),F.sortIndex=F.expirationTime,l(x,F);else break;F=i(v)}}function L(R){if(w=!1,_(R),!E)if(i(x)!==null)E=!0,$||($=!0,ne());else{var F=i(v);F!==null&&X(L,F.startTime-R)}}var $=!1,O=-1,Y=5,z=-1;function G(){return j?!0:!(a.unstable_now()-zR&&G());){var le=y.callback;if(typeof le=="function"){y.callback=null,N=y.priorityLevel;var ue=le(y.expirationTime<=R);if(R=a.unstable_now(),typeof ue=="function"){y.callback=ue,_(R),F=!0;break t}y===i(x)&&o(x),_(R)}else o(x);y=i(x)}if(y!==null)F=!0;else{var q=i(v);q!==null&&X(L,q.startTime-R),F=!1}}break e}finally{y=null,N=Z,M=!1}F=void 0}}finally{F?ne():$=!1}}}var ne;if(typeof C=="function")ne=function(){C(K)};else if(typeof MessageChannel<"u"){var oe=new MessageChannel,me=oe.port2;oe.port1.onmessage=K,ne=function(){me.postMessage(null)}}else ne=function(){k(K,0)};function X(R,F){O=k(function(){R(a.unstable_now())},F)}a.unstable_IdlePriority=5,a.unstable_ImmediatePriority=1,a.unstable_LowPriority=4,a.unstable_NormalPriority=3,a.unstable_Profiling=null,a.unstable_UserBlockingPriority=2,a.unstable_cancelCallback=function(R){R.callback=null},a.unstable_forceFrameRate=function(R){0>R||125le?(R.sortIndex=Z,l(v,R),i(x)===null&&R===i(v)&&(w?(A(O),O=-1):w=!0,X(L,Z-le))):(R.sortIndex=ue,l(x,R),E||M||(E=!0,$||($=!0,ne()))),R},a.unstable_shouldYield=G,a.unstable_wrapCallback=function(R){var F=N;return function(){var Z=N;N=F;try{return R.apply(this,arguments)}finally{N=Z}}}})(Ru)),Ru}var W0;function Hy(){return W0||(W0=1,Mu.exports=Uy()),Mu.exports}var Tu={exports:{}},Ct={};var P0;function Vy(){if(P0)return Ct;P0=1;var a=jf();function l(x){var v="https://react.dev/errors/"+x;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(a)}catch(l){console.error(l)}}return a(),Tu.exports=Vy(),Tu.exports}var tp;function $y(){if(tp)return Fs;tp=1;var a=Hy(),l=jf(),i=Yy();function o(e){var t="https://react.dev/errors/"+e;if(1ue||(e.current=le[ue],le[ue]=null,ue--)}function ee(e,t){ue++,le[ue]=e.current,e.current=t}var ae=q(null),se=q(null),re=q(null),fe=q(null);function ve(e,t){switch(ee(re,t),ee(se,e),ee(ae,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?x0(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=x0(t),e=g0(t,e);else switch(e){case"svg":e=1;break;case"math":e=2;break;default:e=0}}H(ae),ee(ae,e)}function pe(){H(ae),H(se),H(re)}function we(e){e.memoizedState!==null&&ee(fe,e);var t=ae.current,n=g0(t,e.type);t!==n&&(ee(se,e),ee(ae,n))}function te(e){se.current===e&&(H(ae),H(se)),fe.current===e&&(H(fe),Ys._currentValue=Z)}var ie,Se;function Oe(e){if(ie===void 0)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);ie=t&&t[1]||"",Se=-1)":-1c||T[s]!==V[c]){var I=` -`+T[s].replace(" at new "," at ");return e.displayName&&I.includes("")&&(I=I.replace("",e.displayName)),I}while(1<=s&&0<=c);break}}}finally{je=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:"")?Oe(n):""}function qt(e,t){switch(e.tag){case 26:case 27:case 5:return Oe(e.type);case 16:return Oe("Lazy");case 13:return e.child!==t&&t!==null?Oe("Suspense Fallback"):Oe("Suspense");case 19:return Oe("SuspenseList");case 0:case 15:return Le(e.type,!1);case 11:return Le(e.type.render,!1);case 1:return Le(e.type,!0);case 31:return Oe("Activity");default:return""}}function ce(e){try{var t="",n=null;do t+=qt(e,n),n=e,e=e.return;while(e);return t}catch(s){return` -Error generating stack: `+s.message+` -`+s.stack}}var Ce=Object.prototype.hasOwnProperty,Te=a.unstable_scheduleCallback,Lt=a.unstable_cancelCallback,mo=a.unstable_shouldYield,ho=a.unstable_requestPaint,pt=a.unstable_now,Pa=a.unstable_getCurrentPriorityLevel,el=a.unstable_ImmediatePriority,un=a.unstable_UserBlockingPriority,Ca=a.unstable_NormalPriority,gi=a.unstable_LowPriority,tl=a.unstable_IdlePriority,po=a.log,ts=a.unstable_setDisableYieldValue,fn=null,gt=null;function Kt(e){if(typeof po=="function"&&ts(e),gt&&typeof gt.setStrictMode=="function")try{gt.setStrictMode(fn,e)}catch{}}var ct=Math.clz32?Math.clz32:go,xo=Math.log,nl=Math.LN2;function go(e){return e>>>=0,e===0?32:31-(xo(e)/nl|0)|0}var Ea=256,Ie=262144,al=4194304;function zt(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function ea(e,t,n){var s=e.pendingLanes;if(s===0)return 0;var c=0,u=e.suspendedLanes,g=e.pingedLanes;e=e.warmLanes;var S=s&134217727;return S!==0?(s=S&~u,s!==0?c=zt(s):(g&=S,g!==0?c=zt(g):n||(n=S&~e,n!==0&&(c=zt(n))))):(S=s&~u,S!==0?c=zt(S):g!==0?c=zt(g):n||(n=s&~e,n!==0&&(c=zt(n)))),c===0?0:t!==0&&t!==c&&(t&u)===0&&(u=c&-c,n=t&-t,u>=n||u===32&&(n&4194048)!==0)?t:c}function vn(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function vi(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function yi(){var e=al;return al<<=1,(al&62914560)===0&&(al=4194304),e}function ns(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function qa(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function bi(e,t,n,s,c,u){var g=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var S=e.entanglements,T=e.expirationTimes,V=e.hiddenUpdates;for(n=g&~n;0"u")return null;try{return e.activeElement||e.body}catch{return e.body}}var kg=/[\n"\\]/g;function Wt(e){return e.replace(kg,function(t){return"\\"+t.charCodeAt(0).toString(16)+" "})}function So(e,t,n,s,c,u,g,S){e.name="",g!=null&&typeof g!="function"&&typeof g!="symbol"&&typeof g!="boolean"?e.type=g:e.removeAttribute("type"),t!=null?g==="number"?(t===0&&e.value===""||e.value!=t)&&(e.value=""+It(t)):e.value!==""+It(t)&&(e.value=""+It(t)):g!=="submit"&&g!=="reset"||e.removeAttribute("value"),t!=null?Ao(e,g,It(t)):n!=null?Ao(e,g,It(n)):s!=null&&e.removeAttribute("value"),c==null&&u!=null&&(e.defaultChecked=!!u),c!=null&&(e.checked=c&&typeof c!="function"&&typeof c!="symbol"),S!=null&&typeof S!="function"&&typeof S!="symbol"&&typeof S!="boolean"?e.name=""+It(S):e.removeAttribute("name")}function ud(e,t,n,s,c,u,g,S){if(u!=null&&typeof u!="function"&&typeof u!="symbol"&&typeof u!="boolean"&&(e.type=u),t!=null||n!=null){if(!(u!=="submit"&&u!=="reset"||t!=null)){bo(e);return}n=n!=null?""+It(n):"",t=t!=null?""+It(t):n,S||t===e.value||(e.value=t),e.defaultValue=t}s=s??c,s=typeof s!="function"&&typeof s!="symbol"&&!!s,e.checked=S?e.checked:!!s,e.defaultChecked=!!s,g!=null&&typeof g!="function"&&typeof g!="symbol"&&typeof g!="boolean"&&(e.name=g),bo(e)}function Ao(e,t,n){t==="number"&&ji(e.ownerDocument)===e||e.defaultValue===""+n||(e.defaultValue=""+n)}function ol(e,t,n,s){if(e=e.options,t){t={};for(var c=0;c"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),Eo=!1;if(Rn)try{var is={};Object.defineProperty(is,"passive",{get:function(){Eo=!0}}),window.addEventListener("test",is,is),window.removeEventListener("test",is,is)}catch{Eo=!1}var ta=null,qo=null,wi=null;function gd(){if(wi)return wi;var e,t=qo,n=t.length,s,c="value"in ta?ta.value:ta.textContent,u=c.length;for(e=0;e=cs),jd=" ",Nd=!1;function wd(e,t){switch(e){case"keyup":return av.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Cd(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var dl=!1;function sv(e,t){switch(e){case"compositionend":return Cd(t);case"keypress":return t.which!==32?null:(Nd=!0,jd);case"textInput":return e=t.data,e===jd&&Nd?null:e;default:return null}}function iv(e,t){if(dl)return e==="compositionend"||!Do&&wd(e,t)?(e=gd(),wi=qo=ta=null,dl=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=s}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=_d(n)}}function Bd(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Bd(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ld(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=ji(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=ji(e.document)}return t}function Bo(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}var hv=Rn&&"documentMode"in document&&11>=document.documentMode,ml=null,Lo=null,ms=null,zo=!1;function zd(e,t,n){var s=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;zo||ml==null||ml!==ji(s)||(s=ml,"selectionStart"in s&&Bo(s)?s={start:s.selectionStart,end:s.selectionEnd}:(s=(s.ownerDocument&&s.ownerDocument.defaultView||window).getSelection(),s={anchorNode:s.anchorNode,anchorOffset:s.anchorOffset,focusNode:s.focusNode,focusOffset:s.focusOffset}),ms&&ds(ms,s)||(ms=s,s=vr(Lo,"onSelect"),0>=g,c-=g,yn=1<<32-ct(t)+c|n<Ne?(Re=he,he=null):Re=he.sibling;var He=Q(B,he,U[Ne],W);if(He===null){he===null&&(he=Re);break}e&&he&&He.alternate===null&&t(B,he),D=u(He,D,Ne),Ue===null?xe=He:Ue.sibling=He,Ue=He,he=Re}if(Ne===U.length)return n(B,he),De&&Dn(B,Ne),xe;if(he===null){for(;NeNe?(Re=he,he=null):Re=he.sibling;var ja=Q(B,he,He.value,W);if(ja===null){he===null&&(he=Re);break}e&&he&&ja.alternate===null&&t(B,he),D=u(ja,D,Ne),Ue===null?xe=ja:Ue.sibling=ja,Ue=ja,he=Re}if(He.done)return n(B,he),De&&Dn(B,Ne),xe;if(he===null){for(;!He.done;Ne++,He=U.next())He=P(B,He.value,W),He!==null&&(D=u(He,D,Ne),Ue===null?xe=He:Ue.sibling=He,Ue=He);return De&&Dn(B,Ne),xe}for(he=s(he);!He.done;Ne++,He=U.next())He=J(he,B,Ne,He.value,W),He!==null&&(e&&He.alternate!==null&&he.delete(He.key===null?Ne:He.key),D=u(He,D,Ne),Ue===null?xe=He:Ue.sibling=He,Ue=He);return e&&he.forEach(function(_y){return t(B,_y)}),De&&Dn(B,Ne),xe}function Fe(B,D,U,W){if(typeof U=="object"&&U!==null&&U.type===w&&U.key===null&&(U=U.props.children),typeof U=="object"&&U!==null){switch(U.$$typeof){case M:e:{for(var xe=U.key;D!==null;){if(D.key===xe){if(xe=U.type,xe===w){if(D.tag===7){n(B,D.sibling),W=c(D,U.props.children),W.return=B,B=W;break e}}else if(D.elementType===xe||typeof xe=="object"&&xe!==null&&xe.$$typeof===Y&&Ua(xe)===D.type){n(B,D.sibling),W=c(D,U.props),ys(W,U),W.return=B,B=W;break e}n(B,D);break}else t(B,D);D=D.sibling}U.type===w?(W=_a(U.props.children,B.mode,W,U.key),W.return=B,B=W):(W=Oi(U.type,U.key,U.props,null,B.mode,W),ys(W,U),W.return=B,B=W)}return g(B);case E:e:{for(xe=U.key;D!==null;){if(D.key===xe)if(D.tag===4&&D.stateNode.containerInfo===U.containerInfo&&D.stateNode.implementation===U.implementation){n(B,D.sibling),W=c(D,U.children||[]),W.return=B,B=W;break e}else{n(B,D);break}else t(B,D);D=D.sibling}W=Xo(U,B.mode,W),W.return=B,B=W}return g(B);case Y:return U=Ua(U),Fe(B,D,U,W)}if(X(U))return de(B,D,U,W);if(ne(U)){if(xe=ne(U),typeof xe!="function")throw Error(o(150));return U=xe.call(U),ye(B,D,U,W)}if(typeof U.then=="function")return Fe(B,D,Yi(U),W);if(U.$$typeof===C)return Fe(B,D,zi(B,U),W);$i(B,U)}return typeof U=="string"&&U!==""||typeof U=="number"||typeof U=="bigint"?(U=""+U,D!==null&&D.tag===6?(n(B,D.sibling),W=c(D,U),W.return=B,B=W):(n(B,D),W=Go(U,B.mode,W),W.return=B,B=W),g(B)):n(B,D)}return function(B,D,U,W){try{vs=0;var xe=Fe(B,D,U,W);return Nl=null,xe}catch(he){if(he===jl||he===Hi)throw he;var Ue=Ht(29,he,null,B.mode);return Ue.lanes=W,Ue.return=B,Ue}finally{}}}var Va=rm(!0),om=rm(!1),ia=!1;function ac(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function lc(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function ra(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function oa(e,t,n){var s=e.updateQueue;if(s===null)return null;if(s=s.shared,(Ve&2)!==0){var c=s.pending;return c===null?t.next=t:(t.next=c.next,c.next=t),s.pending=t,t=_i(e),Xd(e,null,n),t}return Di(e,s,t,n),_i(e)}function bs(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194048)!==0)){var s=t.lanes;s&=e.pendingLanes,n|=s,t.lanes=n,ge(e,n)}}function sc(e,t){var n=e.updateQueue,s=e.alternate;if(s!==null&&(s=s.updateQueue,n===s)){var c=null,u=null;if(n=n.firstBaseUpdate,n!==null){do{var g={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};u===null?c=u=g:u=u.next=g,n=n.next}while(n!==null);u===null?c=u=t:u=u.next=t}else c=u=t;n={baseState:s.baseState,firstBaseUpdate:c,lastBaseUpdate:u,shared:s.shared,callbacks:s.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var ic=!1;function Ss(){if(ic){var e=Al;if(e!==null)throw e}}function As(e,t,n,s){ic=!1;var c=e.updateQueue;ia=!1;var u=c.firstBaseUpdate,g=c.lastBaseUpdate,S=c.shared.pending;if(S!==null){c.shared.pending=null;var T=S,V=T.next;T.next=null,g===null?u=V:g.next=V,g=T;var I=e.alternate;I!==null&&(I=I.updateQueue,S=I.lastBaseUpdate,S!==g&&(S===null?I.firstBaseUpdate=V:S.next=V,I.lastBaseUpdate=T))}if(u!==null){var P=c.baseState;g=0,I=V=T=null,S=u;do{var Q=S.lane&-536870913,J=Q!==S.lane;if(J?(Me&Q)===Q:(s&Q)===Q){Q!==0&&Q===Sl&&(ic=!0),I!==null&&(I=I.next={lane:0,tag:S.tag,payload:S.payload,callback:null,next:null});e:{var de=e,ye=S;Q=t;var Fe=n;switch(ye.tag){case 1:if(de=ye.payload,typeof de=="function"){P=de.call(Fe,P,Q);break e}P=de;break e;case 3:de.flags=de.flags&-65537|128;case 0:if(de=ye.payload,Q=typeof de=="function"?de.call(Fe,P,Q):de,Q==null)break e;P=y({},P,Q);break e;case 2:ia=!0}}Q=S.callback,Q!==null&&(e.flags|=64,J&&(e.flags|=8192),J=c.callbacks,J===null?c.callbacks=[Q]:J.push(Q))}else J={lane:Q,tag:S.tag,payload:S.payload,callback:S.callback,next:null},I===null?(V=I=J,T=P):I=I.next=J,g|=Q;if(S=S.next,S===null){if(S=c.shared.pending,S===null)break;J=S,S=J.next,J.next=null,c.lastBaseUpdate=J,c.shared.pending=null}}while(!0);I===null&&(T=P),c.baseState=T,c.firstBaseUpdate=V,c.lastBaseUpdate=I,u===null&&(c.shared.lanes=0),ma|=g,e.lanes=g,e.memoizedState=P}}function cm(e,t){if(typeof e!="function")throw Error(o(191,e));e.call(t)}function um(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;eu?u:8;var g=R.T,S={};R.T=S,wc(e,!1,t,n);try{var T=c(),V=R.S;if(V!==null&&V(S,T),T!==null&&typeof T=="object"&&typeof T.then=="function"){var I=jv(T,s);ws(e,t,I,Xt(e))}else ws(e,t,s,Xt(e))}catch(P){ws(e,t,{then:function(){},status:"rejected",reason:P},Xt())}finally{F.p=u,g!==null&&S.types!==null&&(g.types=S.types),R.T=g}}function kv(){}function jc(e,t,n,s){if(e.tag!==5)throw Error(o(476));var c=Ym(e).queue;Vm(e,c,t,Z,n===null?kv:function(){return $m(e),n(s)})}function Ym(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:Z,baseState:Z,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ln,lastRenderedState:Z},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Ln,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function $m(e){var t=Ym(e);t.next===null&&(t=e.alternate.memoizedState),ws(e,t.next.queue,{},Xt())}function Nc(){return At(Ys)}function Gm(){return rt().memoizedState}function Xm(){return rt().memoizedState}function Mv(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=Xt();e=ra(n);var s=oa(t,e,n);s!==null&&(Ot(s,t,n),bs(s,t,n)),t={cache:Po()},e.payload=t;return}t=t.return}}function Rv(e,t,n){var s=Xt();n={lane:s,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Pi(e)?Fm(t,n):(n=Yo(e,t,n,s),n!==null&&(Ot(n,e,s),Km(n,t,s)))}function Qm(e,t,n){var s=Xt();ws(e,t,n,s)}function ws(e,t,n,s){var c={lane:s,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Pi(e))Fm(t,c);else{var u=e.alternate;if(e.lanes===0&&(u===null||u.lanes===0)&&(u=t.lastRenderedReducer,u!==null))try{var g=t.lastRenderedState,S=u(g,n);if(c.hasEagerState=!0,c.eagerState=S,Ut(S,g))return Di(e,t,c,0),Je===null&&Ti(),!1}catch{}finally{}if(n=Yo(e,t,c,s),n!==null)return Ot(n,e,s),Km(n,t,s),!0}return!1}function wc(e,t,n,s){if(s={lane:2,revertLane:au(),gesture:null,action:s,hasEagerState:!1,eagerState:null,next:null},Pi(e)){if(t)throw Error(o(479))}else t=Yo(e,n,s,2),t!==null&&Ot(t,e,2)}function Pi(e){var t=e.alternate;return e===Ae||t!==null&&t===Ae}function Fm(e,t){Cl=Qi=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Km(e,t,n){if((n&4194048)!==0){var s=t.lanes;s&=e.pendingLanes,n|=s,t.lanes=n,ge(e,n)}}var Cs={readContext:At,use:Zi,useCallback:lt,useContext:lt,useEffect:lt,useImperativeHandle:lt,useLayoutEffect:lt,useInsertionEffect:lt,useMemo:lt,useReducer:lt,useRef:lt,useState:lt,useDebugValue:lt,useDeferredValue:lt,useTransition:lt,useSyncExternalStore:lt,useId:lt,useHostTransitionStatus:lt,useFormState:lt,useActionState:lt,useOptimistic:lt,useMemoCache:lt,useCacheRefresh:lt};Cs.useEffectEvent=lt;var Zm={readContext:At,use:Zi,useCallback:function(e,t){return Et().memoizedState=[e,t===void 0?null:t],e},useContext:At,useEffect:Tm,useImperativeHandle:function(e,t,n){n=n!=null?n.concat([e]):null,Ii(4194308,4,Bm.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Ii(4194308,4,e,t)},useInsertionEffect:function(e,t){Ii(4,2,e,t)},useMemo:function(e,t){var n=Et();t=t===void 0?null:t;var s=e();if(Ya){Kt(!0);try{e()}finally{Kt(!1)}}return n.memoizedState=[s,t],s},useReducer:function(e,t,n){var s=Et();if(n!==void 0){var c=n(t);if(Ya){Kt(!0);try{n(t)}finally{Kt(!1)}}}else c=t;return s.memoizedState=s.baseState=c,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:c},s.queue=e,e=e.dispatch=Rv.bind(null,Ae,e),[s.memoizedState,e]},useRef:function(e){var t=Et();return e={current:e},t.memoizedState=e},useState:function(e){e=vc(e);var t=e.queue,n=Qm.bind(null,Ae,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Sc,useDeferredValue:function(e,t){var n=Et();return Ac(n,e,t)},useTransition:function(){var e=vc(!1);return e=Vm.bind(null,Ae,e.queue,!0,!1),Et().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var s=Ae,c=Et();if(De){if(n===void 0)throw Error(o(407));n=n()}else{if(n=t(),Je===null)throw Error(o(349));(Me&127)!==0||xm(s,t,n)}c.memoizedState=n;var u={value:n,getSnapshot:t};return c.queue=u,Tm(vm.bind(null,s,u,e),[e]),s.flags|=2048,ql(9,{destroy:void 0},gm.bind(null,s,u,n,t),null),n},useId:function(){var e=Et(),t=Je.identifierPrefix;if(De){var n=bn,s=yn;n=(s&~(1<<32-ct(s)-1)).toString(32)+n,t="_"+t+"R_"+n,n=Fi++,0<\/script>",u=u.removeChild(u.firstChild);break;case"select":u=typeof s.is=="string"?g.createElement("select",{is:s.is}):g.createElement("select"),s.multiple?u.multiple=!0:s.size&&(u.size=s.size);break;default:u=typeof s.is=="string"?g.createElement(c,{is:s.is}):g.createElement(c)}}u[at]=t,u[ze]=s;e:for(g=t.child;g!==null;){if(g.tag===5||g.tag===6)u.appendChild(g.stateNode);else if(g.tag!==4&&g.tag!==27&&g.child!==null){g.child.return=g,g=g.child;continue}if(g===t)break e;for(;g.sibling===null;){if(g.return===null||g.return===t)break e;g=g.return}g.sibling.return=g.return,g=g.sibling}t.stateNode=u;e:switch(Nt(u,c,s),c){case"button":case"input":case"select":case"textarea":s=!!s.autoFocus;break e;case"img":s=!0;break e;default:s=!1}s&&Un(t)}}return Pe(t),Uc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==s&&Un(t);else{if(typeof s!="string"&&t.stateNode===null)throw Error(o(166));if(e=re.current,yl(t)){if(e=t.stateNode,n=t.memoizedProps,s=null,c=St,c!==null)switch(c.tag){case 27:case 5:s=c.memoizedProps}e[at]=t,e=!!(e.nodeValue===n||s!==null&&s.suppressHydrationWarning===!0||h0(e.nodeValue,n)),e||la(t,!0)}else e=yr(e).createTextNode(s),e[at]=t,t.stateNode=e}return Pe(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(s=yl(t),n!==null){if(e===null){if(!s)throw Error(o(318));if(e=t.memoizedState,e=e!==null?e.dehydrated:null,!e)throw Error(o(557));e[at]=t}else Oa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Pe(t),e=!1}else n=Zo(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(Yt(t),t):(Yt(t),null);if((t.flags&128)!==0)throw Error(o(558))}return Pe(t),null;case 13:if(s=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(c=yl(t),s!==null&&s.dehydrated!==null){if(e===null){if(!c)throw Error(o(318));if(c=t.memoizedState,c=c!==null?c.dehydrated:null,!c)throw Error(o(317));c[at]=t}else Oa(),(t.flags&128)===0&&(t.memoizedState=null),t.flags|=4;Pe(t),c=!1}else c=Zo(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=c),c=!0;if(!c)return t.flags&256?(Yt(t),t):(Yt(t),null)}return Yt(t),(t.flags&128)!==0?(t.lanes=n,t):(n=s!==null,e=e!==null&&e.memoizedState!==null,n&&(s=t.child,c=null,s.alternate!==null&&s.alternate.memoizedState!==null&&s.alternate.memoizedState.cachePool!==null&&(c=s.alternate.memoizedState.cachePool.pool),u=null,s.memoizedState!==null&&s.memoizedState.cachePool!==null&&(u=s.memoizedState.cachePool.pool),u!==c&&(s.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),lr(t,t.updateQueue),Pe(t),null);case 4:return pe(),e===null&&ru(t.stateNode.containerInfo),Pe(t),null;case 10:return On(t.type),Pe(t),null;case 19:if(H(it),s=t.memoizedState,s===null)return Pe(t),null;if(c=(t.flags&128)!==0,u=s.rendering,u===null)if(c)qs(s,!1);else{if(st!==0||e!==null&&(e.flags&128)!==0)for(e=t.child;e!==null;){if(u=Xi(e),u!==null){for(t.flags|=128,qs(s,!1),e=u.updateQueue,t.updateQueue=e,lr(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)Qd(n,e),n=n.sibling;return ee(it,it.current&1|2),De&&Dn(t,s.treeForkCount),t.child}e=e.sibling}s.tail!==null&&pt()>cr&&(t.flags|=128,c=!0,qs(s,!1),t.lanes=4194304)}else{if(!c)if(e=Xi(u),e!==null){if(t.flags|=128,c=!0,e=e.updateQueue,t.updateQueue=e,lr(t,e),qs(s,!0),s.tail===null&&s.tailMode==="hidden"&&!u.alternate&&!De)return Pe(t),null}else 2*pt()-s.renderingStartTime>cr&&n!==536870912&&(t.flags|=128,c=!0,qs(s,!1),t.lanes=4194304);s.isBackwards?(u.sibling=t.child,t.child=u):(e=s.last,e!==null?e.sibling=u:t.child=u,s.last=u)}return s.tail!==null?(e=s.tail,s.rendering=e,s.tail=e.sibling,s.renderingStartTime=pt(),e.sibling=null,n=it.current,ee(it,c?n&1|2:n&1),De&&Dn(t,s.treeForkCount),e):(Pe(t),null);case 22:case 23:return Yt(t),oc(),s=t.memoizedState!==null,e!==null?e.memoizedState!==null!==s&&(t.flags|=8192):s&&(t.flags|=8192),s?(n&536870912)!==0&&(t.flags&128)===0&&(Pe(t),t.subtreeFlags&6&&(t.flags|=8192)):Pe(t),n=t.updateQueue,n!==null&&lr(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),s=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(s=t.memoizedState.cachePool.pool),s!==n&&(t.flags|=2048),e!==null&&H(za),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),On(ut),Pe(t),null;case 25:return null;case 30:return null}throw Error(o(156,t.tag))}function Bv(e,t){switch(Fo(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return On(ut),pe(),e=t.flags,(e&65536)!==0&&(e&128)===0?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return te(t),null;case 31:if(t.memoizedState!==null){if(Yt(t),t.alternate===null)throw Error(o(340));Oa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Yt(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(o(340));Oa()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return H(it),null;case 4:return pe(),null;case 10:return On(t.type),null;case 22:case 23:return Yt(t),oc(),e!==null&&H(za),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return On(ut),null;case 25:return null;default:return null}}function yh(e,t){switch(Fo(t),t.tag){case 3:On(ut),pe();break;case 26:case 27:case 5:te(t);break;case 4:pe();break;case 31:t.memoizedState!==null&&Yt(t);break;case 13:Yt(t);break;case 19:H(it);break;case 10:On(t.type);break;case 22:case 23:Yt(t),oc(),e!==null&&H(za);break;case 24:On(ut)}}function ks(e,t){try{var n=t.updateQueue,s=n!==null?n.lastEffect:null;if(s!==null){var c=s.next;n=c;do{if((n.tag&e)===e){s=void 0;var u=n.create,g=n.inst;s=u(),g.destroy=s}n=n.next}while(n!==c)}}catch(S){Ge(t,t.return,S)}}function fa(e,t,n){try{var s=t.updateQueue,c=s!==null?s.lastEffect:null;if(c!==null){var u=c.next;s=u;do{if((s.tag&e)===e){var g=s.inst,S=g.destroy;if(S!==void 0){g.destroy=void 0,c=t;var T=n,V=S;try{V()}catch(I){Ge(c,T,I)}}}s=s.next}while(s!==u)}}catch(I){Ge(t,t.return,I)}}function bh(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{um(t,n)}catch(s){Ge(e,e.return,s)}}}function Sh(e,t,n){n.props=$a(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(s){Ge(e,t,s)}}function Ms(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var s=e.stateNode;break;case 30:s=e.stateNode;break;default:s=e.stateNode}typeof n=="function"?e.refCleanup=n(s):n.current=s}}catch(c){Ge(e,t,c)}}function Sn(e,t){var n=e.ref,s=e.refCleanup;if(n!==null)if(typeof s=="function")try{s()}catch(c){Ge(e,t,c)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n=="function")try{n(null)}catch(c){Ge(e,t,c)}else n.current=null}function Ah(e){var t=e.type,n=e.memoizedProps,s=e.stateNode;try{e:switch(t){case"button":case"input":case"select":case"textarea":n.autoFocus&&s.focus();break e;case"img":n.src?s.src=n.src:n.srcSet&&(s.srcset=n.srcSet)}}catch(c){Ge(e,e.return,c)}}function Hc(e,t,n){try{var s=e.stateNode;ly(s,e.type,n,t),s[ze]=t}catch(c){Ge(e,e.return,c)}}function jh(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&va(e.type)||e.tag===4}function Vc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||jh(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&va(e.type)||e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Yc(e,t,n){var s=e.tag;if(s===5||s===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName==="HTML"?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName==="HTML"?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=Mn));else if(s!==4&&(s===27&&va(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(Yc(e,t,n),e=e.sibling;e!==null;)Yc(e,t,n),e=e.sibling}function sr(e,t,n){var s=e.tag;if(s===5||s===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(s!==4&&(s===27&&va(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(sr(e,t,n),e=e.sibling;e!==null;)sr(e,t,n),e=e.sibling}function Nh(e){var t=e.stateNode,n=e.memoizedProps;try{for(var s=e.type,c=t.attributes;c.length;)t.removeAttributeNode(c[0]);Nt(t,s,n),t[at]=e,t[ze]=n}catch(u){Ge(e,e.return,u)}}var Hn=!1,mt=!1,$c=!1,wh=typeof WeakSet=="function"?WeakSet:Set,yt=null;function Lv(e,t){if(e=e.containerInfo,uu=Cr,e=Ld(e),Bo(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var s=n.getSelection&&n.getSelection();if(s&&s.rangeCount!==0){n=s.anchorNode;var c=s.anchorOffset,u=s.focusNode;s=s.focusOffset;try{n.nodeType,u.nodeType}catch{n=null;break e}var g=0,S=-1,T=-1,V=0,I=0,P=e,Q=null;t:for(;;){for(var J;P!==n||c!==0&&P.nodeType!==3||(S=g+c),P!==u||s!==0&&P.nodeType!==3||(T=g+s),P.nodeType===3&&(g+=P.nodeValue.length),(J=P.firstChild)!==null;)Q=P,P=J;for(;;){if(P===e)break t;if(Q===n&&++V===c&&(S=g),Q===u&&++I===s&&(T=g),(J=P.nextSibling)!==null)break;P=Q,Q=P.parentNode}P=J}n=S===-1||T===-1?null:{start:S,end:T}}else n=null}n=n||{start:0,end:0}}else n=null;for(fu={focusedElem:e,selectionRange:n},Cr=!1,yt=t;yt!==null;)if(t=yt,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,yt=e;else for(;yt!==null;){switch(t=yt,u=t.alternate,e=t.flags,t.tag){case 0:if((e&4)!==0&&(e=t.updateQueue,e=e!==null?e.events:null,e!==null))for(n=0;n title"))),Nt(u,s,n),u[at]=e,vt(u),s=u;break e;case"link":var g=R0("link","href",c).get(s+(n.href||""));if(g){for(var S=0;SFe&&(g=Fe,Fe=ye,ye=g);var B=Od(S,ye),D=Od(S,Fe);if(B&&D&&(J.rangeCount!==1||J.anchorNode!==B.node||J.anchorOffset!==B.offset||J.focusNode!==D.node||J.focusOffset!==D.offset)){var U=P.createRange();U.setStart(B.node,B.offset),J.removeAllRanges(),ye>Fe?(J.addRange(U),J.extend(D.node,D.offset)):(U.setEnd(D.node,D.offset),J.addRange(U))}}}}for(P=[],J=S;J=J.parentNode;)J.nodeType===1&&P.push({element:J,left:J.scrollLeft,top:J.scrollTop});for(typeof S.focus=="function"&&S.focus(),S=0;Sn?32:n,R.T=null,n=Jc,Jc=null;var u=pa,g=Xn;if(xt=0,Dl=pa=null,Xn=0,(Ve&6)!==0)throw Error(o(331));var S=Ve;if(Ve|=4,Bh(u.current),Dh(u,u.current,g,n),Ve=S,Bs(0,!1),gt&&typeof gt.onPostCommitFiberRoot=="function")try{gt.onPostCommitFiberRoot(fn,u)}catch{}return!0}finally{F.p=c,R.T=s,e0(e,t)}}function n0(e,t,n){t=en(n,t),t=kc(e.stateNode,t,2),e=oa(e,t,2),e!==null&&(qa(e,2),An(e))}function Ge(e,t,n){if(e.tag===3)n0(e,e,n);else for(;t!==null;){if(t.tag===3){n0(t,e,n);break}else if(t.tag===1){var s=t.stateNode;if(typeof t.type.getDerivedStateFromError=="function"||typeof s.componentDidCatch=="function"&&(ha===null||!ha.has(s))){e=en(n,e),n=ah(2),s=oa(t,n,2),s!==null&&(lh(n,s,t,e),qa(s,2),An(s));break}}t=t.return}}function eu(e,t,n){var s=e.pingCache;if(s===null){s=e.pingCache=new Hv;var c=new Set;s.set(t,c)}else c=s.get(t),c===void 0&&(c=new Set,s.set(t,c));c.has(n)||(Qc=!0,c.add(n),e=Xv.bind(null,e,t,n),t.then(e,e))}function Xv(e,t,n){var s=e.pingCache;s!==null&&s.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,Je===e&&(Me&n)===n&&(st===4||st===3&&(Me&62914560)===Me&&300>pt()-or?(Ve&2)===0&&_l(e,0):Fc|=n,Tl===Me&&(Tl=0)),An(e)}function a0(e,t){t===0&&(t=yi()),e=Da(e,t),e!==null&&(qa(e,t),An(e))}function Qv(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),a0(e,n)}function Fv(e,t){var n=0;switch(e.tag){case 31:case 13:var s=e.stateNode,c=e.memoizedState;c!==null&&(n=c.retryLane);break;case 19:s=e.stateNode;break;case 22:s=e.stateNode._retryCache;break;default:throw Error(o(314))}s!==null&&s.delete(t),a0(e,n)}function Kv(e,t){return Te(e,t)}var pr=null,Bl=null,tu=!1,xr=!1,nu=!1,ga=0;function An(e){e!==Bl&&e.next===null&&(Bl===null?pr=Bl=e:Bl=Bl.next=e),xr=!0,tu||(tu=!0,Jv())}function Bs(e,t){if(!nu&&xr){nu=!0;do for(var n=!1,s=pr;s!==null;){if(e!==0){var c=s.pendingLanes;if(c===0)var u=0;else{var g=s.suspendedLanes,S=s.pingedLanes;u=(1<<31-ct(42|e)+1)-1,u&=c&~(g&~S),u=u&201326741?u&201326741|1:u?u|2:0}u!==0&&(n=!0,r0(s,u))}else u=Me,u=ea(s,s===Je?u:0,s.cancelPendingCommit!==null||s.timeoutHandle!==-1),(u&3)===0||vn(s,u)||(n=!0,r0(s,u));s=s.next}while(n);nu=!1}}function Zv(){l0()}function l0(){xr=tu=!1;var e=0;ga!==0&&iy()&&(e=ga);for(var t=pt(),n=null,s=pr;s!==null;){var c=s.next,u=s0(s,t);u===0?(s.next=null,n===null?pr=c:n.next=c,c===null&&(Bl=n)):(n=s,(e!==0||(u&3)!==0)&&(xr=!0)),s=c}xt!==0&&xt!==5||Bs(e),ga!==0&&(ga=0)}function s0(e,t){for(var n=e.suspendedLanes,s=e.pingedLanes,c=e.expirationTimes,u=e.pendingLanes&-62914561;0S)break;var I=T.transferSize,P=T.initiatorType;I&&p0(P)&&(T=T.responseEnd,g+=I*(T"u"?null:document;function E0(e,t,n){var s=Ll;if(s&&typeof t=="string"&&t){var c=Wt(t);c='link[rel="'+e+'"][href="'+c+'"]',typeof n=="string"&&(c+='[crossorigin="'+n+'"]'),C0.has(c)||(C0.add(c),e={rel:e,crossOrigin:n,href:t},s.querySelector(c)===null&&(t=s.createElement("link"),Nt(t,"link",e),vt(t),s.head.appendChild(t)))}}function py(e){Qn.D(e),E0("dns-prefetch",e,null)}function xy(e,t){Qn.C(e,t),E0("preconnect",e,t)}function gy(e,t,n){Qn.L(e,t,n);var s=Ll;if(s&&e&&t){var c='link[rel="preload"][as="'+Wt(t)+'"]';t==="image"&&n&&n.imageSrcSet?(c+='[imagesrcset="'+Wt(n.imageSrcSet)+'"]',typeof n.imageSizes=="string"&&(c+='[imagesizes="'+Wt(n.imageSizes)+'"]')):c+='[href="'+Wt(e)+'"]';var u=c;switch(t){case"style":u=zl(e);break;case"script":u=Ul(e)}rn.has(u)||(e=y({rel:"preload",href:t==="image"&&n&&n.imageSrcSet?void 0:e,as:t},n),rn.set(u,e),s.querySelector(c)!==null||t==="style"&&s.querySelector(Hs(u))||t==="script"&&s.querySelector(Vs(u))||(t=s.createElement("link"),Nt(t,"link",e),vt(t),s.head.appendChild(t)))}}function vy(e,t){Qn.m(e,t);var n=Ll;if(n&&e){var s=t&&typeof t.as=="string"?t.as:"script",c='link[rel="modulepreload"][as="'+Wt(s)+'"][href="'+Wt(e)+'"]',u=c;switch(s){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":u=Ul(e)}if(!rn.has(u)&&(e=y({rel:"modulepreload",href:e},t),rn.set(u,e),n.querySelector(c)===null)){switch(s){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(n.querySelector(Vs(u)))return}s=n.createElement("link"),Nt(s,"link",e),vt(s),n.head.appendChild(s)}}}function yy(e,t,n){Qn.S(e,t,n);var s=Ll;if(s&&e){var c=il(s).hoistableStyles,u=zl(e);t=t||"default";var g=c.get(u);if(!g){var S={loading:0,preload:null};if(g=s.querySelector(Hs(u)))S.loading=5;else{e=y({rel:"stylesheet",href:e,"data-precedence":t},n),(n=rn.get(u))&&vu(e,n);var T=g=s.createElement("link");vt(T),Nt(T,"link",e),T._p=new Promise(function(V,I){T.onload=V,T.onerror=I}),T.addEventListener("load",function(){S.loading|=1}),T.addEventListener("error",function(){S.loading|=2}),S.loading|=4,Sr(g,t,s)}g={type:"stylesheet",instance:g,count:1,state:S},c.set(u,g)}}}function by(e,t){Qn.X(e,t);var n=Ll;if(n&&e){var s=il(n).hoistableScripts,c=Ul(e),u=s.get(c);u||(u=n.querySelector(Vs(c)),u||(e=y({src:e,async:!0},t),(t=rn.get(c))&&yu(e,t),u=n.createElement("script"),vt(u),Nt(u,"link",e),n.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},s.set(c,u))}}function Sy(e,t){Qn.M(e,t);var n=Ll;if(n&&e){var s=il(n).hoistableScripts,c=Ul(e),u=s.get(c);u||(u=n.querySelector(Vs(c)),u||(e=y({src:e,async:!0,type:"module"},t),(t=rn.get(c))&&yu(e,t),u=n.createElement("script"),vt(u),Nt(u,"link",e),n.head.appendChild(u)),u={type:"script",instance:u,count:1,state:null},s.set(c,u))}}function q0(e,t,n,s){var c=(c=re.current)?br(c):null;if(!c)throw Error(o(446));switch(e){case"meta":case"title":return null;case"style":return typeof n.precedence=="string"&&typeof n.href=="string"?(t=zl(n.href),n=il(c).hoistableStyles,s=n.get(t),s||(s={type:"style",instance:null,count:0,state:null},n.set(t,s)),s):{type:"void",instance:null,count:0,state:null};case"link":if(n.rel==="stylesheet"&&typeof n.href=="string"&&typeof n.precedence=="string"){e=zl(n.href);var u=il(c).hoistableStyles,g=u.get(e);if(g||(c=c.ownerDocument||c,g={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},u.set(e,g),(u=c.querySelector(Hs(e)))&&!u._p&&(g.instance=u,g.state.loading=5),rn.has(e)||(n={rel:"preload",as:"style",href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},rn.set(e,n),u||Ay(c,e,n,g.state))),t&&s===null)throw Error(o(528,""));return g}if(t&&s!==null)throw Error(o(529,""));return null;case"script":return t=n.async,n=n.src,typeof n=="string"&&t&&typeof t!="function"&&typeof t!="symbol"?(t=Ul(n),n=il(c).hoistableScripts,s=n.get(t),s||(s={type:"script",instance:null,count:0,state:null},n.set(t,s)),s):{type:"void",instance:null,count:0,state:null};default:throw Error(o(444,e))}}function zl(e){return'href="'+Wt(e)+'"'}function Hs(e){return'link[rel="stylesheet"]['+e+"]"}function k0(e){return y({},e,{"data-precedence":e.precedence,precedence:null})}function Ay(e,t,n,s){e.querySelector('link[rel="preload"][as="style"]['+t+"]")?s.loading=1:(t=e.createElement("link"),s.preload=t,t.addEventListener("load",function(){return s.loading|=1}),t.addEventListener("error",function(){return s.loading|=2}),Nt(t,"link",n),vt(t),e.head.appendChild(t))}function Ul(e){return'[src="'+Wt(e)+'"]'}function Vs(e){return"script[async]"+e}function M0(e,t,n){if(t.count++,t.instance===null)switch(t.type){case"style":var s=e.querySelector('style[data-href~="'+Wt(n.href)+'"]');if(s)return t.instance=s,vt(s),s;var c=y({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return s=(e.ownerDocument||e).createElement("style"),vt(s),Nt(s,"style",c),Sr(s,n.precedence,e),t.instance=s;case"stylesheet":c=zl(n.href);var u=e.querySelector(Hs(c));if(u)return t.state.loading|=4,t.instance=u,vt(u),u;s=k0(n),(c=rn.get(c))&&vu(s,c),u=(e.ownerDocument||e).createElement("link"),vt(u);var g=u;return g._p=new Promise(function(S,T){g.onload=S,g.onerror=T}),Nt(u,"link",s),t.state.loading|=4,Sr(u,n.precedence,e),t.instance=u;case"script":return u=Ul(n.src),(c=e.querySelector(Vs(u)))?(t.instance=c,vt(c),c):(s=n,(c=rn.get(u))&&(s=y({},n),yu(s,c)),e=e.ownerDocument||e,c=e.createElement("script"),vt(c),Nt(c,"link",s),e.head.appendChild(c),t.instance=c);case"void":return null;default:throw Error(o(443,t.type))}else t.type==="stylesheet"&&(t.state.loading&4)===0&&(s=t.instance,t.state.loading|=4,Sr(s,n.precedence,e));return t.instance}function Sr(e,t,n){for(var s=n.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),c=s.length?s[s.length-1]:null,u=c,g=0;g title"):null)}function jy(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case"meta":case"title":return!0;case"style":if(typeof t.precedence!="string"||typeof t.href!="string"||t.href==="")break;return!0;case"link":if(typeof t.rel!="string"||typeof t.href!="string"||t.href===""||t.onLoad||t.onError)break;switch(t.rel){case"stylesheet":return e=t.disabled,typeof t.precedence=="string"&&e==null;default:return!0}case"script":if(t.async&&typeof t.async!="function"&&typeof t.async!="symbol"&&!t.onLoad&&!t.onError&&t.src&&typeof t.src=="string")return!0}return!1}function D0(e){return!(e.type==="stylesheet"&&(e.state.loading&3)===0)}function Ny(e,t,n,s){if(n.type==="stylesheet"&&(typeof s.media!="string"||matchMedia(s.media).matches!==!1)&&(n.state.loading&4)===0){if(n.instance===null){var c=zl(s.href),u=t.querySelector(Hs(c));if(u){t=u._p,t!==null&&typeof t=="object"&&typeof t.then=="function"&&(e.count++,e=jr.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=u,vt(u);return}u=t.ownerDocument||t,s=k0(s),(c=rn.get(c))&&vu(s,c),u=u.createElement("link"),vt(u);var g=u;g._p=new Promise(function(S,T){g.onload=S,g.onerror=T}),Nt(u,"link",s),n.instance=u}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&(n.state.loading&3)===0&&(e.count++,n=jr.bind(e),t.addEventListener("load",n),t.addEventListener("error",n))}}var bu=0;function wy(e,t){return e.stylesheets&&e.count===0&&wr(e,e.stylesheets),0bu?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(s),clearTimeout(c)}}:null}function jr(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)wr(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Nr=null;function wr(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Nr=new Map,t.forEach(Cy,e),Nr=null,jr.call(e))}function Cy(e,t){if(!(t.state.loading&4)){var n=Nr.get(e);if(n)var s=n.get(null);else{n=new Map,Nr.set(e,n);for(var c=e.querySelectorAll("link[data-precedence],style[data-precedence]"),u=0;u"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(a)}catch(l){console.error(l)}}return a(),ku.exports=$y(),ku.exports}var Xy=Gy();var ap="popstate";function Qy(a={}){function l(o,f){let{pathname:d,search:h,hash:p}=o.location;return lf("",{pathname:d,search:h,hash:p},f.state&&f.state.usr||null,f.state&&f.state.key||"default")}function i(o,f){return typeof f=="string"?f:li(f)}return Ky(l,i,null,a)}function nt(a,l){if(a===!1||a===null||typeof a>"u")throw new Error(l)}function gn(a,l){if(!a){typeof console<"u"&&console.warn(l);try{throw new Error(l)}catch{}}}function Fy(){return Math.random().toString(36).substring(2,10)}function lp(a,l){return{usr:a.state,key:a.key,idx:l}}function lf(a,l,i=null,o){return{pathname:typeof a=="string"?a:a.pathname,search:"",hash:"",...typeof l=="string"?Il(l):l,state:i,key:l&&l.key||o||Fy()}}function li({pathname:a="/",search:l="",hash:i=""}){return l&&l!=="?"&&(a+=l.charAt(0)==="?"?l:"?"+l),i&&i!=="#"&&(a+=i.charAt(0)==="#"?i:"#"+i),a}function Il(a){let l={};if(a){let i=a.indexOf("#");i>=0&&(l.hash=a.substring(i),a=a.substring(0,i));let o=a.indexOf("?");o>=0&&(l.search=a.substring(o),a=a.substring(0,o)),a&&(l.pathname=a)}return l}function Ky(a,l,i,o={}){let{window:f=document.defaultView,v5Compat:d=!1}=o,h=f.history,p="POP",x=null,v=b();v==null&&(v=0,h.replaceState({...h.state,idx:v},""));function b(){return(h.state||{idx:null}).idx}function y(){p="POP";let j=b(),k=j==null?null:j-v;v=j,x&&x({action:p,location:w.location,delta:k})}function N(j,k){p="PUSH";let A=lf(w.location,j,k);v=b()+1;let C=lp(A,v),_=w.createHref(A);try{h.pushState(C,"",_)}catch(L){if(L instanceof DOMException&&L.name==="DataCloneError")throw L;f.location.assign(_)}d&&x&&x({action:p,location:w.location,delta:1})}function M(j,k){p="REPLACE";let A=lf(w.location,j,k);v=b();let C=lp(A,v),_=w.createHref(A);h.replaceState(C,"",_),d&&x&&x({action:p,location:w.location,delta:0})}function E(j){return Zy(j)}let w={get action(){return p},get location(){return a(f,h)},listen(j){if(x)throw new Error("A history only accepts one active listener");return f.addEventListener(ap,y),x=j,()=>{f.removeEventListener(ap,y),x=null}},createHref(j){return l(f,j)},createURL:E,encodeLocation(j){let k=E(j);return{pathname:k.pathname,search:k.search,hash:k.hash}},push:N,replace:M,go(j){return h.go(j)}};return w}function Zy(a,l=!1){let i="http://localhost";typeof window<"u"&&(i=window.location.origin!=="null"?window.location.origin:window.location.href),nt(i,"No window.location.(origin|href) available to create URL");let o=typeof a=="string"?a:li(a);return o=o.replace(/ $/,"%20"),!l&&o.startsWith("//")&&(o=i+o),new URL(o,i)}function Ip(a,l,i="/"){return Jy(a,l,i,!1)}function Jy(a,l,i,o){let f=typeof l=="string"?Il(l):l,d=Wn(f.pathname||"/",i);if(d==null)return null;let h=Wp(a);Iy(h);let p=null;for(let x=0;p==null&&x{let b={relativePath:v===void 0?h.path||"":v,caseSensitive:h.caseSensitive===!0,childrenIndex:p,route:h};if(b.relativePath.startsWith("/")){if(!b.relativePath.startsWith(o)&&x)return;nt(b.relativePath.startsWith(o),`Absolute route path "${b.relativePath}" nested under path "${o}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),b.relativePath=b.relativePath.slice(o.length)}let y=In([o,b.relativePath]),N=i.concat(b);h.children&&h.children.length>0&&(nt(h.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${y}".`),Wp(h.children,l,N,y,x)),!(h.path==null&&!h.index)&&l.push({path:y,score:lb(y,h.index),routesMeta:N})};return a.forEach((h,p)=>{if(h.path===""||!h.path?.includes("?"))d(h,p);else for(let x of Pp(h.path))d(h,p,!0,x)}),l}function Pp(a){let l=a.split("/");if(l.length===0)return[];let[i,...o]=l,f=i.endsWith("?"),d=i.replace(/\?$/,"");if(o.length===0)return f?[d,""]:[d];let h=Pp(o.join("/")),p=[];return p.push(...h.map(x=>x===""?d:[d,x].join("/"))),f&&p.push(...h),p.map(x=>a.startsWith("/")&&x===""?"/":x)}function Iy(a){a.sort((l,i)=>l.score!==i.score?i.score-l.score:sb(l.routesMeta.map(o=>o.childrenIndex),i.routesMeta.map(o=>o.childrenIndex)))}var Wy=/^:[\w-]+$/,Py=3,eb=2,tb=1,nb=10,ab=-2,sp=a=>a==="*";function lb(a,l){let i=a.split("/"),o=i.length;return i.some(sp)&&(o+=ab),l&&(o+=eb),i.filter(f=>!sp(f)).reduce((f,d)=>f+(Wy.test(d)?Py:d===""?tb:nb),o)}function sb(a,l){return a.length===l.length&&a.slice(0,-1).every((o,f)=>o===l[f])?a[a.length-1]-l[l.length-1]:0}function ib(a,l,i=!1){let{routesMeta:o}=a,f={},d="/",h=[];for(let p=0;p{if(b==="*"){let E=p[N]||"";h=d.slice(0,d.length-E.length).replace(/(.)\/+$/,"$1")}const M=p[N];return y&&!M?v[b]=void 0:v[b]=(M||"").replace(/%2F/g,"/"),v},{}),pathname:d,pathnameBase:h,pattern:a}}function rb(a,l=!1,i=!0){gn(a==="*"||!a.endsWith("*")||a.endsWith("/*"),`Route path "${a}" will be treated as if it were "${a.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${a.replace(/\*$/,"/*")}".`);let o=[],f="^"+a.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(h,p,x)=>(o.push({paramName:p,isOptional:x!=null}),x?"/?([^\\/]+)?":"/([^\\/]+)")).replace(/\/([\w-]+)\?(\/|$)/g,"(/$1)?$2");return a.endsWith("*")?(o.push({paramName:"*"}),f+=a==="*"||a==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):i?f+="\\/*$":a!==""&&a!=="/"&&(f+="(?:(?=\\/|$))"),[new RegExp(f,l?void 0:"i"),o]}function ob(a){try{return a.split("/").map(l=>decodeURIComponent(l).replace(/\//g,"%2F")).join("/")}catch(l){return gn(!1,`The URL path "${a}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${l}).`),a}}function Wn(a,l){if(l==="/")return a;if(!a.toLowerCase().startsWith(l.toLowerCase()))return null;let i=l.endsWith("/")?l.length-1:l.length,o=a.charAt(i);return o&&o!=="/"?null:a.slice(i)||"/"}var cb=/^(?:[a-z][a-z0-9+.-]*:|\/\/)/i,ub=a=>cb.test(a);function fb(a,l="/"){let{pathname:i,search:o="",hash:f=""}=typeof a=="string"?Il(a):a,d;if(i)if(ub(i))d=i;else{if(i.includes("//")){let h=i;i=i.replace(/\/\/+/g,"/"),gn(!1,`Pathnames cannot have embedded double slashes - normalizing ${h} -> ${i}`)}i.startsWith("/")?d=ip(i.substring(1),"/"):d=ip(i,l)}else d=l;return{pathname:d,search:hb(o),hash:pb(f)}}function ip(a,l){let i=l.replace(/\/+$/,"").split("/");return a.split("/").forEach(f=>{f===".."?i.length>1&&i.pop():f!=="."&&i.push(f)}),i.length>1?i.join("/"):"/"}function Du(a,l,i,o){return`Cannot include a '${a}' character in a manually specified \`to.${l}\` field [${JSON.stringify(o)}]. Please separate it out to the \`to.${i}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function db(a){return a.filter((l,i)=>i===0||l.route.path&&l.route.path.length>0)}function ex(a){let l=db(a);return l.map((i,o)=>o===l.length-1?i.pathname:i.pathnameBase)}function tx(a,l,i,o=!1){let f;typeof a=="string"?f=Il(a):(f={...a},nt(!f.pathname||!f.pathname.includes("?"),Du("?","pathname","search",f)),nt(!f.pathname||!f.pathname.includes("#"),Du("#","pathname","hash",f)),nt(!f.search||!f.search.includes("#"),Du("#","search","hash",f)));let d=a===""||f.pathname==="",h=d?"/":f.pathname,p;if(h==null)p=i;else{let y=l.length-1;if(!o&&h.startsWith("..")){let N=h.split("/");for(;N[0]==="..";)N.shift(),y-=1;f.pathname=N.join("/")}p=y>=0?l[y]:"/"}let x=fb(f,p),v=h&&h!=="/"&&h.endsWith("/"),b=(d||h===".")&&i.endsWith("/");return!x.pathname.endsWith("/")&&(v||b)&&(x.pathname+="/"),x}var In=a=>a.join("/").replace(/\/\/+/g,"/"),mb=a=>a.replace(/\/+$/,"").replace(/^\/*/,"/"),hb=a=>!a||a==="?"?"":a.startsWith("?")?a:"?"+a,pb=a=>!a||a==="#"?"":a.startsWith("#")?a:"#"+a;function xb(a){return a!=null&&typeof a.status=="number"&&typeof a.statusText=="string"&&typeof a.internal=="boolean"&&"data"in a}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");var nx=["POST","PUT","PATCH","DELETE"];new Set(nx);var gb=["GET",...nx];new Set(gb);var Wl=m.createContext(null);Wl.displayName="DataRouter";var no=m.createContext(null);no.displayName="DataRouterState";m.createContext(!1);var ax=m.createContext({isTransitioning:!1});ax.displayName="ViewTransition";var vb=m.createContext(new Map);vb.displayName="Fetchers";var yb=m.createContext(null);yb.displayName="Await";var En=m.createContext(null);En.displayName="Navigation";var di=m.createContext(null);di.displayName="Location";var Pn=m.createContext({outlet:null,matches:[],isDataRoute:!1});Pn.displayName="Route";var Nf=m.createContext(null);Nf.displayName="RouteError";function bb(a,{relative:l}={}){nt(mi(),"useHref() may be used only in the context of a component.");let{basename:i,navigator:o}=m.useContext(En),{hash:f,pathname:d,search:h}=hi(a,{relative:l}),p=d;return i!=="/"&&(p=d==="/"?i:In([i,d])),o.createHref({pathname:p,search:h,hash:f})}function mi(){return m.useContext(di)!=null}function Wa(){return nt(mi(),"useLocation() may be used only in the context of a component."),m.useContext(di).location}var lx="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function sx(a){m.useContext(En).static||m.useLayoutEffect(a)}function Sb(){let{isDataRoute:a}=m.useContext(Pn);return a?_b():Ab()}function Ab(){nt(mi(),"useNavigate() may be used only in the context of a component.");let a=m.useContext(Wl),{basename:l,navigator:i}=m.useContext(En),{matches:o}=m.useContext(Pn),{pathname:f}=Wa(),d=JSON.stringify(ex(o)),h=m.useRef(!1);return sx(()=>{h.current=!0}),m.useCallback((x,v={})=>{if(gn(h.current,lx),!h.current)return;if(typeof x=="number"){i.go(x);return}let b=tx(x,JSON.parse(d),f,v.relative==="path");a==null&&l!=="/"&&(b.pathname=b.pathname==="/"?l:In([l,b.pathname])),(v.replace?i.replace:i.push)(b,v.state,v)},[l,i,d,f,a])}m.createContext(null);function hi(a,{relative:l}={}){let{matches:i}=m.useContext(Pn),{pathname:o}=Wa(),f=JSON.stringify(ex(i));return m.useMemo(()=>tx(a,JSON.parse(f),o,l==="path"),[a,f,o,l])}function jb(a,l){return ix(a,l)}function ix(a,l,i,o,f){nt(mi(),"useRoutes() may be used only in the context of a component.");let{navigator:d}=m.useContext(En),{matches:h}=m.useContext(Pn),p=h[h.length-1],x=p?p.params:{},v=p?p.pathname:"/",b=p?p.pathnameBase:"/",y=p&&p.route;{let A=y&&y.path||"";rx(v,!y||A.endsWith("*")||A.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${v}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. - -Please change the parent to .`)}let N=Wa(),M;if(l){let A=typeof l=="string"?Il(l):l;nt(b==="/"||A.pathname?.startsWith(b),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${b}" but pathname "${A.pathname}" was given in the \`location\` prop.`),M=A}else M=N;let E=M.pathname||"/",w=E;if(b!=="/"){let A=b.replace(/^\//,"").split("/");w="/"+E.replace(/^\//,"").split("/").slice(A.length).join("/")}let j=Ip(a,{pathname:w});gn(y||j!=null,`No routes matched location "${M.pathname}${M.search}${M.hash}" `),gn(j==null||j[j.length-1].route.element!==void 0||j[j.length-1].route.Component!==void 0||j[j.length-1].route.lazy!==void 0,`Matched leaf route at location "${M.pathname}${M.search}${M.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let k=qb(j&&j.map(A=>Object.assign({},A,{params:Object.assign({},x,A.params),pathname:In([b,d.encodeLocation?d.encodeLocation(A.pathname.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:A.pathname]),pathnameBase:A.pathnameBase==="/"?b:In([b,d.encodeLocation?d.encodeLocation(A.pathnameBase.replace(/\?/g,"%3F").replace(/#/g,"%23")).pathname:A.pathnameBase])})),h,i,o,f);return l&&k?m.createElement(di.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...M},navigationType:"POP"}},k):k}function Nb(){let a=Db(),l=xb(a)?`${a.status} ${a.statusText}`:a instanceof Error?a.message:JSON.stringify(a),i=a instanceof Error?a.stack:null,o="rgba(200,200,200, 0.5)",f={padding:"0.5rem",backgroundColor:o},d={padding:"2px 4px",backgroundColor:o},h=null;return console.error("Error handled by React Router default ErrorBoundary:",a),h=m.createElement(m.Fragment,null,m.createElement("p",null,"💿 Hey developer 👋"),m.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",m.createElement("code",{style:d},"ErrorBoundary")," or"," ",m.createElement("code",{style:d},"errorElement")," prop on your route.")),m.createElement(m.Fragment,null,m.createElement("h2",null,"Unexpected Application Error!"),m.createElement("h3",{style:{fontStyle:"italic"}},l),i?m.createElement("pre",{style:f},i):null,h)}var wb=m.createElement(Nb,null),Cb=class extends m.Component{constructor(a){super(a),this.state={location:a.location,revalidation:a.revalidation,error:a.error}}static getDerivedStateFromError(a){return{error:a}}static getDerivedStateFromProps(a,l){return l.location!==a.location||l.revalidation!=="idle"&&a.revalidation==="idle"?{error:a.error,location:a.location,revalidation:a.revalidation}:{error:a.error!==void 0?a.error:l.error,location:l.location,revalidation:a.revalidation||l.revalidation}}componentDidCatch(a,l){this.props.onError?this.props.onError(a,l):console.error("React Router caught the following error during render",a)}render(){return this.state.error!==void 0?m.createElement(Pn.Provider,{value:this.props.routeContext},m.createElement(Nf.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function Eb({routeContext:a,match:l,children:i}){let o=m.useContext(Wl);return o&&o.static&&o.staticContext&&(l.route.errorElement||l.route.ErrorBoundary)&&(o.staticContext._deepestRenderedBoundaryId=l.route.id),m.createElement(Pn.Provider,{value:a},i)}function qb(a,l=[],i=null,o=null,f=null){if(a==null){if(!i)return null;if(i.errors)a=i.matches;else if(l.length===0&&!i.initialized&&i.matches.length>0)a=i.matches;else return null}let d=a,h=i?.errors;if(h!=null){let b=d.findIndex(y=>y.route.id&&h?.[y.route.id]!==void 0);nt(b>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(h).join(",")}`),d=d.slice(0,Math.min(d.length,b+1))}let p=!1,x=-1;if(i)for(let b=0;b=0?d=d.slice(0,x+1):d=[d[0]];break}}}let v=i&&o?(b,y)=>{o(b,{location:i.location,params:i.matches?.[0]?.params??{},errorInfo:y})}:void 0;return d.reduceRight((b,y,N)=>{let M,E=!1,w=null,j=null;i&&(M=h&&y.route.id?h[y.route.id]:void 0,w=y.route.errorElement||wb,p&&(x<0&&N===0?(rx("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),E=!0,j=null):x===N&&(E=!0,j=y.route.hydrateFallbackElement||null)));let k=l.concat(d.slice(0,N+1)),A=()=>{let C;return M?C=w:E?C=j:y.route.Component?C=m.createElement(y.route.Component,null):y.route.element?C=y.route.element:C=b,m.createElement(Eb,{match:y,routeContext:{outlet:b,matches:k,isDataRoute:i!=null},children:C})};return i&&(y.route.ErrorBoundary||y.route.errorElement||N===0)?m.createElement(Cb,{location:i.location,revalidation:i.revalidation,component:w,error:M,children:A(),routeContext:{outlet:null,matches:k,isDataRoute:!0},onError:v}):A()},null)}function wf(a){return`${a} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function kb(a){let l=m.useContext(Wl);return nt(l,wf(a)),l}function Mb(a){let l=m.useContext(no);return nt(l,wf(a)),l}function Rb(a){let l=m.useContext(Pn);return nt(l,wf(a)),l}function Cf(a){let l=Rb(a),i=l.matches[l.matches.length-1];return nt(i.route.id,`${a} can only be used on routes that contain a unique "id"`),i.route.id}function Tb(){return Cf("useRouteId")}function Db(){let a=m.useContext(Nf),l=Mb("useRouteError"),i=Cf("useRouteError");return a!==void 0?a:l.errors?.[i]}function _b(){let{router:a}=kb("useNavigate"),l=Cf("useNavigate"),i=m.useRef(!1);return sx(()=>{i.current=!0}),m.useCallback(async(f,d={})=>{gn(i.current,lx),i.current&&(typeof f=="number"?a.navigate(f):await a.navigate(f,{fromRouteId:l,...d}))},[a,l])}var rp={};function rx(a,l,i){!l&&!rp[a]&&(rp[a]=!0,gn(!1,i))}m.memo(Ob);function Ob({routes:a,future:l,state:i,unstable_onError:o}){return ix(a,void 0,i,o,l)}function Ur(a){nt(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function Bb({basename:a="/",children:l=null,location:i,navigationType:o="POP",navigator:f,static:d=!1}){nt(!mi(),"You cannot render a inside another . You should never have more than one in your app.");let h=a.replace(/^\/*/,"/"),p=m.useMemo(()=>({basename:h,navigator:f,static:d,future:{}}),[h,f,d]);typeof i=="string"&&(i=Il(i));let{pathname:x="/",search:v="",hash:b="",state:y=null,key:N="default"}=i,M=m.useMemo(()=>{let E=Wn(x,h);return E==null?null:{location:{pathname:E,search:v,hash:b,state:y,key:N},navigationType:o}},[h,x,v,b,y,N,o]);return gn(M!=null,` is not able to match the URL "${x}${v}${b}" because it does not start with the basename, so the won't render anything.`),M==null?null:m.createElement(En.Provider,{value:p},m.createElement(di.Provider,{children:l,value:M}))}function Lb({children:a,location:l}){return jb(sf(a),l)}function sf(a,l=[]){let i=[];return m.Children.forEach(a,(o,f)=>{if(!m.isValidElement(o))return;let d=[...l,f];if(o.type===m.Fragment){i.push.apply(i,sf(o.props.children,d));return}nt(o.type===Ur,`[${typeof o.type=="string"?o.type:o.type.name}] is not a component. All component children of must be a or `),nt(!o.props.index||!o.props.children,"An index route cannot have child routes.");let h={id:o.props.id||d.join("-"),caseSensitive:o.props.caseSensitive,element:o.props.element,Component:o.props.Component,index:o.props.index,path:o.props.path,middleware:o.props.middleware,loader:o.props.loader,action:o.props.action,hydrateFallbackElement:o.props.hydrateFallbackElement,HydrateFallback:o.props.HydrateFallback,errorElement:o.props.errorElement,ErrorBoundary:o.props.ErrorBoundary,hasErrorBoundary:o.props.hasErrorBoundary===!0||o.props.ErrorBoundary!=null||o.props.errorElement!=null,shouldRevalidate:o.props.shouldRevalidate,handle:o.props.handle,lazy:o.props.lazy};o.props.children&&(h.children=sf(o.props.children,d)),i.push(h)}),i}var Hr="get",Vr="application/x-www-form-urlencoded";function ao(a){return a!=null&&typeof a.tagName=="string"}function zb(a){return ao(a)&&a.tagName.toLowerCase()==="button"}function Ub(a){return ao(a)&&a.tagName.toLowerCase()==="form"}function Hb(a){return ao(a)&&a.tagName.toLowerCase()==="input"}function Vb(a){return!!(a.metaKey||a.altKey||a.ctrlKey||a.shiftKey)}function Yb(a,l){return a.button===0&&(!l||l==="_self")&&!Vb(a)}var Dr=null;function $b(){if(Dr===null)try{new FormData(document.createElement("form"),0),Dr=!1}catch{Dr=!0}return Dr}var Gb=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function _u(a){return a!=null&&!Gb.has(a)?(gn(!1,`"${a}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${Vr}"`),null):a}function Xb(a,l){let i,o,f,d,h;if(Ub(a)){let p=a.getAttribute("action");o=p?Wn(p,l):null,i=a.getAttribute("method")||Hr,f=_u(a.getAttribute("enctype"))||Vr,d=new FormData(a)}else if(zb(a)||Hb(a)&&(a.type==="submit"||a.type==="image")){let p=a.form;if(p==null)throw new Error('Cannot submit a - - audio: {session?.audioForward?.[rover.id]?.state || 'idle'} diff --git a/webui/src/components/VipPanel.jsx b/webui/src/components/VipPanel.jsx index 86d35015..9afcf89f 100644 --- a/webui/src/components/VipPanel.jsx +++ b/webui/src/components/VipPanel.jsx @@ -1,19 +1,13 @@ import { useMemo, useState } from 'react'; import { useSession } from '../context/SessionContext.jsx'; import { useSettingsNamespace } from '../settings/index.js'; -import NicknameForm from './NicknameForm.jsx'; - -function maskKey(value) { - const key = String(value || '').trim(); - if (!key) return ''; - if (key.length <= 10) return `${key.slice(0, 2)}***${key.slice(-2)}`; - return `${key.slice(0, 6)}...${key.slice(-6)}`; -} - -const cookieKeyRegex = /^cu_[a-f0-9]{32}$/; +import { COOKIE_KEY_REGEX, flowWrapClass } from './vip/constants.js'; +import VipAudioForwardingCard from './vip/VipAudioForwardingCard.jsx'; +import VipVerificationCard from './vip/VipVerificationCard.jsx'; +import VipIdentityCard from './vip/VipIdentityCard.jsx'; export default function VipPanel() { - const { session, identifySession, requestVerification } = useSession(); + const { session, identifySession, requestVerification, playUploadedAudio, stopUploadedAudio } = useSession(); const { value: identity, save: saveIdentity } = useSettingsNamespace('identity', { cookieUserId: '' }); const { value: profile } = useSettingsNamespace('profile', { nickname: '' }); @@ -21,24 +15,15 @@ export default function VipPanel() { const nickname = (profile?.nickname || '').trim(); const isVerified = Boolean(session?.isVerified); const pendingRequestId = session?.verification?.pendingRequestId || null; - - const [requestFlowStep, setRequestFlowStep] = useState(0); - const [requestKeyInput, setRequestKeyInput] = useState(''); - const [confirmNickname, setConfirmNickname] = useState(false); - const [restoreFlowStep, setRestoreFlowStep] = useState(0); - const [restoreKeyInput, setRestoreKeyInput] = useState(''); - const [working, setWorking] = useState(false); + const roster = useMemo(() => session?.roster ?? [], [session?.roster]); const [message, setMessage] = useState(''); - const fieldClass = 'field-input w-full max-w-sm text-left focus:ring-emerald-500'; - const flowWrapClass = 'mx-auto w-full max-w-xl flex justify-center'; - const innerFlowClass = 'mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center'; const applyIdentityKey = async (nextRaw) => { const next = String(nextRaw || '').trim().toLowerCase(); if (!next) { throw new Error('Identity key required.'); } - if (!cookieKeyRegex.test(next)) { + if (!COOKIE_KEY_REGEX.test(next)) { throw new Error('Identity key must match format: cu_ + 32 lowercase hex chars.'); } saveIdentity((current) => ({ ...(current || {}), cookieUserId: next })); @@ -46,277 +31,32 @@ export default function VipPanel() { return next; }; - const beginRequestFlow = () => { - setRequestFlowStep(1); - setRequestKeyInput(currentStoredKey); - setConfirmNickname(false); - setMessage(''); - }; - - const cancelRequestFlow = () => { - setRequestFlowStep(0); - setConfirmNickname(false); - }; - - const beginRestoreFlow = () => { - setRestoreFlowStep(1); - setRestoreKeyInput(''); - setMessage(''); - }; - - const cancelRestoreFlow = () => { - setRestoreFlowStep(0); - setRestoreKeyInput(''); - }; - - const handleRequestSubmit = async (event) => { - event.preventDefault(); - if (!confirmNickname) { - setMessage('Please confirm your nickname agreement before sending.'); - return; - } - if (requestFlowStep < 3) { - setMessage('Complete all request steps before sending.'); - return; - } - setWorking(true); - setMessage(''); - try { - const applied = await applyIdentityKey(requestKeyInput); - await requestVerification(); - setRequestKeyInput(applied); - setRequestFlowStep(0); - setConfirmNickname(false); - setMessage('Verification request sent to lockdown admins.'); - } catch (err) { - setMessage(err.message || 'Failed to submit request.'); - } finally { - setWorking(false); - } - }; - - const handleRestoreSubmit = async (event) => { - event.preventDefault(); - if (restoreFlowStep < 2) return; - setWorking(true); - setMessage(''); - try { - await applyIdentityKey(restoreKeyInput); - setRestoreFlowStep(0); - setRestoreKeyInput(''); - setMessage('Identity key restored.'); - } catch (err) { - setMessage(err.message || 'Failed to restore key.'); - } finally { - setWorking(false); - } - }; - return (
{isVerified ? ( -
- VIP controls will show here... when there are some... -
- ) : null} + + ) : ( + + )} - {!isVerified ? ( - pendingRequestId ? ( -
-
Verification request pending: {pendingRequestId}
-
- ) : requestFlowStep === 0 ? ( -
-
-

Verification

- -
-
- ) : ( - -
-

Request verification

-

- Step {requestFlowStep} of 3 -

- - {requestFlowStep === 1 ? ( -
-

- Confirm your nickname, which is used as part of the verification process. You can edit it here before requesting. -

-
- -
-
- Current nickname: {nickname || '(not set)'} -
- -
- - -
-
- ) : null} - - {requestFlowStep === 2 ? ( -
-

- Save your identity key in a safe place. You can use it to restore your identity in another browser. -

- setRequestKeyInput(event.target.value.toLowerCase())} - placeholder="Identity key for this request" - /> -
- - - -
-
- ) : null} - - {requestFlowStep === 3 ? ( -
-

- Final step: confirm and send your verification request. -

- setRequestKeyInput(event.target.value.toLowerCase())} - placeholder="Identity key for this request" - /> -
- - -
-
- ) : null} -
- - ) - ) : null} - -
-
-

Identity key

-

Current: {maskKey(currentStoredKey) || 'not set yet'}

- - {restoreFlowStep === 0 ? ( -
- - -
- ) : null} - - {restoreFlowStep === 1 ? ( -
-

- Restoring your key should only be done when needed. Use this to move your identity to another browser. -

-
- - -
-
- ) : null} - - {restoreFlowStep === 2 ? ( -
- setRestoreKeyInput(event.target.value.toLowerCase())} - placeholder="Paste key to restore" - /> -
- - -
-
- ) : null} -
-
+ {message ? (
diff --git a/webui/src/components/vip/VipAudioForwardingCard.jsx b/webui/src/components/vip/VipAudioForwardingCard.jsx new file mode 100644 index 00000000..c4c2e711 --- /dev/null +++ b/webui/src/components/vip/VipAudioForwardingCard.jsx @@ -0,0 +1,120 @@ +import { useMemo, useState } from 'react'; +import { MAX_UPLOAD_BYTES, bytesToBase64, fieldClass } from './constants.js'; + +export default function VipAudioForwardingCard({ + roster = [], + audioForwardByRover = {}, + playUploadedAudio, + stopUploadedAudio, + onMessage, +}) { + const [selectedRoverId, setSelectedRoverId] = useState(''); + const [selectedUpload, setSelectedUpload] = useState(null); + const [working, setWorking] = useState(false); + const selectedForwardState = useMemo( + () => (selectedRoverId ? audioForwardByRover?.[selectedRoverId] || null : null), + [audioForwardByRover, selectedRoverId], + ); + + const handleUploadPlay = async () => { + const roverId = String(selectedRoverId || '').trim(); + if (!roverId) { + onMessage?.('Select a rover first.'); + return; + } + if (!selectedUpload) { + onMessage?.('Select an audio file first.'); + return; + } + if (selectedUpload.size > MAX_UPLOAD_BYTES) { + onMessage?.(`File too large (max ${MAX_UPLOAD_BYTES} bytes).`); + return; + } + setWorking(true); + onMessage?.(''); + try { + const buffer = await selectedUpload.arrayBuffer(); + const base64 = bytesToBase64(new Uint8Array(buffer)); + await playUploadedAudio?.({ + roverId, + name: selectedUpload.name, + mime: selectedUpload.type || '', + dataBase64: base64, + }); + onMessage?.(`Playing upload on ${roverId}.`); + } catch (err) { + onMessage?.(err.message || 'Failed to play upload.'); + } finally { + setWorking(false); + } + }; + + const handleUploadStop = async () => { + const roverId = String(selectedRoverId || '').trim(); + if (!roverId) { + onMessage?.('Select a rover first.'); + return; + } + setWorking(true); + onMessage?.(''); + try { + await stopUploadedAudio?.(roverId); + onMessage?.(`Stopped upload on ${roverId}.`); + } catch (err) { + onMessage?.(err.message || 'Failed to stop upload.'); + } finally { + setWorking(false); + } + }; + + return ( +
+

VIP Audio Forwarding

+ + + {selectedUpload ? ( +
+ {selectedUpload.name} ({selectedUpload.size} bytes) +
+ ) : null} +
+ + +
+ {selectedForwardState ? ( +
+ state: {selectedForwardState.state || 'idle'} + {selectedForwardState.error ? ` | error: ${selectedForwardState.error}` : ''} +
+ ) : null} +
+ ); +} diff --git a/webui/src/components/vip/VipIdentityCard.jsx b/webui/src/components/vip/VipIdentityCard.jsx new file mode 100644 index 00000000..ccf51522 --- /dev/null +++ b/webui/src/components/vip/VipIdentityCard.jsx @@ -0,0 +1,109 @@ +import { useState } from 'react'; +import { fieldClass, flowWrapClass, innerFlowClass, maskKey } from './constants.js'; + +export default function VipIdentityCard({ currentStoredKey, applyIdentityKey, onMessage }) { + const [restoreFlowStep, setRestoreFlowStep] = useState(0); + const [restoreKeyInput, setRestoreKeyInput] = useState(''); + const [working, setWorking] = useState(false); + + const beginRestoreFlow = () => { + setRestoreFlowStep(1); + setRestoreKeyInput(''); + onMessage?.(''); + }; + + const cancelRestoreFlow = () => { + setRestoreFlowStep(0); + setRestoreKeyInput(''); + }; + + const handleRestoreSubmit = async (event) => { + event.preventDefault(); + if (restoreFlowStep < 2) return; + setWorking(true); + onMessage?.(''); + try { + await applyIdentityKey(restoreKeyInput); + setRestoreFlowStep(0); + setRestoreKeyInput(''); + onMessage?.('Identity key restored.'); + } catch (err) { + onMessage?.(err.message || 'Failed to restore key.'); + } finally { + setWorking(false); + } + }; + + return ( +
+
+

Identity key

+

Current: {maskKey(currentStoredKey) || 'not set yet'}

+ + {restoreFlowStep === 0 ? ( +
+ + +
+ ) : null} + + {restoreFlowStep === 1 ? ( +
+

+ Restoring your key should only be done when needed. Use this to move your identity to another browser. +

+
+ + +
+
+ ) : null} + + {restoreFlowStep === 2 ? ( +
+ setRestoreKeyInput(event.target.value.toLowerCase())} + placeholder="Paste key to restore" + /> +
+ + +
+
+ ) : null} +
+
+ ); +} diff --git a/webui/src/components/vip/VipVerificationCard.jsx b/webui/src/components/vip/VipVerificationCard.jsx new file mode 100644 index 00000000..f27e234c --- /dev/null +++ b/webui/src/components/vip/VipVerificationCard.jsx @@ -0,0 +1,188 @@ +import { useState } from 'react'; +import NicknameForm from '../NicknameForm.jsx'; +import { flowWrapClass, innerFlowClass, fieldClass } from './constants.js'; + +export default function VipVerificationCard({ + pendingRequestId, + currentStoredKey, + nickname, + requestVerification, + applyIdentityKey, + onMessage, +}) { + const [requestFlowStep, setRequestFlowStep] = useState(0); + const [requestKeyInput, setRequestKeyInput] = useState(''); + const [confirmNickname, setConfirmNickname] = useState(false); + const [working, setWorking] = useState(false); + + const beginRequestFlow = () => { + setRequestFlowStep(1); + setRequestKeyInput(currentStoredKey); + setConfirmNickname(false); + onMessage?.(''); + }; + + const cancelRequestFlow = () => { + setRequestFlowStep(0); + setConfirmNickname(false); + }; + + const handleRequestSubmit = async (event) => { + event.preventDefault(); + if (!confirmNickname) { + onMessage?.('Please confirm your nickname agreement before sending.'); + return; + } + if (requestFlowStep < 3) { + onMessage?.('Complete all request steps before sending.'); + return; + } + setWorking(true); + onMessage?.(''); + try { + const applied = await applyIdentityKey(requestKeyInput); + await requestVerification?.(); + setRequestKeyInput(applied); + setRequestFlowStep(0); + setConfirmNickname(false); + onMessage?.('Verification request sent to lockdown admins.'); + } catch (err) { + onMessage?.(err.message || 'Failed to submit request.'); + } finally { + setWorking(false); + } + }; + + if (pendingRequestId) { + return ( +
+
Verification request pending: {pendingRequestId}
+
+ ); + } + + if (requestFlowStep === 0) { + return ( +
+
+

Verification

+ +
+
+ ); + } + + return ( +
+
+

Request verification

+

+ Step {requestFlowStep} of 3 +

+ + {requestFlowStep === 1 ? ( +
+

+ Confirm your nickname, which is used as part of the verification process. You can edit it here before requesting. +

+
+ +
+
+ Current nickname: {nickname || '(not set)'} +
+ +
+ + +
+
+ ) : null} + + {requestFlowStep === 2 ? ( +
+

+ Save your identity key in a safe place. You can use it to restore your identity in another browser. +

+ setRequestKeyInput(event.target.value.toLowerCase())} + placeholder="Identity key for this request" + /> +
+ + + +
+
+ ) : null} + + {requestFlowStep === 3 ? ( +
+

+ Final step: confirm and send your verification request. +

+ setRequestKeyInput(event.target.value.toLowerCase())} + placeholder="Identity key for this request" + /> +
+ + +
+
+ ) : null} +
+
+ ); +} diff --git a/webui/src/components/vip/constants.js b/webui/src/components/vip/constants.js new file mode 100644 index 00000000..1eed112d --- /dev/null +++ b/webui/src/components/vip/constants.js @@ -0,0 +1,23 @@ +export const COOKIE_KEY_REGEX = /^cu_[a-f0-9]{32}$/; +export const MAX_UPLOAD_BYTES = 8 * 1024 * 1024; + +export const fieldClass = 'field-input w-full max-w-sm text-left focus:ring-emerald-500'; +export const flowWrapClass = 'mx-auto w-full max-w-xl flex justify-center'; +export const innerFlowClass = 'mx-auto flex w-full max-w-md flex-col items-center space-y-0.5 text-center'; + +export function maskKey(value) { + const key = String(value || '').trim(); + if (!key) return ''; + if (key.length <= 10) return `${key.slice(0, 2)}***${key.slice(-2)}`; + return `${key.slice(0, 6)}...${key.slice(-6)}`; +} + +export function bytesToBase64(bytes) { + let binary = ''; + const chunkSize = 0x8000; + for (let i = 0; i < bytes.length; i += chunkSize) { + const chunk = bytes.subarray(i, i + chunkSize); + binary += String.fromCharCode(...chunk); + } + return btoa(binary); +} diff --git a/webui/src/context/SessionContext.jsx b/webui/src/context/SessionContext.jsx index f054dab6..5b4e764a 100644 --- a/webui/src/context/SessionContext.jsx +++ b/webui/src/context/SessionContext.jsx @@ -26,8 +26,8 @@ const SessionContext = createContext({ setAdminReason: async () => {}, rebootRover: async () => {}, rebootServer: async () => {}, - playTestAudio: async () => {}, - stopTestAudio: async () => {}, + playUploadedAudio: async () => {}, + stopUploadedAudio: async () => {}, setAudioLevels: async () => {}, llmControl: async () => {}, }); @@ -144,8 +144,9 @@ export function SessionProvider({ children }) { rebootRover: (roverId) => emitWithAck('command', { roverId, type: 'reboot', data: { reboot: {} } }), rebootServer: () => emitWithAck('server:reboot'), - playTestAudio: (roverId) => emitWithAck('audio:testPlay', { roverId }), - stopTestAudio: (roverId) => emitWithAck('audio:testStop', { roverId }), + playUploadedAudio: ({ roverId, name, mime, dataBase64 }) => + emitWithAck('audio:uploadPlay', { roverId, name, mime, dataBase64 }), + stopUploadedAudio: (roverId) => emitWithAck('audio:uploadStop', { roverId }), setAudioLevels: (levels = {}) => emitWithAck('audioLevels:set', levels), llmControl: (action, controls = {}) => emitWithAck('llm:control', { controls: { action, ...controls } }),