@connectycube/use-chat
Version:
A React hook for state management in ConnectyCube-powered chat solutions
3 lines (2 loc) • 25.8 kB
JavaScript
import{jsx as t}from"react/jsx-runtime";import e,{useState as n,useRef as a,useEffect as r,useCallback as i,createContext as s,useContext as o}from"react";import c from"connectycube";import{PrivacyListAction as d,ChatEvent as u,ChatType as l,DialogType as h}from"connectycube/types";function m(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var f,g;var _=m(function(){if(g)return f;g=1;var t=e;return f=function(e){var n=t.useState(e),a=n[0],r=n[1],i=t.useRef(a);return[a,t.useCallback(function(t){i.current=function(t){return"function"==typeof t}(t)?t(i.current):t,r(i.current)},[]),i]}}());const p=43200,y=Symbol.for("constructDateFrom");function w(t,e){return"function"==typeof t?t(e):t&&"object"==typeof t&&y in t?t[y](e):t instanceof Date?new t.constructor(e):new Date(e)}function v(t,e){return w(t,t)}let D={};function E(){return D}function A(t){const e=v(t),n=new Date(Date.UTC(e.getFullYear(),e.getMonth(),e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),e.getMilliseconds()));return n.setUTCFullYear(e.getFullYear()),+t-+n}function b(t,...e){const n=w.bind(null,t||e.find(t=>"object"==typeof t));return e.map(n)}function T(t,e){const n=+v(t)-+v(e);return n<0?-1:n>0?1:n}function S(t,e){const n=v(t);return+function(t){const e=v(t);return e.setHours(23,59,59,999),e}(n)===+function(t){const e=v(t),n=e.getMonth();return e.setFullYear(e.getFullYear(),n+1,0),e.setHours(23,59,59,999),e}(n)}function M(t,e,n){const[a,r,i]=b(n?.in,t,t,e),s=T(r,i),o=Math.abs(function(t,e,n){const[a,r]=b(n?.in,t,e);return 12*(a.getFullYear()-r.getFullYear())+(a.getMonth()-r.getMonth())}(r,i));if(o<1)return 0;1===r.getMonth()&&r.getDate()>27&&r.setDate(30),r.setMonth(r.getMonth()-s*o);let c=T(r,i)===-s;S(a)&&1===o&&1===T(a,i)&&(c=!1);const d=s*(o-+c);return 0===d?0:d}function O(t,e,n){const a=function(t,e){return+v(t)-+v(e)}(t,e)/1e3;return(r=n?.roundingMethod,t=>{const e=(r?Math[r]:Math.trunc)(t);return 0===e?0:e})(a);var r}const C={lessThanXSeconds:{one:"less than a second",other:"less than {{count}} seconds"},xSeconds:{one:"1 second",other:"{{count}} seconds"},halfAMinute:"half a minute",lessThanXMinutes:{one:"less than a minute",other:"less than {{count}} minutes"},xMinutes:{one:"1 minute",other:"{{count}} minutes"},aboutXHours:{one:"about 1 hour",other:"about {{count}} hours"},xHours:{one:"1 hour",other:"{{count}} hours"},xDays:{one:"1 day",other:"{{count}} days"},aboutXWeeks:{one:"about 1 week",other:"about {{count}} weeks"},xWeeks:{one:"1 week",other:"{{count}} weeks"},aboutXMonths:{one:"about 1 month",other:"about {{count}} months"},xMonths:{one:"1 month",other:"{{count}} months"},aboutXYears:{one:"about 1 year",other:"about {{count}} years"},xYears:{one:"1 year",other:"{{count}} years"},overXYears:{one:"over 1 year",other:"over {{count}} years"},almostXYears:{one:"almost 1 year",other:"almost {{count}} years"}};function N(t){return(e={})=>{const n=e.width?String(e.width):t.defaultWidth;return t.formats[n]||t.formats[t.defaultWidth]}}const I={date:N({formats:{full:"EEEE, MMMM do, y",long:"MMMM do, y",medium:"MMM d, y",short:"MM/dd/yyyy"},defaultWidth:"full"}),time:N({formats:{full:"h:mm:ss a zzzz",long:"h:mm:ss a z",medium:"h:mm:ss a",short:"h:mm a"},defaultWidth:"full"}),dateTime:N({formats:{full:"{{date}} 'at' {{time}}",long:"{{date}} 'at' {{time}}",medium:"{{date}}, {{time}}",short:"{{date}}, {{time}}"},defaultWidth:"full"})},P={lastWeek:"'last' eeee 'at' p",yesterday:"'yesterday at' p",today:"'today at' p",tomorrow:"'tomorrow at' p",nextWeek:"eeee 'at' p",other:"P"};function R(t){return(e,n)=>{let a;if("formatting"===(n?.context?String(n.context):"standalone")&&t.formattingValues){const e=t.defaultFormattingWidth||t.defaultWidth,r=n?.width?String(n.width):e;a=t.formattingValues[r]||t.formattingValues[e]}else{const e=t.defaultWidth,r=n?.width?String(n.width):t.defaultWidth;a=t.values[r]||t.values[e]}return a[t.argumentCallback?t.argumentCallback(e):e]}}function L(t){return(e,n={})=>{const a=n.width,r=a&&t.matchPatterns[a]||t.matchPatterns[t.defaultMatchWidth],i=e.match(r);if(!i)return null;const s=i[0],o=a&&t.parsePatterns[a]||t.parsePatterns[t.defaultParseWidth],c=Array.isArray(o)?function(t,e){for(let n=0;n<t.length;n++)if(e(t[n]))return n;return}(o,t=>t.test(s)):function(t,e){for(const n in t)if(Object.prototype.hasOwnProperty.call(t,n)&&e(t[n]))return n;return}(o,t=>t.test(s));let d;d=t.valueCallback?t.valueCallback(c):c,d=n.valueCallback?n.valueCallback(d):d;return{value:d,rest:e.slice(s.length)}}}var W;const k={code:"en-US",formatDistance:(t,e,n)=>{let a;const r=C[t];return a="string"==typeof r?r:1===e?r.one:r.other.replace("{{count}}",e.toString()),n?.addSuffix?n.comparison&&n.comparison>0?"in "+a:a+" ago":a},formatLong:I,formatRelative:(t,e,n,a)=>P[t],localize:{ordinalNumber:(t,e)=>{const n=Number(t),a=n%100;if(a>20||a<10)switch(a%10){case 1:return n+"st";case 2:return n+"nd";case 3:return n+"rd"}return n+"th"},era:R({values:{narrow:["B","A"],abbreviated:["BC","AD"],wide:["Before Christ","Anno Domini"]},defaultWidth:"wide"}),quarter:R({values:{narrow:["1","2","3","4"],abbreviated:["Q1","Q2","Q3","Q4"],wide:["1st quarter","2nd quarter","3rd quarter","4th quarter"]},defaultWidth:"wide",argumentCallback:t=>t-1}),month:R({values:{narrow:["J","F","M","A","M","J","J","A","S","O","N","D"],abbreviated:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],wide:["January","February","March","April","May","June","July","August","September","October","November","December"]},defaultWidth:"wide"}),day:R({values:{narrow:["S","M","T","W","T","F","S"],short:["Su","Mo","Tu","We","Th","Fr","Sa"],abbreviated:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wide:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]},defaultWidth:"wide"}),dayPeriod:R({values:{narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"morning",afternoon:"afternoon",evening:"evening",night:"night"}},defaultWidth:"wide",formattingValues:{narrow:{am:"a",pm:"p",midnight:"mi",noon:"n",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},abbreviated:{am:"AM",pm:"PM",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"},wide:{am:"a.m.",pm:"p.m.",midnight:"midnight",noon:"noon",morning:"in the morning",afternoon:"in the afternoon",evening:"in the evening",night:"at night"}},defaultFormattingWidth:"wide"})},match:{ordinalNumber:(W={matchPattern:/^(\d+)(th|st|nd|rd)?/i,parsePattern:/\d+/i,valueCallback:t=>parseInt(t,10)},(t,e={})=>{const n=t.match(W.matchPattern);if(!n)return null;const a=n[0],r=t.match(W.parsePattern);if(!r)return null;let i=W.valueCallback?W.valueCallback(r[0]):r[0];return i=e.valueCallback?e.valueCallback(i):i,{value:i,rest:t.slice(a.length)}}),era:L({matchPatterns:{narrow:/^(b|a)/i,abbreviated:/^(b\.?\s?c\.?|b\.?\s?c\.?\s?e\.?|a\.?\s?d\.?|c\.?\s?e\.?)/i,wide:/^(before christ|before common era|anno domini|common era)/i},defaultMatchWidth:"wide",parsePatterns:{any:[/^b/i,/^(a|c)/i]},defaultParseWidth:"any"}),quarter:L({matchPatterns:{narrow:/^[1234]/i,abbreviated:/^q[1234]/i,wide:/^[1234](th|st|nd|rd)? quarter/i},defaultMatchWidth:"wide",parsePatterns:{any:[/1/i,/2/i,/3/i,/4/i]},defaultParseWidth:"any",valueCallback:t=>t+1}),month:L({matchPatterns:{narrow:/^[jfmasond]/i,abbreviated:/^(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)/i,wide:/^(january|february|march|april|may|june|july|august|september|october|november|december)/i},defaultMatchWidth:"wide",parsePatterns:{narrow:[/^j/i,/^f/i,/^m/i,/^a/i,/^m/i,/^j/i,/^j/i,/^a/i,/^s/i,/^o/i,/^n/i,/^d/i],any:[/^ja/i,/^f/i,/^mar/i,/^ap/i,/^may/i,/^jun/i,/^jul/i,/^au/i,/^s/i,/^o/i,/^n/i,/^d/i]},defaultParseWidth:"any"}),day:L({matchPatterns:{narrow:/^[smtwf]/i,short:/^(su|mo|tu|we|th|fr|sa)/i,abbreviated:/^(sun|mon|tue|wed|thu|fri|sat)/i,wide:/^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)/i},defaultMatchWidth:"wide",parsePatterns:{narrow:[/^s/i,/^m/i,/^t/i,/^w/i,/^t/i,/^f/i,/^s/i],any:[/^su/i,/^m/i,/^tu/i,/^w/i,/^th/i,/^f/i,/^sa/i]},defaultParseWidth:"any"}),dayPeriod:L({matchPatterns:{narrow:/^(a|p|mi|n|(in the|at) (morning|afternoon|evening|night))/i,any:/^([ap]\.?\s?m\.?|midnight|noon|(in the|at) (morning|afternoon|evening|night))/i},defaultMatchWidth:"any",parsePatterns:{any:{am:/^a/i,pm:/^p/i,midnight:/^mi/i,noon:/^no/i,morning:/morning/i,afternoon:/afternoon/i,evening:/evening/i,night:/night/i}},defaultParseWidth:"any"})},options:{weekStartsOn:0,firstWeekContainsDate:1}};function x(t,e){return function(t,e,n){const a=E(),r=n?.locale??a.locale??k,i=T(t,e);if(isNaN(i))throw new RangeError("Invalid time value");const s=Object.assign({},n,{addSuffix:n?.addSuffix,comparison:i}),[o,c]=b(n?.in,...i>0?[e,t]:[t,e]),d=O(c,o),u=(A(c)-A(o))/1e3,l=Math.round((d-u)/60);let h;if(l<2)return n?.includeSeconds?d<5?r.formatDistance("lessThanXSeconds",5,s):d<10?r.formatDistance("lessThanXSeconds",10,s):d<20?r.formatDistance("lessThanXSeconds",20,s):d<40?r.formatDistance("halfAMinute",0,s):d<60?r.formatDistance("lessThanXMinutes",1,s):r.formatDistance("xMinutes",1,s):0===l?r.formatDistance("lessThanXMinutes",1,s):r.formatDistance("xMinutes",l,s);if(l<45)return r.formatDistance("xMinutes",l,s);if(l<90)return r.formatDistance("aboutXHours",1,s);if(l<1440){const t=Math.round(l/60);return r.formatDistance("aboutXHours",t,s)}if(l<2520)return r.formatDistance("xDays",1,s);if(l<p){const t=Math.round(l/1440);return r.formatDistance("xDays",t,s)}if(l<86400)return h=Math.round(l/p),r.formatDistance("aboutXMonths",h,s);if(h=M(c,o),h<12){const t=Math.round(l/p);return r.formatDistance("xMonths",t,s)}{const t=h%12,e=Math.trunc(h/12);return t<3?r.formatDistance("aboutXYears",e,s):t<9?r.formatDistance("overXYears",e,s):r.formatDistance("almostXYears",e+1,s)}}(t,function(t){return w(t,Date.now())}(t),e)}var U,G,j;!function(t){t.ADDED_TO_DIALOG="dialog/ADDED_TO_DIALOG",t.REMOVED_FROM_DIALOG="dialog/REMOVED_FROM_DIALOG",t.ADD_PARTICIPANTS="dialog/ADD_PARTICIPANTS",t.REMOVE_PARTICIPANTS="dialog/REMOVE_PARTICIPANTS",t.NEW_DIALOG="dialog/NEW_DIALOG"}(U||(U={})),function(t){t.WAIT="wait",t.LOST="lost",t.SENT="sent",t.READ="read"}(G||(G={})),function(t){t.DISCONNECTED="disconnected",t.CONNECTING="connecting",t.CONNECTED="connected",t.NOT_AUTHORIZED="not-authorized",t.ERROR="error"}(j||(j={}));const F="[useChat][useBlockList]",V="ConnectyCubeBlockList";function Y(t){const[e,i]=n(new Set),s=a(!1),o=t=>e.has(t),u=async(n,a)=>{if(!t)return void console.warn(`${F}[upsert]: ${a} user ${n} failed, chat is not connected`);const r=new Set(e),o={name:V,items:[{user_id:n,action:a,mutualBlock:!0}]};try{a===d.DENY?r.add(n):a===d.ALLOW&&r.delete(n),s.current?(await c.chat.privacylist.setAsDefault(null),await c.chat.privacylist.update(o),r.size>0&&await c.chat.privacylist.setAsDefault(V)):(await c.chat.privacylist.create(o),await c.chat.privacylist.setAsDefault(V))}catch(t){return}finally{i(r)}};return r(()=>{t&&(async()=>{if(!t)return void console.warn(`${F}[fetch]: chat is not connected`);if((await c.chat.privacylist.getNames()).default===V){const t=(await c.chat.privacylist.getList(V)).items.reduce((t,e)=>(e.action===d.DENY&&t.add(+e.user_id),t),new Set);s.current=!0,i(t)}})()},[t]),{blockedUsers:Array.from(e),isBlockedUser:o,unblockUser:async t=>{o(t)?await u(t,d.ALLOW):console.warn(`${F}[unblock]: user ${t} is not blocked`)},blockUser:async t=>{o(t)?console.warn(`${F}[block]: user ${t} is already blocked`):await u(t,d.DENY)}}}function $(t){const e=a(void 0),[i,s]=n(navigator.onLine),o=()=>{e.current&&(clearInterval(e.current),e.current=void 0)};return r(()=>{t?(o(),e.current=setInterval(async()=>{try{await c.chat.pingWithTimeout(1e3),s(!0)}catch(t){s(!1),setTimeout(async()=>{try{await c.chat.pingWithTimeout(1e3),s(!0)}catch(t){s(!1)}},5e3)}},4e4)):o()},[t]),r(()=>{const t=()=>s(!0),e=()=>s(!1);return window.addEventListener("online",t),window.addEventListener("offline",e),()=>{window.removeEventListener("online",t),window.removeEventListener("offline",e)}},[]),{isOnline:i}}const X=t=>{let e;if("string"==typeof t){const n=new Date(t).getTime();e=isNaN(n)?void 0:n}else"number"==typeof t&&(e=1e3*t);return e},H=t=>{let e;if(t<=30)e="Online";else if(t<3600)e=`Last seen ${Math.ceil(t/60)} minutes ago`;else if(t<86400)e=`Last seen ${Math.ceil(t/3600)} hours ago`;else{const n=new Date(Date.now()-1e3*t);e=`Last seen ${n.getUTCDate()}/${(n.getMonth()+1).toString().padStart(2,"0")}/${n.getFullYear()}`}return e},z=t=>X(t.last_message_date_sent)||X(t.updated_at)||X(t.created_at)||0,J="[useChat][useUsers]",q=100;function B(t){const[e,s]=n({}),[o,d]=n({}),[l,h]=n(0),[m,f]=n({}),g=a(0),_=a({}),p=async t=>{const{items:e}=await c.users.getV2(t);return s(t=>e.reduce((t,e)=>({...t,[e.id]:e}),{...t})),d(t=>e.reduce((t,e)=>t[e.id]?{...t,[e.id]:e}:t,{...t})),e.forEach(t=>{_.current[t.id]=Date.now()}),e},y=i(async e=>{const{items:n}=await c.users.getV2({full_name:{start_with:e},limit:q}),{items:a}=await c.users.getV2({login:{start_with:e},limit:q}),r=new Map;return[...n,...a].forEach(t=>{r.set(t.id,t)}),Array.from(r.values()).filter(e=>e.id!==t)},[t]),w=async()=>{let t=l;try{const{count:e}=await c.users.getOnlineCount();t=e,h(t)}catch(t){console.error(`${J}[getOnlineCount][Error]:`,t)}return t};return r(()=>(c.chat.addListener(u.USER_LAST_ACTIVITY,(t,e)=>{if("number"==typeof t&&e>=0){const n=H(e);f(e=>({...e,[t]:n}))}}),()=>{c.chat.removeListener(u.USER_LAST_ACTIVITY)}),[]),{_retrieveAndStoreUsers:async t=>{const n=t.filter(t=>!e[t]);n.length>0&&await p({limit:q,id:{in:n}})},exports:{users:e,getAndStoreUsers:p,searchUsers:y,fetchUserById:async(t,n=!1)=>{const a=_.current[t]||0,r=Date.now()-a>3e4;let i=e[t];if(r||n){const e=await c.users.getV2({id:t,limit:1}),n=e?.items?.[0];n&&(s(e=>({...e,[t]:n})),d(e=>e[t]?{...e,[t]:n}:e),_.current[t]=Date.now(),i=n)}return i},listOnlineUsers:async(t=!1)=>{const e=g.current,n=Date.now();let a=o;return(n-e>6e4||t)&&(a=await(async()=>{const t=await w(),e=[];let n={};try{let a=q,r=0;for(;r<t;)e.push(c.users.listOnline({limit:a,offset:r}).then(({users:t})=>t)),r+=a;const i=(await Promise.all(e)).flat();n=i.reduce((t,e)=>(t[e.id]=e,t),{}),s(t=>({...t,...n})),d(n)}catch(t){console.error(`${J}[listOnline][Error]:`,t)}return n})(),g.current=Date.now()),Object.values(a)},listOnlineUsersWithParams:async t=>{let e={};try{const{users:n}=await c.users.listOnline(t);e=n.reduce((t,e)=>(t[e.id]=e,t),{}),s(t=>({...t,...e})),d(e)}catch(t){console.error(`${J}[listOnlineWithParams][Error]:`,t)}return Object.values(e)},onlineUsers:Object.values(o),getOnlineUsersCount:w,onlineUsersCount:l,lastActivity:m,getLastActivity:async t=>{let e="Last seen recently";try{const{seconds:n}=await c.chat.getLastUserActivity(t);e=H(n)}catch(t){console.error(`${J}[getLastActivity][Error]:`,t)}finally{return f(n=>({...n,[t]:e})),e}},subscribeToUserLastActivityStatus:t=>{c.chat.subscribeToUserLastActivityStatus(t)},unsubscribeFromUserLastActivityStatus:t=>{c.chat.unsubscribeFromUserLastActivityStatus(t)}}}}const Q=s(void 0);Q.displayName="ChatContext";const Z=()=>{const t=o(Q);if(!t)throw new Error("useChat must be within ChatProvider");return t},K=({children:e})=>{const[i,s]=n(!1),[o,d]=n({total:0}),[m,f]=n({}),[g,p]=n({}),[y,w]=n(!1),[v,D,E]=_({}),[A,b,T]=_([]),[S,M,O]=_(),[C,N,I]=_(),[P,R,L]=_(j.DISCONNECTED),W=a({}),k=a(null),F=a(null),V=a(null),H=a(null),J=a({}),q=a({}),Z=Y(i),K=B(S),{isOnline:tt}=$(i),{_retrieveAndStoreUsers:et}=K,nt=async(t=j.DISCONNECTED)=>{let e=!1;return c.chat.isConnected&&(e=await c.chat.disconnect(),s(!1),M(void 0),R(t),rt()),e},at=(t=j.DISCONNECTED)=>{c.chat.terminate(),R(t),rt(),mt()},rt=()=>{J.current={},w(!1),p({})},it=async t=>{const e={sort_desc:"date_sent",limit:100,skip:0,...t},{items:n,skip:a,limit:r,total_entries:i}=await c.chat.dialog.list(e);w(a+r>=i),b(t=>{const e=[...t,...n];return Array.from(new Map(e.map(t=>[t._id,t])).values()).sort((t,e)=>z(e)-z(t))});const s=n.flatMap(t=>t.occupants_ids),o=Array.from(new Set(s));return et(o),n},st=async(t,e={})=>{const n={chat_dialog_id:t,sort_desc:"date_sent",limit:100,skip:0,...e};try{const{items:e,skip:a,limit:r}=await c.chat.message.list(n),i=E.current[t]??[],s=a+r>e.length+i.length;return p(e=>({...e,[t]:s})),e.sort((t,e)=>t._id.toString().localeCompare(e._id.toString())).map(t=>{const e=t.attachments?.map(t=>({...t,url:c.storage.privateUrl(t.uid)}));return{...t,attachments:e,status:t.read?G.READ:G.SENT}})}catch(t){if(404===t.code)return[];throw t}},ot=async t=>{try{const e=await st(t);return D(n=>({...n,[t]:e})),e}catch(t){throw t}},ct=t=>{if(t??=C,!t)throw"No dialog provided. You need to provide a dialog via function argument or select a dialog via 'selectDialog'.";if(t.type!==h.PRIVATE)return;const e=t.occupants_ids.find(t=>t!==S);return e&&(q.current[e]=t._id),e},dt=async t=>{const e={read:1,chat_dialog_id:t._id};await c.chat.message.update("",e),b(e=>e.map(e=>e._id===t._id?{...e,unread_messages_count:0}:e))},ut=(t,e,n,a)=>{const r={type:n.type===h.PRIVATE?l.CHAT:l.GROUPCHAT,body:t,extension:{save_to_history:1,dialog_id:n._id}};e&&(r.extension.attachments=e);return c.chat.send(n.type===h.PRIVATE?a:n._id,r)},lt=(t,e,n,a,r,i,s)=>{const o=Math.round((new Date).getTime()/1e3);b(t=>t.map(t=>t._id===n?{...t,last_message:e,last_message_user_id:a,last_message_date_sent:o}:t).sort((t,e)=>{const n=X(t.last_message_date_sent)||X(t.created_at);return(X(e.last_message_date_sent)||X(e.created_at))-n})),D(c=>({...c,[n]:[...c[n]||[],{_id:t,created_at:o,updated_at:o,chat_dialog_id:n,message:e,sender_id:a,recipient_id:r,date_sent:o,read:0,read_ids:[a],delivered_ids:[a],views_count:0,attachments:i||[],reactions:{},isLoading:s,status:L.current===j.CONNECTED?G.WAIT:G.LOST}]}))},ht=(t,e,n,a)=>{D(r=>({...r,[n]:r[n]?.map(n=>n._id===e?{...n,read_ids:a?n.read_ids?[...new Set([...n.read_ids,a])]:[a]:n.read_ids,read:t===G.READ?1:n.read,status:t===G.SENT&&n.status===G.LOST?n.status:t}:n)??[]}))},mt=()=>{D(t=>Object.fromEntries(Object.entries(t).map(([t,e])=>[t,e.map(t=>t.status===G.WAIT?{...t,status:G.LOST}:t)])))},ft=(t,e,n,a={})=>{const r={body:t,extension:{dialogId:e,...a}};c.chat.sendSystemMessage(n,r)},gt=(t,e,n)=>{f(a=>{const r=a[t],i=r?new Set(r):new Set;return n?i.add(e):i.delete(e),{...a,[t]:[...i]}})},_t=(t,e)=>{gt(t,e,!1),clearTimeout(W.current[t]?.[e]),delete W.current[t]?.[e]},pt=()=>{L.current!==j.CONNECTING&&(R(j.DISCONNECTED),rt()),mt()},yt=()=>{R(j.CONNECTED)},wt=async(t={})=>{if("not-authorized"===t?.condition||"Password not verified"===t?.text||"SASLError"===t?.name){await nt(j.NOT_AUTHORIZED)||at(j.NOT_AUTHORIZED)}else R(j.ERROR)},vt=(t,e)=>{if(k.current&&k.current(t,e),t===O.current||e.delay&&e.type===l.CHAT)return;const n=I.current,a=e.dialog_id,r=e.id,i=e.body||"",s=e.type===l.CHAT?O.current:void 0,o=e.extension.attachments?.length>0?e.extension.attachments.map(t=>({...t,url:c.storage.privateUrl(t.uid)})):void 0;lt(r,i,a,t,s,o),_t(a,t),b(t=>t.map(t=>t._id===a?{...t,unread_messages_count:n&&n._id===e.dialog_id?t.unread_messages_count:(t.unread_messages_count||0)+1,last_message:e.body,last_message_date_sent:parseInt(e.extension.date_sent)}:t))},Dt=(t,e)=>{H.current&&H.current(t,e)},Et=(t,e)=>{V.current&&V.current(t,e);const n=e?G.SENT:t?G.LOST:void 0,a=e?e.id:t?t.id:void 0,r=e?e.extension.dialog_id:t?t.extension.dialog_id:void 0;n&&a&&r&&ht(n,a,r)},At=async t=>{const e=t.extension.dialogId,n=t.userId;if(F.current&&F.current(t),n!==O.current)switch(t.body){case U.NEW_DIALOG:case U.ADDED_TO_DIALOG:{const t=(await c.chat.dialog.list({_id:e})).items[0];et(t.occupants_ids),b(e=>[t,...e.filter(e=>e._id!==t._id)]);break}case U.ADD_PARTICIPANTS:{const n=t.extension.addedParticipantsIds.split(",").map(Number);et(n),b(t=>t.map(t=>(t._id===e&&(t.occupants_ids=Array.from(new Set([...t.occupants_ids,...n]))),t)));break}case U.REMOVE_PARTICIPANTS:{const n=t.extension.removedParticipantsIds.split(",").map(Number);b(t=>t.map(t=>(t._id===e&&(t.occupants_ids=t.occupants_ids.filter(t=>!n.includes(t))),t)));break}case U.REMOVED_FROM_DIALOG:b(t=>t.map(t=>(t._id===e&&t.type!==h.PRIVATE&&(t.occupants_ids=t.occupants_ids.filter(t=>t!==n)),t)))}},bt=(t,e,n)=>{n!==O.current&&ht(G.READ,t,e,n)},Tt=(t,e,n)=>{const a=n||(t=>{let e=q.current[t];if(!e){const n=T.current.find(e=>e.type===h.PRIVATE&&ct(e)===t);n&&(e=n._id,q.current[t]=e)}return e})(e);a&&e&&e!==O.current&&(gt(a,e,t),W.current[a]||(W.current[a]={}),t?(W.current[a][e]&&(clearTimeout(W.current[a][e]),delete W.current[a][e]),W.current[a][e]=setTimeout(()=>{_t(a,e)},6e3)):_t(a,e))};return r(()=>(c.chat.addListener(u.DISCONNECTED,pt),c.chat.addListener(u.RECONNECTED,yt),c.chat.addListener(u.ERROR,wt),c.chat.addListener(u.MESSAGE,vt),c.chat.addListener(u.ERROR_MESSAGE,Dt),c.chat.addListener(u.SENT_MESSAGE,Et),c.chat.addListener(u.SYSTEM_MESSAGE,At),c.chat.addListener(u.READ_MESSAGE,bt),c.chat.addListener(u.TYPING_MESSAGE,Tt),()=>{c.chat.removeAllListeners()}),[]),r(()=>{(()=>{const t={total:0};A.forEach(({_id:e,unread_messages_count:n=0})=>{e!==C?._id&&(t[e]=n,t.total+=n)}),d(t)})()},[A]),r(()=>{(async t=>{if(t&&L.current!==j.ERROR)L.current!==j.DISCONNECTED&&L.current!==j.NOT_AUTHORIZED||R(j.CONNECTING);else try{await c.chat.pingWithTimeout(1e3),R(j.CONNECTED)}catch(t){at()}})(tt)},[tt]),t(Q.Provider,{value:{isOnline:tt,isConnected:i,chatStatus:P,connect:async t=>{R(j.CONNECTING);try{const e=await c.chat.connect(t);return e&&(R(j.CONNECTED),s(e),M(t.userId)),e}catch(t){return R(j.DISCONNECTED),console.error(`Failed to connect due to ${t}`),!1}},disconnect:nt,terminate:at,currentUserId:S,selectDialog:async t=>{N(t),t&&(J.current[t._id]||(await ot(t._id),J.current[t._id]=!0),t.unread_messages_count>0&&await dt(t).catch(t=>{}))},selectedDialog:C,getDialogOpponentId:ct,unreadMessagesCount:o,getMessages:ot,getNextMessages:async t=>{const e=E.current[t]??[],n=e.length;try{const a=[...await st(t,{skip:n}),...e];return D(e=>({...e,[t]:a})),a}catch(t){throw t}},totalMessagesReached:g,messages:v,sendSignal:(t,e,n={})=>{const a=Array.isArray(t)?t:[t],r={body:e,extension:n};a.forEach(t=>{c.chat.sendSystemMessage(t,r)})},sendMessage:(t,e)=>{if(e??=C,!e)throw"No dialog provided. You need to provide a dialog via function argument or select a dialog via 'selectDialog'.";const n=ct(e),a=ut(t,null,e,n);lt(a,t,e._id,S,n)},dialogs:A,getDialogs:it,getNextDialogs:async()=>{const t=T.current.length;return it({skip:t})},totalDialogReached:y,createChat:async(t,e)=>{const n={type:h.PRIVATE,occupants_ids:[t],extensions:e},a=await c.chat.dialog.create(n);return b(t=>[a,...t.filter(t=>t._id!==a._id)]),p(t=>({...t,[a._id]:!0})),q.current[t]=a._id,ft(U.NEW_DIALOG,a._id,t),et([t,S]),a},createGroupChat:async(t,e,n,a)=>{const r={name:e,photo:n,type:h.GROUP,occupants_ids:t,extensions:a},i=await c.chat.dialog.create(r);return b(t=>[i,...t.filter(t=>t._id!==i._id)]),p(t=>({...t,[i._id]:!0})),t.forEach(t=>{ft(U.NEW_DIALOG,i._id,t)}),et([...t,S]),i},sendTypingStatus:t=>{if(t??=C,!t)throw"No dialog provided. You need to provide a dialog via function argument or select a dialog via 'selectDialog'.";c.chat.sendIsTypingStatus(t.type===h.PRIVATE?ct(t):t._id)},typingStatus:m,sendMessageWithAttachment:async(t,e)=>{if(e??=C,!e)throw"No dialog provided. You need to provide a dialog via function argument or select a dialog via 'selectDialog'.";const n=ct(e),a=Date.now()+"",r=t.map((t,e)=>({uid:`local-${a}-${e}`,type:t.type,url:URL.createObjectURL(t)}));lt(a,"Attachment",e._id,S,n,r,!0);const i=t.map(t=>{const{name:e,type:n,size:a}=t,r={file:t,name:e,type:n,size:a,public:!1};return c.storage.createAndUpload(r)}),s=(await Promise.all(i)).map(({uid:t,content_type:e=""})=>({uid:t,type:e,url:c.storage.privateUrl(t)})),o=ut("Attachment",s,e,n);D(t=>({...t,[e._id]:t[e._id].map(t=>t._id===a?{...t,_id:o,attachments:r,isLoading:!1,status:L.current===j.CONNECTED?G.WAIT:G.LOST}:t)}))},markDialogAsRead:dt,removeUsersFromGroupChat:async t=>{if(!C)throw new Error("No dialog selected");const e=C._id,n={pull_all:{occupants_ids:t}};await c.chat.dialog.update(e,n),t.forEach(t=>{ft(U.REMOVED_FROM_DIALOG,e,t)}),C.occupants_ids.filter(e=>!t.includes(e)&&e!==S).forEach(n=>{ft(U.REMOVE_PARTICIPANTS,e,n,{removedParticipantsIds:t.join()})});const a={...C,occupants_ids:C.occupants_ids.filter(e=>!t.includes(e))};b(t=>t.map(t=>t._id===e?a:t)),N(a)},addUsersToGroupChat:async t=>{if(!C)throw new Error("No dialog selected");const e=C._id,n={push_all:{occupants_ids:t}};await c.chat.dialog.update(e,n),C.occupants_ids.filter(t=>t!==S).forEach(n=>{ft(U.ADD_PARTICIPANTS,e,n,{addedParticipantsIds:t.join()})}),t.forEach(t=>{ft(U.ADDED_TO_DIALOG,e,t)}),et(t);const a={...C,occupants_ids:Array.from(new Set([...C.occupants_ids,...t]))};b(t=>t.map(t=>t._id===e?a:t)),N(a)},leaveGroupChat:async()=>{if(!C)throw new Error("No dialog selected");await c.chat.dialog.delete(C._id),C.occupants_ids.filter(t=>t!==S).forEach(t=>{ft(U.REMOVED_FROM_DIALOG,C._id,t)}),b(A.filter(t=>t._id!==C._id)),N(void 0)},readMessage:(t,e,n)=>{c.chat.sendReadStatus({messageId:t,userId:e,dialogId:n}),ht(G.READ,t,n,e),b(t=>t.map(t=>t._id===n?{...t,unread_messages_count:Math.max(0,t.unread_messages_count-1)}:t))},lastMessageSentTimeString:t=>x(t.last_message_date_sent?1e3*t.last_message_date_sent:t.created_at,{addSuffix:!0}),messageSentTimeString:t=>x(1e3*t.date_sent,{addSuffix:!0}),processOnSignal:t=>{F.current=t},processOnMessage:t=>{k.current=t},processOnMessageError:t=>{H.current=t},processOnMessageSent:t=>{V.current=t},...Z,...K.exports},children:e})};export{K as ChatProvider,j as ChatStatus,G as MessageStatus,Z as useChat};
//# sourceMappingURL=index.js.map