airdcpp-webui 2.14.0-beta.10 → 2.14.0-beta.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/index.html +1 -1
  2. package/dist/js/381.648720e987fa59ec0e87.chunk.js +2 -0
  3. package/dist/js/381.648720e987fa59ec0e87.chunk.js.gz +0 -0
  4. package/dist/js/381.648720e987fa59ec0e87.chunk.js.map +1 -0
  5. package/dist/js/{550.d7f48465222a7a1fae31.chunk.js → 550.83271f41ad0cccc6815b.chunk.js} +2 -2
  6. package/dist/js/550.83271f41ad0cccc6815b.chunk.js.gz +0 -0
  7. package/dist/js/{550.d7f48465222a7a1fae31.chunk.js.map → 550.83271f41ad0cccc6815b.chunk.js.map} +1 -1
  8. package/dist/js/944.890172ae3c849dfa9e12.chunk.js +2 -0
  9. package/dist/js/944.890172ae3c849dfa9e12.chunk.js.gz +0 -0
  10. package/dist/js/944.890172ae3c849dfa9e12.chunk.js.map +1 -0
  11. package/dist/js/hubs.43ca34eee0ef61fc32b2.chunk.js +2 -0
  12. package/dist/js/hubs.43ca34eee0ef61fc32b2.chunk.js.gz +0 -0
  13. package/dist/js/{hubs.d9afbf8619ef75a32047.chunk.js.map → hubs.43ca34eee0ef61fc32b2.chunk.js.map} +1 -1
  14. package/dist/js/locales/zh_CN-GB2312-webui-main-json.c56c6d389b7951c4f74d.chunk.js +1 -0
  15. package/dist/js/locales/zh_CN-GB2312-webui-main-json.c56c6d389b7951c4f74d.chunk.js.gz +0 -0
  16. package/dist/js/main.cacce80f03c18d3bf7d9.entry.js +3 -0
  17. package/dist/js/main.cacce80f03c18d3bf7d9.entry.js.gz +0 -0
  18. package/dist/js/{main.9dc668dfea0c72fee615.entry.js.map → main.cacce80f03c18d3bf7d9.entry.js.map} +1 -1
  19. package/dist/js/messages.1a4f756d835c59f6c925.chunk.js +2 -0
  20. package/dist/js/messages.1a4f756d835c59f6c925.chunk.js.gz +0 -0
  21. package/dist/js/messages.1a4f756d835c59f6c925.chunk.js.map +1 -0
  22. package/dist/js/settings.e2c30f0541c9eaaa8741.chunk.js +2 -0
  23. package/dist/js/settings.e2c30f0541c9eaaa8741.chunk.js.gz +0 -0
  24. package/dist/js/settings.e2c30f0541c9eaaa8741.chunk.js.map +1 -0
  25. package/dist/sw.js +1 -1
  26. package/dist/sw.js.gz +0 -0
  27. package/dist/sw.js.map +1 -1
  28. package/package.json +1 -1
  29. package/dist/js/381.a69bc79f29e120dfa3fa.chunk.js +0 -2
  30. package/dist/js/381.a69bc79f29e120dfa3fa.chunk.js.gz +0 -0
  31. package/dist/js/381.a69bc79f29e120dfa3fa.chunk.js.map +0 -1
  32. package/dist/js/503.168f92c3ec4611e29dd5.chunk.js +0 -2
  33. package/dist/js/503.168f92c3ec4611e29dd5.chunk.js.gz +0 -0
  34. package/dist/js/503.168f92c3ec4611e29dd5.chunk.js.map +0 -1
  35. package/dist/js/550.d7f48465222a7a1fae31.chunk.js.gz +0 -0
  36. package/dist/js/hubs.d9afbf8619ef75a32047.chunk.js +0 -2
  37. package/dist/js/hubs.d9afbf8619ef75a32047.chunk.js.gz +0 -0
  38. package/dist/js/main.9dc668dfea0c72fee615.entry.js +0 -3
  39. package/dist/js/main.9dc668dfea0c72fee615.entry.js.gz +0 -0
  40. package/dist/js/messages.64d8ee21a29cf7b1236b.chunk.js +0 -2
  41. package/dist/js/messages.64d8ee21a29cf7b1236b.chunk.js.gz +0 -0
  42. package/dist/js/messages.64d8ee21a29cf7b1236b.chunk.js.map +0 -1
  43. package/dist/js/settings.dd2219b4918454acebe2.chunk.js +0 -2
  44. package/dist/js/settings.dd2219b4918454acebe2.chunk.js.gz +0 -0
  45. package/dist/js/settings.dd2219b4918454acebe2.chunk.js.map +0 -1
  46. /package/dist/js/{main.9dc668dfea0c72fee615.entry.js.LICENSE.txt → main.cacce80f03c18d3bf7d9.entry.js.LICENSE.txt} +0 -0
package/dist/index.html CHANGED
@@ -16,7 +16,7 @@
16
16
  {
17
17
  // We must inject the main chunk dynamically as well because the final path is not known on compile time
18
18
  var script = document.createElement('script');
19
- script.src = getBasePath() + "js/main.9dc668dfea0c72fee615.entry.js";
19
+ script.src = getBasePath() + "js/main.cacce80f03c18d3bf7d9.entry.js";
20
20
  document.body.appendChild(script);
21
21
  }
22
22
 
@@ -0,0 +1,2 @@
1
+ "use strict";(self.webpackChunkairdcpp_webui=self.webpackChunkairdcpp_webui||[]).push([[381],{59089:(e,t,s)=>{s.d(t,{A:()=>a});var n=s(71354),o=s.n(n),i=s(76314),r=s.n(i)()(o());r.push([e.id,".message-section {\n flex: 1;\n overflow-y: auto;\n}\n\n.message-list .date.divider i {\n margin-right: 5px;\n}\n\n.message-list .item .text .highlight.link {\n color: #4183c4;\n}\n\n.message-list .item .text .highlight.bold {\n font-weight: bold;\n}\n\n.message-list .item .text .table.dropdown,\n.message-list .item .text .table.dropdown .popup.trigger {\n max-width: 100%;\n}\n\n.message-list .item .text .table.dropdown .caption {\n overflow: hidden;\n}\n","",{version:3,sources:["webpack://./src/components/messages/messages.css"],names:[],mappings:"AAAA;EACE,OAAO;EACP,gBAAgB;AAClB;;AAEA;EACE,iBAAiB;AACnB;;AAEA;EACE,cAAc;AAChB;;AAEA;EACE,iBAAiB;AACnB;;AAEA;;EAEE,eAAe;AACjB;;AAEA;EACE,gBAAgB;AAClB",sourcesContent:[".message-section {\n flex: 1;\n overflow-y: auto;\n}\n\n.message-list .date.divider i {\n margin-right: 5px;\n}\n\n.message-list .item .text .highlight.link {\n color: #4183c4;\n}\n\n.message-list .item .text .highlight.bold {\n font-weight: bold;\n}\n\n.message-list .item .text .table.dropdown,\n.message-list .item .text .table.dropdown .popup.trigger {\n max-width: 100%;\n}\n\n.message-list .item .text .table.dropdown .caption {\n overflow: hidden;\n}\n"],sourceRoot:""}]);const a=r},91381:(e,t,s)=>{s.d(t,{A:()=>ee});var n=s(74848),o=s(96540),i=s(46942),r=s.n(i),a=s(99347),l=s(68443),h=s(71987),d=Object.defineProperty,c=(e,t,s)=>((e,t,s)=>t in e?d(e,t,{enumerable:!0,configurable:!0,writable:!0,value:s}):e[t]=s)(e,"symbol"!=typeof t?t+"":t,s),g=new Map,m=new WeakMap,p=0;function u(e,t,s={},n=undefined){if(void 0===window.IntersectionObserver&&void 0!==n){const o=e.getBoundingClientRect();return t(n,{isIntersecting:n,target:e,intersectionRatio:"number"==typeof s.threshold?s.threshold:0,time:0,boundingClientRect:o,intersectionRect:o,rootBounds:o}),()=>{}}const{id:o,observer:i,elements:r}=function(e){const t=function(e){return Object.keys(e).sort().filter(t=>void 0!==e[t]).map(t=>{return`${t}_${"root"===t?(s=e.root,s?(m.has(s)||(p+=1,m.set(s,p.toString())),m.get(s)):"0"):e[t]}`;var s}).toString()}(e);let s=g.get(t);if(!s){const n=new Map;let o;const i=new IntersectionObserver(t=>{t.forEach(t=>{var s;const i=t.isIntersecting&&o.some(e=>t.intersectionRatio>=e);e.trackVisibility&&void 0===t.isVisible&&(t.isVisible=i),null==(s=n.get(t.target))||s.forEach(e=>{e(i,t)})})},e);o=i.thresholds||(Array.isArray(e.threshold)?e.threshold:[e.threshold||0]),s={id:t,observer:i,elements:n},g.set(t,s)}return s}(s),a=r.get(e)||[];return r.has(e)||r.set(e,a),a.push(t),i.observe(e),function(){a.splice(a.indexOf(t),1),0===a.length&&(r.delete(e),i.unobserve(e)),0===r.size&&(i.disconnect(),g.delete(o))}}var b=class extends o.Component{constructor(e){super(e),c(this,"node",null),c(this,"_unobserveCb",null),c(this,"handleNode",e=>{this.node&&(this.unobserve(),e||this.props.triggerOnce||this.props.skip||this.setState({inView:!!this.props.initialInView,entry:void 0})),this.node=e||null,this.observeNode()}),c(this,"handleChange",(e,t)=>{e&&this.props.triggerOnce&&this.unobserve(),function(e){return"function"!=typeof e.children}(this.props)||this.setState({inView:e,entry:t}),this.props.onChange&&this.props.onChange(e,t)}),this.state={inView:!!e.initialInView,entry:void 0}}componentDidMount(){this.unobserve(),this.observeNode()}componentDidUpdate(e){e.rootMargin===this.props.rootMargin&&e.root===this.props.root&&e.threshold===this.props.threshold&&e.skip===this.props.skip&&e.trackVisibility===this.props.trackVisibility&&e.delay===this.props.delay||(this.unobserve(),this.observeNode())}componentWillUnmount(){this.unobserve()}observeNode(){if(!this.node||this.props.skip)return;const{threshold:e,root:t,rootMargin:s,trackVisibility:n,delay:o,fallbackInView:i}=this.props;this._unobserveCb=u(this.node,this.handleChange,{threshold:e,root:t,rootMargin:s,trackVisibility:n,delay:o},i)}unobserve(){this._unobserveCb&&(this._unobserveCb(),this._unobserveCb=null)}render(){const{children:e}=this.props;if("function"==typeof e){const{inView:t,entry:s}=this.state;return e({inView:t,entry:s,ref:this.handleNode})}const{as:t,triggerOnce:s,threshold:n,root:i,rootMargin:r,onChange:a,skip:l,trackVisibility:h,delay:d,initialInView:c,fallbackInView:g,...m}=this.props;return o.createElement(t||"div",{ref:this.handleNode,...m},e)}},f=s(71352),y=s(39115),A=s(74416);const v=({time:e})=>{const{formatTimestamp:t}=(0,A.k)();return(0,n.jsx)("div",{className:"time",children:t(e)})};var w=s(28122);const x=e=>{var{emojify:t,message:s,user:o,label:i,highlightMenuProps:r}=e,a=function(e,t){var s={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(s[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(n=Object.getOwnPropertySymbols(e);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(s[n[o]]=e[n[o]])}return s}(e,["emojify","message","user","label","highlightMenuProps"]);return(0,n.jsxs)("div",{className:"text",children:[!!i&&(0,n.jsx)("span",{className:"label",children:`${i}: `}),(0,n.jsx)(w.z,Object.assign({emojify:t,text:s.text,highlights:s.highlights,user:o,menuProps:r},a))]})};const O=({message:e,dropdownContext:t})=>(0,n.jsxs)("div",{className:"header author",children:[e.third_person&&(0,n.jsx)("span",{children:"*"}),(0,n.jsx)(f.Bg,{contextElement:t,triggerIcon:null,user:e.from,remoteMenuId:y.Ay.HUB_USER,entity:e.from.hub_session_id})]});class j extends o.Component{shouldComponentUpdate(){return!1}render(){const e=this.props,{message:t,dropdownContext:s,highlightMenuProps:o}=e,i=function(e,t){var s={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(s[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(n=Object.getOwnPropertySymbols(e);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(s[n[o]]=e[n[o]])}return s}(e,["message","dropdownContext","highlightMenuProps"]);return(0,n.jsxs)(b,Object.assign({className:r()("ui item chat",t.from.flags.join(" "))},i,{children:[(0,n.jsx)(v,{time:t.time}),(0,n.jsxs)("div",{className:r()("left",t.third_person?"third-person":"normal"),children:[(0,n.jsx)(O,{message:t,dropdownContext:s}),(0,n.jsx)(x,{message:t,emojify:!0,user:t.from,highlightMenuProps:o})]})]}))}}var C=s(83994),E=s(4425),I=s(86038);const M=e=>{switch(e){case I.F$.VERBOSE:return E.A.VERBOSE;case I.F$.INFO:return E.A.INFO+" circle";case I.F$.WARNING:return E.A.WARNING;case I.F$.ERROR:return E.A.ERROR;default:return""}};class P extends o.Component{shouldComponentUpdate(){return!1}render(){const e=this.props,{message:t,highlightMenuProps:s}=e,o=function(e,t){var s={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(s[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(n=Object.getOwnPropertySymbols(e);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(s[n[o]]=e[n[o]])}return s}(e,["message","highlightMenuProps"]);return(0,n.jsxs)(b,Object.assign({className:r()("ui item status",t.severity,t.type)},o,{children:[(0,n.jsx)(C.A,{icon:M(t.severity)}),t.time>0&&(0,n.jsx)(v,{time:t.time}),(0,n.jsx)(x,{label:t.label,message:t,emojify:!1,highlightMenuProps:s})]}))}}const N=e=>{var{message:t}=e,s=function(e,t){var s={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(s[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var o=0;for(n=Object.getOwnPropertySymbols(e);o<n.length;o++)t.indexOf(n[o])<0&&Object.prototype.propertyIsEnumerable.call(e,n[o])&&(s[n[o]]=e[n[o]])}return s}(e,["message"]);return t.chat_message?(0,n.jsx)(j,Object.assign({message:t.chat_message,dropdownContext:s.highlightMenuProps.boundary},s)):t.log_message?(0,n.jsx)(P,Object.assign({message:t.log_message},s)):null},_=e=>{const t=e.chat_message?e.chat_message:e.log_message;return t&&new Date(1e3*t.time).getDate()},k=e=>!!e.log_message&&e.log_message.type===I.Lu.HISTORY,S=({time:e})=>{const{formatCalendarTime:t}=(0,A.k)();return(0,n.jsxs)("div",{className:"ui horizontal date divider",children:[(0,n.jsx)(C.A,{icon:E.A.DATE}),t(e)]},`divider${e}`)};var R=s(25507);const V=({entity:e,onMessageVisibilityChanged:t,addDownload:s,highlightRemoteMenuId:o,scrollable:i,instanceId:r},a,l,d,c)=>{if(((e,t)=>{const s=t[e];return 0===e||1===e&&k(t[e-1])?_(s)!==(new Date).getDate()&&!k(s):_(t[e-1])!==_(s)})(d,c)){const e=l.chat_message?l.chat_message:l.log_message;e&&a.push((0,n.jsx)(S,{time:e.time},`divider${e.id}`))}const g=(0,h.Lw)(l);return a.push((0,n.jsx)(N,{id:(0,h.AS)(g,r),onChange:e=>{t(g,e)},threshold:.4,root:i,message:l,highlightMenuProps:{addDownload:s,entity:e,remoteMenuId:o,boundary:".message-section"}},g)),a};var B=s(42695),D=s(88544),$=s(67749),F=s(85072),T=s.n(F),G=s(97825),H=s.n(G),U=s(77659),W=s.n(U),z=s(55056),L=s.n(z),K=s(10540),Y=s.n(K),q=s(41113),J=s.n(q),Q=s(59089),X={};X.styleTagTransform=J(),X.setAttributes=L(),X.insert=W().bind(null,"head"),X.domAPI=H(),X.insertStyleElement=Y(),T()(Q.A,X),Q.A&&Q.A.locals&&Q.A.locals;const Z=o.memo(function({className:e,t,messages:s,chatSession:i,highlightRemoteMenuId:h,scrollPositionHandler:d}){const[c,g]=o.useState(null),m=(p=i,(0,o.useMemo)(()=>{const e={},t=t=>{const s=e[t];if(!s)throw new Error("Download was not found");return s};return{downloadDialogProps:{downloadHandler:(e,s,n)=>t(e.itemInfo.id).downloadHandler(e,s,n),userGetter:(e,s)=>{const n=t(e).userGetter;return n?n(e,s):void 0},itemDataGetter:(e,s)=>t(e).itemDataGetter(e,s),sessionItem:p},addDownloadItem:(t,s)=>{e[t]=s}}},[]));var p;const{messageNodes:u,visibleItems:b}=(({highlightRemoteMenuId:e,messages:t,chatSession:s},n,i)=>{const r=(0,R.te)(),a=(0,o.useMemo)(()=>new Set,[s]),l=(e,t)=>{t?a.add(e):a.delete(e)};return{messageNodes:(0,o.useMemo)(()=>t?t.reduce(V.bind(null,{highlightRemoteMenuId:e,entity:s,onMessageVisibilityChanged:l,addDownload:n.addDownloadItem,scrollable:i,instanceId:r}),[]):null,[t]),visibleItems:a}})({highlightRemoteMenuId:h,messages:s,chatSession:i},m,c);return(0,l.sg)({messages:s,scrollPositionHandler:d,chatSession:i},b,c),(0,n.jsx)("div",{ref:g,className:r()("message-section",e),role:"article",children:u?(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)("div",{className:"ui list message-list",children:u}),(0,n.jsx)(D.A,Object.assign({},m.downloadDialogProps))]}):(0,n.jsx)(a.A,{text:(0,B.Tl)("Loading messages",t,$.KV.COMMON)})})},(e,t)=>e.messages===t.messages),ee=Z}}]);
2
+ //# sourceMappingURL=381.648720e987fa59ec0e87.chunk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"js/381.648720e987fa59ec0e87.chunk.js","mappings":"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","sources":["webpack://airdcpp-webui/./src/components/messages/messages.css","webpack://airdcpp-webui/./node_modules/react-intersection-observer/dist/index.mjs","webpack://airdcpp-webui/./src/components/messages/message/Timestamp.tsx","webpack://airdcpp-webui/./src/components/messages/message/MessageText.tsx","webpack://airdcpp-webui/./src/components/messages/message/ChatMessage.tsx","webpack://airdcpp-webui/./src/components/messages/message/StatusMessage.tsx","webpack://airdcpp-webui/./src/components/messages/list/MessageListItem.tsx","webpack://airdcpp-webui/./src/components/messages/list/MessageListDateDivider.tsx","webpack://airdcpp-webui/./src/components/messages/effects/MessageNodeManager.tsx","webpack://airdcpp-webui/./src/components/messages/messages.css?1e0d","webpack://airdcpp-webui/./src/components/messages/MessageView.tsx","webpack://airdcpp-webui/./src/effects/ItemDownloadManager.ts"],"sourcesContent":["// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.message-section {\n flex: 1;\n overflow-y: auto;\n}\n\n.message-list .date.divider i {\n margin-right: 5px;\n}\n\n.message-list .item .text .highlight.link {\n color: #4183c4;\n}\n\n.message-list .item .text .highlight.bold {\n font-weight: bold;\n}\n\n.message-list .item .text .table.dropdown,\n.message-list .item .text .table.dropdown .popup.trigger {\n max-width: 100%;\n}\n\n.message-list .item .text .table.dropdown .caption {\n overflow: hidden;\n}\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/components/messages/messages.css\"],\"names\":[],\"mappings\":\"AAAA;EACE,OAAO;EACP,gBAAgB;AAClB;;AAEA;EACE,iBAAiB;AACnB;;AAEA;EACE,cAAc;AAChB;;AAEA;EACE,iBAAiB;AACnB;;AAEA;;EAEE,eAAe;AACjB;;AAEA;EACE,gBAAgB;AAClB\",\"sourcesContent\":[\".message-section {\\n flex: 1;\\n overflow-y: auto;\\n}\\n\\n.message-list .date.divider i {\\n margin-right: 5px;\\n}\\n\\n.message-list .item .text .highlight.link {\\n color: #4183c4;\\n}\\n\\n.message-list .item .text .highlight.bold {\\n font-weight: bold;\\n}\\n\\n.message-list .item .text .table.dropdown,\\n.message-list .item .text .table.dropdown .popup.trigger {\\n max-width: 100%;\\n}\\n\\n.message-list .item .text .table.dropdown .caption {\\n overflow: hidden;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","\"use client\";\nvar __defProp = Object.defineProperty;\nvar __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;\nvar __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== \"symbol\" ? key + \"\" : key, value);\n\n// src/InView.tsx\nimport * as React from \"react\";\n\n// src/observe.ts\nvar observerMap = /* @__PURE__ */ new Map();\nvar RootIds = /* @__PURE__ */ new WeakMap();\nvar rootId = 0;\nvar unsupportedValue = void 0;\nfunction defaultFallbackInView(inView) {\n unsupportedValue = inView;\n}\nfunction getRootId(root) {\n if (!root) return \"0\";\n if (RootIds.has(root)) return RootIds.get(root);\n rootId += 1;\n RootIds.set(root, rootId.toString());\n return RootIds.get(root);\n}\nfunction optionsToId(options) {\n return Object.keys(options).sort().filter(\n (key) => options[key] !== void 0\n ).map((key) => {\n return `${key}_${key === \"root\" ? getRootId(options.root) : options[key]}`;\n }).toString();\n}\nfunction createObserver(options) {\n const id = optionsToId(options);\n let instance = observerMap.get(id);\n if (!instance) {\n const elements = /* @__PURE__ */ new Map();\n let thresholds;\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n var _a;\n const inView = entry.isIntersecting && thresholds.some((threshold) => entry.intersectionRatio >= threshold);\n if (options.trackVisibility && typeof entry.isVisible === \"undefined\") {\n entry.isVisible = inView;\n }\n (_a = elements.get(entry.target)) == null ? void 0 : _a.forEach((callback) => {\n callback(inView, entry);\n });\n });\n }, options);\n thresholds = observer.thresholds || (Array.isArray(options.threshold) ? options.threshold : [options.threshold || 0]);\n instance = {\n id,\n observer,\n elements\n };\n observerMap.set(id, instance);\n }\n return instance;\n}\nfunction observe(element, callback, options = {}, fallbackInView = unsupportedValue) {\n if (typeof window.IntersectionObserver === \"undefined\" && fallbackInView !== void 0) {\n const bounds = element.getBoundingClientRect();\n callback(fallbackInView, {\n isIntersecting: fallbackInView,\n target: element,\n intersectionRatio: typeof options.threshold === \"number\" ? options.threshold : 0,\n time: 0,\n boundingClientRect: bounds,\n intersectionRect: bounds,\n rootBounds: bounds\n });\n return () => {\n };\n }\n const { id, observer, elements } = createObserver(options);\n const callbacks = elements.get(element) || [];\n if (!elements.has(element)) {\n elements.set(element, callbacks);\n }\n callbacks.push(callback);\n observer.observe(element);\n return function unobserve() {\n callbacks.splice(callbacks.indexOf(callback), 1);\n if (callbacks.length === 0) {\n elements.delete(element);\n observer.unobserve(element);\n }\n if (elements.size === 0) {\n observer.disconnect();\n observerMap.delete(id);\n }\n };\n}\n\n// src/InView.tsx\nfunction isPlainChildren(props) {\n return typeof props.children !== \"function\";\n}\nvar InView = class extends React.Component {\n constructor(props) {\n super(props);\n __publicField(this, \"node\", null);\n __publicField(this, \"_unobserveCb\", null);\n __publicField(this, \"handleNode\", (node) => {\n if (this.node) {\n this.unobserve();\n if (!node && !this.props.triggerOnce && !this.props.skip) {\n this.setState({ inView: !!this.props.initialInView, entry: void 0 });\n }\n }\n this.node = node ? node : null;\n this.observeNode();\n });\n __publicField(this, \"handleChange\", (inView, entry) => {\n if (inView && this.props.triggerOnce) {\n this.unobserve();\n }\n if (!isPlainChildren(this.props)) {\n this.setState({ inView, entry });\n }\n if (this.props.onChange) {\n this.props.onChange(inView, entry);\n }\n });\n this.state = {\n inView: !!props.initialInView,\n entry: void 0\n };\n }\n componentDidMount() {\n this.unobserve();\n this.observeNode();\n }\n componentDidUpdate(prevProps) {\n if (prevProps.rootMargin !== this.props.rootMargin || prevProps.root !== this.props.root || prevProps.threshold !== this.props.threshold || prevProps.skip !== this.props.skip || prevProps.trackVisibility !== this.props.trackVisibility || prevProps.delay !== this.props.delay) {\n this.unobserve();\n this.observeNode();\n }\n }\n componentWillUnmount() {\n this.unobserve();\n }\n observeNode() {\n if (!this.node || this.props.skip) return;\n const {\n threshold,\n root,\n rootMargin,\n trackVisibility,\n delay,\n fallbackInView\n } = this.props;\n this._unobserveCb = observe(\n this.node,\n this.handleChange,\n {\n threshold,\n root,\n rootMargin,\n // @ts-ignore\n trackVisibility,\n // @ts-ignore\n delay\n },\n fallbackInView\n );\n }\n unobserve() {\n if (this._unobserveCb) {\n this._unobserveCb();\n this._unobserveCb = null;\n }\n }\n render() {\n const { children } = this.props;\n if (typeof children === \"function\") {\n const { inView, entry } = this.state;\n return children({ inView, entry, ref: this.handleNode });\n }\n const {\n as,\n triggerOnce,\n threshold,\n root,\n rootMargin,\n onChange,\n skip,\n trackVisibility,\n delay,\n initialInView,\n fallbackInView,\n ...props\n } = this.props;\n return React.createElement(\n as || \"div\",\n { ref: this.handleNode, ...props },\n children\n );\n }\n};\n\n// src/useInView.tsx\nimport * as React2 from \"react\";\nfunction useInView({\n threshold,\n delay,\n trackVisibility,\n rootMargin,\n root,\n triggerOnce,\n skip,\n initialInView,\n fallbackInView,\n onChange\n} = {}) {\n var _a;\n const [ref, setRef] = React2.useState(null);\n const callback = React2.useRef(onChange);\n const [state, setState] = React2.useState({\n inView: !!initialInView,\n entry: void 0\n });\n callback.current = onChange;\n React2.useEffect(\n () => {\n if (skip || !ref) return;\n let unobserve;\n unobserve = observe(\n ref,\n (inView, entry) => {\n setState({\n inView,\n entry\n });\n if (callback.current) callback.current(inView, entry);\n if (entry.isIntersecting && triggerOnce && unobserve) {\n unobserve();\n unobserve = void 0;\n }\n },\n {\n root,\n rootMargin,\n threshold,\n // @ts-ignore\n trackVisibility,\n // @ts-ignore\n delay\n },\n fallbackInView\n );\n return () => {\n if (unobserve) {\n unobserve();\n }\n };\n },\n // We break the rule here, because we aren't including the actual `threshold` variable\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n // If the threshold is an array, convert it to a string, so it won't change between renders.\n Array.isArray(threshold) ? threshold.toString() : threshold,\n ref,\n root,\n rootMargin,\n triggerOnce,\n skip,\n trackVisibility,\n fallbackInView,\n delay\n ]\n );\n const entryTarget = (_a = state.entry) == null ? void 0 : _a.target;\n const previousEntryTarget = React2.useRef(void 0);\n if (!ref && entryTarget && !triggerOnce && !skip && previousEntryTarget.current !== entryTarget) {\n previousEntryTarget.current = entryTarget;\n setState({\n inView: !!initialInView,\n entry: void 0\n });\n }\n const result = [setRef, state.inView, state.entry];\n result.ref = result[0];\n result.inView = result[1];\n result.entry = result[2];\n return result;\n}\nexport {\n InView,\n defaultFallbackInView,\n observe,\n useInView\n};\n//# sourceMappingURL=index.mjs.map","import * as React from 'react';\n\nimport { useFormatter } from '@/context/FormatterContext';\n\ninterface TimeStampProps {\n time: number;\n}\n\nexport const TimeStamp: React.FC<TimeStampProps> = ({ time }) => {\n const { formatTimestamp } = useFormatter();\n return <div className=\"time\">{formatTimestamp(time)}</div>;\n};\n","import * as React from 'react';\n\nimport * as API from '@/types/api';\nimport * as UI from '@/types/ui';\n\nimport { HighlightedText } from '../../text/HighlightedText';\n\ninterface MessageTextProps {\n message: API.Message;\n emojify: boolean;\n user?: API.HubUser;\n label?: string;\n highlightMenuProps: UI.MessageActionMenuData;\n}\n\nexport const MessageText: React.FC<MessageTextProps> = ({\n emojify,\n message,\n user,\n label,\n highlightMenuProps,\n ...other\n}) => (\n <div className=\"text\">\n {!!label && <span className=\"label\">{`${label}: `}</span>}\n <HighlightedText\n emojify={emojify}\n text={message.text}\n highlights={message.highlights}\n user={user}\n menuProps={highlightMenuProps}\n {...other}\n />\n </div>\n);\n","import * as React from 'react';\nimport { InView } from 'react-intersection-observer';\n\nimport { UserMenu } from '@/components/action-menu';\n\nimport * as API from '@/types/api';\n\nimport MenuConstants from '@/constants/MenuConstants';\nimport { CommonMessageProps } from '../types';\nimport { TimeStamp } from './Timestamp';\nimport { MessageText } from './MessageText';\nimport classNames from 'classnames';\n\ninterface AuthorProps {\n message: API.ChatMessage;\n dropdownContext: string;\n}\n\n// Message sections\nconst Author: React.FC<AuthorProps> = ({ message, dropdownContext }) => (\n <div className=\"header author\">\n {message.third_person && <span>*</span>}\n <UserMenu\n contextElement={dropdownContext}\n triggerIcon={null}\n user={message.from}\n remoteMenuId={MenuConstants.HUB_USER}\n entity={message.from.hub_session_id}\n />\n </div>\n);\n\ninterface ChatMessageProps extends CommonMessageProps {\n message: API.ChatMessage;\n dropdownContext: string;\n}\n\n// Main message types\nclass ChatMessage extends React.Component<ChatMessageProps> {\n shouldComponentUpdate() {\n return false;\n }\n\n render() {\n const { message, dropdownContext, highlightMenuProps, ...other } = this.props;\n\n return (\n <InView\n className={classNames('ui item chat', message.from.flags.join(' '))}\n {...other}\n >\n <TimeStamp time={message.time} />\n <div\n className={classNames('left', message.third_person ? 'third-person' : 'normal')}\n >\n <Author message={message} dropdownContext={dropdownContext} />\n <MessageText\n message={message}\n emojify={true}\n user={message.from}\n highlightMenuProps={highlightMenuProps}\n />\n </div>\n </InView>\n );\n }\n}\n\nexport { ChatMessage };\n","import classNames from 'classnames';\nimport { Component } from 'react';\nimport { InView } from 'react-intersection-observer';\n\nimport Icon from '@/components/semantic/Icon';\nimport IconConstants from '@/constants/IconConstants';\n\nimport * as API from '@/types/api';\n\nimport { CommonMessageProps } from '../types';\nimport { MessageText } from './MessageText';\nimport { TimeStamp } from './Timestamp';\n\nconst getSeverityIcon = (severity: API.SeverityEnum) => {\n switch (severity) {\n case API.SeverityEnum.VERBOSE:\n return IconConstants.VERBOSE;\n case API.SeverityEnum.INFO:\n return IconConstants.INFO + ' circle';\n case API.SeverityEnum.WARNING:\n return IconConstants.WARNING;\n case API.SeverityEnum.ERROR:\n return IconConstants.ERROR;\n default:\n return '';\n }\n};\n\ninterface StatusMessageProps extends CommonMessageProps {\n message: API.StatusMessage;\n}\n\nclass StatusMessage extends Component<StatusMessageProps> {\n shouldComponentUpdate() {\n return false;\n }\n\n render() {\n const { message, highlightMenuProps, ...other } = this.props;\n return (\n <InView\n className={classNames('ui item status', message.severity, message.type)}\n {...other}\n >\n <Icon icon={getSeverityIcon(message.severity)} />\n {message.time > 0 && <TimeStamp time={message.time} />}\n <MessageText\n label={message.label}\n message={message}\n emojify={false}\n highlightMenuProps={highlightMenuProps}\n />\n </InView>\n );\n }\n}\n\nexport { StatusMessage };\n","import * as React from 'react';\n\nimport { ChatMessage, StatusMessage } from '../message';\n\nimport * as UI from '@/types/ui';\nimport { CommonMessageProps } from '../types';\n\ninterface MessageListItemProps extends CommonMessageProps {\n id: string;\n message: UI.MessageListItem;\n}\n\nexport const MessageListItem: React.FC<MessageListItemProps> = ({\n message,\n ...other\n}) => {\n if (message.chat_message) {\n return (\n <ChatMessage\n message={message.chat_message}\n dropdownContext={other.highlightMenuProps.boundary}\n {...other}\n />\n );\n } else if (message.log_message) {\n return <StatusMessage message={message.log_message} {...other} />;\n }\n\n return null;\n};\n","import * as React from 'react';\n\nimport * as API from '@/types/api';\nimport * as UI from '@/types/ui';\n\nimport Icon from '@/components/semantic/Icon';\nimport IconConstants from '@/constants/IconConstants';\nimport { useFormatter } from '@/context/FormatterContext';\n\nconst getMessageDay = (listItem: UI.MessageListItem) => {\n const message = !!listItem.chat_message ? listItem.chat_message : listItem.log_message;\n return message && new Date(message.time * 1000).getDate();\n};\n\nconst isToday = (message: UI.MessageListItem) => {\n return getMessageDay(message) === new Date().getDate();\n};\n\nconst isHistoryItem = (listItem: UI.MessageListItem) => {\n if (listItem.log_message) {\n return listItem.log_message.type === API.StatusMessageTypeEnum.HISTORY;\n }\n\n return false;\n};\n\nexport const showDateDivider = (index: number, messageList: UI.MessageListItem[]) => {\n const currentMessage = messageList[index];\n\n // First message? History log won't count\n if (index === 0 || (index === 1 && isHistoryItem(messageList[index - 1]))) {\n // Don't show for message that were received today\n if (!isToday(currentMessage) && !isHistoryItem(currentMessage)) {\n return true;\n }\n\n return false;\n }\n\n return getMessageDay(messageList[index - 1]) !== getMessageDay(currentMessage);\n};\n\ninterface MessageListDateDividerProps {\n time: number;\n}\n\nexport const MessageListDateDivider: React.FC<MessageListDateDividerProps> = ({\n time,\n}) => {\n const { formatCalendarTime } = useFormatter();\n return (\n <div key={`divider${time}`} className=\"ui horizontal date divider\">\n <Icon icon={IconConstants.DATE} />\n {formatCalendarTime(time)}\n </div>\n );\n};\n","import { useMemo } from 'react';\r\nimport * as React from 'react';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { getListMessageId, getListMessageIdString } from '@/utils/MessageUtils';\r\n\r\nimport { MessageListItem } from '../list/MessageListItem';\r\nimport { MessageListDateDivider, showDateDivider } from '../list/MessageListDateDivider';\r\n\r\nimport { ItemDownloadManager } from '../../../effects/ItemDownloadManager';\r\nimport { UIInstanceId, useUIInstance } from '@/context/InstanceContext';\r\n\r\ninterface MessageItemData {\r\n entity: UI.SessionItemBase | undefined;\r\n onMessageVisibilityChanged: (id: number, inView: boolean) => void;\r\n addDownload: UI.AddItemDownload;\r\n highlightRemoteMenuId: string | undefined;\r\n scrollable: HTMLDivElement | null;\r\n instanceId: UIInstanceId;\r\n}\r\n\r\nconst reduceMessageListItem = (\r\n {\r\n entity,\r\n onMessageVisibilityChanged,\r\n addDownload,\r\n highlightRemoteMenuId,\r\n scrollable,\r\n instanceId,\r\n }: MessageItemData,\r\n reduced: React.ReactNode[],\r\n message: UI.MessageListItem,\r\n index: number,\r\n messageList: UI.MessageListItem[],\r\n) => {\r\n // Push a divider when the date was changed\r\n if (showDateDivider(index, messageList)) {\r\n const messageObj = !!message.chat_message\r\n ? message.chat_message\r\n : message.log_message;\r\n if (!!messageObj) {\r\n reduced.push(\r\n <MessageListDateDivider key={`divider${messageObj.id}`} time={messageObj.time} />,\r\n );\r\n }\r\n }\r\n\r\n // Push message\r\n const id = getListMessageId(message)!;\r\n reduced.push(\r\n <MessageListItem\r\n key={id}\r\n id={getListMessageIdString(id, instanceId)}\r\n onChange={(inView) => {\r\n onMessageVisibilityChanged(id, inView);\r\n }}\r\n threshold={0.4}\r\n root={scrollable}\r\n message={message}\r\n // Highlight menus must use table action menu because the text element has overflow: hidden\r\n // to allow long words to be cut (author action menu can still use the regular dropdown)\r\n highlightMenuProps={{\r\n addDownload,\r\n entity,\r\n remoteMenuId: highlightRemoteMenuId,\r\n boundary: '.message-section',\r\n // Determining the position is somewhat complex since the number of remote menu items isn't known at this point\r\n // Only use the boundary for now, could be improved later...\r\n // position: index < 4 ? 'bottom left' : 'top left',\r\n }}\r\n />,\r\n );\r\n\r\n return reduced;\r\n};\r\n\r\ninterface Props {\r\n messages: UI.MessageListItem[] | null;\r\n chatSession: UI.SessionItemBase | undefined;\r\n highlightRemoteMenuId: string | undefined;\r\n}\r\n\r\nexport const useMessagesNode = (\r\n { highlightRemoteMenuId, messages, chatSession }: Props,\r\n downloadManager: ItemDownloadManager<UI.DownloadableItemInfo, Props>,\r\n scrollable: HTMLDivElement | null,\r\n) => {\r\n const instanceId = useUIInstance();\r\n const visibleItems = useMemo(() => new Set<number>(), [chatSession]);\r\n\r\n const onMessageVisibilityChanged = (id: number, inView: boolean) => {\r\n if (!inView) {\r\n // console.log(`Remove view item ${id}`);\r\n visibleItems.delete(id);\r\n } else {\r\n // console.log(`Add view item ${id}`);\r\n visibleItems.add(id);\r\n }\r\n };\r\n\r\n const messageNodes = useMemo(() => {\r\n if (!messages) {\r\n return null;\r\n }\r\n\r\n return messages.reduce(\r\n reduceMessageListItem.bind(null, {\r\n highlightRemoteMenuId,\r\n entity: chatSession,\r\n onMessageVisibilityChanged,\r\n addDownload: downloadManager.addDownloadItem,\r\n scrollable,\r\n instanceId,\r\n }),\r\n [],\r\n );\r\n }, [messages]);\r\n\r\n return {\r\n messageNodes,\r\n visibleItems,\r\n };\r\n};\r\n","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!./messages.css\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\noptions.insert = insertFn.bind(null, \"head\");\noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!./messages.css\";\n export default content && content.locals ? content.locals : undefined;\n","import * as React from 'react';\r\nimport classNames from 'classnames';\r\n\r\nimport Loader from '@/components/semantic/Loader';\r\n\r\nimport { useMessageViewScrollEffect } from '@/effects';\r\nimport { useMessagesNode } from './effects/MessageNodeManager';\r\nimport { useItemDownloadManager } from '../../effects/ItemDownloadManager';\r\nimport { translate } from '@/utils/TranslationUtils';\r\n\r\nimport DownloadDialog from '@/components/download/DownloadDialog';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\nimport './messages.css';\r\n\r\ninterface MessageViewProps {\r\n messages: UI.MessageListItem[] | null;\r\n chatSession?: UI.SessionItemBase;\r\n className?: string;\r\n scrollPositionHandler: UI.ScrollHandler;\r\n highlightRemoteMenuId?: string;\r\n t: UI.TranslateF;\r\n}\r\n\r\nconst MessageView: React.FC<MessageViewProps> = React.memo(\r\n function MessageView({\r\n className,\r\n t,\r\n messages,\r\n chatSession,\r\n highlightRemoteMenuId,\r\n scrollPositionHandler,\r\n }) {\r\n // Can't use ref because we need to re-run the scroll hooks when the element is available\r\n const [scrollable, setScrollable] = React.useState<HTMLDivElement | null>(null);\r\n const downloadManager = useItemDownloadManager(chatSession);\r\n const { messageNodes, visibleItems } = useMessagesNode(\r\n {\r\n highlightRemoteMenuId,\r\n messages,\r\n chatSession,\r\n },\r\n downloadManager,\r\n scrollable,\r\n );\r\n\r\n useMessageViewScrollEffect(\r\n { messages, scrollPositionHandler, chatSession },\r\n visibleItems,\r\n scrollable,\r\n );\r\n\r\n return (\r\n <div\r\n ref={setScrollable}\r\n className={classNames('message-section', className)}\r\n role=\"article\"\r\n >\r\n {!!messageNodes ? (\r\n <>\r\n <div className=\"ui list message-list\">{messageNodes}</div>\r\n <DownloadDialog {...downloadManager.downloadDialogProps} />\r\n </>\r\n ) : (\r\n <Loader text={translate('Loading messages', t, UI.Modules.COMMON)} />\r\n )}\r\n </div>\r\n );\r\n },\r\n (prevProps, nextProps) => {\r\n return prevProps.messages === nextProps.messages;\r\n },\r\n);\r\n\r\nexport default MessageView;\r\n","import { useMemo } from 'react';\r\n\r\nimport * as API from '@/types/api';\r\nimport * as UI from '@/types/ui';\r\n\r\nexport interface ItemDownloadManager<\r\n ItemT extends UI.DownloadableItemInfo,\r\n PropsT extends object,\r\n> {\r\n addDownloadItem: UI.AddItemDownload<ItemT, PropsT>;\r\n downloadDialogProps: UI.ItemDownloadHandler<ItemT, PropsT>;\r\n}\r\n\r\nexport const useItemDownloadManager = <\r\n ItemT extends UI.DownloadableItemInfo,\r\n PropsT extends object,\r\n>(\r\n sessionItem: UI.SessionItemBase | undefined,\r\n) => {\r\n const downloadManager = useMemo<ItemDownloadManager<ItemT, PropsT>>(() => {\r\n const downloads: { [key in string]: UI.ItemDownloadHandler<ItemT, PropsT> } = {};\r\n\r\n const getDownloadItem = (itemId: API.IdType) => {\r\n const item = downloads[itemId];\r\n if (!item) {\r\n throw new Error('Download was not found');\r\n }\r\n\r\n return item;\r\n };\r\n\r\n const ret: ItemDownloadManager<ItemT, PropsT> = {\r\n downloadDialogProps: {\r\n downloadHandler: (itemData, downloadData, socket) => {\r\n return getDownloadItem(itemData.itemInfo.id).downloadHandler(\r\n itemData,\r\n downloadData,\r\n socket,\r\n );\r\n },\r\n userGetter: (itemId, props) => {\r\n const userGetter = getDownloadItem(itemId).userGetter;\r\n return !!userGetter ? userGetter(itemId, props) : undefined;\r\n },\r\n itemDataGetter: (itemId, socket) => {\r\n return getDownloadItem(itemId).itemDataGetter(itemId, socket);\r\n },\r\n sessionItem,\r\n },\r\n addDownloadItem: (itemId, itemDownloadHandler) => {\r\n downloads[itemId] = itemDownloadHandler;\r\n },\r\n };\r\n\r\n return ret;\r\n }, []);\r\n\r\n return downloadManager;\r\n};\r\n"],"names":["___CSS_LOADER_EXPORT___","push","module","id","__defProp","Object","defineProperty","__publicField","obj","key","value","enumerable","configurable","writable","__defNormalProp","observerMap","Map","RootIds","WeakMap","rootId","observe","element","callback","options","fallbackInView","window","IntersectionObserver","bounds","getBoundingClientRect","isIntersecting","target","intersectionRatio","threshold","time","boundingClientRect","intersectionRect","rootBounds","observer","elements","keys","sort","filter","map","root","has","set","toString","get","optionsToId","instance","thresholds","entries","forEach","entry","_a","inView","some","trackVisibility","isVisible","Array","isArray","createObserver","callbacks","splice","indexOf","length","delete","unobserve","size","disconnect","InView","constructor","props","super","this","node","triggerOnce","skip","setState","initialInView","observeNode","children","isPlainChildren","onChange","state","componentDidMount","componentDidUpdate","prevProps","rootMargin","delay","componentWillUnmount","_unobserveCb","handleChange","render","ref","handleNode","as","TimeStamp","formatTimestamp","className","MessageText","emojify","message","user","label","highlightMenuProps","other","HighlightedText","text","highlights","menuProps","Author","dropdownContext","third_person","contextElement","triggerIcon","from","remoteMenuId","MenuConstants","HUB_USER","entity","hub_session_id","ChatMessage","shouldComponentUpdate","flags","join","getSeverityIcon","severity","VERBOSE","IconConstants","INFO","WARNING","ERROR","StatusMessage","Component","type","Icon","icon","MessageListItem","chat_message","boundary","log_message","getMessageDay","listItem","Date","getDate","isHistoryItem","HISTORY","MessageListDateDivider","formatCalendarTime","DATE","reduceMessageListItem","onMessageVisibilityChanged","addDownload","highlightRemoteMenuId","scrollable","instanceId","reduced","index","messageList","currentMessage","showDateDivider","messageObj","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","locals","MessageView","messages","chatSession","scrollPositionHandler","setScrollable","downloadManager","sessionItem","useMemo","downloads","getDownloadItem","itemId","item","Error","downloadDialogProps","downloadHandler","itemData","downloadData","socket","itemInfo","userGetter","undefined","itemDataGetter","addDownloadItem","itemDownloadHandler","messageNodes","visibleItems","Set","add","reduce","bind","useMessagesNode","role","DownloadDialog","Loader","t","COMMON","nextProps"],"sourceRoot":""}
@@ -1,2 +1,2 @@
1
- "use strict";(self.webpackChunkairdcpp_webui=self.webpackChunkairdcpp_webui||[]).push([[550],{4112:(n,e,s)=>{s.d(e,{R:()=>t});var i=s(4425);const t=(n,e)=>({id:"remove",displayName:"Close",access:e,icon:i.A.REMOVE,handler:({itemData:e,socket:s})=>s.delete(`${n}/${e.id}`)})},38453:(n,e,s)=>{s.d(e,{J:()=>t,q:()=>o});var i=s(74848);s(96540);const t=({label:n,text:e})=>(0,i.jsx)("div",{className:"grid-item",children:(0,i.jsx)("div",{className:"item-inner",children:n&&"string"==typeof e?`${n}: ${e}`:e})}),o=({children:n})=>(0,i.jsxs)("div",{className:"session-footer",children:[(0,i.jsx)("div",{className:"ui footer divider"}),(0,i.jsx)("div",{className:"info-grid ui",children:n})]})},46510:(n,e,s)=>{s.d(e,{A:()=>a});var i=s(71354),t=s.n(i),o=s(76314),r=s.n(o)()(t());r.push([n.id,".session-container {\n background-color: white;\n}\n\n.session-container.horizontal.ui.grid {\n margin: 0px !important;\n}\n\n.session-container.horizontal .menu-column .item.new {\n padding: 0.78571429em 1.1em !important;\n}\n\n.session-container.horizontal .ui.vertical.menu .item > i.icon {\n margin: 0 0.35714286em 0 0 !important;\n}\n\n.session-container.horizontal .session-layout > .ui.divider {\n margin: 5px 0px 0px 0px;\n}\n\n.session-container.vertical {\n padding: 15px;\n display: flex;\n flex-direction: column;\n}\n.session-layout {\n flex: 100 100 auto;\n display: flex;\n overflow: hidden;\n}\n\n.session-container.horizontal .session-layout {\n flex-direction: column;\n}\n\n.session-container.vertical .menu-bar {\n justify-content: space-between;\n margin: 0px !important;\n}\n\n.session-container.vertical .menu-bar .content-left {\n width: 100%;\n}\n\n.session-container.vertical .menu-bar .close-button.item:before {\n background: none !important;\n}\n\n.session-container.vertical .menu-bar .close-button.item {\n box-shadow: none !important;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown {\n float: left;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown .menu {\n max-height: calc(100dvh - 140px);\n overflow-y: auto;\n overflow-x: hidden;\n max-width: calc(100vw - 30px);\n}\n\n.session-container.vertical .session-item .count.label {\n margin-left: 1em !important;\n}\n\n.session-container.vertical .session-header {\n display: flex;\n align-items: center;\n height: 100%;\n}\n\n.session-container.vertical .session-header > div {\n max-width: 90%; /* Hack, auto width won't work without \"overflow: hidden\", but that would prevent viewing the menu items */\n padding: 0.82857143em 0.4285714em;\n line-height: 1.2;\n}\n\n.session-container.vertical .session-header > div:before {\n background: none !important;\n}\n\n.session-container.vertical .session-header > i {\n margin-left: 10px;\n}\n\n.session-container.vertical .session-header .ui.dropdown > i {\n margin: 0px 5px;\n}\n\n/* Fix a few inconsistencies between 'icon' and 'icons' classnames */\n.session-container.horizontal .session-header .header > i,\n.session-container.vertical .session-header > i {\n width: inherit !important;\n font-size: 1.5em;\n}\n\n.session-container.horizontal .session-header .ui.header {\n align-items: center;\n}\n\n.session-container.vertical .menu-bar {\n border-radius: 0px !important;\n padding-bottom: 0px;\n}\n\n.session-container,\n.session-layout,\n.session-container.horizontal .column {\n height: 100%;\n}\n\n.session-container.horizontal .column > div {\n max-height: 100%;\n}\n\n.session-container .session-item {\n overflow: hidden;\n display: flex !important;\n align-items: center;\n padding: 0.68571429em 0.92857143em !important;\n height: 35px;\n}\n\n.session-container .session-item .session-status {\n float: none !important;\n margin: 0 0.5em 0 0 !important;\n}\n\n.session-container .session-item span.name {\n overflow: hidden;\n flex: 1 1 100%;\n line-height: 1.2;\n}\n\n.session-container .session-status {\n margin-right: 5px;\n margin-top: 3px;\n}\n\n.session-container.horizontal .menu-column {\n display: flex !important;\n flex-direction: column;\n padding-right: 0px !important;\n}\n\n.session-container.horizontal .menu-column .menu {\n width: initial !important;\n overflow-y: auto;\n padding-top: 10px;\n flex: 1;\n}\n\n.session-container.horizontal .menu-column .session-item span.name,\n.session-container .session-header .ui.dropdown .caption {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.session-container .session-header .title .ui.dropdown {\n width: 100%;\n}\n\n.session-layout .sub.header {\n overflow: hidden;\n}\n\n.session-layout .sub.header img {\n vertical-align: text-top;\n}\n\n.session-footer .info-grid {\n margin-top: 7px !important;\n font-size: small;\n color: grey;\n display: flex;\n flex: 1;\n align-items: flex-end;\n}\n\n.session-footer .info-grid > div {\n flex: 1;\n}\n\n.session-footer .info-grid > div:last-child > div {\n float: right;\n}\n\n.session-footer .info-grid > div:only-child > div {\n float: inherit;\n}\n\n.session-footer .ui.checkbox {\n min-height: inherit !important;\n}\n\n.session-footer .divider {\n margin-top: 8px;\n margin-bottom: 0px;\n}\n\n/* New session layout */\n.session.new {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n overflow-y: hidden;\n margin-top: 20px;\n padding: 1px;\n}\n\n.session.new .recents {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n margin-top: 20px;\n overflow-y: hidden;\n}\n\n.session.new .recents .list {\n padding: 3px 5px;\n flex: 100 100 0%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n","",{version:3,sources:["webpack://./src/routes/Sidebar/sessions.css"],names:[],mappings:"AAAA;EACE,uBAAuB;AACzB;;AAEA;EACE,sBAAsB;AACxB;;AAEA;EACE,sCAAsC;AACxC;;AAEA;EACE,qCAAqC;AACvC;;AAEA;EACE,uBAAuB;AACzB;;AAEA;EACE,aAAa;EACb,aAAa;EACb,sBAAsB;AACxB;AACA;EACE,kBAAkB;EAClB,aAAa;EACb,gBAAgB;AAClB;;AAEA;EACE,sBAAsB;AACxB;;AAEA;EACE,8BAA8B;EAC9B,sBAAsB;AACxB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,gCAAgC;EAChC,gBAAgB;EAChB,kBAAkB;EAClB,6BAA6B;AAC/B;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,YAAY;AACd;;AAEA;EACE,cAAc,EAAE,2GAA2G;EAC3H,iCAAiC;EACjC,gBAAgB;AAClB;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,iBAAiB;AACnB;;AAEA;EACE,eAAe;AACjB;;AAEA,oEAAoE;AACpE;;EAEE,yBAAyB;EACzB,gBAAgB;AAClB;;AAEA;EACE,mBAAmB;AACrB;;AAEA;EACE,6BAA6B;EAC7B,mBAAmB;AACrB;;AAEA;;;EAGE,YAAY;AACd;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,gBAAgB;EAChB,wBAAwB;EACxB,mBAAmB;EACnB,6CAA6C;EAC7C,YAAY;AACd;;AAEA;EACE,sBAAsB;EACtB,8BAA8B;AAChC;;AAEA;EACE,gBAAgB;EAChB,cAAc;EACd,gBAAgB;AAClB;;AAEA;EACE,iBAAiB;EACjB,eAAe;AACjB;;AAEA;EACE,wBAAwB;EACxB,sBAAsB;EACtB,6BAA6B;AAC/B;;AAEA;EACE,yBAAyB;EACzB,gBAAgB;EAChB,iBAAiB;EACjB,OAAO;AACT;;AAEA;;EAEE,gBAAgB;EAChB,mBAAmB;AACrB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,wBAAwB;AAC1B;;AAEA;EACE,0BAA0B;EAC1B,gBAAgB;EAChB,WAAW;EACX,aAAa;EACb,OAAO;EACP,qBAAqB;AACvB;;AAEA;EACE,OAAO;AACT;;AAEA;EACE,YAAY;AACd;;AAEA;EACE,cAAc;AAChB;;AAEA;EACE,8BAA8B;AAChC;;AAEA;EACE,eAAe;EACf,kBAAkB;AACpB;;AAEA,uBAAuB;AACvB;EACE,gBAAgB;EAChB,aAAa;EACb,sBAAsB;EACtB,kBAAkB;EAClB,gBAAgB;EAChB,YAAY;AACd;;AAEA;EACE,gBAAgB;EAChB,aAAa;EACb,sBAAsB;EACtB,gBAAgB;EAChB,kBAAkB;AACpB;;AAEA;EACE,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAChB,kBAAkB;AACpB",sourcesContent:[".session-container {\n background-color: white;\n}\n\n.session-container.horizontal.ui.grid {\n margin: 0px !important;\n}\n\n.session-container.horizontal .menu-column .item.new {\n padding: 0.78571429em 1.1em !important;\n}\n\n.session-container.horizontal .ui.vertical.menu .item > i.icon {\n margin: 0 0.35714286em 0 0 !important;\n}\n\n.session-container.horizontal .session-layout > .ui.divider {\n margin: 5px 0px 0px 0px;\n}\n\n.session-container.vertical {\n padding: 15px;\n display: flex;\n flex-direction: column;\n}\n.session-layout {\n flex: 100 100 auto;\n display: flex;\n overflow: hidden;\n}\n\n.session-container.horizontal .session-layout {\n flex-direction: column;\n}\n\n.session-container.vertical .menu-bar {\n justify-content: space-between;\n margin: 0px !important;\n}\n\n.session-container.vertical .menu-bar .content-left {\n width: 100%;\n}\n\n.session-container.vertical .menu-bar .close-button.item:before {\n background: none !important;\n}\n\n.session-container.vertical .menu-bar .close-button.item {\n box-shadow: none !important;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown {\n float: left;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown .menu {\n max-height: calc(100dvh - 140px);\n overflow-y: auto;\n overflow-x: hidden;\n max-width: calc(100vw - 30px);\n}\n\n.session-container.vertical .session-item .count.label {\n margin-left: 1em !important;\n}\n\n.session-container.vertical .session-header {\n display: flex;\n align-items: center;\n height: 100%;\n}\n\n.session-container.vertical .session-header > div {\n max-width: 90%; /* Hack, auto width won't work without \"overflow: hidden\", but that would prevent viewing the menu items */\n padding: 0.82857143em 0.4285714em;\n line-height: 1.2;\n}\n\n.session-container.vertical .session-header > div:before {\n background: none !important;\n}\n\n.session-container.vertical .session-header > i {\n margin-left: 10px;\n}\n\n.session-container.vertical .session-header .ui.dropdown > i {\n margin: 0px 5px;\n}\n\n/* Fix a few inconsistencies between 'icon' and 'icons' classnames */\n.session-container.horizontal .session-header .header > i,\n.session-container.vertical .session-header > i {\n width: inherit !important;\n font-size: 1.5em;\n}\n\n.session-container.horizontal .session-header .ui.header {\n align-items: center;\n}\n\n.session-container.vertical .menu-bar {\n border-radius: 0px !important;\n padding-bottom: 0px;\n}\n\n.session-container,\n.session-layout,\n.session-container.horizontal .column {\n height: 100%;\n}\n\n.session-container.horizontal .column > div {\n max-height: 100%;\n}\n\n.session-container .session-item {\n overflow: hidden;\n display: flex !important;\n align-items: center;\n padding: 0.68571429em 0.92857143em !important;\n height: 35px;\n}\n\n.session-container .session-item .session-status {\n float: none !important;\n margin: 0 0.5em 0 0 !important;\n}\n\n.session-container .session-item span.name {\n overflow: hidden;\n flex: 1 1 100%;\n line-height: 1.2;\n}\n\n.session-container .session-status {\n margin-right: 5px;\n margin-top: 3px;\n}\n\n.session-container.horizontal .menu-column {\n display: flex !important;\n flex-direction: column;\n padding-right: 0px !important;\n}\n\n.session-container.horizontal .menu-column .menu {\n width: initial !important;\n overflow-y: auto;\n padding-top: 10px;\n flex: 1;\n}\n\n.session-container.horizontal .menu-column .session-item span.name,\n.session-container .session-header .ui.dropdown .caption {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.session-container .session-header .title .ui.dropdown {\n width: 100%;\n}\n\n.session-layout .sub.header {\n overflow: hidden;\n}\n\n.session-layout .sub.header img {\n vertical-align: text-top;\n}\n\n.session-footer .info-grid {\n margin-top: 7px !important;\n font-size: small;\n color: grey;\n display: flex;\n flex: 1;\n align-items: flex-end;\n}\n\n.session-footer .info-grid > div {\n flex: 1;\n}\n\n.session-footer .info-grid > div:last-child > div {\n float: right;\n}\n\n.session-footer .info-grid > div:only-child > div {\n float: inherit;\n}\n\n.session-footer .ui.checkbox {\n min-height: inherit !important;\n}\n\n.session-footer .divider {\n margin-top: 8px;\n margin-bottom: 0px;\n}\n\n/* New session layout */\n.session.new {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n overflow-y: hidden;\n margin-top: 20px;\n padding: 1px;\n}\n\n.session.new .recents {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n margin-top: 20px;\n overflow-y: hidden;\n}\n\n.session.new .recents .list {\n padding: 3px 5px;\n flex: 100 100 0%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n"],sourceRoot:""}]);const a=r},78046:(n,e,s)=>{s.d(e,{Z:()=>c});var i=s(74848),t=(s(96540),s(99347)),o=s(67749),r=s(32389),a=s(42695),A=s(31290),l=s(97145);const c=(n,e,s)=>c=>{const{t:d}=(0,r.Bd)(),m=(0,a.lw)(d,s),u=(0,A.g)(),p=(0,l.c7)(n=>e(n).sessions);return p?(0,i.jsx)(n,{items:p,params:u,sessionT:m}):(0,i.jsx)(t.A,{text:(0,a.Tl)("Loading sessions",d,o.KV.COMMON)})}},80783:(n,e,s)=>{s.d(e,{q:()=>l});var i=s(96540),t=s(97145),o=s(48249),r=s(39364),a=s(80377),A=s(35106);const l=(n,e,s,l=!1)=>{const c=(0,r.sL)(),d=(0,o.F)(),m=(0,t.c7)(n=>n.activity.userActive),u=(0,t.c7)(n=>s(n).setActiveSession),p=i.useRef(void 0),h=n=>{(0,A.m)(n,()=>{e.setRead(n,d)}),p.current=void 0};i.useEffect(()=>()=>{u(null)},[]),i.useEffect(()=>(u(n),()=>{p.current&&(clearTimeout(p.current),n&&h(n))}),[n.id]),i.useEffect(()=>{m&&(n=>{const e=l?1e3*c.getState().settings.getValue(a.x.UNREAD_LABEL_DELAY):0;p.current=window.setTimeout(()=>h(n),e)})(n)},[m,n.id])}},91950:(n,e,s)=>{s.d(e,{A:()=>en});var i=s(74848),t=s(96540),o=s(99347),r=s(8098),a=s(68514),A=s(31104),l=s(19247),c=s(25906),d=s(67749),m=s(42695),u=s(4425),p=s(32389),h=s(97145);const E=({sessionMenuItems:n,newButton:e,sessionStoreSelector:s,listActionMenuGetter:t})=>{const{t:o}=(0,p.Bd)(),r=(0,h.c7)(n=>s(n).getTotalUrgencies);return(0,i.jsxs)(A.A,{triggerIcon:(0,i.jsx)(c.Z,{label:"Session menu",urgencies:r()}),children:[(0,i.jsx)(l.A,{caption:(0,m.Tl)("New",o,d.KV.COMMON),children:e}),(0,i.jsx)(l.A,{caption:(0,m.Tl)("Current sessions",o,d.KV.COMMON),children:n}),(0,i.jsx)(l.A,{children:t()})]})},g=({actions:n,activeItem:e})=>{if(!e||(0,r.vU)())return null;const s=Object.values(n.actions)[Object.values(n.actions).length-1];return(0,i.jsx)(a.A,{className:"basic small item close-button",action:s,moduleData:n.moduleData,itemData:e,icon:u.A.CLOSE})},B=({itemHeaderIcon:n,itemHeaderTitle:e})=>(0,i.jsxs)("div",{className:"session-header",children:[n,e]}),x=n=>{var{children:e,onKeyDown:s}=n,t=function(n,e){var s={};for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&e.indexOf(i)<0&&(s[i]=n[i]);if(null!=n&&"function"==typeof Object.getOwnPropertySymbols){var t=0;for(i=Object.getOwnPropertySymbols(n);t<i.length;t++)e.indexOf(i[t])<0&&Object.prototype.propertyIsEnumerable.call(n,i[t])&&(s[i[t]]=n[i[t]])}return s}(n,["children","onKeyDown"]);return(0,i.jsxs)("div",{className:"session-container vertical",onKeyDown:s,tabIndex:0,children:[(0,i.jsxs)("div",{className:"ui main menu menu-bar",children:[(0,i.jsxs)("div",{className:"content-left",children:[(0,i.jsx)(E,Object.assign({},t)),(0,i.jsx)(B,Object.assign({},t))]}),(0,i.jsx)(g,Object.assign({},t))]}),(0,i.jsx)("div",{className:"session-layout",children:e})]})};var f=s(31224),v=s(73070);const C=({sessionMenuItems:n,newButton:e,itemHeaderIcon:s,itemHeaderTitle:o,children:r,itemHeaderDescription:a,onKeyDown:A})=>(e&&(e=t.cloneElement(e,{className:e.props.className+" ui fluid button"})),(0,i.jsxs)(v.xA,{className:"session-container horizontal",onKeyDown:A,tabIndex:0,children:[(0,i.jsxs)("div",{className:"four wide column menu-column",children:[e,!!n.length&&(0,i.jsx)("div",{className:"ui vertical secondary menu",role:"menu",children:n})]}),(0,i.jsx)("div",{className:"twelve wide stretched column content-column session",children:(0,i.jsxs)("div",{className:"ui segment session-layout",children:[(0,i.jsx)(f.A,{className:"session-header",icon:s,title:(0,i.jsx)("div",{className:"title",children:o}),subHeader:a}),(0,i.jsx)("div",{className:"ui divider",style:{margin:"5px 0px 0px 0px"}}),r]})})]}));var w=s(32728),b=s(18220),y=s(31290),j=s(20311),I=s.n(j);const N=({baseUrl:n})=>{const e=(0,y.Zp)(),s=e=>(I()(!!e,"Trying to get session URL without a session"),`/${n}/session/${e}`),i=`/${n}/new`;return{newUrl:`/${n}/new`,replaceNew:()=>{e(i,{replace:!0})},getSessionUrl:s,pushSession:n=>{e(s(n))},replaceSession:(n,i)=>{e(s(n),{replace:!0,state:i})}}};var O=s(48249);const S=(n,e)=>n.find(n=>n.id===e);var z=s(71352),k=s(46942),T=s.n(k),M=s(45325);const D=({url:n,title:e,className:s})=>(0,i.jsx)(M.A,{className:T()("new",s),icon:u.A.CREATE,url:n,children:e},"button-new"),H=({sessionItem:n,status:e,name:s,unreadInfoStoreSelector:t,url:o})=>(0,i.jsx)(M.A,{url:o,className:"session-item",icon:e,sessionItem:n,unreadInfoStoreSelector:t,children:s});var U=s(83994),K=s(27725),L=s(39364),G=s(85072),V=s.n(G),Y=s(97825),W=s.n(Y),R=s(77659),$=s.n(R),q=s(55056),_=s.n(q),F=s(10540),P=s.n(F),Z=s(41113),J=s.n(Z),X=s(46510),Q={};Q.styleTagTransform=J(),Q.setAttributes=_(),Q.insert=$().bind(null,"head"),Q.domAPI=W(),Q.insertStyleElement=P(),V()(X.A,Q),X.A&&X.A.locals&&X.A.locals;var nn=s(70756);const en=n=>{const e=(0,L.wV)(),s=(0,b.y)(),a=(0,y.Zp)(),A=(0,y.zy)(),{activeItem:l,onKeyDown:c}=(n=>{const[e,s]=t.useState(null),i=(0,y.zy)(),o=(0,O.F)(),{pushSession:a,replaceSession:A,newUrl:l,replaceNew:c}=N({baseUrl:n.baseUrl}),d=()=>`${n.baseUrl}_last_active`;return t.useLayoutEffect(()=>{if(i.pathname===l)return void(e&&s(null));if((()=>{const e=i,t=e.state&&e.state.pending,o=S(n.items,n.activeId);return o?t?(A(o.id,{pending:!1}),!0):(s(o),(0,r.MS)(d(),n.activeId),!0):!!t||0===n.items.length&&(c(),s(null),!0)})())return;if(!e){const e=(0,r.H5)(d());if(e&&S(n.items,e))return void A(e)}const{items:t,activeId:o}=n;let a=0;const m=S(t,o);m&&(a=t.indexOf(m),a===t.length-1&&(a-=1)),A(t[a].id)},[i,n.items]),{onKeyDown:e=>{const{key:s,altKey:i}=e;if(!i||"ArrowUp"!==s&&"ArrowDown"!==s){if(i&&"Insert"===s)e.preventDefault(),c();else if(i&&"Delete"===s){e.preventDefault();const{items:s,activeId:i,sessionApi:t}=n,r=S(s,i);r&&t.removeSession(r,o)}}else{e.preventDefault();const{items:i,activeId:t}=n,o=S(i,t);if(!o)return;const r=i.indexOf(o);if(-1===r)return;const A=i["ArrowUp"===s?r-1:r+1];A&&a(A.id)}},activeItem:e}})(n),h=(0,nn.z)(e,n.editAccess),E=!!n.newLayout&&A.pathname.endsWith("/new"),{disableSideMenu:g,items:B,sessionStoreSelector:f,sessionT:v,uiActions:j}=n,I=g||(0,r.vU)(s),{getItemHeaderTitle:k,getItemHeaderDescription:T,getItemHeaderIcon:M,getNewButton:G,getSessionMenuItems:V,getSessionActionMenuItems:Y}=(n=>{const e=(0,O.F)(),s=(0,y.zy)(),{t}=(0,p.Bd)(),{newUrl:o,getSessionUrl:r}=N({baseUrl:n.baseUrl}),a=e=>{const{itemStatusGetter:s,itemHeaderIconGetter:t}=n;return s?(0,i.jsx)("div",{className:"ui session-status empty circular left mini label "+s(e)}):(0,i.jsx)(U.A,{icon:t(e)})};return{getItemHeaderDescription:()=>{const{itemHeaderDescriptionGetter:e,newDescription:s,activeItem:i,isNewLayout:t}=n;return t?s:i?e(i):null},getItemHeaderIcon:()=>{const{itemHeaderIconGetter:e,newIcon:s,activeItem:t,isNewLayout:o}=n;return o?(0,i.jsx)(U.A,{icon:s}):t?(0,i.jsx)(U.A,{icon:e(t)}):null},getItemHeaderTitle:()=>{const{activeItem:e,newCaption:t,remoteMenuId:o,isNewLayout:r}=n;if(r)return(0,i.jsx)("div",{children:t});if(!e)return null;const{uiActions:a,actionIds:A,itemNameGetter:l,itemHeaderTitleGetter:c}=n,d=A?[...A,"divider","remove"]:void 0,m=(0,i.jsx)(z.Wy,{caption:l(e),actions:a,itemData:e,ids:d,remoteMenuId:o});if(c){const n=c(e,s,m);if(n)return n}return m},getSessionActionMenuItems:()=>{const{items:s,hasEditAccess:o}=n;return o&&0!==s.length?(0,i.jsx)(K.A,{onClick:()=>{const{sessionApi:s,items:i}=n;i.forEach(n=>s.removeSession(n,e))},icon:u.A.REMOVE,children:(0,m.Tl)("Close all",t,d.KV.COMMON)},"close"):null},getNewButton:()=>{const{newCaption:e,hasEditAccess:s}=n;return s&&e?(0,i.jsx)(D,{title:e,url:o},"new-button"):null},getSessionMenuItems:()=>n.items.map(e=>{const{itemNameGetter:s,sessionStoreSelector:t}=n;return(0,i.jsx)(H,{url:r(e.id),name:s(e),unreadInfoStoreSelector:t,status:a(e),sessionItem:e},e.id)})}})(Object.assign(Object.assign({},n),{activeItem:l,hasEditAccess:h,isNewLayout:E}));if(!h&&0===B.length)return(0,i.jsx)(w.A,{title:(0,m.Tl)("No items to show",v.plainT,d.KV.COMMON),description:v.plainT((0,m.j2)("noSessionEditAccess",d.KV.COMMON),"You aren't allowed to open new sessions")});const W=I?x:C;return(0,i.jsx)(W,{itemHeaderTitle:k(),itemHeaderDescription:T(),itemHeaderIcon:M(),newButton:G(),sessionMenuItems:V(),listActionMenuGetter:Y,activeItem:l,sessionStoreSelector:f,onKeyDown:c,actions:j,children:(()=>{const{newLayout:e,sessionT:s}=n;return E&&e?(0,i.jsx)(e,{navigate:a,location:A,sessionT:s}):(()=>{const{activeId:e,items:s,sessionItemLayout:t,sessionApi:r,uiActions:c,sessionT:u,baseUrl:p}=n;if(!l){const{state:n}=A;return n&&n.pending?(0,i.jsx)(o.A,{text:(0,m.Tl)("Waiting for server response",u.plainT,d.KV.COMMON)}):e||0!==s.length?(0,i.jsx)(o.A,{text:(0,m.Tl)("Loading session",u.plainT,d.KV.COMMON)}):void console.error("SessionLayout route: active session missing")}return(0,i.jsx)(t,{sessionItem:l,sessionApi:r,uiActions:c,location:A,navigate:a,sessionT:u,baseUrl:p})})()})()})}}}]);
2
- //# sourceMappingURL=550.d7f48465222a7a1fae31.chunk.js.map
1
+ "use strict";(self.webpackChunkairdcpp_webui=self.webpackChunkairdcpp_webui||[]).push([[550],{4112:(n,e,s)=>{s.d(e,{R:()=>t});var i=s(4425);const t=(n,e)=>({id:"remove",displayName:"Close",access:e,icon:i.A.REMOVE,handler:({itemData:e,socket:s})=>s.delete(`${n}/${e.id}`)})},38453:(n,e,s)=>{s.d(e,{J:()=>t,q:()=>o});var i=s(74848);s(96540);const t=({label:n,text:e})=>(0,i.jsx)("div",{className:"grid-item",children:(0,i.jsx)("div",{className:"item-inner",children:n&&"string"==typeof e?`${n}: ${e}`:e})}),o=({children:n})=>(0,i.jsxs)("div",{className:"session-footer",children:[(0,i.jsx)("div",{className:"ui footer divider"}),(0,i.jsx)("div",{className:"info-grid ui",children:n})]})},46510:(n,e,s)=>{s.d(e,{A:()=>a});var i=s(71354),t=s.n(i),o=s(76314),r=s.n(o)()(t());r.push([n.id,".session-container {\n background-color: white;\n}\n\n.session-container.horizontal.ui.grid {\n margin: 0px !important;\n}\n\n.session-container.horizontal .menu-column .item.new {\n padding: 0.78571429em 1.1em !important;\n}\n\n.session-container.horizontal .ui.vertical.menu .item > i.icon {\n margin: 0 0.35714286em 0 0 !important;\n}\n\n.session-container.horizontal .session-layout > .ui.divider {\n margin: 5px 0px 0px 0px;\n}\n\n.session-container.vertical {\n padding: 15px;\n display: flex;\n flex-direction: column;\n}\n.session-layout {\n flex: 100 100 auto;\n display: flex;\n overflow: hidden;\n}\n\n.session-container.horizontal .session-layout {\n flex-direction: column;\n}\n\n.session-container.vertical .menu-bar {\n justify-content: space-between;\n margin: 0px !important;\n}\n\n.session-container.vertical .menu-bar .content-left {\n width: 100%;\n}\n\n.session-container.vertical .menu-bar .close-button.item:before {\n background: none !important;\n}\n\n.session-container.vertical .menu-bar .close-button.item {\n box-shadow: none !important;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown {\n float: left;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown .menu {\n max-height: calc(100dvh - 140px);\n overflow-y: auto;\n overflow-x: hidden;\n max-width: calc(100vw - 30px);\n}\n\n.session-container.vertical .session-item .count.label {\n margin-left: 1em !important;\n}\n\n.session-container.vertical .session-header {\n display: flex;\n align-items: center;\n height: 100%;\n}\n\n.session-container.vertical .session-header > div {\n max-width: 90%; /* Hack, auto width won't work without \"overflow: hidden\", but that would prevent viewing the menu items */\n padding: 0.82857143em 0.4285714em;\n line-height: 1.2;\n}\n\n.session-container.vertical .session-header > div:before {\n background: none !important;\n}\n\n.session-container.vertical .session-header > i {\n margin-left: 10px;\n}\n\n.session-container.vertical .session-header .ui.dropdown > i {\n margin: 0px 5px;\n}\n\n/* Fix a few inconsistencies between 'icon' and 'icons' classnames */\n.session-container.horizontal .session-header .header > i,\n.session-container.vertical .session-header > i {\n width: inherit !important;\n font-size: 1.5em;\n}\n\n.session-container.horizontal .session-header .ui.header {\n align-items: center;\n}\n\n.session-container.vertical .menu-bar {\n border-radius: 0px !important;\n padding-bottom: 0px;\n}\n\n.session-container,\n.session-layout,\n.session-container.horizontal .column {\n height: 100%;\n}\n\n.session-container.horizontal .column > div {\n max-height: 100%;\n}\n\n.session-container .session-item {\n overflow: hidden;\n display: flex !important;\n align-items: center;\n padding: 0.68571429em 0.92857143em !important;\n height: 35px;\n}\n\n.session-container .session-item .session-status {\n float: none !important;\n margin: 0 0.5em 0 0 !important;\n}\n\n.session-container .session-item span.name {\n overflow: hidden;\n flex: 1 1 100%;\n line-height: 1.2;\n}\n\n.session-container .session-status {\n margin-right: 5px;\n margin-top: 3px;\n}\n\n.session-container.horizontal .menu-column {\n display: flex !important;\n flex-direction: column;\n padding-right: 0px !important;\n}\n\n.session-container.horizontal .menu-column .menu {\n width: initial !important;\n overflow-y: auto;\n padding-top: 10px;\n flex: 1;\n}\n\n.session-container.horizontal .menu-column .session-item span.name,\n.session-container .session-header .ui.dropdown .caption {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.session-container .session-header .title .ui.dropdown {\n width: 100%;\n}\n\n.session-layout .sub.header {\n overflow: hidden;\n}\n\n.session-layout .sub.header img {\n vertical-align: text-top;\n}\n\n.session-footer .info-grid {\n margin-top: 7px !important;\n font-size: small;\n color: grey;\n display: flex;\n flex: 1;\n align-items: flex-end;\n}\n\n.session-footer .info-grid > div {\n flex: 1;\n}\n\n.session-footer .info-grid > div:last-child > div {\n float: right;\n}\n\n.session-footer .info-grid > div:only-child > div {\n float: inherit;\n}\n\n.session-footer .ui.checkbox {\n min-height: inherit !important;\n}\n\n.session-footer .divider {\n margin-top: 8px;\n margin-bottom: 0px;\n}\n\n/* New session layout */\n.session.new {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n overflow-y: hidden;\n margin-top: 20px;\n padding: 1px;\n}\n\n.session.new .recents {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n margin-top: 20px;\n overflow-y: hidden;\n}\n\n.session.new .recents .list {\n padding: 3px 5px;\n flex: 100 100 0%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n","",{version:3,sources:["webpack://./src/routes/Sidebar/sessions.css"],names:[],mappings:"AAAA;EACE,uBAAuB;AACzB;;AAEA;EACE,sBAAsB;AACxB;;AAEA;EACE,sCAAsC;AACxC;;AAEA;EACE,qCAAqC;AACvC;;AAEA;EACE,uBAAuB;AACzB;;AAEA;EACE,aAAa;EACb,aAAa;EACb,sBAAsB;AACxB;AACA;EACE,kBAAkB;EAClB,aAAa;EACb,gBAAgB;AAClB;;AAEA;EACE,sBAAsB;AACxB;;AAEA;EACE,8BAA8B;EAC9B,sBAAsB;AACxB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,gCAAgC;EAChC,gBAAgB;EAChB,kBAAkB;EAClB,6BAA6B;AAC/B;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,YAAY;AACd;;AAEA;EACE,cAAc,EAAE,2GAA2G;EAC3H,iCAAiC;EACjC,gBAAgB;AAClB;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,iBAAiB;AACnB;;AAEA;EACE,eAAe;AACjB;;AAEA,oEAAoE;AACpE;;EAEE,yBAAyB;EACzB,gBAAgB;AAClB;;AAEA;EACE,mBAAmB;AACrB;;AAEA;EACE,6BAA6B;EAC7B,mBAAmB;AACrB;;AAEA;;;EAGE,YAAY;AACd;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,gBAAgB;EAChB,wBAAwB;EACxB,mBAAmB;EACnB,6CAA6C;EAC7C,YAAY;AACd;;AAEA;EACE,sBAAsB;EACtB,8BAA8B;AAChC;;AAEA;EACE,gBAAgB;EAChB,cAAc;EACd,gBAAgB;AAClB;;AAEA;EACE,iBAAiB;EACjB,eAAe;AACjB;;AAEA;EACE,wBAAwB;EACxB,sBAAsB;EACtB,6BAA6B;AAC/B;;AAEA;EACE,yBAAyB;EACzB,gBAAgB;EAChB,iBAAiB;EACjB,OAAO;AACT;;AAEA;;EAEE,gBAAgB;EAChB,mBAAmB;AACrB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,wBAAwB;AAC1B;;AAEA;EACE,0BAA0B;EAC1B,gBAAgB;EAChB,WAAW;EACX,aAAa;EACb,OAAO;EACP,qBAAqB;AACvB;;AAEA;EACE,OAAO;AACT;;AAEA;EACE,YAAY;AACd;;AAEA;EACE,cAAc;AAChB;;AAEA;EACE,8BAA8B;AAChC;;AAEA;EACE,eAAe;EACf,kBAAkB;AACpB;;AAEA,uBAAuB;AACvB;EACE,gBAAgB;EAChB,aAAa;EACb,sBAAsB;EACtB,kBAAkB;EAClB,gBAAgB;EAChB,YAAY;AACd;;AAEA;EACE,gBAAgB;EAChB,aAAa;EACb,sBAAsB;EACtB,gBAAgB;EAChB,kBAAkB;AACpB;;AAEA;EACE,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAChB,kBAAkB;AACpB",sourcesContent:[".session-container {\n background-color: white;\n}\n\n.session-container.horizontal.ui.grid {\n margin: 0px !important;\n}\n\n.session-container.horizontal .menu-column .item.new {\n padding: 0.78571429em 1.1em !important;\n}\n\n.session-container.horizontal .ui.vertical.menu .item > i.icon {\n margin: 0 0.35714286em 0 0 !important;\n}\n\n.session-container.horizontal .session-layout > .ui.divider {\n margin: 5px 0px 0px 0px;\n}\n\n.session-container.vertical {\n padding: 15px;\n display: flex;\n flex-direction: column;\n}\n.session-layout {\n flex: 100 100 auto;\n display: flex;\n overflow: hidden;\n}\n\n.session-container.horizontal .session-layout {\n flex-direction: column;\n}\n\n.session-container.vertical .menu-bar {\n justify-content: space-between;\n margin: 0px !important;\n}\n\n.session-container.vertical .menu-bar .content-left {\n width: 100%;\n}\n\n.session-container.vertical .menu-bar .close-button.item:before {\n background: none !important;\n}\n\n.session-container.vertical .menu-bar .close-button.item {\n box-shadow: none !important;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown {\n float: left;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown .menu {\n max-height: calc(100dvh - 140px);\n overflow-y: auto;\n overflow-x: hidden;\n max-width: calc(100vw - 30px);\n}\n\n.session-container.vertical .session-item .count.label {\n margin-left: 1em !important;\n}\n\n.session-container.vertical .session-header {\n display: flex;\n align-items: center;\n height: 100%;\n}\n\n.session-container.vertical .session-header > div {\n max-width: 90%; /* Hack, auto width won't work without \"overflow: hidden\", but that would prevent viewing the menu items */\n padding: 0.82857143em 0.4285714em;\n line-height: 1.2;\n}\n\n.session-container.vertical .session-header > div:before {\n background: none !important;\n}\n\n.session-container.vertical .session-header > i {\n margin-left: 10px;\n}\n\n.session-container.vertical .session-header .ui.dropdown > i {\n margin: 0px 5px;\n}\n\n/* Fix a few inconsistencies between 'icon' and 'icons' classnames */\n.session-container.horizontal .session-header .header > i,\n.session-container.vertical .session-header > i {\n width: inherit !important;\n font-size: 1.5em;\n}\n\n.session-container.horizontal .session-header .ui.header {\n align-items: center;\n}\n\n.session-container.vertical .menu-bar {\n border-radius: 0px !important;\n padding-bottom: 0px;\n}\n\n.session-container,\n.session-layout,\n.session-container.horizontal .column {\n height: 100%;\n}\n\n.session-container.horizontal .column > div {\n max-height: 100%;\n}\n\n.session-container .session-item {\n overflow: hidden;\n display: flex !important;\n align-items: center;\n padding: 0.68571429em 0.92857143em !important;\n height: 35px;\n}\n\n.session-container .session-item .session-status {\n float: none !important;\n margin: 0 0.5em 0 0 !important;\n}\n\n.session-container .session-item span.name {\n overflow: hidden;\n flex: 1 1 100%;\n line-height: 1.2;\n}\n\n.session-container .session-status {\n margin-right: 5px;\n margin-top: 3px;\n}\n\n.session-container.horizontal .menu-column {\n display: flex !important;\n flex-direction: column;\n padding-right: 0px !important;\n}\n\n.session-container.horizontal .menu-column .menu {\n width: initial !important;\n overflow-y: auto;\n padding-top: 10px;\n flex: 1;\n}\n\n.session-container.horizontal .menu-column .session-item span.name,\n.session-container .session-header .ui.dropdown .caption {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.session-container .session-header .title .ui.dropdown {\n width: 100%;\n}\n\n.session-layout .sub.header {\n overflow: hidden;\n}\n\n.session-layout .sub.header img {\n vertical-align: text-top;\n}\n\n.session-footer .info-grid {\n margin-top: 7px !important;\n font-size: small;\n color: grey;\n display: flex;\n flex: 1;\n align-items: flex-end;\n}\n\n.session-footer .info-grid > div {\n flex: 1;\n}\n\n.session-footer .info-grid > div:last-child > div {\n float: right;\n}\n\n.session-footer .info-grid > div:only-child > div {\n float: inherit;\n}\n\n.session-footer .ui.checkbox {\n min-height: inherit !important;\n}\n\n.session-footer .divider {\n margin-top: 8px;\n margin-bottom: 0px;\n}\n\n/* New session layout */\n.session.new {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n overflow-y: hidden;\n margin-top: 20px;\n padding: 1px;\n}\n\n.session.new .recents {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n margin-top: 20px;\n overflow-y: hidden;\n}\n\n.session.new .recents .list {\n padding: 3px 5px;\n flex: 100 100 0%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n"],sourceRoot:""}]);const a=r},78046:(n,e,s)=>{s.d(e,{Z:()=>c});var i=s(74848),t=(s(96540),s(99347)),o=s(67749),r=s(32389),a=s(42695),A=s(31290),l=s(97145);const c=(n,e,s)=>c=>{const{t:d}=(0,r.Bd)(),m=(0,a.lw)(d,s),u=(0,A.g)(),p=(0,l.c7)(n=>e(n).sessions);return p?(0,i.jsx)(n,{items:p,params:u,sessionT:m}):(0,i.jsx)(t.A,{text:(0,a.Tl)("Loading sessions",d,o.KV.COMMON)})}},80783:(n,e,s)=>{s.d(e,{q:()=>l});var i=s(96540),t=s(97145),o=s(48249),r=s(39364),a=s(80377),A=s(35106);const l=(n,e,s,l=!1)=>{const c=(0,r.sL)(),d=(0,o.F)(),m=(0,t.c7)(n=>n.activity.userActive),u=(0,t.c7)(n=>s(n).setActiveSession),p=i.useRef(void 0),h=n=>{(0,A.m)(n,()=>{e.setRead(n,d)}),p.current=void 0};i.useEffect(()=>()=>{u(null)},[]),i.useEffect(()=>(u(n),()=>{p.current&&(clearTimeout(p.current),n&&h(n))}),[n.id]),i.useEffect(()=>{m&&(n=>{const e=l?1e3*c.getState().settings.getValue(a.x.UNREAD_LABEL_DELAY):0;p.current=window.setTimeout(()=>h(n),e)})(n)},[m,n.id])}},91950:(n,e,s)=>{s.d(e,{A:()=>en});var i=s(74848),t=s(96540),o=s(99347),r=s(8098),a=s(68514),A=s(31104),l=s(19247),c=s(25906),d=s(67749),m=s(42695),u=s(4425),p=s(32389),h=s(97145);const E=({sessionMenuItems:n,newButton:e,sessionStoreSelector:s,listActionMenuGetter:t})=>{const{t:o}=(0,p.Bd)(),r=(0,h.c7)(n=>s(n).getTotalUrgencies);return(0,i.jsxs)(A.A,{triggerIcon:(0,i.jsx)(c.Z,{label:"Session menu",urgencies:r()}),children:[(0,i.jsx)(l.A,{caption:(0,m.Tl)("New",o,d.KV.COMMON),children:e}),(0,i.jsx)(l.A,{caption:(0,m.Tl)("Current sessions",o,d.KV.COMMON),children:n}),(0,i.jsx)(l.A,{children:t()})]})},g=({actions:n,activeItem:e})=>{if(!e||(0,r.vU)())return null;const s=Object.values(n.actions)[Object.values(n.actions).length-1];return(0,i.jsx)(a.A,{className:"basic small item close-button",action:s,moduleData:n.moduleData,itemData:e,icon:u.A.CLOSE})},B=({itemHeaderIcon:n,itemHeaderTitle:e})=>(0,i.jsxs)("div",{className:"session-header",children:[n,e]}),x=n=>{var{children:e,onKeyDown:s}=n,t=function(n,e){var s={};for(var i in n)Object.prototype.hasOwnProperty.call(n,i)&&e.indexOf(i)<0&&(s[i]=n[i]);if(null!=n&&"function"==typeof Object.getOwnPropertySymbols){var t=0;for(i=Object.getOwnPropertySymbols(n);t<i.length;t++)e.indexOf(i[t])<0&&Object.prototype.propertyIsEnumerable.call(n,i[t])&&(s[i[t]]=n[i[t]])}return s}(n,["children","onKeyDown"]);return(0,i.jsxs)("div",{className:"session-container vertical",onKeyDown:s,tabIndex:0,children:[(0,i.jsxs)("div",{className:"ui main menu menu-bar",children:[(0,i.jsxs)("div",{className:"content-left",children:[(0,i.jsx)(E,Object.assign({},t)),(0,i.jsx)(B,Object.assign({},t))]}),(0,i.jsx)(g,Object.assign({},t))]}),(0,i.jsx)("div",{className:"session-layout",children:e})]})};var f=s(31224),v=s(73070);const C=({sessionMenuItems:n,newButton:e,itemHeaderIcon:s,itemHeaderTitle:o,children:r,itemHeaderDescription:a,onKeyDown:A})=>(e&&(e=t.cloneElement(e,{className:e.props.className+" ui fluid button"})),(0,i.jsxs)(v.xA,{className:"session-container horizontal",onKeyDown:A,tabIndex:0,children:[(0,i.jsxs)("div",{className:"four wide column menu-column",children:[e,!!n.length&&(0,i.jsx)("div",{className:"ui vertical secondary menu",role:"menubar",children:n})]}),(0,i.jsx)("div",{className:"twelve wide stretched column content-column session",children:(0,i.jsxs)("div",{className:"ui segment session-layout",children:[(0,i.jsx)(f.A,{className:"session-header",icon:s,title:(0,i.jsx)("div",{className:"title",children:o}),subHeader:a}),(0,i.jsx)("div",{className:"ui divider",style:{margin:"5px 0px 0px 0px"}}),r]})})]}));var w=s(32728),b=s(18220),y=s(31290),j=s(20311),I=s.n(j);const N=({baseUrl:n})=>{const e=(0,y.Zp)(),s=e=>(I()(!!e,"Trying to get session URL without a session"),`/${n}/session/${e}`),i=`/${n}/new`;return{newUrl:`/${n}/new`,replaceNew:()=>{e(i,{replace:!0})},getSessionUrl:s,pushSession:n=>{e(s(n))},replaceSession:(n,i)=>{e(s(n),{replace:!0,state:i})}}};var O=s(48249);const S=(n,e)=>n.find(n=>n.id===e);var z=s(71352),k=s(46942),T=s.n(k),M=s(45325);const D=({url:n,title:e,className:s})=>(0,i.jsx)(M.A,{className:T()("new",s),icon:u.A.CREATE,url:n,children:e},"button-new"),H=({sessionItem:n,status:e,name:s,unreadInfoStoreSelector:t,url:o})=>(0,i.jsx)(M.A,{url:o,className:"session-item",icon:e,sessionItem:n,unreadInfoStoreSelector:t,children:s});var U=s(83994),K=s(27725),L=s(39364),G=s(85072),V=s.n(G),Y=s(97825),W=s.n(Y),R=s(77659),$=s.n(R),q=s(55056),_=s.n(q),F=s(10540),P=s.n(F),Z=s(41113),J=s.n(Z),X=s(46510),Q={};Q.styleTagTransform=J(),Q.setAttributes=_(),Q.insert=$().bind(null,"head"),Q.domAPI=W(),Q.insertStyleElement=P(),V()(X.A,Q),X.A&&X.A.locals&&X.A.locals;var nn=s(70756);const en=n=>{const e=(0,L.wV)(),s=(0,b.y)(),a=(0,y.Zp)(),A=(0,y.zy)(),{activeItem:l,onKeyDown:c}=(n=>{const[e,s]=t.useState(null),i=(0,y.zy)(),o=(0,O.F)(),{pushSession:a,replaceSession:A,newUrl:l,replaceNew:c}=N({baseUrl:n.baseUrl}),d=()=>`${n.baseUrl}_last_active`;return t.useLayoutEffect(()=>{if(i.pathname===l)return void(e&&s(null));if((()=>{const e=i,t=e.state&&e.state.pending,o=S(n.items,n.activeId);return o?t?(A(o.id,{pending:!1}),!0):(s(o),(0,r.MS)(d(),n.activeId),!0):!!t||0===n.items.length&&(c(),s(null),!0)})())return;if(!e){const e=(0,r.H5)(d());if(e&&S(n.items,e))return void A(e)}const{items:t,activeId:o}=n;let a=0;const m=S(t,o);m&&(a=t.indexOf(m),a===t.length-1&&(a-=1)),A(t[a].id)},[i,n.items]),{onKeyDown:e=>{const{key:s,altKey:i}=e;if(!i||"ArrowUp"!==s&&"ArrowDown"!==s){if(i&&"Insert"===s)e.preventDefault(),c();else if(i&&"Delete"===s){e.preventDefault();const{items:s,activeId:i,sessionApi:t}=n,r=S(s,i);r&&t.removeSession(r,o)}}else{e.preventDefault();const{items:i,activeId:t}=n,o=S(i,t);if(!o)return;const r=i.indexOf(o);if(-1===r)return;const A=i["ArrowUp"===s?r-1:r+1];A&&a(A.id)}},activeItem:e}})(n),h=(0,nn.z)(e,n.editAccess),E=!!n.newLayout&&A.pathname.endsWith("/new"),{disableSideMenu:g,items:B,sessionStoreSelector:f,sessionT:v,uiActions:j}=n,I=g||(0,r.vU)(s),{getItemHeaderTitle:k,getItemHeaderDescription:T,getItemHeaderIcon:M,getNewButton:G,getSessionMenuItems:V,getSessionActionMenuItems:Y}=(n=>{const e=(0,O.F)(),s=(0,y.zy)(),{t}=(0,p.Bd)(),{newUrl:o,getSessionUrl:r}=N({baseUrl:n.baseUrl}),a=e=>{const{itemStatusGetter:s,itemHeaderIconGetter:t}=n;return s?(0,i.jsx)("div",{className:"ui session-status empty circular left mini label "+s(e)}):(0,i.jsx)(U.A,{icon:t(e)})};return{getItemHeaderDescription:()=>{const{itemHeaderDescriptionGetter:e,newDescription:s,activeItem:i,isNewLayout:t}=n;return t?s:i?e(i):null},getItemHeaderIcon:()=>{const{itemHeaderIconGetter:e,newIcon:s,activeItem:t,isNewLayout:o}=n;return o?(0,i.jsx)(U.A,{icon:s}):t?(0,i.jsx)(U.A,{icon:e(t)}):null},getItemHeaderTitle:()=>{const{activeItem:e,newCaption:t,remoteMenuId:o,isNewLayout:r}=n;if(r)return(0,i.jsx)("div",{children:t});if(!e)return null;const{uiActions:a,actionIds:A,itemNameGetter:l,itemHeaderTitleGetter:c}=n,d=A?[...A,"divider","remove"]:void 0,m=(0,i.jsx)(z.Wy,{caption:l(e),actions:a,itemData:e,ids:d,remoteMenuId:o});if(c){const n=c(e,s,m);if(n)return n}return m},getSessionActionMenuItems:()=>{const{items:s,hasEditAccess:o}=n;return o&&0!==s.length?(0,i.jsx)(K.A,{onClick:()=>{const{sessionApi:s,items:i}=n;i.forEach(n=>s.removeSession(n,e))},icon:u.A.REMOVE,children:(0,m.Tl)("Close all",t,d.KV.COMMON)},"close"):null},getNewButton:()=>{const{newCaption:e,hasEditAccess:s}=n;return s&&e?(0,i.jsx)(D,{title:e,url:o},"new-button"):null},getSessionMenuItems:()=>n.items.map(e=>{const{itemNameGetter:s,sessionStoreSelector:t}=n;return(0,i.jsx)(H,{url:r(e.id),name:s(e),unreadInfoStoreSelector:t,status:a(e),sessionItem:e},e.id)})}})(Object.assign(Object.assign({},n),{activeItem:l,hasEditAccess:h,isNewLayout:E}));if(!h&&0===B.length)return(0,i.jsx)(w.A,{title:(0,m.Tl)("No items to show",v.plainT,d.KV.COMMON),description:v.plainT((0,m.j2)("noSessionEditAccess",d.KV.COMMON),"You aren't allowed to open new sessions")});const W=I?x:C;return(0,i.jsx)(W,{itemHeaderTitle:k(),itemHeaderDescription:T(),itemHeaderIcon:M(),newButton:G(),sessionMenuItems:V(),listActionMenuGetter:Y,activeItem:l,sessionStoreSelector:f,onKeyDown:c,actions:j,children:(()=>{const{newLayout:e,sessionT:s}=n;return E&&e?(0,i.jsx)(e,{navigate:a,location:A,sessionT:s}):(()=>{const{activeId:e,items:s,sessionItemLayout:t,sessionApi:r,uiActions:c,sessionT:u,baseUrl:p}=n;if(!l){const{state:n}=A;return n&&n.pending?(0,i.jsx)(o.A,{text:(0,m.Tl)("Waiting for server response",u.plainT,d.KV.COMMON)}):e||0!==s.length?(0,i.jsx)(o.A,{text:(0,m.Tl)("Loading session",u.plainT,d.KV.COMMON)}):void console.error("SessionLayout route: active session missing")}return(0,i.jsx)(t,{sessionItem:l,sessionApi:r,uiActions:c,location:A,navigate:a,sessionT:u,baseUrl:p})})()})()})}}}]);
2
+ //# sourceMappingURL=550.83271f41ad0cccc6815b.chunk.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"js/550.d7f48465222a7a1fae31.chunk.js","mappings":"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","sources":["webpack://airdcpp-webui/./src/actions/ui/decorators/SessionActionDecorator.ts","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionFooter.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/sessions.css","webpack://airdcpp-webui/./src/routes/Sidebar/decorators/SessionProviderDecorator.tsx","webpack://airdcpp-webui/./src/effects/ActiveSessionEffect.ts","webpack://airdcpp-webui/./src/routes/Sidebar/components/TopMenuLayout.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/components/SideMenuLayout.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/components/effects/useSessionHelpers.ts","webpack://airdcpp-webui/./src/routes/Sidebar/components/effects/useSessionManager.ts","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionNewButton.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionMenuItem.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/sessions.css?90b7","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionLayout.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionMenuComponents.tsx"],"sourcesContent":["import IconConstants from '@/constants/IconConstants';\r\n\r\nimport * as API from '@/types/api';\r\nimport * as UI from '@/types/ui';\r\n\r\ntype SessionType = UI.SessionItemBase;\r\n\r\nexport const BuildRemoveSessionAction = (\r\n sessionsUrl: string,\r\n editAccess: API.AccessEnum,\r\n) => {\r\n const handleRemoveSession: UI.ActionHandler<SessionType> = ({\r\n itemData: session,\r\n socket,\r\n }) => {\r\n return socket.delete(`${sessionsUrl}/${session.id}`);\r\n };\r\n\r\n const SessionRemoveAction = {\r\n id: 'remove',\r\n displayName: 'Close',\r\n access: editAccess,\r\n icon: IconConstants.REMOVE,\r\n handler: handleRemoveSession,\r\n };\r\n\r\n return SessionRemoveAction;\r\n};\r\n","import * as React from 'react';\n\nimport * as UI from '@/types/ui';\n\ninterface FooterItemProps {\n label?: string;\n text: string | React.ReactElement<any>;\n}\n\nexport const FooterItem: React.FC<FooterItemProps> = ({ label, text }) => (\n <div className=\"grid-item\">\n <div className=\"item-inner\">\n {!!label && typeof text === 'string' ? `${label}: ${text}` : text}\n </div>\n </div>\n);\n\nexport const SessionFooter: React.FC<UI.PropsWithChildren> = ({ children }) => (\n <div className=\"session-footer\">\n <div className=\"ui footer divider\" />\n <div className=\"info-grid ui\">{children}</div>\n </div>\n);\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.session-container {\n background-color: white;\n}\n\n.session-container.horizontal.ui.grid {\n margin: 0px !important;\n}\n\n.session-container.horizontal .menu-column .item.new {\n padding: 0.78571429em 1.1em !important;\n}\n\n.session-container.horizontal .ui.vertical.menu .item > i.icon {\n margin: 0 0.35714286em 0 0 !important;\n}\n\n.session-container.horizontal .session-layout > .ui.divider {\n margin: 5px 0px 0px 0px;\n}\n\n.session-container.vertical {\n padding: 15px;\n display: flex;\n flex-direction: column;\n}\n.session-layout {\n flex: 100 100 auto;\n display: flex;\n overflow: hidden;\n}\n\n.session-container.horizontal .session-layout {\n flex-direction: column;\n}\n\n.session-container.vertical .menu-bar {\n justify-content: space-between;\n margin: 0px !important;\n}\n\n.session-container.vertical .menu-bar .content-left {\n width: 100%;\n}\n\n.session-container.vertical .menu-bar .close-button.item:before {\n background: none !important;\n}\n\n.session-container.vertical .menu-bar .close-button.item {\n box-shadow: none !important;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown {\n float: left;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown .menu {\n max-height: calc(100dvh - 140px);\n overflow-y: auto;\n overflow-x: hidden;\n max-width: calc(100vw - 30px);\n}\n\n.session-container.vertical .session-item .count.label {\n margin-left: 1em !important;\n}\n\n.session-container.vertical .session-header {\n display: flex;\n align-items: center;\n height: 100%;\n}\n\n.session-container.vertical .session-header > div {\n max-width: 90%; /* Hack, auto width won't work without \"overflow: hidden\", but that would prevent viewing the menu items */\n padding: 0.82857143em 0.4285714em;\n line-height: 1.2;\n}\n\n.session-container.vertical .session-header > div:before {\n background: none !important;\n}\n\n.session-container.vertical .session-header > i {\n margin-left: 10px;\n}\n\n.session-container.vertical .session-header .ui.dropdown > i {\n margin: 0px 5px;\n}\n\n/* Fix a few inconsistencies between 'icon' and 'icons' classnames */\n.session-container.horizontal .session-header .header > i,\n.session-container.vertical .session-header > i {\n width: inherit !important;\n font-size: 1.5em;\n}\n\n.session-container.horizontal .session-header .ui.header {\n align-items: center;\n}\n\n.session-container.vertical .menu-bar {\n border-radius: 0px !important;\n padding-bottom: 0px;\n}\n\n.session-container,\n.session-layout,\n.session-container.horizontal .column {\n height: 100%;\n}\n\n.session-container.horizontal .column > div {\n max-height: 100%;\n}\n\n.session-container .session-item {\n overflow: hidden;\n display: flex !important;\n align-items: center;\n padding: 0.68571429em 0.92857143em !important;\n height: 35px;\n}\n\n.session-container .session-item .session-status {\n float: none !important;\n margin: 0 0.5em 0 0 !important;\n}\n\n.session-container .session-item span.name {\n overflow: hidden;\n flex: 1 1 100%;\n line-height: 1.2;\n}\n\n.session-container .session-status {\n margin-right: 5px;\n margin-top: 3px;\n}\n\n.session-container.horizontal .menu-column {\n display: flex !important;\n flex-direction: column;\n padding-right: 0px !important;\n}\n\n.session-container.horizontal .menu-column .menu {\n width: initial !important;\n overflow-y: auto;\n padding-top: 10px;\n flex: 1;\n}\n\n.session-container.horizontal .menu-column .session-item span.name,\n.session-container .session-header .ui.dropdown .caption {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.session-container .session-header .title .ui.dropdown {\n width: 100%;\n}\n\n.session-layout .sub.header {\n overflow: hidden;\n}\n\n.session-layout .sub.header img {\n vertical-align: text-top;\n}\n\n.session-footer .info-grid {\n margin-top: 7px !important;\n font-size: small;\n color: grey;\n display: flex;\n flex: 1;\n align-items: flex-end;\n}\n\n.session-footer .info-grid > div {\n flex: 1;\n}\n\n.session-footer .info-grid > div:last-child > div {\n float: right;\n}\n\n.session-footer .info-grid > div:only-child > div {\n float: inherit;\n}\n\n.session-footer .ui.checkbox {\n min-height: inherit !important;\n}\n\n.session-footer .divider {\n margin-top: 8px;\n margin-bottom: 0px;\n}\n\n/* New session layout */\n.session.new {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n overflow-y: hidden;\n margin-top: 20px;\n padding: 1px;\n}\n\n.session.new .recents {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n margin-top: 20px;\n overflow-y: hidden;\n}\n\n.session.new .recents .list {\n padding: 3px 5px;\n flex: 100 100 0%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/routes/Sidebar/sessions.css\"],\"names\":[],\"mappings\":\"AAAA;EACE,uBAAuB;AACzB;;AAEA;EACE,sBAAsB;AACxB;;AAEA;EACE,sCAAsC;AACxC;;AAEA;EACE,qCAAqC;AACvC;;AAEA;EACE,uBAAuB;AACzB;;AAEA;EACE,aAAa;EACb,aAAa;EACb,sBAAsB;AACxB;AACA;EACE,kBAAkB;EAClB,aAAa;EACb,gBAAgB;AAClB;;AAEA;EACE,sBAAsB;AACxB;;AAEA;EACE,8BAA8B;EAC9B,sBAAsB;AACxB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,gCAAgC;EAChC,gBAAgB;EAChB,kBAAkB;EAClB,6BAA6B;AAC/B;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,YAAY;AACd;;AAEA;EACE,cAAc,EAAE,2GAA2G;EAC3H,iCAAiC;EACjC,gBAAgB;AAClB;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,iBAAiB;AACnB;;AAEA;EACE,eAAe;AACjB;;AAEA,oEAAoE;AACpE;;EAEE,yBAAyB;EACzB,gBAAgB;AAClB;;AAEA;EACE,mBAAmB;AACrB;;AAEA;EACE,6BAA6B;EAC7B,mBAAmB;AACrB;;AAEA;;;EAGE,YAAY;AACd;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,gBAAgB;EAChB,wBAAwB;EACxB,mBAAmB;EACnB,6CAA6C;EAC7C,YAAY;AACd;;AAEA;EACE,sBAAsB;EACtB,8BAA8B;AAChC;;AAEA;EACE,gBAAgB;EAChB,cAAc;EACd,gBAAgB;AAClB;;AAEA;EACE,iBAAiB;EACjB,eAAe;AACjB;;AAEA;EACE,wBAAwB;EACxB,sBAAsB;EACtB,6BAA6B;AAC/B;;AAEA;EACE,yBAAyB;EACzB,gBAAgB;EAChB,iBAAiB;EACjB,OAAO;AACT;;AAEA;;EAEE,gBAAgB;EAChB,mBAAmB;AACrB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,wBAAwB;AAC1B;;AAEA;EACE,0BAA0B;EAC1B,gBAAgB;EAChB,WAAW;EACX,aAAa;EACb,OAAO;EACP,qBAAqB;AACvB;;AAEA;EACE,OAAO;AACT;;AAEA;EACE,YAAY;AACd;;AAEA;EACE,cAAc;AAChB;;AAEA;EACE,8BAA8B;AAChC;;AAEA;EACE,eAAe;EACf,kBAAkB;AACpB;;AAEA,uBAAuB;AACvB;EACE,gBAAgB;EAChB,aAAa;EACb,sBAAsB;EACtB,kBAAkB;EAClB,gBAAgB;EAChB,YAAY;AACd;;AAEA;EACE,gBAAgB;EAChB,aAAa;EACb,sBAAsB;EACtB,gBAAgB;EAChB,kBAAkB;AACpB;;AAEA;EACE,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAChB,kBAAkB;AACpB\",\"sourcesContent\":[\".session-container {\\n background-color: white;\\n}\\n\\n.session-container.horizontal.ui.grid {\\n margin: 0px !important;\\n}\\n\\n.session-container.horizontal .menu-column .item.new {\\n padding: 0.78571429em 1.1em !important;\\n}\\n\\n.session-container.horizontal .ui.vertical.menu .item > i.icon {\\n margin: 0 0.35714286em 0 0 !important;\\n}\\n\\n.session-container.horizontal .session-layout > .ui.divider {\\n margin: 5px 0px 0px 0px;\\n}\\n\\n.session-container.vertical {\\n padding: 15px;\\n display: flex;\\n flex-direction: column;\\n}\\n.session-layout {\\n flex: 100 100 auto;\\n display: flex;\\n overflow: hidden;\\n}\\n\\n.session-container.horizontal .session-layout {\\n flex-direction: column;\\n}\\n\\n.session-container.vertical .menu-bar {\\n justify-content: space-between;\\n margin: 0px !important;\\n}\\n\\n.session-container.vertical .menu-bar .content-left {\\n width: 100%;\\n}\\n\\n.session-container.vertical .menu-bar .close-button.item:before {\\n background: none !important;\\n}\\n\\n.session-container.vertical .menu-bar .close-button.item {\\n box-shadow: none !important;\\n}\\n\\n.session-container.vertical .menu-bar .content-left > .ui.dropdown {\\n float: left;\\n}\\n\\n.session-container.vertical .menu-bar .content-left > .ui.dropdown .menu {\\n max-height: calc(100dvh - 140px);\\n overflow-y: auto;\\n overflow-x: hidden;\\n max-width: calc(100vw - 30px);\\n}\\n\\n.session-container.vertical .session-item .count.label {\\n margin-left: 1em !important;\\n}\\n\\n.session-container.vertical .session-header {\\n display: flex;\\n align-items: center;\\n height: 100%;\\n}\\n\\n.session-container.vertical .session-header > div {\\n max-width: 90%; /* Hack, auto width won't work without \\\"overflow: hidden\\\", but that would prevent viewing the menu items */\\n padding: 0.82857143em 0.4285714em;\\n line-height: 1.2;\\n}\\n\\n.session-container.vertical .session-header > div:before {\\n background: none !important;\\n}\\n\\n.session-container.vertical .session-header > i {\\n margin-left: 10px;\\n}\\n\\n.session-container.vertical .session-header .ui.dropdown > i {\\n margin: 0px 5px;\\n}\\n\\n/* Fix a few inconsistencies between 'icon' and 'icons' classnames */\\n.session-container.horizontal .session-header .header > i,\\n.session-container.vertical .session-header > i {\\n width: inherit !important;\\n font-size: 1.5em;\\n}\\n\\n.session-container.horizontal .session-header .ui.header {\\n align-items: center;\\n}\\n\\n.session-container.vertical .menu-bar {\\n border-radius: 0px !important;\\n padding-bottom: 0px;\\n}\\n\\n.session-container,\\n.session-layout,\\n.session-container.horizontal .column {\\n height: 100%;\\n}\\n\\n.session-container.horizontal .column > div {\\n max-height: 100%;\\n}\\n\\n.session-container .session-item {\\n overflow: hidden;\\n display: flex !important;\\n align-items: center;\\n padding: 0.68571429em 0.92857143em !important;\\n height: 35px;\\n}\\n\\n.session-container .session-item .session-status {\\n float: none !important;\\n margin: 0 0.5em 0 0 !important;\\n}\\n\\n.session-container .session-item span.name {\\n overflow: hidden;\\n flex: 1 1 100%;\\n line-height: 1.2;\\n}\\n\\n.session-container .session-status {\\n margin-right: 5px;\\n margin-top: 3px;\\n}\\n\\n.session-container.horizontal .menu-column {\\n display: flex !important;\\n flex-direction: column;\\n padding-right: 0px !important;\\n}\\n\\n.session-container.horizontal .menu-column .menu {\\n width: initial !important;\\n overflow-y: auto;\\n padding-top: 10px;\\n flex: 1;\\n}\\n\\n.session-container.horizontal .menu-column .session-item span.name,\\n.session-container .session-header .ui.dropdown .caption {\\n overflow: hidden;\\n white-space: nowrap;\\n}\\n\\n.session-container .session-header .title .ui.dropdown {\\n width: 100%;\\n}\\n\\n.session-layout .sub.header {\\n overflow: hidden;\\n}\\n\\n.session-layout .sub.header img {\\n vertical-align: text-top;\\n}\\n\\n.session-footer .info-grid {\\n margin-top: 7px !important;\\n font-size: small;\\n color: grey;\\n display: flex;\\n flex: 1;\\n align-items: flex-end;\\n}\\n\\n.session-footer .info-grid > div {\\n flex: 1;\\n}\\n\\n.session-footer .info-grid > div:last-child > div {\\n float: right;\\n}\\n\\n.session-footer .info-grid > div:only-child > div {\\n float: inherit;\\n}\\n\\n.session-footer .ui.checkbox {\\n min-height: inherit !important;\\n}\\n\\n.session-footer .divider {\\n margin-top: 8px;\\n margin-bottom: 0px;\\n}\\n\\n/* New session layout */\\n.session.new {\\n flex: 100 100 0%;\\n display: flex;\\n flex-direction: column;\\n overflow-y: hidden;\\n margin-top: 20px;\\n padding: 1px;\\n}\\n\\n.session.new .recents {\\n flex: 100 100 0%;\\n display: flex;\\n flex-direction: column;\\n margin-top: 20px;\\n overflow-y: hidden;\\n}\\n\\n.session.new .recents .list {\\n padding: 3px 5px;\\n flex: 100 100 0%;\\n overflow-y: auto;\\n overflow-x: hidden;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","import * as React from 'react';\r\n\r\nimport Loader from '@/components/semantic/Loader';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { useTranslation } from 'react-i18next';\r\nimport { getModuleT, translate } from '@/utils/TranslationUtils';\r\nimport { useParams } from 'react-router';\r\nimport { useSessionStoreProperty } from '@/context/SessionStoreContext';\r\n\r\nexport interface SessionProviderDecoratorProps {}\r\n\r\nexport interface SessionProviderDecoratorChildProps<SessionT extends UI.SessionItem> {\r\n items: SessionT[];\r\n sessionT: UI.ModuleTranslator;\r\n params: UI.RouteParams;\r\n}\r\n\r\nconst SessionProviderDecorator = <SessionT extends UI.SessionItem>(\r\n Component: React.ComponentType<SessionProviderDecoratorChildProps<SessionT>>,\r\n sessionStoreSelector: UI.SessionStoreSelector<SessionT>,\r\n moduleId: UI.Modules,\r\n) => {\r\n const Decorator = (props: SessionProviderDecoratorProps) => {\r\n const { t } = useTranslation();\r\n const sessionT = getModuleT(t, moduleId);\r\n const params = useParams();\r\n\r\n const sessions = useSessionStoreProperty(\r\n (state) => sessionStoreSelector(state).sessions,\r\n );\r\n if (!sessions) {\r\n return <Loader text={translate('Loading sessions', t, UI.Modules.COMMON)} />;\r\n }\r\n\r\n return <Component items={sessions} params={params} sessionT={sessionT} />;\r\n };\r\n\r\n return Decorator;\r\n};\r\n\r\nexport { SessionProviderDecorator };\r\n","import * as React from 'react';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { useSessionStoreProperty } from '@/context/SessionStoreContext';\r\nimport { useSocket } from '@/context/SocketContext';\r\nimport { useAppStoreApi } from '@/context/AppStoreContext';\r\nimport { LocalSettings } from '@/constants/LocalSettingConstants';\r\nimport { checkUnreadSessionInfo } from '@/utils/SessionUtils';\r\n\r\nexport const useActiveSession = (\r\n sessionItem: UI.SessionItem,\r\n actions: UI.SessionAPIActions<UI.SessionItem>,\r\n sessionStoreSelector: UI.SessionStoreSelector,\r\n useReadDelay = false,\r\n) => {\r\n const appStoreApi = useAppStoreApi();\r\n const socket = useSocket();\r\n const userActive = useSessionStoreProperty((state) => state.activity.userActive);\r\n const activeSessionStoreSetter = useSessionStoreProperty(\r\n (state) => sessionStoreSelector(state).setActiveSession,\r\n );\r\n\r\n const readTimeout = React.useRef<number | undefined>(undefined);\r\n\r\n const checkSetRead = (sessionItemRead: UI.SessionItem) => {\r\n checkUnreadSessionInfo(sessionItemRead, () => {\r\n actions.setRead(sessionItemRead, socket);\r\n });\r\n\r\n readTimeout.current = undefined;\r\n };\r\n\r\n const scheduleCheckSetRead = (sessionItemNew: UI.SessionItem) => {\r\n const timeout = !useReadDelay\r\n ? 0\r\n : appStoreApi\r\n .getState()\r\n .settings.getValue<number>(LocalSettings.UNREAD_LABEL_DELAY) * 1000;\r\n\r\n readTimeout.current = window.setTimeout(() => checkSetRead(sessionItemNew), timeout);\r\n };\r\n\r\n React.useEffect(() => {\r\n return () => {\r\n activeSessionStoreSetter(null);\r\n };\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n activeSessionStoreSetter(sessionItem);\r\n return () => {\r\n if (readTimeout.current) {\r\n // Set the previously active session as read\r\n clearTimeout(readTimeout.current);\r\n\r\n if (sessionItem) {\r\n checkSetRead(sessionItem);\r\n }\r\n }\r\n };\r\n }, [sessionItem.id]);\r\n\r\n React.useEffect(() => {\r\n if (userActive) {\r\n scheduleCheckSetRead(sessionItem);\r\n }\r\n }, [userActive, sessionItem.id]);\r\n};\r\n","import * as React from 'react';\r\nimport { usingMobileLayout } from '@/utils/BrowserUtils';\r\n\r\nimport ActionButton from '@/components/ActionButton';\r\nimport SectionedDropdown from '@/components/semantic/SectionedDropdown';\r\nimport MenuSection from '@/components/semantic/MenuSection';\r\nimport { MenuIcon } from '@/components/icon/MenuIcon';\r\n\r\nimport * as UI from '@/types/ui';\r\nimport { translate } from '@/utils/TranslationUtils';\r\nimport IconConstants from '@/constants/IconConstants';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { SessionMainLayoutProps } from './types';\r\nimport { useSessionStoreProperty } from '@/context/SessionStoreContext';\r\n\r\ntype SessionDropdownProps<SessionT extends UI.SessionItemBase> = Pick<\r\n SessionMainLayoutProps<SessionT>,\r\n 'sessionMenuItems' | 'newButton' | 'sessionStoreSelector' | 'listActionMenuGetter'\r\n>;\r\n\r\nconst SessionDropdown = <SessionT extends UI.SessionItemBase>({\r\n sessionMenuItems,\r\n newButton,\r\n sessionStoreSelector,\r\n listActionMenuGetter,\r\n}: SessionDropdownProps<SessionT>) => {\r\n const { t } = useTranslation();\r\n const getTotalUrgencies = useSessionStoreProperty(\r\n (state) => sessionStoreSelector(state).getTotalUrgencies,\r\n );\r\n return (\r\n <SectionedDropdown\r\n triggerIcon={<MenuIcon label=\"Session menu\" urgencies={getTotalUrgencies()} />}\r\n >\r\n <MenuSection caption={translate('New', t, UI.Modules.COMMON)}>\r\n {newButton}\r\n </MenuSection>\r\n <MenuSection caption={translate('Current sessions', t, UI.Modules.COMMON)}>\r\n {sessionMenuItems}\r\n </MenuSection>\r\n <MenuSection>{listActionMenuGetter()}</MenuSection>\r\n </SectionedDropdown>\r\n );\r\n};\r\n\r\ntype CloseButtonProps<\r\n SessionT extends UI.SessionItemBase,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n> = Pick<\r\n SessionMainLayoutProps<SessionT, UI.EmptyObject, UIActionsT>,\r\n 'actions' | 'activeItem'\r\n>;\r\n\r\nconst CloseButton = <\r\n SessionT extends UI.SessionItemBase,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n>({\r\n actions,\r\n activeItem,\r\n}: CloseButtonProps<SessionT, UIActionsT>) => {\r\n if (!activeItem || usingMobileLayout()) {\r\n return null;\r\n }\r\n\r\n /*const closeAction = Object.values(actions.actions).find(\r\n (action) => !!action && action.id === 'remove',\r\n ) as UI.ActionDefinition<UI.SessionItemBase>;*/\r\n\r\n const closeAction = Object.values(actions.actions)[\r\n Object.values(actions.actions).length - 1\r\n ];\r\n return (\r\n <ActionButton\r\n className=\"basic small item close-button\"\r\n action={closeAction as UI.ActionDefinition<UI.SessionItemBase>}\r\n moduleData={actions.moduleData}\r\n itemData={activeItem}\r\n icon={IconConstants.CLOSE}\r\n />\r\n );\r\n};\r\n\r\ntype SessionItemHeaderProps = Pick<\r\n SessionMainLayoutProps<any>,\r\n 'itemHeaderIcon' | 'itemHeaderTitle'\r\n>;\r\n\r\nconst SessionItemHeader: React.FC<SessionItemHeaderProps> = ({\r\n itemHeaderIcon,\r\n itemHeaderTitle,\r\n}) => (\r\n <div className=\"session-header\">\r\n {itemHeaderIcon}\r\n {itemHeaderTitle}\r\n </div>\r\n);\r\n\r\nconst TopMenuLayout = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n>({\r\n children,\r\n onKeyDown,\r\n ...props\r\n}: SessionMainLayoutProps<SessionT, SessionApiT, UIActionsT>) => (\r\n <div className=\"session-container vertical\" onKeyDown={onKeyDown} tabIndex={0}>\r\n <div className=\"ui main menu menu-bar\">\r\n <div className=\"content-left\">\r\n <SessionDropdown {...props} />\r\n <SessionItemHeader {...props} />\r\n </div>\r\n <CloseButton {...props} />\r\n </div>\r\n\r\n <div className=\"session-layout\">{children}</div>\r\n </div>\r\n);\r\n\r\nexport default TopMenuLayout;\r\n","import * as React from 'react';\r\n\r\nimport LayoutHeader from '@/components/semantic/LayoutHeader';\r\nimport { Grid } from '@/components/semantic/Grid';\r\n\r\nimport * as UI from '@/types/ui';\r\nimport { SessionMainLayoutProps } from './types';\r\n\r\nconst SideMenuLayout = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n>({\r\n sessionMenuItems,\r\n newButton,\r\n itemHeaderIcon,\r\n itemHeaderTitle,\r\n children,\r\n itemHeaderDescription,\r\n onKeyDown,\r\n}: SessionMainLayoutProps<SessionT, SessionApiT, UIActionsT>) => {\r\n if (newButton) {\r\n newButton = React.cloneElement(newButton, {\r\n className: newButton.props.className + ' ui fluid button',\r\n });\r\n }\r\n\r\n return (\r\n <Grid className=\"session-container horizontal\" onKeyDown={onKeyDown} tabIndex={0}>\r\n <div className=\"four wide column menu-column\">\r\n {newButton}\r\n {!!sessionMenuItems.length && (\r\n <div className=\"ui vertical secondary menu\" role=\"menu\">\r\n {sessionMenuItems}\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"twelve wide stretched column content-column session\">\r\n <div className=\"ui segment session-layout\">\r\n <LayoutHeader\r\n className=\"session-header\"\r\n icon={itemHeaderIcon}\r\n title={<div className=\"title\">{itemHeaderTitle}</div>}\r\n subHeader={itemHeaderDescription}\r\n />\r\n <div className=\"ui divider\" style={{ margin: '5px 0px 0px 0px' }} />\r\n {children}\r\n </div>\r\n </div>\r\n </Grid>\r\n );\r\n};\r\n\r\nexport default SideMenuLayout;\r\n","import invariant from 'invariant';\r\n\r\nimport * as API from '@/types/api';\r\n\r\nimport { useNavigate } from 'react-router';\r\nimport { SessionLocationState } from '../types';\r\n\r\ninterface SessionRouteHelperProps {\r\n baseUrl: string;\r\n}\r\n\r\nexport const useSessionRouteHelpers = ({ baseUrl }: SessionRouteHelperProps) => {\r\n const navigate = useNavigate();\r\n\r\n // HELPERS\r\n const getSessionUrl = (id: API.IdType) => {\r\n invariant(!!id, 'Trying to get session URL without a session');\r\n return `/${baseUrl}/session/${id}`;\r\n };\r\n\r\n const pushSession = (id: API.IdType) => {\r\n navigate(getSessionUrl(id));\r\n };\r\n\r\n const replaceSession = (id: API.IdType, state?: SessionLocationState) => {\r\n navigate(getSessionUrl(id), { replace: true, state });\r\n };\r\n\r\n const newUrl = `/${baseUrl}/new`;\r\n const replaceNew = () => {\r\n navigate(newUrl, { replace: true });\r\n };\r\n\r\n return {\r\n newUrl: `/${baseUrl}/new`,\r\n replaceNew,\r\n\r\n getSessionUrl,\r\n pushSession,\r\n replaceSession,\r\n };\r\n};\r\n","import * as React from 'react';\r\n\r\nimport { loadLocalProperty, saveLocalProperty } from '@/utils/BrowserUtils';\r\n\r\nimport * as API from '@/types/api';\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { useLocation } from 'react-router';\r\nimport { useSessionRouteHelpers } from './useSessionHelpers';\r\nimport { SessionLocationState } from '../types';\r\nimport { useSocket } from '@/context/SocketContext';\r\n\r\nconst findItem = <SessionT extends UI.SessionItemBase>(\r\n items: SessionT[],\r\n id: API.IdType | undefined,\r\n): SessionT | undefined => {\r\n return items.find((item) => item.id === id);\r\n};\r\n\r\nexport interface SessionManagerProps<\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object = UI.EmptyObject,\r\n> {\r\n // Item ID that is currently active (if any)\r\n activeId: API.IdType | undefined;\r\n\r\n // Array of the items to list\r\n items: SessionT[];\r\n\r\n baseUrl: string;\r\n\r\n sessionApi: UI.SessionAPIActions<SessionT> & SessionApiT;\r\n}\r\n\r\nexport const useSessionManager = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object = UI.EmptyObject,\r\n>(\r\n props: SessionManagerProps<SessionT, SessionApiT>,\r\n) => {\r\n const [activeItem, setActiveItem] = React.useState<SessionT | null>(null);\r\n const location = useLocation();\r\n const socket = useSocket();\r\n\r\n const { pushSession, replaceSession, newUrl, replaceNew } = useSessionRouteHelpers({\r\n baseUrl: props.baseUrl,\r\n });\r\n\r\n // HELPERS\r\n const getStorageKey = () => {\r\n return `${props.baseUrl}_last_active`;\r\n };\r\n\r\n // Common logic for selecting the item to display (after mounting or session updates)\r\n // Returns true active item selection was handled\r\n // Returns false if the active item couldn't be selected but there are valid items to choose from by the caller\r\n const checkActiveItem = () => {\r\n // Did we just create this session?\r\n const routerLocation = location;\r\n const pending =\r\n routerLocation.state && (routerLocation.state as SessionLocationState).pending;\r\n\r\n // Update the active item\r\n const activeItemNew = findItem(props.items, props.activeId);\r\n if (activeItemNew) {\r\n if (pending) {\r\n // Disable pending state\r\n replaceSession(activeItemNew.id, {\r\n pending: false,\r\n });\r\n\r\n return true;\r\n }\r\n\r\n setActiveItem(activeItemNew);\r\n saveLocalProperty(getStorageKey(), props.activeId);\r\n return true;\r\n } else if (pending) {\r\n // We'll just display a loading indicator in 'render', no item needed\r\n return true;\r\n } else if (/*routerLocation.action === 'POP' ||*/ props.items.length === 0) {\r\n // Browsing from history and item removed (or all items removed)... go to \"new session\" page\r\n replaceNew();\r\n setActiveItem(null);\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n // LIFECYCLE/REACT\r\n // Set the session early so that we wont' flash the \"new session\" layout\r\n React.useLayoutEffect(() => {\r\n if (location.pathname === newUrl) {\r\n // Don't redirect to it if the \"new session\" layout is open\r\n if (activeItem) {\r\n setActiveItem(null);\r\n }\r\n return;\r\n }\r\n\r\n if (checkActiveItem()) {\r\n // We got an item\r\n return;\r\n }\r\n\r\n if (!activeItem) {\r\n const lastId = loadLocalProperty<API.IdType>(getStorageKey());\r\n if (lastId && findItem(props.items, lastId)) {\r\n // Previous session exists\r\n replaceSession(lastId);\r\n return;\r\n }\r\n }\r\n\r\n // The old tab was closed or we didn't have any session before\r\n\r\n const { items, activeId } = props;\r\n let newItemPos = 0;\r\n const oldItem = findItem(items, activeId);\r\n if (oldItem) {\r\n // Find the old position and use the item in that position (if possible)\r\n newItemPos = items.indexOf(oldItem);\r\n if (newItemPos === items.length - 1) {\r\n // The last item was removed\r\n newItemPos = newItemPos - 1;\r\n }\r\n }\r\n\r\n replaceSession(items[newItemPos].id);\r\n }, [location, props.items]);\r\n\r\n const onKeyDown = (event: React.KeyboardEvent) => {\r\n const { key, altKey } = event;\r\n\r\n if (altKey && (key === 'ArrowUp' || key === 'ArrowDown')) {\r\n // Arrow up/down\r\n event.preventDefault();\r\n\r\n const { items, activeId } = props;\r\n const item = findItem(items, activeId);\r\n if (!item) {\r\n return;\r\n }\r\n\r\n const currentIndex = items.indexOf(item);\r\n if (currentIndex === -1) {\r\n return;\r\n }\r\n\r\n const newSession = items[key === 'ArrowUp' ? currentIndex - 1 : currentIndex + 1];\r\n if (newSession) {\r\n pushSession(newSession.id);\r\n }\r\n } else if (altKey && key === 'Insert') {\r\n // Insert\r\n event.preventDefault();\r\n\r\n replaceNew();\r\n } else if (altKey && key === 'Delete') {\r\n // Delete\r\n event.preventDefault();\r\n\r\n const { items, activeId, sessionApi } = props;\r\n const item = findItem(items, activeId);\r\n if (!!item) {\r\n sessionApi.removeSession(item, socket);\r\n }\r\n }\r\n };\r\n\r\n return {\r\n onKeyDown,\r\n activeItem,\r\n };\r\n};\r\n","import * as React from 'react';\r\nimport classNames from 'classnames';\r\n\r\nimport IconConstants from '@/constants/IconConstants';\r\nimport RouterMenuItemLink from '@/components/semantic/RouterMenuItemLink';\r\n\r\ninterface SessionNewButtonProps {\r\n url: string;\r\n title: React.ReactNode;\r\n className?: string;\r\n}\r\n\r\nconst SessionNewButton: React.FC<SessionNewButtonProps> = ({\r\n url,\r\n title,\r\n // pushNew,\r\n className,\r\n}) => (\r\n <RouterMenuItemLink\r\n key=\"button-new\"\r\n className={classNames('new', className)}\r\n icon={IconConstants.CREATE}\r\n url={url}\r\n >\r\n {title}\r\n </RouterMenuItemLink>\r\n);\r\n\r\nexport default SessionNewButton;\r\n","import * as React from 'react';\r\n\r\nimport RouterMenuItemLink from '@/components/semantic/RouterMenuItemLink';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\ninterface SessionMenuItemProps {\r\n url: string;\r\n name: React.ReactNode;\r\n unreadInfoStoreSelector: UI.SessionStoreSelector;\r\n status: React.ReactElement<any>;\r\n sessionItem: UI.SessionItemBase;\r\n}\r\n\r\nconst SessionMenuItem: React.FC<SessionMenuItemProps> = ({\r\n sessionItem,\r\n status,\r\n name,\r\n unreadInfoStoreSelector,\r\n url,\r\n}) => (\r\n <RouterMenuItemLink\r\n url={url}\r\n className=\"session-item\"\r\n icon={status}\r\n sessionItem={sessionItem}\r\n unreadInfoStoreSelector={unreadInfoStoreSelector}\r\n >\r\n {name}\r\n </RouterMenuItemLink>\r\n);\r\n\r\nexport default SessionMenuItem;\r\n","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!./sessions.css\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\noptions.insert = insertFn.bind(null, \"head\");\noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!./sessions.css\";\n export default content && content.locals ? content.locals : undefined;\n","import * as React from 'react';\r\n\r\nimport Loader from '@/components/semantic/Loader';\r\n\r\nimport TopMenuLayout from './TopMenuLayout';\r\nimport SideMenuLayout from './SideMenuLayout';\r\n\r\nimport Message from '@/components/semantic/Message';\r\n\r\nimport { usingMobileLayout } from '@/utils/BrowserUtils';\r\n\r\nimport * as API from '@/types/api';\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { translate, toI18nKey } from '@/utils/TranslationUtils';\r\nimport { useLayoutWidth } from '@/context/LayoutWidthContext';\r\nimport { useSessionManager } from './effects/useSessionManager';\r\nimport { useLocation, useNavigate } from 'react-router';\r\n\r\nimport {\r\n NewSessionLayoutProps,\r\n SessionChildProps,\r\n SessionLayoutLabels,\r\n SessionLayoutManageProps,\r\n SessionLocationState,\r\n} from './types';\r\nimport { useComponents } from './SessionMenuComponents';\r\nimport { useSession } from '@/context/AppStoreContext';\r\n\r\nimport '../sessions.css';\r\nimport { hasAccess } from '@/utils/AuthUtils';\r\n\r\nexport interface SessionLayoutProps<\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object = UI.EmptyObject,\r\n UIActionT extends UI.ActionListType<UI.SessionItemBase> = UI.EmptyObject,\r\n> extends UI.SessionInfoGetter<SessionT>,\r\n SessionLayoutLabels,\r\n SessionLayoutManageProps<SessionT, SessionApiT, UIActionT> {\r\n // Item ID that is currently active (if any)\r\n activeId: API.IdType | undefined;\r\n\r\n // Set to false if the side menu should never be shown (the session will use all width that is available)\r\n disableSideMenu?: boolean;\r\n\r\n sessionItemLayout: React.ComponentType<\r\n SessionChildProps<SessionT, SessionApiT, UIActionT>\r\n >;\r\n\r\n newLayout?: React.ComponentType<NewSessionLayoutProps>;\r\n\r\n sessionT: UI.ModuleTranslator;\r\n}\r\n\r\nconst SessionLayout = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n>(\r\n props: SessionLayoutProps<SessionT, SessionApiT, UIActionsT>,\r\n) => {\r\n const session = useSession();\r\n const layoutWidth = useLayoutWidth();\r\n const navigate = useNavigate();\r\n const location = useLocation();\r\n\r\n const { activeItem, onKeyDown } = useSessionManager(props);\r\n\r\n const hasEditAccess = hasAccess(session, props.editAccess);\r\n const isNewLayout = !!props.newLayout && location.pathname.endsWith('/new');\r\n\r\n const getSessionChildren = () => {\r\n const {\r\n activeId,\r\n items,\r\n sessionItemLayout: SessionItemLayout,\r\n sessionApi,\r\n uiActions,\r\n sessionT,\r\n baseUrl,\r\n } = props;\r\n\r\n if (!activeItem) {\r\n const { state } = location;\r\n if (!!state && (state as SessionLocationState).pending) {\r\n // The session was just created\r\n return (\r\n <Loader\r\n text={translate(\r\n 'Waiting for server response',\r\n sessionT.plainT,\r\n UI.Modules.COMMON,\r\n )}\r\n />\r\n );\r\n } else if (activeId || items.length !== 0) {\r\n // Redirecting to a new page\r\n return (\r\n <Loader\r\n text={translate('Loading session', sessionT.plainT, UI.Modules.COMMON)}\r\n />\r\n );\r\n }\r\n\r\n console.error('SessionLayout route: active session missing');\r\n return;\r\n }\r\n\r\n // We have a session\r\n return (\r\n <SessionItemLayout\r\n sessionItem={activeItem}\r\n sessionApi={sessionApi}\r\n uiActions={uiActions}\r\n location={location}\r\n navigate={navigate}\r\n sessionT={sessionT}\r\n baseUrl={baseUrl}\r\n />\r\n );\r\n };\r\n\r\n const getChildren = () => {\r\n const { newLayout: NewLayout, sessionT } = props;\r\n if (isNewLayout && NewLayout) {\r\n return <NewLayout navigate={navigate} location={location} sessionT={sessionT} />;\r\n }\r\n\r\n return getSessionChildren();\r\n };\r\n\r\n const { disableSideMenu, items, sessionStoreSelector, sessionT, uiActions } = props;\r\n\r\n const useTopMenu = disableSideMenu || usingMobileLayout(layoutWidth);\r\n\r\n const {\r\n getItemHeaderTitle,\r\n getItemHeaderDescription,\r\n getItemHeaderIcon,\r\n getNewButton,\r\n getSessionMenuItems,\r\n getSessionActionMenuItems,\r\n } = useComponents({ ...props, activeItem, hasEditAccess, isNewLayout });\r\n\r\n if (!hasEditAccess && items.length === 0) {\r\n // Nothing to show\r\n return (\r\n <Message\r\n title={translate('No items to show', sessionT.plainT, UI.Modules.COMMON)}\r\n description={sessionT.plainT(\r\n toI18nKey('noSessionEditAccess', UI.Modules.COMMON),\r\n `You aren't allowed to open new sessions`,\r\n )}\r\n />\r\n );\r\n }\r\n\r\n const MenuLayout = useTopMenu ? TopMenuLayout : SideMenuLayout;\r\n return (\r\n <MenuLayout\r\n itemHeaderTitle={getItemHeaderTitle()}\r\n itemHeaderDescription={getItemHeaderDescription()}\r\n itemHeaderIcon={getItemHeaderIcon()}\r\n newButton={getNewButton()}\r\n sessionMenuItems={getSessionMenuItems()}\r\n listActionMenuGetter={getSessionActionMenuItems}\r\n activeItem={activeItem}\r\n sessionStoreSelector={sessionStoreSelector}\r\n onKeyDown={onKeyDown}\r\n actions={uiActions}\r\n >\r\n {getChildren()}\r\n </MenuLayout>\r\n );\r\n};\r\n\r\nexport default SessionLayout;\r\n","import { ActionMenu } from '@/components/action-menu';\r\nimport SessionNewButton from './SessionNewButton';\r\nimport SessionMenuItem from './SessionMenuItem';\r\n\r\nimport Icon from '@/components/semantic/Icon';\r\n\r\nimport IconConstants from '@/constants/IconConstants';\r\nimport MenuItemLink from '@/components/semantic/MenuItemLink';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { translate } from '@/utils/TranslationUtils';\r\nimport { SessionLayoutLabels, SessionLayoutManageProps } from './types';\r\nimport { useLocation } from 'react-router';\r\nimport { useSessionRouteHelpers } from './effects/useSessionHelpers';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useSocket } from '@/context/SocketContext';\r\n\r\nexport const useComponents = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object = UI.EmptyObject,\r\n UIActionT extends UI.ActionListType<UI.SessionItemBase> = UI.EmptyObject,\r\n>(\r\n props: UI.SessionInfoGetter<SessionT> & {\r\n activeItem: SessionT | null;\r\n hasEditAccess: boolean;\r\n isNewLayout: boolean;\r\n } & SessionLayoutLabels &\r\n SessionLayoutManageProps<SessionT, SessionApiT, UIActionT>,\r\n) => {\r\n const socket = useSocket();\r\n const location = useLocation();\r\n const { t } = useTranslation();\r\n const { newUrl, getSessionUrl } = useSessionRouteHelpers({\r\n baseUrl: props.baseUrl,\r\n });\r\n\r\n // COMPONENT GETTERS\r\n const getItemStatus = (sessionItem: SessionT) => {\r\n const { itemStatusGetter, itemHeaderIconGetter } = props;\r\n if (itemStatusGetter) {\r\n return (\r\n <div\r\n className={\r\n 'ui session-status empty circular left mini label ' +\r\n itemStatusGetter(sessionItem)\r\n }\r\n />\r\n );\r\n }\r\n\r\n return <Icon icon={itemHeaderIconGetter(sessionItem)} />;\r\n };\r\n\r\n const components = {\r\n // Current session\r\n getItemHeaderDescription: () => {\r\n const { itemHeaderDescriptionGetter, newDescription, activeItem, isNewLayout } =\r\n props;\r\n if (isNewLayout) {\r\n return newDescription;\r\n }\r\n\r\n if (activeItem) {\r\n return itemHeaderDescriptionGetter(activeItem);\r\n }\r\n\r\n return null;\r\n },\r\n getItemHeaderIcon: () => {\r\n const { itemHeaderIconGetter, newIcon, activeItem, isNewLayout } = props;\r\n if (isNewLayout) {\r\n return <Icon icon={newIcon} />;\r\n }\r\n\r\n if (activeItem) {\r\n return <Icon icon={itemHeaderIconGetter(activeItem)} />;\r\n }\r\n\r\n return null;\r\n },\r\n getItemHeaderTitle: () => {\r\n const { activeItem, newCaption, remoteMenuId, isNewLayout } = props;\r\n if (isNewLayout) {\r\n return <div>{newCaption}</div>;\r\n }\r\n\r\n if (!activeItem) {\r\n return null;\r\n }\r\n\r\n const { uiActions, actionIds, itemNameGetter, itemHeaderTitleGetter } = props;\r\n\r\n const ids = actionIds ? [...actionIds, 'divider', 'remove'] : undefined;\r\n const actionMenu = (\r\n <ActionMenu\r\n caption={itemNameGetter(activeItem)}\r\n actions={uiActions}\r\n itemData={activeItem}\r\n ids={ids}\r\n remoteMenuId={remoteMenuId}\r\n />\r\n );\r\n\r\n // Use the header getter only if there is a getter that returns a valid value\r\n if (itemHeaderTitleGetter) {\r\n const header = itemHeaderTitleGetter(activeItem, location, actionMenu);\r\n if (header) {\r\n return header;\r\n }\r\n }\r\n\r\n return actionMenu;\r\n },\r\n\r\n // Other\r\n getSessionActionMenuItems: () => {\r\n const { items, hasEditAccess } = props;\r\n if (!hasEditAccess || items.length === 0) {\r\n return null;\r\n }\r\n\r\n const handleCloseAll = () => {\r\n const { sessionApi, items } = props;\r\n items.forEach((session) => sessionApi.removeSession(session, socket));\r\n };\r\n\r\n return (\r\n <MenuItemLink key=\"close\" onClick={handleCloseAll} icon={IconConstants.REMOVE}>\r\n {translate('Close all', t, UI.Modules.COMMON)}\r\n </MenuItemLink>\r\n );\r\n },\r\n getNewButton: () => {\r\n const { newCaption, hasEditAccess } = props;\r\n if (!hasEditAccess || !newCaption) {\r\n return null;\r\n }\r\n\r\n return <SessionNewButton key=\"new-button\" title={newCaption} url={newUrl} />;\r\n },\r\n getSessionMenuItems: () => {\r\n const getSessionMenuItem = (sessionItem: SessionT) => {\r\n const { itemNameGetter, sessionStoreSelector } = props;\r\n return (\r\n <SessionMenuItem\r\n key={sessionItem.id}\r\n url={getSessionUrl(sessionItem.id)}\r\n name={itemNameGetter(sessionItem)}\r\n unreadInfoStoreSelector={sessionStoreSelector}\r\n status={getItemStatus(sessionItem)}\r\n sessionItem={sessionItem}\r\n />\r\n );\r\n };\r\n\r\n return props.items.map(getSessionMenuItem);\r\n },\r\n };\r\n\r\n return components;\r\n};\r\n"],"names":["BuildRemoveSessionAction","sessionsUrl","editAccess","id","displayName","access","icon","REMOVE","handler","itemData","session","socket","delete","FooterItem","label","text","className","SessionFooter","children","___CSS_LOADER_EXPORT___","push","module","SessionProviderDecorator","Component","sessionStoreSelector","moduleId","props","t","sessionT","params","sessions","state","items","COMMON","useActiveSession","sessionItem","actions","useReadDelay","appStoreApi","userActive","activity","activeSessionStoreSetter","setActiveSession","readTimeout","undefined","checkSetRead","sessionItemRead","setRead","current","clearTimeout","sessionItemNew","timeout","getState","settings","getValue","UNREAD_LABEL_DELAY","window","setTimeout","scheduleCheckSetRead","SessionDropdown","sessionMenuItems","newButton","listActionMenuGetter","getTotalUrgencies","SectionedDropdown","triggerIcon","MenuIcon","urgencies","MenuSection","caption","CloseButton","activeItem","closeAction","Object","values","length","ActionButton","A","action","moduleData","IconConstants","CLOSE","SessionItemHeader","itemHeaderIcon","itemHeaderTitle","onKeyDown","tabIndex","itemHeaderDescription","Grid","role","LayoutHeader","title","subHeader","style","margin","useSessionRouteHelpers","baseUrl","navigate","getSessionUrl","newUrl","replaceNew","replace","pushSession","replaceSession","findItem","find","item","url","RouterMenuItemLink","CREATE","status","name","unreadInfoStoreSelector","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","locals","layoutWidth","location","setActiveItem","getStorageKey","pathname","routerLocation","pending","activeItemNew","activeId","checkActiveItem","lastId","newItemPos","oldItem","indexOf","event","key","altKey","preventDefault","sessionApi","removeSession","currentIndex","newSession","useSessionManager","hasEditAccess","isNewLayout","newLayout","endsWith","disableSideMenu","uiActions","useTopMenu","getItemHeaderTitle","getItemHeaderDescription","getItemHeaderIcon","getNewButton","getSessionMenuItems","getSessionActionMenuItems","getItemStatus","itemStatusGetter","itemHeaderIconGetter","Icon","itemHeaderDescriptionGetter","newDescription","newIcon","newCaption","remoteMenuId","actionIds","itemNameGetter","itemHeaderTitleGetter","ids","actionMenu","header","MenuItemLink","onClick","forEach","map","useComponents","Message","plainT","description","MenuLayout","NewLayout","sessionItemLayout","SessionItemLayout","Loader","console","error","getSessionChildren","getChildren"],"sourceRoot":""}
1
+ {"version":3,"file":"js/550.83271f41ad0cccc6815b.chunk.js","mappings":"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","sources":["webpack://airdcpp-webui/./src/actions/ui/decorators/SessionActionDecorator.ts","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionFooter.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/sessions.css","webpack://airdcpp-webui/./src/routes/Sidebar/decorators/SessionProviderDecorator.tsx","webpack://airdcpp-webui/./src/effects/ActiveSessionEffect.ts","webpack://airdcpp-webui/./src/routes/Sidebar/components/TopMenuLayout.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/components/SideMenuLayout.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/components/effects/useSessionHelpers.ts","webpack://airdcpp-webui/./src/routes/Sidebar/components/effects/useSessionManager.ts","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionNewButton.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionMenuItem.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/sessions.css?90b7","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionLayout.tsx","webpack://airdcpp-webui/./src/routes/Sidebar/components/SessionMenuComponents.tsx"],"sourcesContent":["import IconConstants from '@/constants/IconConstants';\r\n\r\nimport * as API from '@/types/api';\r\nimport * as UI from '@/types/ui';\r\n\r\ntype SessionType = UI.SessionItemBase;\r\n\r\nexport const BuildRemoveSessionAction = (\r\n sessionsUrl: string,\r\n editAccess: API.AccessEnum,\r\n) => {\r\n const handleRemoveSession: UI.ActionHandler<SessionType> = ({\r\n itemData: session,\r\n socket,\r\n }) => {\r\n return socket.delete(`${sessionsUrl}/${session.id}`);\r\n };\r\n\r\n const SessionRemoveAction = {\r\n id: 'remove',\r\n displayName: 'Close',\r\n access: editAccess,\r\n icon: IconConstants.REMOVE,\r\n handler: handleRemoveSession,\r\n };\r\n\r\n return SessionRemoveAction;\r\n};\r\n","import * as React from 'react';\n\nimport * as UI from '@/types/ui';\n\ninterface FooterItemProps {\n label?: string;\n text: string | React.ReactElement<any>;\n}\n\nexport const FooterItem: React.FC<FooterItemProps> = ({ label, text }) => (\n <div className=\"grid-item\">\n <div className=\"item-inner\">\n {!!label && typeof text === 'string' ? `${label}: ${text}` : text}\n </div>\n </div>\n);\n\nexport const SessionFooter: React.FC<UI.PropsWithChildren> = ({ children }) => (\n <div className=\"session-footer\">\n <div className=\"ui footer divider\" />\n <div className=\"info-grid ui\">{children}</div>\n </div>\n);\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.session-container {\n background-color: white;\n}\n\n.session-container.horizontal.ui.grid {\n margin: 0px !important;\n}\n\n.session-container.horizontal .menu-column .item.new {\n padding: 0.78571429em 1.1em !important;\n}\n\n.session-container.horizontal .ui.vertical.menu .item > i.icon {\n margin: 0 0.35714286em 0 0 !important;\n}\n\n.session-container.horizontal .session-layout > .ui.divider {\n margin: 5px 0px 0px 0px;\n}\n\n.session-container.vertical {\n padding: 15px;\n display: flex;\n flex-direction: column;\n}\n.session-layout {\n flex: 100 100 auto;\n display: flex;\n overflow: hidden;\n}\n\n.session-container.horizontal .session-layout {\n flex-direction: column;\n}\n\n.session-container.vertical .menu-bar {\n justify-content: space-between;\n margin: 0px !important;\n}\n\n.session-container.vertical .menu-bar .content-left {\n width: 100%;\n}\n\n.session-container.vertical .menu-bar .close-button.item:before {\n background: none !important;\n}\n\n.session-container.vertical .menu-bar .close-button.item {\n box-shadow: none !important;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown {\n float: left;\n}\n\n.session-container.vertical .menu-bar .content-left > .ui.dropdown .menu {\n max-height: calc(100dvh - 140px);\n overflow-y: auto;\n overflow-x: hidden;\n max-width: calc(100vw - 30px);\n}\n\n.session-container.vertical .session-item .count.label {\n margin-left: 1em !important;\n}\n\n.session-container.vertical .session-header {\n display: flex;\n align-items: center;\n height: 100%;\n}\n\n.session-container.vertical .session-header > div {\n max-width: 90%; /* Hack, auto width won't work without \"overflow: hidden\", but that would prevent viewing the menu items */\n padding: 0.82857143em 0.4285714em;\n line-height: 1.2;\n}\n\n.session-container.vertical .session-header > div:before {\n background: none !important;\n}\n\n.session-container.vertical .session-header > i {\n margin-left: 10px;\n}\n\n.session-container.vertical .session-header .ui.dropdown > i {\n margin: 0px 5px;\n}\n\n/* Fix a few inconsistencies between 'icon' and 'icons' classnames */\n.session-container.horizontal .session-header .header > i,\n.session-container.vertical .session-header > i {\n width: inherit !important;\n font-size: 1.5em;\n}\n\n.session-container.horizontal .session-header .ui.header {\n align-items: center;\n}\n\n.session-container.vertical .menu-bar {\n border-radius: 0px !important;\n padding-bottom: 0px;\n}\n\n.session-container,\n.session-layout,\n.session-container.horizontal .column {\n height: 100%;\n}\n\n.session-container.horizontal .column > div {\n max-height: 100%;\n}\n\n.session-container .session-item {\n overflow: hidden;\n display: flex !important;\n align-items: center;\n padding: 0.68571429em 0.92857143em !important;\n height: 35px;\n}\n\n.session-container .session-item .session-status {\n float: none !important;\n margin: 0 0.5em 0 0 !important;\n}\n\n.session-container .session-item span.name {\n overflow: hidden;\n flex: 1 1 100%;\n line-height: 1.2;\n}\n\n.session-container .session-status {\n margin-right: 5px;\n margin-top: 3px;\n}\n\n.session-container.horizontal .menu-column {\n display: flex !important;\n flex-direction: column;\n padding-right: 0px !important;\n}\n\n.session-container.horizontal .menu-column .menu {\n width: initial !important;\n overflow-y: auto;\n padding-top: 10px;\n flex: 1;\n}\n\n.session-container.horizontal .menu-column .session-item span.name,\n.session-container .session-header .ui.dropdown .caption {\n overflow: hidden;\n white-space: nowrap;\n}\n\n.session-container .session-header .title .ui.dropdown {\n width: 100%;\n}\n\n.session-layout .sub.header {\n overflow: hidden;\n}\n\n.session-layout .sub.header img {\n vertical-align: text-top;\n}\n\n.session-footer .info-grid {\n margin-top: 7px !important;\n font-size: small;\n color: grey;\n display: flex;\n flex: 1;\n align-items: flex-end;\n}\n\n.session-footer .info-grid > div {\n flex: 1;\n}\n\n.session-footer .info-grid > div:last-child > div {\n float: right;\n}\n\n.session-footer .info-grid > div:only-child > div {\n float: inherit;\n}\n\n.session-footer .ui.checkbox {\n min-height: inherit !important;\n}\n\n.session-footer .divider {\n margin-top: 8px;\n margin-bottom: 0px;\n}\n\n/* New session layout */\n.session.new {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n overflow-y: hidden;\n margin-top: 20px;\n padding: 1px;\n}\n\n.session.new .recents {\n flex: 100 100 0%;\n display: flex;\n flex-direction: column;\n margin-top: 20px;\n overflow-y: hidden;\n}\n\n.session.new .recents .list {\n padding: 3px 5px;\n flex: 100 100 0%;\n overflow-y: auto;\n overflow-x: hidden;\n}\n`, \"\",{\"version\":3,\"sources\":[\"webpack://./src/routes/Sidebar/sessions.css\"],\"names\":[],\"mappings\":\"AAAA;EACE,uBAAuB;AACzB;;AAEA;EACE,sBAAsB;AACxB;;AAEA;EACE,sCAAsC;AACxC;;AAEA;EACE,qCAAqC;AACvC;;AAEA;EACE,uBAAuB;AACzB;;AAEA;EACE,aAAa;EACb,aAAa;EACb,sBAAsB;AACxB;AACA;EACE,kBAAkB;EAClB,aAAa;EACb,gBAAgB;AAClB;;AAEA;EACE,sBAAsB;AACxB;;AAEA;EACE,8BAA8B;EAC9B,sBAAsB;AACxB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,gCAAgC;EAChC,gBAAgB;EAChB,kBAAkB;EAClB,6BAA6B;AAC/B;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,aAAa;EACb,mBAAmB;EACnB,YAAY;AACd;;AAEA;EACE,cAAc,EAAE,2GAA2G;EAC3H,iCAAiC;EACjC,gBAAgB;AAClB;;AAEA;EACE,2BAA2B;AAC7B;;AAEA;EACE,iBAAiB;AACnB;;AAEA;EACE,eAAe;AACjB;;AAEA,oEAAoE;AACpE;;EAEE,yBAAyB;EACzB,gBAAgB;AAClB;;AAEA;EACE,mBAAmB;AACrB;;AAEA;EACE,6BAA6B;EAC7B,mBAAmB;AACrB;;AAEA;;;EAGE,YAAY;AACd;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,gBAAgB;EAChB,wBAAwB;EACxB,mBAAmB;EACnB,6CAA6C;EAC7C,YAAY;AACd;;AAEA;EACE,sBAAsB;EACtB,8BAA8B;AAChC;;AAEA;EACE,gBAAgB;EAChB,cAAc;EACd,gBAAgB;AAClB;;AAEA;EACE,iBAAiB;EACjB,eAAe;AACjB;;AAEA;EACE,wBAAwB;EACxB,sBAAsB;EACtB,6BAA6B;AAC/B;;AAEA;EACE,yBAAyB;EACzB,gBAAgB;EAChB,iBAAiB;EACjB,OAAO;AACT;;AAEA;;EAEE,gBAAgB;EAChB,mBAAmB;AACrB;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,wBAAwB;AAC1B;;AAEA;EACE,0BAA0B;EAC1B,gBAAgB;EAChB,WAAW;EACX,aAAa;EACb,OAAO;EACP,qBAAqB;AACvB;;AAEA;EACE,OAAO;AACT;;AAEA;EACE,YAAY;AACd;;AAEA;EACE,cAAc;AAChB;;AAEA;EACE,8BAA8B;AAChC;;AAEA;EACE,eAAe;EACf,kBAAkB;AACpB;;AAEA,uBAAuB;AACvB;EACE,gBAAgB;EAChB,aAAa;EACb,sBAAsB;EACtB,kBAAkB;EAClB,gBAAgB;EAChB,YAAY;AACd;;AAEA;EACE,gBAAgB;EAChB,aAAa;EACb,sBAAsB;EACtB,gBAAgB;EAChB,kBAAkB;AACpB;;AAEA;EACE,gBAAgB;EAChB,gBAAgB;EAChB,gBAAgB;EAChB,kBAAkB;AACpB\",\"sourcesContent\":[\".session-container {\\n background-color: white;\\n}\\n\\n.session-container.horizontal.ui.grid {\\n margin: 0px !important;\\n}\\n\\n.session-container.horizontal .menu-column .item.new {\\n padding: 0.78571429em 1.1em !important;\\n}\\n\\n.session-container.horizontal .ui.vertical.menu .item > i.icon {\\n margin: 0 0.35714286em 0 0 !important;\\n}\\n\\n.session-container.horizontal .session-layout > .ui.divider {\\n margin: 5px 0px 0px 0px;\\n}\\n\\n.session-container.vertical {\\n padding: 15px;\\n display: flex;\\n flex-direction: column;\\n}\\n.session-layout {\\n flex: 100 100 auto;\\n display: flex;\\n overflow: hidden;\\n}\\n\\n.session-container.horizontal .session-layout {\\n flex-direction: column;\\n}\\n\\n.session-container.vertical .menu-bar {\\n justify-content: space-between;\\n margin: 0px !important;\\n}\\n\\n.session-container.vertical .menu-bar .content-left {\\n width: 100%;\\n}\\n\\n.session-container.vertical .menu-bar .close-button.item:before {\\n background: none !important;\\n}\\n\\n.session-container.vertical .menu-bar .close-button.item {\\n box-shadow: none !important;\\n}\\n\\n.session-container.vertical .menu-bar .content-left > .ui.dropdown {\\n float: left;\\n}\\n\\n.session-container.vertical .menu-bar .content-left > .ui.dropdown .menu {\\n max-height: calc(100dvh - 140px);\\n overflow-y: auto;\\n overflow-x: hidden;\\n max-width: calc(100vw - 30px);\\n}\\n\\n.session-container.vertical .session-item .count.label {\\n margin-left: 1em !important;\\n}\\n\\n.session-container.vertical .session-header {\\n display: flex;\\n align-items: center;\\n height: 100%;\\n}\\n\\n.session-container.vertical .session-header > div {\\n max-width: 90%; /* Hack, auto width won't work without \\\"overflow: hidden\\\", but that would prevent viewing the menu items */\\n padding: 0.82857143em 0.4285714em;\\n line-height: 1.2;\\n}\\n\\n.session-container.vertical .session-header > div:before {\\n background: none !important;\\n}\\n\\n.session-container.vertical .session-header > i {\\n margin-left: 10px;\\n}\\n\\n.session-container.vertical .session-header .ui.dropdown > i {\\n margin: 0px 5px;\\n}\\n\\n/* Fix a few inconsistencies between 'icon' and 'icons' classnames */\\n.session-container.horizontal .session-header .header > i,\\n.session-container.vertical .session-header > i {\\n width: inherit !important;\\n font-size: 1.5em;\\n}\\n\\n.session-container.horizontal .session-header .ui.header {\\n align-items: center;\\n}\\n\\n.session-container.vertical .menu-bar {\\n border-radius: 0px !important;\\n padding-bottom: 0px;\\n}\\n\\n.session-container,\\n.session-layout,\\n.session-container.horizontal .column {\\n height: 100%;\\n}\\n\\n.session-container.horizontal .column > div {\\n max-height: 100%;\\n}\\n\\n.session-container .session-item {\\n overflow: hidden;\\n display: flex !important;\\n align-items: center;\\n padding: 0.68571429em 0.92857143em !important;\\n height: 35px;\\n}\\n\\n.session-container .session-item .session-status {\\n float: none !important;\\n margin: 0 0.5em 0 0 !important;\\n}\\n\\n.session-container .session-item span.name {\\n overflow: hidden;\\n flex: 1 1 100%;\\n line-height: 1.2;\\n}\\n\\n.session-container .session-status {\\n margin-right: 5px;\\n margin-top: 3px;\\n}\\n\\n.session-container.horizontal .menu-column {\\n display: flex !important;\\n flex-direction: column;\\n padding-right: 0px !important;\\n}\\n\\n.session-container.horizontal .menu-column .menu {\\n width: initial !important;\\n overflow-y: auto;\\n padding-top: 10px;\\n flex: 1;\\n}\\n\\n.session-container.horizontal .menu-column .session-item span.name,\\n.session-container .session-header .ui.dropdown .caption {\\n overflow: hidden;\\n white-space: nowrap;\\n}\\n\\n.session-container .session-header .title .ui.dropdown {\\n width: 100%;\\n}\\n\\n.session-layout .sub.header {\\n overflow: hidden;\\n}\\n\\n.session-layout .sub.header img {\\n vertical-align: text-top;\\n}\\n\\n.session-footer .info-grid {\\n margin-top: 7px !important;\\n font-size: small;\\n color: grey;\\n display: flex;\\n flex: 1;\\n align-items: flex-end;\\n}\\n\\n.session-footer .info-grid > div {\\n flex: 1;\\n}\\n\\n.session-footer .info-grid > div:last-child > div {\\n float: right;\\n}\\n\\n.session-footer .info-grid > div:only-child > div {\\n float: inherit;\\n}\\n\\n.session-footer .ui.checkbox {\\n min-height: inherit !important;\\n}\\n\\n.session-footer .divider {\\n margin-top: 8px;\\n margin-bottom: 0px;\\n}\\n\\n/* New session layout */\\n.session.new {\\n flex: 100 100 0%;\\n display: flex;\\n flex-direction: column;\\n overflow-y: hidden;\\n margin-top: 20px;\\n padding: 1px;\\n}\\n\\n.session.new .recents {\\n flex: 100 100 0%;\\n display: flex;\\n flex-direction: column;\\n margin-top: 20px;\\n overflow-y: hidden;\\n}\\n\\n.session.new .recents .list {\\n padding: 3px 5px;\\n flex: 100 100 0%;\\n overflow-y: auto;\\n overflow-x: hidden;\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","import * as React from 'react';\r\n\r\nimport Loader from '@/components/semantic/Loader';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { useTranslation } from 'react-i18next';\r\nimport { getModuleT, translate } from '@/utils/TranslationUtils';\r\nimport { useParams } from 'react-router';\r\nimport { useSessionStoreProperty } from '@/context/SessionStoreContext';\r\n\r\nexport interface SessionProviderDecoratorProps {}\r\n\r\nexport interface SessionProviderDecoratorChildProps<SessionT extends UI.SessionItem> {\r\n items: SessionT[];\r\n sessionT: UI.ModuleTranslator;\r\n params: UI.RouteParams;\r\n}\r\n\r\nconst SessionProviderDecorator = <SessionT extends UI.SessionItem>(\r\n Component: React.ComponentType<SessionProviderDecoratorChildProps<SessionT>>,\r\n sessionStoreSelector: UI.SessionStoreSelector<SessionT>,\r\n moduleId: UI.Modules,\r\n) => {\r\n const Decorator = (props: SessionProviderDecoratorProps) => {\r\n const { t } = useTranslation();\r\n const sessionT = getModuleT(t, moduleId);\r\n const params = useParams();\r\n\r\n const sessions = useSessionStoreProperty(\r\n (state) => sessionStoreSelector(state).sessions,\r\n );\r\n if (!sessions) {\r\n return <Loader text={translate('Loading sessions', t, UI.Modules.COMMON)} />;\r\n }\r\n\r\n return <Component items={sessions} params={params} sessionT={sessionT} />;\r\n };\r\n\r\n return Decorator;\r\n};\r\n\r\nexport { SessionProviderDecorator };\r\n","import * as React from 'react';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { useSessionStoreProperty } from '@/context/SessionStoreContext';\r\nimport { useSocket } from '@/context/SocketContext';\r\nimport { useAppStoreApi } from '@/context/AppStoreContext';\r\nimport { LocalSettings } from '@/constants/LocalSettingConstants';\r\nimport { checkUnreadSessionInfo } from '@/utils/SessionUtils';\r\n\r\nexport const useActiveSession = (\r\n sessionItem: UI.SessionItem,\r\n actions: UI.SessionAPIActions<UI.SessionItem>,\r\n sessionStoreSelector: UI.SessionStoreSelector,\r\n useReadDelay = false,\r\n) => {\r\n const appStoreApi = useAppStoreApi();\r\n const socket = useSocket();\r\n const userActive = useSessionStoreProperty((state) => state.activity.userActive);\r\n const activeSessionStoreSetter = useSessionStoreProperty(\r\n (state) => sessionStoreSelector(state).setActiveSession,\r\n );\r\n\r\n const readTimeout = React.useRef<number | undefined>(undefined);\r\n\r\n const checkSetRead = (sessionItemRead: UI.SessionItem) => {\r\n checkUnreadSessionInfo(sessionItemRead, () => {\r\n actions.setRead(sessionItemRead, socket);\r\n });\r\n\r\n readTimeout.current = undefined;\r\n };\r\n\r\n const scheduleCheckSetRead = (sessionItemNew: UI.SessionItem) => {\r\n const timeout = !useReadDelay\r\n ? 0\r\n : appStoreApi\r\n .getState()\r\n .settings.getValue<number>(LocalSettings.UNREAD_LABEL_DELAY) * 1000;\r\n\r\n readTimeout.current = window.setTimeout(() => checkSetRead(sessionItemNew), timeout);\r\n };\r\n\r\n React.useEffect(() => {\r\n return () => {\r\n activeSessionStoreSetter(null);\r\n };\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n activeSessionStoreSetter(sessionItem);\r\n return () => {\r\n if (readTimeout.current) {\r\n // Set the previously active session as read\r\n clearTimeout(readTimeout.current);\r\n\r\n if (sessionItem) {\r\n checkSetRead(sessionItem);\r\n }\r\n }\r\n };\r\n }, [sessionItem.id]);\r\n\r\n React.useEffect(() => {\r\n if (userActive) {\r\n scheduleCheckSetRead(sessionItem);\r\n }\r\n }, [userActive, sessionItem.id]);\r\n};\r\n","import * as React from 'react';\r\nimport { usingMobileLayout } from '@/utils/BrowserUtils';\r\n\r\nimport ActionButton from '@/components/ActionButton';\r\nimport SectionedDropdown from '@/components/semantic/SectionedDropdown';\r\nimport MenuSection from '@/components/semantic/MenuSection';\r\nimport { MenuIcon } from '@/components/icon/MenuIcon';\r\n\r\nimport * as UI from '@/types/ui';\r\nimport { translate } from '@/utils/TranslationUtils';\r\nimport IconConstants from '@/constants/IconConstants';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { SessionMainLayoutProps } from './types';\r\nimport { useSessionStoreProperty } from '@/context/SessionStoreContext';\r\n\r\ntype SessionDropdownProps<SessionT extends UI.SessionItemBase> = Pick<\r\n SessionMainLayoutProps<SessionT>,\r\n 'sessionMenuItems' | 'newButton' | 'sessionStoreSelector' | 'listActionMenuGetter'\r\n>;\r\n\r\nconst SessionDropdown = <SessionT extends UI.SessionItemBase>({\r\n sessionMenuItems,\r\n newButton,\r\n sessionStoreSelector,\r\n listActionMenuGetter,\r\n}: SessionDropdownProps<SessionT>) => {\r\n const { t } = useTranslation();\r\n const getTotalUrgencies = useSessionStoreProperty(\r\n (state) => sessionStoreSelector(state).getTotalUrgencies,\r\n );\r\n return (\r\n <SectionedDropdown\r\n triggerIcon={<MenuIcon label=\"Session menu\" urgencies={getTotalUrgencies()} />}\r\n >\r\n <MenuSection caption={translate('New', t, UI.Modules.COMMON)}>\r\n {newButton}\r\n </MenuSection>\r\n <MenuSection caption={translate('Current sessions', t, UI.Modules.COMMON)}>\r\n {sessionMenuItems}\r\n </MenuSection>\r\n <MenuSection>{listActionMenuGetter()}</MenuSection>\r\n </SectionedDropdown>\r\n );\r\n};\r\n\r\ntype CloseButtonProps<\r\n SessionT extends UI.SessionItemBase,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n> = Pick<\r\n SessionMainLayoutProps<SessionT, UI.EmptyObject, UIActionsT>,\r\n 'actions' | 'activeItem'\r\n>;\r\n\r\nconst CloseButton = <\r\n SessionT extends UI.SessionItemBase,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n>({\r\n actions,\r\n activeItem,\r\n}: CloseButtonProps<SessionT, UIActionsT>) => {\r\n if (!activeItem || usingMobileLayout()) {\r\n return null;\r\n }\r\n\r\n /*const closeAction = Object.values(actions.actions).find(\r\n (action) => !!action && action.id === 'remove',\r\n ) as UI.ActionDefinition<UI.SessionItemBase>;*/\r\n\r\n const closeAction = Object.values(actions.actions)[\r\n Object.values(actions.actions).length - 1\r\n ];\r\n return (\r\n <ActionButton\r\n className=\"basic small item close-button\"\r\n action={closeAction as UI.ActionDefinition<UI.SessionItemBase>}\r\n moduleData={actions.moduleData}\r\n itemData={activeItem}\r\n icon={IconConstants.CLOSE}\r\n />\r\n );\r\n};\r\n\r\ntype SessionItemHeaderProps = Pick<\r\n SessionMainLayoutProps<any>,\r\n 'itemHeaderIcon' | 'itemHeaderTitle'\r\n>;\r\n\r\nconst SessionItemHeader: React.FC<SessionItemHeaderProps> = ({\r\n itemHeaderIcon,\r\n itemHeaderTitle,\r\n}) => (\r\n <div className=\"session-header\">\r\n {itemHeaderIcon}\r\n {itemHeaderTitle}\r\n </div>\r\n);\r\n\r\nconst TopMenuLayout = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n>({\r\n children,\r\n onKeyDown,\r\n ...props\r\n}: SessionMainLayoutProps<SessionT, SessionApiT, UIActionsT>) => (\r\n <div className=\"session-container vertical\" onKeyDown={onKeyDown} tabIndex={0}>\r\n <div className=\"ui main menu menu-bar\">\r\n <div className=\"content-left\">\r\n <SessionDropdown {...props} />\r\n <SessionItemHeader {...props} />\r\n </div>\r\n <CloseButton {...props} />\r\n </div>\r\n\r\n <div className=\"session-layout\">{children}</div>\r\n </div>\r\n);\r\n\r\nexport default TopMenuLayout;\r\n","import * as React from 'react';\r\n\r\nimport LayoutHeader from '@/components/semantic/LayoutHeader';\r\nimport { Grid } from '@/components/semantic/Grid';\r\n\r\nimport * as UI from '@/types/ui';\r\nimport { SessionMainLayoutProps } from './types';\r\n\r\nconst SideMenuLayout = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n>({\r\n sessionMenuItems,\r\n newButton,\r\n itemHeaderIcon,\r\n itemHeaderTitle,\r\n children,\r\n itemHeaderDescription,\r\n onKeyDown,\r\n}: SessionMainLayoutProps<SessionT, SessionApiT, UIActionsT>) => {\r\n if (newButton) {\r\n newButton = React.cloneElement(newButton, {\r\n className: newButton.props.className + ' ui fluid button',\r\n });\r\n }\r\n\r\n return (\r\n <Grid className=\"session-container horizontal\" onKeyDown={onKeyDown} tabIndex={0}>\r\n <div className=\"four wide column menu-column\">\r\n {newButton}\r\n {!!sessionMenuItems.length && (\r\n <div className=\"ui vertical secondary menu\" role=\"menubar\">\r\n {sessionMenuItems}\r\n </div>\r\n )}\r\n </div>\r\n <div className=\"twelve wide stretched column content-column session\">\r\n <div className=\"ui segment session-layout\">\r\n <LayoutHeader\r\n className=\"session-header\"\r\n icon={itemHeaderIcon}\r\n title={<div className=\"title\">{itemHeaderTitle}</div>}\r\n subHeader={itemHeaderDescription}\r\n />\r\n <div className=\"ui divider\" style={{ margin: '5px 0px 0px 0px' }} />\r\n {children}\r\n </div>\r\n </div>\r\n </Grid>\r\n );\r\n};\r\n\r\nexport default SideMenuLayout;\r\n","import invariant from 'invariant';\r\n\r\nimport * as API from '@/types/api';\r\n\r\nimport { useNavigate } from 'react-router';\r\nimport { SessionLocationState } from '../types';\r\n\r\ninterface SessionRouteHelperProps {\r\n baseUrl: string;\r\n}\r\n\r\nexport const useSessionRouteHelpers = ({ baseUrl }: SessionRouteHelperProps) => {\r\n const navigate = useNavigate();\r\n\r\n // HELPERS\r\n const getSessionUrl = (id: API.IdType) => {\r\n invariant(!!id, 'Trying to get session URL without a session');\r\n return `/${baseUrl}/session/${id}`;\r\n };\r\n\r\n const pushSession = (id: API.IdType) => {\r\n navigate(getSessionUrl(id));\r\n };\r\n\r\n const replaceSession = (id: API.IdType, state?: SessionLocationState) => {\r\n navigate(getSessionUrl(id), { replace: true, state });\r\n };\r\n\r\n const newUrl = `/${baseUrl}/new`;\r\n const replaceNew = () => {\r\n navigate(newUrl, { replace: true });\r\n };\r\n\r\n return {\r\n newUrl: `/${baseUrl}/new`,\r\n replaceNew,\r\n\r\n getSessionUrl,\r\n pushSession,\r\n replaceSession,\r\n };\r\n};\r\n","import * as React from 'react';\r\n\r\nimport { loadLocalProperty, saveLocalProperty } from '@/utils/BrowserUtils';\r\n\r\nimport * as API from '@/types/api';\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { useLocation } from 'react-router';\r\nimport { useSessionRouteHelpers } from './useSessionHelpers';\r\nimport { SessionLocationState } from '../types';\r\nimport { useSocket } from '@/context/SocketContext';\r\n\r\nconst findItem = <SessionT extends UI.SessionItemBase>(\r\n items: SessionT[],\r\n id: API.IdType | undefined,\r\n): SessionT | undefined => {\r\n return items.find((item) => item.id === id);\r\n};\r\n\r\nexport interface SessionManagerProps<\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object = UI.EmptyObject,\r\n> {\r\n // Item ID that is currently active (if any)\r\n activeId: API.IdType | undefined;\r\n\r\n // Array of the items to list\r\n items: SessionT[];\r\n\r\n baseUrl: string;\r\n\r\n sessionApi: UI.SessionAPIActions<SessionT> & SessionApiT;\r\n}\r\n\r\nexport const useSessionManager = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object = UI.EmptyObject,\r\n>(\r\n props: SessionManagerProps<SessionT, SessionApiT>,\r\n) => {\r\n const [activeItem, setActiveItem] = React.useState<SessionT | null>(null);\r\n const location = useLocation();\r\n const socket = useSocket();\r\n\r\n const { pushSession, replaceSession, newUrl, replaceNew } = useSessionRouteHelpers({\r\n baseUrl: props.baseUrl,\r\n });\r\n\r\n // HELPERS\r\n const getStorageKey = () => {\r\n return `${props.baseUrl}_last_active`;\r\n };\r\n\r\n // Common logic for selecting the item to display (after mounting or session updates)\r\n // Returns true active item selection was handled\r\n // Returns false if the active item couldn't be selected but there are valid items to choose from by the caller\r\n const checkActiveItem = () => {\r\n // Did we just create this session?\r\n const routerLocation = location;\r\n const pending =\r\n routerLocation.state && (routerLocation.state as SessionLocationState).pending;\r\n\r\n // Update the active item\r\n const activeItemNew = findItem(props.items, props.activeId);\r\n if (activeItemNew) {\r\n if (pending) {\r\n // Disable pending state\r\n replaceSession(activeItemNew.id, {\r\n pending: false,\r\n });\r\n\r\n return true;\r\n }\r\n\r\n setActiveItem(activeItemNew);\r\n saveLocalProperty(getStorageKey(), props.activeId);\r\n return true;\r\n } else if (pending) {\r\n // We'll just display a loading indicator in 'render', no item needed\r\n return true;\r\n } else if (/*routerLocation.action === 'POP' ||*/ props.items.length === 0) {\r\n // Browsing from history and item removed (or all items removed)... go to \"new session\" page\r\n replaceNew();\r\n setActiveItem(null);\r\n return true;\r\n }\r\n\r\n return false;\r\n };\r\n\r\n // LIFECYCLE/REACT\r\n // Set the session early so that we wont' flash the \"new session\" layout\r\n React.useLayoutEffect(() => {\r\n if (location.pathname === newUrl) {\r\n // Don't redirect to it if the \"new session\" layout is open\r\n if (activeItem) {\r\n setActiveItem(null);\r\n }\r\n return;\r\n }\r\n\r\n if (checkActiveItem()) {\r\n // We got an item\r\n return;\r\n }\r\n\r\n if (!activeItem) {\r\n const lastId = loadLocalProperty<API.IdType>(getStorageKey());\r\n if (lastId && findItem(props.items, lastId)) {\r\n // Previous session exists\r\n replaceSession(lastId);\r\n return;\r\n }\r\n }\r\n\r\n // The old tab was closed or we didn't have any session before\r\n\r\n const { items, activeId } = props;\r\n let newItemPos = 0;\r\n const oldItem = findItem(items, activeId);\r\n if (oldItem) {\r\n // Find the old position and use the item in that position (if possible)\r\n newItemPos = items.indexOf(oldItem);\r\n if (newItemPos === items.length - 1) {\r\n // The last item was removed\r\n newItemPos = newItemPos - 1;\r\n }\r\n }\r\n\r\n replaceSession(items[newItemPos].id);\r\n }, [location, props.items]);\r\n\r\n const onKeyDown = (event: React.KeyboardEvent) => {\r\n const { key, altKey } = event;\r\n\r\n if (altKey && (key === 'ArrowUp' || key === 'ArrowDown')) {\r\n // Arrow up/down\r\n event.preventDefault();\r\n\r\n const { items, activeId } = props;\r\n const item = findItem(items, activeId);\r\n if (!item) {\r\n return;\r\n }\r\n\r\n const currentIndex = items.indexOf(item);\r\n if (currentIndex === -1) {\r\n return;\r\n }\r\n\r\n const newSession = items[key === 'ArrowUp' ? currentIndex - 1 : currentIndex + 1];\r\n if (newSession) {\r\n pushSession(newSession.id);\r\n }\r\n } else if (altKey && key === 'Insert') {\r\n // Insert\r\n event.preventDefault();\r\n\r\n replaceNew();\r\n } else if (altKey && key === 'Delete') {\r\n // Delete\r\n event.preventDefault();\r\n\r\n const { items, activeId, sessionApi } = props;\r\n const item = findItem(items, activeId);\r\n if (!!item) {\r\n sessionApi.removeSession(item, socket);\r\n }\r\n }\r\n };\r\n\r\n return {\r\n onKeyDown,\r\n activeItem,\r\n };\r\n};\r\n","import * as React from 'react';\r\nimport classNames from 'classnames';\r\n\r\nimport IconConstants from '@/constants/IconConstants';\r\nimport RouterMenuItemLink from '@/components/semantic/RouterMenuItemLink';\r\n\r\ninterface SessionNewButtonProps {\r\n url: string;\r\n title: React.ReactNode;\r\n className?: string;\r\n}\r\n\r\nconst SessionNewButton: React.FC<SessionNewButtonProps> = ({\r\n url,\r\n title,\r\n // pushNew,\r\n className,\r\n}) => (\r\n <RouterMenuItemLink\r\n key=\"button-new\"\r\n className={classNames('new', className)}\r\n icon={IconConstants.CREATE}\r\n url={url}\r\n >\r\n {title}\r\n </RouterMenuItemLink>\r\n);\r\n\r\nexport default SessionNewButton;\r\n","import * as React from 'react';\r\n\r\nimport RouterMenuItemLink from '@/components/semantic/RouterMenuItemLink';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\ninterface SessionMenuItemProps {\r\n url: string;\r\n name: React.ReactNode;\r\n unreadInfoStoreSelector: UI.SessionStoreSelector;\r\n status: React.ReactElement<any>;\r\n sessionItem: UI.SessionItemBase;\r\n}\r\n\r\nconst SessionMenuItem: React.FC<SessionMenuItemProps> = ({\r\n sessionItem,\r\n status,\r\n name,\r\n unreadInfoStoreSelector,\r\n url,\r\n}) => (\r\n <RouterMenuItemLink\r\n url={url}\r\n className=\"session-item\"\r\n icon={status}\r\n sessionItem={sessionItem}\r\n unreadInfoStoreSelector={unreadInfoStoreSelector}\r\n >\r\n {name}\r\n </RouterMenuItemLink>\r\n);\r\n\r\nexport default SessionMenuItem;\r\n","\n import API from \"!../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../node_modules/css-loader/dist/cjs.js!./sessions.css\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\noptions.insert = insertFn.bind(null, \"head\");\noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../node_modules/css-loader/dist/cjs.js!./sessions.css\";\n export default content && content.locals ? content.locals : undefined;\n","import * as React from 'react';\r\n\r\nimport Loader from '@/components/semantic/Loader';\r\n\r\nimport TopMenuLayout from './TopMenuLayout';\r\nimport SideMenuLayout from './SideMenuLayout';\r\n\r\nimport Message from '@/components/semantic/Message';\r\n\r\nimport { usingMobileLayout } from '@/utils/BrowserUtils';\r\n\r\nimport * as API from '@/types/api';\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { translate, toI18nKey } from '@/utils/TranslationUtils';\r\nimport { useLayoutWidth } from '@/context/LayoutWidthContext';\r\nimport { useSessionManager } from './effects/useSessionManager';\r\nimport { useLocation, useNavigate } from 'react-router';\r\n\r\nimport {\r\n NewSessionLayoutProps,\r\n SessionChildProps,\r\n SessionLayoutLabels,\r\n SessionLayoutManageProps,\r\n SessionLocationState,\r\n} from './types';\r\nimport { useComponents } from './SessionMenuComponents';\r\nimport { useSession } from '@/context/AppStoreContext';\r\n\r\nimport '../sessions.css';\r\nimport { hasAccess } from '@/utils/AuthUtils';\r\n\r\nexport interface SessionLayoutProps<\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object = UI.EmptyObject,\r\n UIActionT extends UI.ActionListType<UI.SessionItemBase> = UI.EmptyObject,\r\n> extends UI.SessionInfoGetter<SessionT>,\r\n SessionLayoutLabels,\r\n SessionLayoutManageProps<SessionT, SessionApiT, UIActionT> {\r\n // Item ID that is currently active (if any)\r\n activeId: API.IdType | undefined;\r\n\r\n // Set to false if the side menu should never be shown (the session will use all width that is available)\r\n disableSideMenu?: boolean;\r\n\r\n sessionItemLayout: React.ComponentType<\r\n SessionChildProps<SessionT, SessionApiT, UIActionT>\r\n >;\r\n\r\n newLayout?: React.ComponentType<NewSessionLayoutProps>;\r\n\r\n sessionT: UI.ModuleTranslator;\r\n}\r\n\r\nconst SessionLayout = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object,\r\n UIActionsT extends UI.ActionListType<UI.SessionItemBase>,\r\n>(\r\n props: SessionLayoutProps<SessionT, SessionApiT, UIActionsT>,\r\n) => {\r\n const session = useSession();\r\n const layoutWidth = useLayoutWidth();\r\n const navigate = useNavigate();\r\n const location = useLocation();\r\n\r\n const { activeItem, onKeyDown } = useSessionManager(props);\r\n\r\n const hasEditAccess = hasAccess(session, props.editAccess);\r\n const isNewLayout = !!props.newLayout && location.pathname.endsWith('/new');\r\n\r\n const getSessionChildren = () => {\r\n const {\r\n activeId,\r\n items,\r\n sessionItemLayout: SessionItemLayout,\r\n sessionApi,\r\n uiActions,\r\n sessionT,\r\n baseUrl,\r\n } = props;\r\n\r\n if (!activeItem) {\r\n const { state } = location;\r\n if (!!state && (state as SessionLocationState).pending) {\r\n // The session was just created\r\n return (\r\n <Loader\r\n text={translate(\r\n 'Waiting for server response',\r\n sessionT.plainT,\r\n UI.Modules.COMMON,\r\n )}\r\n />\r\n );\r\n } else if (activeId || items.length !== 0) {\r\n // Redirecting to a new page\r\n return (\r\n <Loader\r\n text={translate('Loading session', sessionT.plainT, UI.Modules.COMMON)}\r\n />\r\n );\r\n }\r\n\r\n console.error('SessionLayout route: active session missing');\r\n return;\r\n }\r\n\r\n // We have a session\r\n return (\r\n <SessionItemLayout\r\n sessionItem={activeItem}\r\n sessionApi={sessionApi}\r\n uiActions={uiActions}\r\n location={location}\r\n navigate={navigate}\r\n sessionT={sessionT}\r\n baseUrl={baseUrl}\r\n />\r\n );\r\n };\r\n\r\n const getChildren = () => {\r\n const { newLayout: NewLayout, sessionT } = props;\r\n if (isNewLayout && NewLayout) {\r\n return <NewLayout navigate={navigate} location={location} sessionT={sessionT} />;\r\n }\r\n\r\n return getSessionChildren();\r\n };\r\n\r\n const { disableSideMenu, items, sessionStoreSelector, sessionT, uiActions } = props;\r\n\r\n const useTopMenu = disableSideMenu || usingMobileLayout(layoutWidth);\r\n\r\n const {\r\n getItemHeaderTitle,\r\n getItemHeaderDescription,\r\n getItemHeaderIcon,\r\n getNewButton,\r\n getSessionMenuItems,\r\n getSessionActionMenuItems,\r\n } = useComponents({ ...props, activeItem, hasEditAccess, isNewLayout });\r\n\r\n if (!hasEditAccess && items.length === 0) {\r\n // Nothing to show\r\n return (\r\n <Message\r\n title={translate('No items to show', sessionT.plainT, UI.Modules.COMMON)}\r\n description={sessionT.plainT(\r\n toI18nKey('noSessionEditAccess', UI.Modules.COMMON),\r\n `You aren't allowed to open new sessions`,\r\n )}\r\n />\r\n );\r\n }\r\n\r\n const MenuLayout = useTopMenu ? TopMenuLayout : SideMenuLayout;\r\n return (\r\n <MenuLayout\r\n itemHeaderTitle={getItemHeaderTitle()}\r\n itemHeaderDescription={getItemHeaderDescription()}\r\n itemHeaderIcon={getItemHeaderIcon()}\r\n newButton={getNewButton()}\r\n sessionMenuItems={getSessionMenuItems()}\r\n listActionMenuGetter={getSessionActionMenuItems}\r\n activeItem={activeItem}\r\n sessionStoreSelector={sessionStoreSelector}\r\n onKeyDown={onKeyDown}\r\n actions={uiActions}\r\n >\r\n {getChildren()}\r\n </MenuLayout>\r\n );\r\n};\r\n\r\nexport default SessionLayout;\r\n","import { ActionMenu } from '@/components/action-menu';\r\nimport SessionNewButton from './SessionNewButton';\r\nimport SessionMenuItem from './SessionMenuItem';\r\n\r\nimport Icon from '@/components/semantic/Icon';\r\n\r\nimport IconConstants from '@/constants/IconConstants';\r\nimport MenuItemLink from '@/components/semantic/MenuItemLink';\r\n\r\nimport * as UI from '@/types/ui';\r\n\r\nimport { translate } from '@/utils/TranslationUtils';\r\nimport { SessionLayoutLabels, SessionLayoutManageProps } from './types';\r\nimport { useLocation } from 'react-router';\r\nimport { useSessionRouteHelpers } from './effects/useSessionHelpers';\r\nimport { useTranslation } from 'react-i18next';\r\nimport { useSocket } from '@/context/SocketContext';\r\n\r\nexport const useComponents = <\r\n SessionT extends UI.SessionItemBase,\r\n SessionApiT extends object = UI.EmptyObject,\r\n UIActionT extends UI.ActionListType<UI.SessionItemBase> = UI.EmptyObject,\r\n>(\r\n props: UI.SessionInfoGetter<SessionT> & {\r\n activeItem: SessionT | null;\r\n hasEditAccess: boolean;\r\n isNewLayout: boolean;\r\n } & SessionLayoutLabels &\r\n SessionLayoutManageProps<SessionT, SessionApiT, UIActionT>,\r\n) => {\r\n const socket = useSocket();\r\n const location = useLocation();\r\n const { t } = useTranslation();\r\n const { newUrl, getSessionUrl } = useSessionRouteHelpers({\r\n baseUrl: props.baseUrl,\r\n });\r\n\r\n // COMPONENT GETTERS\r\n const getItemStatus = (sessionItem: SessionT) => {\r\n const { itemStatusGetter, itemHeaderIconGetter } = props;\r\n if (itemStatusGetter) {\r\n return (\r\n <div\r\n className={\r\n 'ui session-status empty circular left mini label ' +\r\n itemStatusGetter(sessionItem)\r\n }\r\n />\r\n );\r\n }\r\n\r\n return <Icon icon={itemHeaderIconGetter(sessionItem)} />;\r\n };\r\n\r\n const components = {\r\n // Current session\r\n getItemHeaderDescription: () => {\r\n const { itemHeaderDescriptionGetter, newDescription, activeItem, isNewLayout } =\r\n props;\r\n if (isNewLayout) {\r\n return newDescription;\r\n }\r\n\r\n if (activeItem) {\r\n return itemHeaderDescriptionGetter(activeItem);\r\n }\r\n\r\n return null;\r\n },\r\n getItemHeaderIcon: () => {\r\n const { itemHeaderIconGetter, newIcon, activeItem, isNewLayout } = props;\r\n if (isNewLayout) {\r\n return <Icon icon={newIcon} />;\r\n }\r\n\r\n if (activeItem) {\r\n return <Icon icon={itemHeaderIconGetter(activeItem)} />;\r\n }\r\n\r\n return null;\r\n },\r\n getItemHeaderTitle: () => {\r\n const { activeItem, newCaption, remoteMenuId, isNewLayout } = props;\r\n if (isNewLayout) {\r\n return <div>{newCaption}</div>;\r\n }\r\n\r\n if (!activeItem) {\r\n return null;\r\n }\r\n\r\n const { uiActions, actionIds, itemNameGetter, itemHeaderTitleGetter } = props;\r\n\r\n const ids = actionIds ? [...actionIds, 'divider', 'remove'] : undefined;\r\n const actionMenu = (\r\n <ActionMenu\r\n caption={itemNameGetter(activeItem)}\r\n actions={uiActions}\r\n itemData={activeItem}\r\n ids={ids}\r\n remoteMenuId={remoteMenuId}\r\n />\r\n );\r\n\r\n // Use the header getter only if there is a getter that returns a valid value\r\n if (itemHeaderTitleGetter) {\r\n const header = itemHeaderTitleGetter(activeItem, location, actionMenu);\r\n if (header) {\r\n return header;\r\n }\r\n }\r\n\r\n return actionMenu;\r\n },\r\n\r\n // Other\r\n getSessionActionMenuItems: () => {\r\n const { items, hasEditAccess } = props;\r\n if (!hasEditAccess || items.length === 0) {\r\n return null;\r\n }\r\n\r\n const handleCloseAll = () => {\r\n const { sessionApi, items } = props;\r\n items.forEach((session) => sessionApi.removeSession(session, socket));\r\n };\r\n\r\n return (\r\n <MenuItemLink key=\"close\" onClick={handleCloseAll} icon={IconConstants.REMOVE}>\r\n {translate('Close all', t, UI.Modules.COMMON)}\r\n </MenuItemLink>\r\n );\r\n },\r\n getNewButton: () => {\r\n const { newCaption, hasEditAccess } = props;\r\n if (!hasEditAccess || !newCaption) {\r\n return null;\r\n }\r\n\r\n return <SessionNewButton key=\"new-button\" title={newCaption} url={newUrl} />;\r\n },\r\n getSessionMenuItems: () => {\r\n const getSessionMenuItem = (sessionItem: SessionT) => {\r\n const { itemNameGetter, sessionStoreSelector } = props;\r\n return (\r\n <SessionMenuItem\r\n key={sessionItem.id}\r\n url={getSessionUrl(sessionItem.id)}\r\n name={itemNameGetter(sessionItem)}\r\n unreadInfoStoreSelector={sessionStoreSelector}\r\n status={getItemStatus(sessionItem)}\r\n sessionItem={sessionItem}\r\n />\r\n );\r\n };\r\n\r\n return props.items.map(getSessionMenuItem);\r\n },\r\n };\r\n\r\n return components;\r\n};\r\n"],"names":["BuildRemoveSessionAction","sessionsUrl","editAccess","id","displayName","access","icon","REMOVE","handler","itemData","session","socket","delete","FooterItem","label","text","className","SessionFooter","children","___CSS_LOADER_EXPORT___","push","module","SessionProviderDecorator","Component","sessionStoreSelector","moduleId","props","t","sessionT","params","sessions","state","items","COMMON","useActiveSession","sessionItem","actions","useReadDelay","appStoreApi","userActive","activity","activeSessionStoreSetter","setActiveSession","readTimeout","undefined","checkSetRead","sessionItemRead","setRead","current","clearTimeout","sessionItemNew","timeout","getState","settings","getValue","UNREAD_LABEL_DELAY","window","setTimeout","scheduleCheckSetRead","SessionDropdown","sessionMenuItems","newButton","listActionMenuGetter","getTotalUrgencies","SectionedDropdown","triggerIcon","MenuIcon","urgencies","MenuSection","caption","CloseButton","activeItem","closeAction","Object","values","length","ActionButton","A","action","moduleData","IconConstants","CLOSE","SessionItemHeader","itemHeaderIcon","itemHeaderTitle","onKeyDown","tabIndex","itemHeaderDescription","Grid","role","LayoutHeader","title","subHeader","style","margin","useSessionRouteHelpers","baseUrl","navigate","getSessionUrl","newUrl","replaceNew","replace","pushSession","replaceSession","findItem","find","item","url","RouterMenuItemLink","CREATE","status","name","unreadInfoStoreSelector","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","locals","layoutWidth","location","setActiveItem","getStorageKey","pathname","routerLocation","pending","activeItemNew","activeId","checkActiveItem","lastId","newItemPos","oldItem","indexOf","event","key","altKey","preventDefault","sessionApi","removeSession","currentIndex","newSession","useSessionManager","hasEditAccess","isNewLayout","newLayout","endsWith","disableSideMenu","uiActions","useTopMenu","getItemHeaderTitle","getItemHeaderDescription","getItemHeaderIcon","getNewButton","getSessionMenuItems","getSessionActionMenuItems","getItemStatus","itemStatusGetter","itemHeaderIconGetter","Icon","itemHeaderDescriptionGetter","newDescription","newIcon","newCaption","remoteMenuId","actionIds","itemNameGetter","itemHeaderTitleGetter","ids","actionMenu","header","MenuItemLink","onClick","forEach","map","useComponents","Message","plainT","description","MenuLayout","NewLayout","sessionItemLayout","SessionItemLayout","Loader","console","error","getSessionChildren","getChildren"],"sourceRoot":""}