- apps/web: test updates (Vitest/setup), playbackAnalyticsService, TrackGrid, serviceErrorHandler - veza-common: logging, metrics, traits, validation, random - veza-stream-server: audio pipeline, codecs, cache, monitoring, routes - apps/web/dist_verification: refresh build assets (content-hashed filenames) Co-authored-by: Cursor <cursoragent@cursor.com>
2 lines
32 KiB
JavaScript
2 lines
32 KiB
JavaScript
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/vendor-CjLUfV8Y.js","assets/vendor-react-C9dYU-TK.js","assets/vendor-security-DsrNJhpn.js","assets/vendor-BD_zwJK7.css"])))=>i.map(i=>d[i]);
|
|
import{a as n,j as e,R as me}from"./vendor-react-C9dYU-TK.js";import{D as he,h as W,B as k,p as ee,g as M,q as te,c as y,v as A,l as O,L as re,_ as se,j as fe,x as H,C as q}from"./index-BMBS6scK.js";import{b as ae,u as ne,a as V}from"./vendor-tanstack-C4XaEYj2.js";import{L as J,I as oe}from"./input-DeoQfymd.js";import{S as xe}from"./Select-EdCpbbCo.js";import{u as z}from"./chatStore-Cmmpwqns.js";import{W as F,aI as pe,g as ge,ag as be,aJ as ye,aw as ve,i as je,P as Ne,aK as Q,m as we,aL as Ce,S as ie,X as $,aM as B,aN as Se,aO as ke,aP as _e,ak as Ee,e as G}from"./vendor-icons-BSV6HBy1.js";import{D as Re,a as De,b as Te,c as X,u as ze}from"./useIsRateLimited-8kuXO8Mx.js";import{C as Y}from"./confirmation-dialog-BlZmJOYR.js";import{A as le}from"./avatar-DAue0w7u.js";import{af as Le,ag as ce,ah as Me}from"./vendor-CjLUfV8Y.js";import"./vendor-router-Dr0ZB7zf.js";import"./vendor-http-CctT3C58.js";import"./vendor-utils-D0JLFg89.js";import"./vendor-motion-CbAtAbUE.js";import"./vendor-i18n-PN7w4axr.js";import"./dropdown-CPqsiWN7.js";import"./vendor-security-DsrNJhpn.js";function Pe({open:t,onClose:c}){const[a,o]=n.useState(""),[u,d]=n.useState("public"),[m,r]=n.useState(!1),[i,l]=n.useState(null),[x,p]=n.useState(null),[s,g]=n.useState(0),v=n.useRef(null),R=te(),{addConversation:_,setCurrentConversation:E}=z(),D=async()=>{if(l(null),p(null),!a.trim()){l("Room name is required");return}const j=a.trim(),f=u,N=async()=>{const S=await M.post("/conversations",{name:j,type:f}),w={id:S.data.id||S.data.conversation?.id,name:S.data.name||S.data.conversation?.name,type:S.data.type||S.data.conversation?.type||f,participants:S.data.participants||[],unread_count:0};_(w),E(w.id),R.success("Room created successfully"),o(""),d("public"),p(null),g(0),v.current=null,c()};v.current=N,r(!0);try{await N()}catch(S){const w=ee(S);p(new Error(w.message))}finally{r(!1)}},P=async()=>{if(!(!v.current||s>=3)){g(j=>j+1),r(!0);try{await v.current()}catch{}finally{r(!1)}}};return e.jsx(he,{open:t,onClose:c,title:"Create New Room",variant:"default",size:"md",children:e.jsxs("div",{className:"space-y-4",children:[x&&e.jsx(W,{error:x,variant:"banner",severity:"error",context:{action:"creating room",resource:"conversation"},onRetry:s<3?P:void 0,onDismiss:()=>{p(null),g(0),v.current=null}}),i&&e.jsx(W,{error:i,variant:"inline",severity:"error",size:"sm",dismissible:!1}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(J,{htmlFor:"room-name",children:"Room Name"}),e.jsx(oe,{id:"room-name",value:a,onChange:j=>{o(j.target.value),l(null)},placeholder:"Enter room name",maxLength:100})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(J,{htmlFor:"room-type",children:"Room Type"}),e.jsx(xe,{options:[{value:"public",label:"Public"},{value:"private",label:"Private"}],value:u,onChange:j=>d(Array.isArray(j)?j[0]:j),name:"room-type"})]}),e.jsxs("div",{className:"flex justify-end gap-2 pt-4",children:[e.jsx(k,{variant:"outline",onClick:c,disabled:m,children:"Cancel"}),e.jsx(k,{onClick:D,disabled:m||!a.trim(),children:m?"Creating...":"Create Room"})]})]})})}function Ae(t,c,a){const{data:o,isLoading:u,error:d}=ae({queryKey:["chatConversations",t],queryFn:async()=>{if(!t)return[];const r=(await M.get("/conversations")).data,i=Array.isArray(r)?r:r?.conversations??[];return Array.isArray(i)?i:[]},enabled:!!t});return n.useEffect(()=>{o&&o.forEach(m=>{a.some(r=>r.id===m.id)||c({id:m.id,name:m.name,type:m.type??"direct",participants:Array.isArray(m.participants)?m.participants:[],unread_count:0})})},[o,a,c]),{data:o??[],isLoading:u,error:d}}function Ie({count:t,className:c}){return e.jsx("div",{className:y("p-4 border-b border-white/5 bg-white/2 backdrop-blur-sm",c),children:e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsxs("h2",{className:"text-sm font-bold text-foreground tracking-wide uppercase flex items-center gap-2",children:[e.jsx(F,{className:"w-4 h-4 text-muted-foreground"}),"Active Channels"]}),e.jsx("span",{className:"text-xs font-mono text-muted-foreground bg-muted px-1.5 py-0.5 rounded",children:t})]})})}function Oe({className:t}){return e.jsxs("div",{className:y("flex flex-col items-center gap-3 text-sm p-6 text-center border border-dashed border-border rounded-xl m-2 animate-empty-state-in",t),children:[e.jsx("div",{className:"w-10 h-10 rounded-full bg-muted flex items-center justify-center",children:e.jsx(pe,{className:"w-5 h-5 text-muted-foreground"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground font-medium text-sm",children:"No conversations yet"}),e.jsx("p",{className:"text-muted-foreground text-xs mt-1",children:"Start a new conversation to get going."})]})]})}function qe({className:t}){return e.jsx("div",{className:y("flex flex-1 items-center justify-center min-h-layout-story",t),"data-testid":"chat-sidebar-skeleton",children:e.jsx(ge,{className:"animate-spin text-muted-foreground",size:24})})}function We(t,c){const a=ne(),o=te(),u=z(r=>r.setCurrentConversation),d=V({mutationFn:async r=>{await M.delete(`/conversations/${r}/participants/${t}`)},onMutate:async r=>{await a.cancelQueries({queryKey:["chatConversations",t]});const i=a.getQueryData(["chatConversations",t]);return i&&Array.isArray(i)&&a.setQueryData(["chatConversations",t],i.filter(l=>l.id!==r)),{previous:i}},onError:(r,i,l)=>{l?.previous&&a.setQueryData(["chatConversations",t],l.previous);const x=r?.response?.data?.error??"Failed to leave room";c?.onLeaveError?.(new Error(x))},onSuccess:()=>{a.invalidateQueries({queryKey:["chatConversations",t]}),o.success("Left room successfully"),u(null),c?.onLeaveSuccess?.()}}),m=V({mutationFn:async r=>{await M.delete(`/conversations/${r}`)},onMutate:async r=>{await a.cancelQueries({queryKey:["chatConversations",t]});const i=a.getQueryData(["chatConversations",t]);return i&&Array.isArray(i)&&a.setQueryData(["chatConversations",t],i.filter(l=>l.id!==r)),{previous:i}},onError:(r,i,l)=>{l?.previous&&a.setQueryData(["chatConversations",t],l.previous);const x=r?.response?.data?.error??"Failed to delete room";c?.onDeleteError?.(new Error(x))},onSuccess:()=>{a.invalidateQueries({queryKey:["chatConversations",t]}),o.success("Room deleted successfully"),u(null),c?.onDeleteSuccess?.()}});return{leaveRoomMutation:d,deleteRoomMutation:m}}function Z(t){if(t==null)return"";if(typeof t=="string")return t;try{return String(t)}catch{return"Invalid Value"}}function Ue({conversation:t,onSelect:c,isSelected:a}){const{data:o}=A(),[u,d]=n.useState(!1),[m,r]=n.useState(!1),[i,l]=n.useState(null),[x,p]=n.useState(0),[s,g]=n.useState(null),[v,R]=n.useState(null),{leaveRoomMutation:_,deleteRoomMutation:E}=We(o?.id,{onLeaveError:l,onDeleteError:l,onLeaveSuccess:()=>{d(!1),l(null)},onDeleteSuccess:()=>{r(!1),l(null)}}),D=()=>{g("leave"),R(t.id),_.mutate(t.id)},P=()=>{g("delete"),R(t.id),E.mutate(t.id)},j=()=>{!s||!v||x>=3||(p(f=>f+1),s==="leave"?_.mutate(v):E.mutate(v))};return e.jsxs(e.Fragment,{children:[i&&e.jsx(W,{error:i,variant:"banner",severity:"error",context:{action:"managing room",resource:"conversation",resourceId:t.id},onRetry:x<3?j:void 0,onDismiss:()=>{l(null),p(0),g(null),R(null)}}),e.jsxs("button",{type:"button",tabIndex:0,onClick:()=>c(t.id),className:y("appearance-none bg-transparent border-0 p-0 text-left w-full","group relative flex items-center justify-between p-4 rounded-xl cursor-pointer transition-all duration-[var(--sumi-duration-normal)] border border-transparent","focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",a?"bg-primary/10 border-primary/30 shadow-queue-item-current":"hover:bg-muted/50 hover:border-muted"),children:[e.jsxs("div",{className:"flex items-center gap-4 min-w-0",children:[t.type==="direct"?e.jsx(le,{fallback:t.name||"U",size:"sm",status:"online"}):e.jsx("div",{className:y("w-8 h-8 rounded-lg flex items-center justify-center transition-colors shrink-0",a?"bg-primary text-foreground":"bg-white/5 text-muted-foreground group-hover:text-foreground"),children:e.jsx(be,{size:14})}),e.jsxs("div",{className:"flex flex-col min-w-0",children:[e.jsx("span",{className:y("text-sm font-medium truncate transition-colors",a?"text-foreground":"text-muted-foreground group-hover:text-foreground"),children:Z(t.name||`Channel ${t.id.substring(0,4)}`)}),t.type!=="direct"&&e.jsx("span",{className:"text-xs text-muted-foreground/50 uppercase tracking-wider",children:Z(t.type)})]})]}),t.unread_count!=null&&Number(t.unread_count)>0?e.jsx("span",{className:"bg-primary text-primary-foreground text-xs px-1.5 py-0.5 rounded-full font-bold shadow-lg shrink-0",children:t.unread_count}):null,e.jsxs(Re,{children:[e.jsx(De,{asChild:!0,onClick:f=>f.stopPropagation(),children:e.jsx(k,{variant:"ghost",size:"sm",className:y("h-6 w-6 p-0 opacity-0 group-hover:opacity-100 transition-opacity shrink-0",a?"text-primary hover:bg-primary/20":"text-muted-foreground hover:text-foreground"),children:e.jsx(ye,{className:"h-4 w-4"})})}),e.jsxs(Te,{align:"end",className:"bg-card border-border text-foreground",children:[e.jsxs(X,{onClick:f=>{f.stopPropagation(),d(!0)},className:"focus:bg-white/10 cursor-pointer",children:[e.jsx(ve,{className:"mr-2 h-4 w-4"}),"Leave Channel"]}),t.type!=="direct"&&e.jsxs(X,{onClick:f=>{f.stopPropagation(),r(!0)},className:"text-destructive focus:bg-destructive/10 cursor-pointer",children:[e.jsx(je,{className:"mr-2 h-4 w-4"}),"Delete Channel"]})]})]}),a&&e.jsx("div",{className:"absolute left-0 top-3 bottom-3 w-0.5 bg-primary rounded-r-full shadow-status-dot-cyan"})]}),e.jsx(Y,{open:u,onClose:()=>d(!1),onConfirm:D,title:"Leave Channel",description:"Disconnect from this secure frequency? Incoming transmission will cease.",confirmLabel:"Disconnect",cancelLabel:"Cancel",variant:"default",isLoading:_.isPending}),e.jsx(Y,{open:m,onClose:()=>r(!1),onConfirm:P,title:"Delete Channel",description:"Permanently purge this channel from the network? This action is irreversible.",confirmLabel:"Purge",cancelLabel:"Cancel",variant:"destructive",isLoading:E.isPending})]})}const de=me.memo(Ue);de.displayName="ConversationItem";const Fe=()=>{const{data:t}=A(),c=t?.id,a=ne(),{conversations:o,currentConversationId:u,setCurrentConversation:d,addConversation:m}=z(),{isLoading:r,error:i}=Ae(c,m,o),[l,x]=n.useState(!1);return r?e.jsx(qe,{}):i?e.jsx("div",{className:"flex flex-1 items-center justify-center p-4 min-h-layout-page-sm",children:e.jsx(W,{error:i instanceof Error?i:new Error("Signal Lost"),variant:"card",severity:"error",context:{action:"fetching conversations",resource:"conversations"},onRetry:()=>a.invalidateQueries({queryKey:["chatConversations",c]})})}):e.jsxs("div",{className:y("flex flex-col h-full"),children:[e.jsx(Ie,{count:o.length}),e.jsx("div",{className:"flex-1 overflow-y-auto custom-scrollbar p-4 space-y-1",children:o.length===0?e.jsx(Oe,{}):o.map(p=>e.jsx(de,{conversation:{id:p.id,name:p.name,type:p.type,unread_count:p.unread_count},onSelect:s=>d(s),isSelected:p.id===u},p.id))}),e.jsx("div",{className:"p-4 border-t border-white/5 bg-white/2 backdrop-blur-sm",children:e.jsxs(k,{onClick:()=>x(!0),className:"w-full shadow-lg shadow-sm",variant:"default",children:[e.jsx(Ne,{className:"mr-2 h-4 w-4"}),"New Channel"]})}),e.jsx(Pe,{open:l,onClose:()=>x(!1)})]})},K=()=>{const{data:t}=A(),c=t?.id,{wsToken:a,wsUrl:o,wsStatus:u,setWsStatus:d,addMessage:m,currentConversationId:r,loadMessages:i,addReaction:l,removeReaction:x,setUserTyping:p}=z(),s=n.useRef(null),g=n.useRef(0),[v,R]=n.useState([]),_=n.useCallback(()=>{if(!a||!o||s.current?.readyState===WebSocket.OPEN)return;s.current&&(s.current.onopen=null,s.current.onmessage=null,s.current.onclose=null,s.current.onerror=null,(s.current.readyState===WebSocket.OPEN||s.current.readyState===WebSocket.CONNECTING)&&s.current.close()),d("connecting");const b=`${o}?token=${a}`;s.current=new WebSocket(b);const C=()=>{d("connected"),g.current=0,R(L=>(L.forEach(T=>s.current?.send(JSON.stringify(T))),[]))},I=L=>{const T=JSON.parse(L.data);if(T.type==="NewMessage"){const h=T;h.conversation_id===r&&h.message_id&&h.sender_id&&h.content&&h.created_at&&m({id:h.message_id,conversation_id:h.conversation_id,sender_id:h.sender_id,sender_username:h.sender_username||"Unknown",content:h.content,created_at:h.created_at,attachments:h.attachments})}else if(T.type==="ReactionAdded"){const h=T;h.message_id&&h.user_id&&h.emoji&&l(h.conversation_id,h.message_id,h.user_id,h.emoji)}else if(T.type==="ReactionRemoved"){const h=T;h.message_id&&h.user_id&&x(h.conversation_id,h.message_id,h.user_id)}else if(T.type==="UserTyping"){const h=T;h.user_id&&p(h.conversation_id,h.user_id,h.is_typing??!1)}},U=()=>{d("disconnected")},ue=L=>{d("error"),g.current+=1,g.current<=3&&O.error("WebSocket error",{error:L instanceof Error?L.message:String(L),stack:L instanceof Error?L.stack:void 0})};s.current.onopen=C,s.current.onmessage=I,s.current.onclose=U,s.current.onerror=ue},[a,o,d,m,r,l,x,p]),E=n.useCallback(()=>{s.current&&(s.current.onopen=null,s.current.onmessage=null,s.current.onclose=null,s.current.onerror=null,(s.current.readyState===WebSocket.OPEN||s.current.readyState===WebSocket.CONNECTING)&&s.current.close(),s.current=null,d("disconnected"))},[d]),D=n.useRef(0),P=5;n.useEffect(()=>{let b;return a&&o&&u==="disconnected"&&D.current<P&&(b=setTimeout(()=>{D.current++,_()},1e3*Math.pow(2,D.current))),u==="connected"&&(D.current=0),()=>{b&&clearTimeout(b)}},[a,o,u,_]),n.useEffect(()=>()=>{E()},[E]);const j=n.useCallback((b,C)=>{if(!s.current||s.current.readyState!==WebSocket.OPEN||!r||!c){O.warn("WebSocket not open or missing conversation/user ID. Message queued.",{conversationId:r,userId:c}),R(U=>[...U,{type:"SendMessage",conversation_id:r||Le(),content:b,parent_message_id:null,attachments:C}]);return}const I={type:"SendMessage",conversation_id:r,content:b,parent_message_id:null,attachments:C};s.current.send(JSON.stringify(I))},[r,c]),f=n.useCallback(async b=>{try{const C=await M.get(`/conversations/${b}/history`);i(b,C.data.messages)}catch(C){O.error("Failed to fetch chat history",{error:C instanceof Error?C.message:String(C),stack:C instanceof Error?C.stack:void 0,conversationId:b})}},[i]),N=n.useCallback((b,C)=>{s.current?.readyState===WebSocket.OPEN&&r&&s.current.send(JSON.stringify({type:"AddReaction",conversation_id:r,message_id:b,emoji:C}))},[r]),S=n.useCallback(b=>{s.current?.readyState===WebSocket.OPEN&&r&&s.current.send(JSON.stringify({type:"RemoveReaction",conversation_id:r,message_id:b}))},[r]),w=n.useCallback(b=>{s.current?.readyState===WebSocket.OPEN&&r&&s.current.send(JSON.stringify({type:"Typing",conversation_id:r,is_typing:b}))},[r]);return{wsStatus:u,connect:_,disconnect:E,sendMessage:j,fetchHistory:f,addReaction:N,removeReaction:S,setTyping:w}},Qe=n.lazy(()=>se(()=>import("./vendor-CjLUfV8Y.js").then(t=>t.aC),__vite__mapDeps([0,1,2,3])).then(t=>({default:t.default}))),$e=t=>{if(t==null)return"";if(typeof t=="string")return t;try{return String(t)}catch{return"Invalid Value"}},Ke=({message:t})=>{const{data:c}=A(),{addReaction:a}=K(),o=c?.id===t.sender_id,[u,d]=n.useState(!1),m=r=>{a(t.id,r.emoji),d(!1)};return e.jsxs("div",{className:y("group flex flex-col gap-1 max-w-[80%] mb-4 relative",o?"ml-auto items-end":"mr-auto items-start"),children:[e.jsxs("div",{className:"flex items-center gap-2 px-1 mb-0.5",children:[!o&&e.jsx(le,{fallback:t.sender_username||"U",size:"xs",status:"online"}),e.jsx("span",{className:y("font-mono text-xs uppercase tracking-wider",o?"text-muted-foreground":"text-destructive"),children:o?"You":$e(t.sender_username||"Unknown_Signal")}),e.jsx("span",{className:"text-xs text-muted-foreground/60",children:new Date(t.created_at).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})})]}),e.jsxs("div",{className:"relative flex items-end gap-2 group/bubble",children:[o&&e.jsx("button",{onClick:()=>d(!u),className:"opacity-0 group-hover/bubble:opacity-100 p-1.5 hover:bg-muted/50 rounded-full transition-all text-muted-foreground hover:text-foreground",children:e.jsx(Q,{size:14})}),e.jsxs("div",{className:y("px-4 py-2.5 rounded-2xl text-sm backdrop-blur-md shadow-lg transition-all",o?"bg-primary/10 border border-primary/20 text-foreground rounded-tr-sm":"bg-muted/30 border border-border text-foreground rounded-tl-sm hover:bg-muted/50"),children:[t.attachments&&t.attachments.length>0&&e.jsx("div",{className:"mb-2 flex flex-wrap gap-2",children:t.attachments.map((r,i)=>e.jsx("div",{className:"max-w-full overflow-hidden rounded-lg border border-white/10 bg-black/20",children:r.file_type.startsWith("image")?e.jsx("img",{src:r.file_url,alt:r.file_name,className:"max-h-60 object-contain cursor-pointer hover:opacity-90 transition-opacity",onClick:()=>window.open(r.file_url,"_blank")}):e.jsxs("a",{href:r.file_url,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-4 p-4 hover:bg-white/5 transition-colors",children:[e.jsx("div",{className:"w-8 h-8 rounded bg-muted/50 flex items-center justify-center",children:e.jsx(we,{size:16,className:"text-muted-foreground"})}),e.jsx("span",{className:"truncate max-w-[150px] text-xs font-mono",children:r.file_name})]})},i))}),e.jsx("p",{className:"whitespace-pre-wrap break-words leading-relaxed",children:t.content})]}),!o&&e.jsx("button",{onClick:()=>d(!u),className:"opacity-0 group-hover/bubble:opacity-100 p-1.5 hover:bg-muted/50 rounded-full transition-all text-muted-foreground hover:text-foreground",children:e.jsx(Q,{size:14})}),u&&e.jsxs("div",{className:y("absolute z-50 bottom-full mb-2",o?"right-0":"left-0"),children:[e.jsx("div",{className:"fixed inset-0",onClick:()=>d(!1)}),e.jsx("div",{className:"relative shadow-2xl rounded-xl overflow-hidden border border-white/10 animate-scaleIn",children:e.jsx(n.Suspense,{fallback:e.jsx("div",{className:"w-[300px] h-[400px] bg-card flex items-center justify-center",children:e.jsx(re,{size:"sm"})}),children:e.jsx(Qe,{onEmojiClick:m,theme:ce.DARK,lazyLoadEmojis:!0,width:300,height:400})})})]})]}),e.jsxs("div",{className:"flex items-center justify-between w-full px-1 mt-1",children:[e.jsx("div",{className:"flex flex-wrap gap-1",children:t.reactions&&Object.entries(t.reactions).map(([r,i])=>e.jsxs("button",{onClick:()=>a(t.id,r),className:y("flex items-center gap-1 px-1.5 py-0.5 rounded-full text-xs border transition-all animate-scaleIn",i.includes(c?.id||"")?"bg-primary/20 border-primary/40 text-primary shadow-queue-item-current":"bg-muted/30 border-border text-muted-foreground hover:bg-muted/50 hover:border-border"),children:[e.jsx("span",{children:r}),i.length>1&&e.jsx("span",{className:"font-bold",children:i.length})]},r))}),o&&e.jsx("div",{className:"text-muted-foreground/40 ml-auto",children:e.jsx(Ce,{size:12})})]})]})};function He({conversationId:t,onMessageSelect:c}){const[a,o]=n.useState(""),[u,d]=n.useState([]),[m,r]=n.useState(!1),[i,l]=n.useState(!1),x=async()=>{if(!(!a.trim()||!t))try{r(!0),l(!0);const s=await M.get(`/conversations/${t}/messages/search`,{params:{q:a,limit:20}});d(s.data.messages||[])}catch(s){const g=ee(s);O.warn("Search endpoint not available or failed",{error:g.message}),d([])}finally{r(!1)}},p=()=>{o(""),d([]),l(!1)};return e.jsxs("div",{className:"relative",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("div",{className:"relative flex-1",children:[e.jsx(ie,{className:"absolute left-2 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx(oe,{type:"text",value:a,onChange:s=>o(s.target.value),onKeyDown:s=>{s.key==="Enter"&&(s.preventDefault(),x())},placeholder:"Search messages...",className:"pl-8 pr-8"}),a&&e.jsx(k,{variant:"ghost",size:"sm",className:"absolute right-1 top-1/2 transform -translate-y-1/2 h-6 w-6 p-0",onClick:p,children:e.jsx($,{className:"h-4 w-4"})})]}),e.jsx(k,{onClick:x,disabled:!a.trim()||m,size:"sm",children:m?"Searching...":"Search"})]}),i&&u.length>0&&e.jsx("div",{className:"absolute z-10 w-full mt-2 bg-white border rounded-lg shadow-lg max-h-64 overflow-y-auto",children:e.jsxs("div",{className:"p-2",children:[e.jsxs("div",{className:"text-xs text-muted-foreground mb-2",children:[u.length," result(s) found"]}),u.map(s=>e.jsxs("div",{className:"p-2 hover:bg-background rounded cursor-pointer",onClick:()=>{c?.(s.id),l(!1)},children:[e.jsx("div",{className:"text-sm font-medium",children:s.sender_username}),e.jsx("div",{className:"text-xs text-muted-foreground truncate",children:s.content}),e.jsx("div",{className:"text-xs text-muted-foreground",children:new Date(s.created_at).toLocaleString()})]},s.id))]})}),i&&u.length===0&&a&&e.jsx("div",{className:"absolute z-10 w-full mt-2 bg-white border rounded-lg shadow-lg p-4 text-sm text-muted-foreground",children:"No messages found"})]})}function Ve({conversationId:t}){const{typingUsers:c,userId:a}=z(),o=(c[t]||[]).filter(u=>u!==a);return o.length===0?e.jsx("div",{className:"h-6"}):e.jsx("div",{className:"px-4 py-1 text-xs text-muted-foreground italic animate-pulse",children:o.length===1?"Quelqu'un écrit...":`${o.length} personnes écrivent...`})}const Je=({conversationId:t})=>{const{messages:c}=z(),{fetchHistory:a}=K(),{data:o}=A(),u=n.useRef(null),[d,m]=n.useState(!1),[r,i]=n.useState(null),l=n.useRef(null);n.useEffect(()=>()=>{l.current&&clearTimeout(l.current)},[]);const x=c[t]||[],p=n.useRef({});n.useEffect(()=>{t&&!c[t]&&!p.current[t]&&(p.current[t]=!0,a(t).finally(()=>{}))},[t,c[t],a]),n.useEffect(()=>{u.current&&u.current.scrollIntoView({behavior:"smooth"})},[x.length,t]);const s=g=>{i(g);const v=document.getElementById(`message-${g}`);v&&(v.scrollIntoView({behavior:"smooth",block:"center"}),l.current&&clearTimeout(l.current),l.current=setTimeout(()=>i(null),3e3))};return t?e.jsxs("div",{className:"flex-1 flex flex-col h-full overflow-hidden",children:[e.jsx("div",{className:y("absolute top-0 left-0 right-0 z-20 px-4 py-2 transition-all duration-[var(--sumi-duration-normal)]",d?"bg-card/90 backdrop-blur-md border-b border-border":"bg-transparent pointer-events-none"),children:d?e.jsxs("div",{className:"flex items-center gap-2 max-w-2xl mx-auto",children:[e.jsx("div",{className:"flex-1",children:e.jsx(He,{conversationId:t,onMessageSelect:s})}),e.jsx(k,{variant:"ghost",size:"sm",onClick:()=>m(!1),className:"hover:bg-muted/50",children:e.jsx($,{className:"h-4 w-4"})})]}):e.jsx("div",{className:"flex justify-end pointer-events-auto",children:e.jsxs(k,{variant:"ghost",size:"sm",onClick:()=>m(!0),className:"text-muted-foreground/50 hover:text-foreground hover:bg-muted/50 bg-muted/30 backdrop-blur-sm rounded-full h-8 px-4 border border-border",children:[e.jsx(ie,{className:"h-3 w-3 mr-2"}),e.jsx("span",{className:"text-xs font-mono uppercase",children:"Search Log"})]})})}),e.jsxs("div",{className:"flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4 scroll-smooth",children:[x.length===0&&e.jsxs("div",{className:"flex flex-col items-center justify-center h-layout-lyrics-sm text-center space-y-4 animate-empty-state-in",children:[e.jsx("div",{className:"w-14 h-14 rounded-full bg-muted flex items-center justify-center",children:e.jsx(F,{className:"w-7 h-7 text-muted-foreground"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground font-medium",children:"No messages yet"}),e.jsx("p",{className:"text-sm text-muted-foreground mt-1",children:"Send the first message to start the conversation."})]})]}),x.map(g=>e.jsx("div",{id:`message-${g.id}`,className:y("transition-all duration-[var(--sumi-duration-slow)] animate-slideUp",r===g.id&&"bg-muted/10 rounded-xl -mx-4 px-4 py-2 ring-1 ring-border/30"),children:e.jsx(Ke,{message:g})},g.id)),e.jsx(Ve,{conversationId:t}),e.jsx("div",{ref:u,className:"h-4"})]})]}):e.jsxs("div",{className:"flex-1 flex flex-col items-center justify-center text-muted-foreground space-y-4 animate-empty-state-in",children:[e.jsx("div",{className:"w-24 h-24 rounded-full bg-muted flex items-center justify-center",children:e.jsx(F,{className:"w-10 h-10 text-muted-foreground"})}),e.jsxs("div",{className:"text-center",children:[e.jsx("p",{className:"text-sm font-medium text-foreground mb-1",children:"No conversation selected"}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Pick a channel from the sidebar to start chatting."})]})]})},Be=n.lazy(()=>se(()=>import("./vendor-CjLUfV8Y.js").then(t=>t.aC),__vite__mapDeps([0,1,2,3])).then(t=>({default:t.default}))),Ge=()=>{const[t,c]=n.useState(""),[a,o]=n.useState([]),[u,d]=n.useState(!1),[m,r]=n.useState(!1),{sendMessage:i,setTyping:l}=K(),{currentConversationId:x}=z(),p=ze(),s=n.useRef(null),g=f=>{f.preventDefault(),(t.trim()||a.length>0)&&x&&(i(t,a.length>0?a:void 0),c(""),o([]),s.current&&clearTimeout(s.current),l(!1))},v=n.useRef(null),R=n.useCallback(async f=>{d(!0);try{const N=f.map(async w=>{const b=new FormData;b.append("file",w);const I=(await M.post("/uploads",b,{headers:{"Content-Type":"multipart/form-data"}})).data;return{file_name:w.name,file_type:w.type,file_url:I.url,file_size:w.size}}),S=await Promise.all(N);o(w=>[...w,...S])}catch(N){O.error("Failed to upload files",{error:N instanceof Error?N.message:String(N)})}finally{d(!1)}},[]),{getRootProps:_,getInputProps:E,isDragActive:D}=Me({onDrop:R,noClick:!0}),P=f=>{c(N=>N+f.emoji),r(!1)},j=f=>{o(N=>N.filter((S,w)=>w!==f))};return n.useEffect(()=>(t.length>0?(l(!0),s.current&&clearTimeout(s.current),s.current=setTimeout(()=>{l(!1)},3e3)):l(!1),()=>{s.current&&clearTimeout(s.current)}),[t,l]),e.jsxs("div",{..._(),className:"relative",children:[e.jsx("input",{...E(),ref:v,className:"hidden"}),D&&e.jsx("div",{className:"absolute bottom-full left-0 right-0 h-48 z-50 bg-muted/10 backdrop-blur-md flex items-center justify-center border-t-2 border-border border-dashed rounded-t-2xl animate-fadeIn",children:e.jsxs("div",{className:"text-center",children:[e.jsx("div",{className:"w-12 h-12 rounded-full bg-muted/20 flex items-center justify-center mx-auto mb-2 animate-bounce",children:e.jsx(B,{className:"w-6 h-6 text-muted-foreground"})}),e.jsx("p",{className:"text-muted-foreground font-mono uppercase tracking-widest text-sm",children:"Initiate Data Transfer"})]})}),a.length>0&&e.jsx("div",{className:"absolute bottom-full left-0 right-0 p-4 bg-background/90 backdrop-blur-xl border-t border-white/10 flex gap-2 overflow-x-auto",children:a.map((f,N)=>e.jsxs("div",{className:"relative group flex items-center gap-2 p-2 bg-white/5 rounded-lg border border-white/10 text-xs text-foreground min-w-36",children:[f.file_type.startsWith("image")?e.jsx(Se,{size:14,className:"text-primary"}):e.jsx(ke,{size:14,className:"text-muted-foreground"}),e.jsx("span",{className:"truncate flex-1",children:f.file_name}),e.jsx("button",{onClick:()=>j(N),className:"p-1 hover:bg-white/10 rounded-full text-destructive opacity-0 group-hover:opacity-100 transition-opacity",children:e.jsx($,{size:12})})]},f.id||f.file_name))}),e.jsxs("form",{onSubmit:g,className:"flex items-center gap-2",children:[e.jsxs("div",{className:"flex gap-1",children:[e.jsx(k,{type:"button",variant:"ghost",size:"icon",className:"text-muted-foreground hover:text-foreground hover:bg-white/5",onClick:()=>v.current?.click(),children:e.jsx(B,{size:20})}),e.jsxs("div",{className:"relative",children:[e.jsx(k,{type:"button",variant:"ghost",size:"icon",className:y("text-muted-foreground hover:text-foreground hover:bg-white/5",m&&"text-muted-foreground bg-white/5"),onClick:()=>r(!m),children:e.jsx(Q,{size:20})}),m&&e.jsxs("div",{className:"absolute bottom-full left-0 mb-4 z-50 animate-scaleIn origin-bottom-left",children:[e.jsx("div",{className:"fixed inset-0",onClick:()=>r(!1)}),e.jsx("div",{className:"relative shadow-2xl rounded-xl overflow-hidden border border-white/10",children:e.jsx(n.Suspense,{fallback:e.jsx("div",{className:"w-[350px] h-[450px] bg-card flex items-center justify-center",children:e.jsx(re,{})}),children:e.jsx(Be,{onEmojiClick:P,theme:ce.DARK,lazyLoadEmojis:!0,width:350,height:450})})})]})]})]}),e.jsxs("div",{className:"flex-1 relative",children:[e.jsx("input",{type:"text",value:t,onChange:f=>c(f.target.value),placeholder:"Broadcast message...","aria-label":"Type a message",className:"w-full bg-white/5 border border-white/10 rounded-xl px-4 py-2.5 text-foreground placeholder:text-muted-foreground/50 focus:outline-none focus:border-border/50 focus:ring-1 focus:ring-border/50 transition-all font-mono text-sm",disabled:!x||u}),t.length===0&&!u&&e.jsx(k,{type:"button",variant:"ghost",size:"icon",className:"absolute right-1 top-1/2 -translate-y-1/2 h-8 w-8 text-muted-foreground/30 hover:text-foreground",children:e.jsx(_e,{className:"w-4 h-4"})})]}),e.jsx(k,{type:"submit",variant:"primary",size:"icon",className:y("rounded-xl transition-all duration-[var(--sumi-duration-normal)]",t.trim()||a.length>0?"bg-primary text-foreground hover:bg-primary-dim shadow-neon-cyan":"bg-white/5 text-muted-foreground hover:bg-white/10"),disabled:!x||!t.trim()&&a.length===0||u||p,children:u?e.jsx("div",{className:"w-5 h-5 border-2 border-border/30 border-t-border rounded-full animate-spin"}):e.jsx(Ee,{size:18,className:y(t.trim()?"translate-x-0.5":"")})})]})]})},xt=()=>{const{isAuthenticated:t}=fe(),{data:c}=A(),a=c?.id,{setWsToken:o,currentConversationId:u,wsStatus:d}=z(),{data:m,isLoading:r,error:i}=ae({queryKey:["chatWsToken",a],queryFn:async()=>!t||!a?null:(await M.post("/chat/token",{})).data,enabled:t&&!!a&&d==="disconnected",refetchOnWindowFocus:!1,retry:!1,staleTime:300*1e3,gcTime:600*1e3});return n.useEffect(()=>{m?.token&&(m.token!==z.getState().wsToken||H.WS_URL!==z.getState().wsUrl)&&o(m.token,H.WS_URL)},[m,o]),t?r||d==="connecting"?e.jsxs("div",{className:"flex flex-col items-center justify-center h-layout-chat",children:[e.jsxs("div",{className:"relative mb-6",children:[e.jsx("div",{className:"w-16 h-16 border-2 border-primary/20 border-t-primary rounded-full animate-spin"}),e.jsx("div",{className:"absolute inset-0 flex items-center justify-center",children:e.jsx("div",{className:"w-2 h-2 bg-primary rounded-full animate-pulse shadow-status-dot-cyan"})})]}),e.jsx("p",{className:"font-mono text-sm text-primary animate-pulse tracking-widest",children:"ESTABLISHING UPLINK..."})]}):i?e.jsx("div",{className:"flex flex-col items-center justify-center h-layout-chat",children:e.jsxs(q,{variant:"glass",className:"p-8 text-center max-w-md border-destructive/30",children:[e.jsx(G,{className:"w-12 h-12 text-destructive mb-4"}),e.jsx("h2",{className:"text-xl font-bold text-foreground mb-2",children:"Connection Terminated"}),e.jsx("p",{className:"text-destructive/80 mb-4",children:i instanceof Error?i.message:"Secure handshake failed."}),e.jsx(k,{variant:"outline",onClick:()=>window.location.reload(),children:"Retry Connection"})]})}):e.jsxs("div",{className:"h-layout-chat-main flex gap-6 overflow-hidden p-4 container mx-auto max-w-layout-content",children:[e.jsxs(q,{variant:"glass",className:"w-80 shrink-0 flex flex-col overflow-hidden p-0 border-white/5 bg-black/40 backdrop-blur-2xl",children:[e.jsxs("div",{className:"p-4 border-b border-white/5 flex items-center justify-between",children:[e.jsx("h3",{className:"font-bold text-sm tracking-widest text-muted-foreground uppercase",children:"Channels"}),e.jsx("div",{className:y("w-2 h-2 rounded-full",d==="connected"?"bg-success shadow-status-dot-lime":"bg-destructive")})]}),e.jsx(Fe,{})]}),e.jsxs(q,{variant:"glass",className:"flex-1 flex flex-col overflow-hidden relative p-0 border-white/5 bg-black/40 backdrop-blur-2xl",children:[e.jsx("div",{className:"absolute inset-0 opacity-[0.03] pointer-events-none",style:{backgroundImage:"linear-gradient(var(--color-primary) 1px, transparent 1px), linear-gradient(90deg, var(--color-primary) 1px, transparent 1px)",backgroundSize:"40px 40px"}}),e.jsx("div",{className:"flex-1 overflow-hidden flex flex-col relative z-10",children:e.jsx(Je,{conversationId:u||""})}),e.jsx("div",{className:"p-4 border-t border-white/5 bg-black/40 relative z-20 backdrop-blur-xl",children:e.jsx(Ge,{})})]})]}):e.jsx("div",{className:"flex flex-col items-center justify-center h-layout-chat",children:e.jsxs(q,{variant:"glass",className:"p-8 text-center max-w-md border-primary/20",children:[e.jsx(G,{className:"w-12 h-12 text-primary mx-auto mb-4 opacity-50"}),e.jsx("h2",{className:"text-xl font-bold text-foreground mb-2",children:"Access Restricted"}),e.jsx("p",{className:"mb-6 text-muted-foreground",children:"Encrypted channel access requires authorization."}),e.jsx(k,{onClick:()=>window.location.href="/login",children:"Initialize Handshake"})]})})};export{xt as ChatPage};
|