UNPKG

@yuebai008/cli

Version:

Command line interface for rapid qg-minigame development

1 lines 14.3 kB
import*as Platform from"../../core/platform/platform.js";import*as Components from"../../ui/legacy/components/utils/utils.js";import*as UI from"../../ui/legacy/legacy.js";export class ConsoleViewport{element;topGapElement;topGapElementActive;contentElementInternal;bottomGapElement;bottomGapElementActive;provider;virtualSelectedIndex;firstActiveIndex;lastActiveIndex;renderedItems;anchorSelection;headSelection;itemCount;cumulativeHeights;muteCopyHandler;observer;observerConfig;stickToBottomInternal;selectionIsBackward;lastSelectedElement;cachedProviderElements;constructor(e){this.element=document.createElement("div"),this.element.style.overflow="auto",this.topGapElement=this.element.createChild("div"),this.topGapElement.style.height="0px",this.topGapElement.style.color="transparent",this.topGapElementActive=!1,this.contentElementInternal=this.element.createChild("div"),this.bottomGapElement=this.element.createChild("div"),this.bottomGapElement.style.height="0px",this.bottomGapElement.style.color="transparent",this.bottomGapElementActive=!1,this.topGapElement.textContent="\ufeff",this.bottomGapElement.textContent="\ufeff",UI.ARIAUtils.markAsHidden(this.topGapElement),UI.ARIAUtils.markAsHidden(this.bottomGapElement),this.provider=e,this.element.addEventListener("scroll",this.onScroll.bind(this),!1),this.element.addEventListener("copy",this.onCopy.bind(this),!1),this.element.addEventListener("dragstart",this.onDragStart.bind(this),!1),this.contentElementInternal.addEventListener("focusin",this.onFocusIn.bind(this),!1),this.contentElementInternal.addEventListener("focusout",this.onFocusOut.bind(this),!1),this.contentElementInternal.addEventListener("keydown",this.onKeyDown.bind(this),!1),this.virtualSelectedIndex=-1,this.contentElementInternal.tabIndex=-1,this.firstActiveIndex=-1,this.lastActiveIndex=-1,this.renderedItems=[],this.anchorSelection=null,this.headSelection=null,this.itemCount=0,this.cumulativeHeights=new Int32Array(0),this.muteCopyHandler=!1,this.observer=new MutationObserver(this.refresh.bind(this)),this.observerConfig={childList:!0,subtree:!0},this.stickToBottomInternal=!1,this.selectionIsBackward=!1}stickToBottom(){return this.stickToBottomInternal}setStickToBottom(e){this.stickToBottomInternal=e,this.stickToBottomInternal?this.observer.observe(this.contentElementInternal,this.observerConfig):this.observer.disconnect()}hasVirtualSelection(){return-1!==this.virtualSelectedIndex}copyWithStyles(){this.muteCopyHandler=!0,this.element.ownerDocument.execCommand("copy"),this.muteCopyHandler=!1}onCopy(e){if(this.muteCopyHandler)return;const t=this.selectedText();t&&(e.preventDefault(),this.selectionContainsTable()?this.copyWithStyles():e.clipboardData&&e.clipboardData.setData("text/plain",t))}onFocusIn(e){const t=this.renderedItems.findIndex((t=>t.element().isSelfOrAncestor(e.target)));-1!==t&&(this.virtualSelectedIndex=this.firstActiveIndex+t);let i=!1;-1===this.virtualSelectedIndex&&this.isOutsideViewport(e.relatedTarget)&&e.target===this.contentElementInternal&&this.itemCount&&(i=!0,this.virtualSelectedIndex=this.itemCount-1,this.refresh(),this.scrollItemIntoView(this.virtualSelectedIndex)),this.updateFocusedItem(i)}onFocusOut(e){this.isOutsideViewport(e.relatedTarget)&&(this.virtualSelectedIndex=-1),this.updateFocusedItem()}isOutsideViewport(e){return null!==e&&!e.isSelfOrDescendant(this.contentElementInternal)}onDragStart(e){const t=this.selectedText();return!!t&&(e.dataTransfer&&(e.dataTransfer.clearData(),e.dataTransfer.setData("text/plain",t),e.dataTransfer.effectAllowed="copy"),!0)}onKeyDown(e){if(UI.UIUtils.isEditing()||!this.itemCount||e.shiftKey)return;let t=!1;switch(e.key){case"ArrowUp":if(!(this.virtualSelectedIndex>0))return;t=!0,this.virtualSelectedIndex--;break;case"ArrowDown":if(!(this.virtualSelectedIndex<this.itemCount-1))return;this.virtualSelectedIndex++;break;case"Home":this.virtualSelectedIndex=0;break;case"End":this.virtualSelectedIndex=this.itemCount-1;break;default:return}e.consume(!0),this.scrollItemIntoView(this.virtualSelectedIndex),this.updateFocusedItem(t)}updateFocusedItem(e){const t=this.renderedElementAt(this.virtualSelectedIndex),i=this.lastSelectedElement!==t,s=this.contentElementInternal===Platform.DOMUtilities.deepActiveElement(this.element.ownerDocument);this.lastSelectedElement&&i&&this.lastSelectedElement.classList.remove("console-selected"),t&&(e||i||s)&&this.element.hasFocus()&&(t.classList.add("console-selected"),e?(this.setStickToBottom(!1),this.renderedItems[this.virtualSelectedIndex-this.firstActiveIndex].focusLastChildOrSelf()):t.hasFocus()||t.focus({preventScroll:!0})),this.itemCount&&!this.contentElementInternal.hasFocus()?this.contentElementInternal.tabIndex=0:this.contentElementInternal.tabIndex=-1,this.lastSelectedElement=t}contentElement(){return this.contentElementInternal}invalidate(){delete this.cachedProviderElements,this.itemCount=this.provider.itemCount(),this.virtualSelectedIndex>this.itemCount-1&&(this.virtualSelectedIndex=this.itemCount-1),this.rebuildCumulativeHeights(),this.refresh()}providerElement(e){this.cachedProviderElements||(this.cachedProviderElements=new Array(this.itemCount));let t=this.cachedProviderElements[e];return t||(t=this.provider.itemElement(e),this.cachedProviderElements[e]=t),t}rebuildCumulativeHeights(){const e=this.firstActiveIndex,t=this.lastActiveIndex;let i=0;this.cumulativeHeights=new Int32Array(this.itemCount);for(let s=0;s<this.itemCount;++s)e<=s&&s-e<this.renderedItems.length&&s<=t?i+=this.renderedItems[s-e].element().offsetHeight:i+=this.provider.fastHeight(s),this.cumulativeHeights[s]=i}rebuildCumulativeHeightsIfNeeded(){let e=0,t=0;for(let i=0;i<this.renderedItems.length;++i){const s=this.cachedItemHeight(this.firstActiveIndex+i),n=this.renderedItems[i].element().offsetHeight;if(Math.abs(s-n)>1)return void this.rebuildCumulativeHeights();if(t+=n,e+=s,Math.abs(e-t)>1)return void this.rebuildCumulativeHeights()}}cachedItemHeight(e){return 0===e?this.cumulativeHeights[0]:this.cumulativeHeights[e]-this.cumulativeHeights[e-1]}isSelectionBackwards(e){if(!(e&&e.rangeCount&&e.anchorNode&&e.focusNode))return!1;const t=document.createRange();return t.setStart(e.anchorNode,e.anchorOffset),t.setEnd(e.focusNode,e.focusOffset),t.collapsed}createSelectionModel(e,t,i){return{item:e,node:t,offset:i}}updateSelectionModel(e){const t=e&&e.rangeCount?e.getRangeAt(0):null;if(!t||!e||e.isCollapsed||!this.element.hasSelection())return this.headSelection=null,this.anchorSelection=null,!1;let i=Number.MAX_VALUE,s=-1,n=!1;for(let e=0;e<this.renderedItems.length;++e)if(t.intersectsNode(this.renderedItems[e].element())){const t=e+this.firstActiveIndex;i=Math.min(i,t),s=Math.max(s,t),n=!0}const o=t.intersectsNode(this.topGapElement)&&this.topGapElementActive,l=t.intersectsNode(this.bottomGapElement)&&this.bottomGapElementActive;if(!o&&!l&&!n)return this.headSelection=null,this.anchorSelection=null,!1;this.anchorSelection&&this.headSelection||(this.anchorSelection=this.createSelectionModel(0,this.element,0),this.headSelection=this.createSelectionModel(this.itemCount-1,this.element,this.element.children.length),this.selectionIsBackward=!1);const r=this.isSelectionBackwards(e),h=this.selectionIsBackward?this.headSelection:this.anchorSelection,a=this.selectionIsBackward?this.anchorSelection:this.headSelection;let c=null,d=null;return n&&(c=this.createSelectionModel(i,t.startContainer,t.startOffset),d=this.createSelectionModel(s,t.endContainer,t.endOffset)),o&&l&&n?(c=c&&c.item<h.item?c:h,d=d&&d.item>a.item?d:a):n?o?c=r?this.headSelection:this.anchorSelection:l&&(d=r?this.anchorSelection:this.headSelection):(c=h,d=a),r?(this.anchorSelection=d,this.headSelection=c):(this.anchorSelection=c,this.headSelection=d),this.selectionIsBackward=r,!0}restoreSelection(e){if(!e||!this.anchorSelection||!this.headSelection)return;const t=(e,t)=>{if(this.firstActiveIndex<=e.item&&e.item<=this.lastActiveIndex)return{element:e.node,offset:e.offset};return{element:e.item<this.firstActiveIndex?this.topGapElement:this.bottomGapElement,offset:t?1:0}},{element:i,offset:s}=t(this.anchorSelection,Boolean(this.selectionIsBackward)),{element:n,offset:o}=t(this.headSelection,!this.selectionIsBackward);e.setBaseAndExtent(i,s,n,o)}selectionContainsTable(){if(!this.anchorSelection||!this.headSelection)return!1;const e=this.selectionIsBackward?this.headSelection.item:this.anchorSelection.item,t=this.selectionIsBackward?this.anchorSelection.item:this.headSelection.item;for(let i=e;i<=t;i++){const e=this.providerElement(i);if(e&&"table"===e.consoleMessage().type)return!0}return!1}refresh(){this.observer.disconnect(),this.innerRefresh(),this.stickToBottomInternal&&this.observer.observe(this.contentElementInternal,this.observerConfig)}innerRefresh(){if(!this.visibleHeight())return;if(!this.itemCount){for(let e=0;e<this.renderedItems.length;++e)this.renderedItems[e].willHide();return this.renderedItems=[],this.contentElementInternal.removeChildren(),this.topGapElement.style.height="0px",this.bottomGapElement.style.height="0px",this.firstActiveIndex=-1,this.lastActiveIndex=-1,void this.updateFocusedItem()}const e=this.element.getComponentSelection(),t=this.updateSelectionModel(e),i=this.element.scrollTop,s=this.visibleHeight(),n=2*s;this.rebuildCumulativeHeightsIfNeeded(),this.stickToBottomInternal?(this.firstActiveIndex=Math.max(this.itemCount-Math.ceil(n/this.provider.minimumRowHeight()),0),this.lastActiveIndex=this.itemCount-1):(this.firstActiveIndex=Math.max(Platform.ArrayUtilities.lowerBound(this.cumulativeHeights,i+1-(n-s)/2,Platform.ArrayUtilities.DEFAULT_COMPARATOR),0),this.lastActiveIndex=this.firstActiveIndex+Math.ceil(n/this.provider.minimumRowHeight())-1,this.lastActiveIndex=Math.min(this.lastActiveIndex,this.itemCount-1));const o=this.cumulativeHeights[this.firstActiveIndex-1]||0,l=this.cumulativeHeights[this.cumulativeHeights.length-1]-this.cumulativeHeights[this.lastActiveIndex];this.partialViewportUpdate(function(){this.topGapElement.style.height=o+"px",this.bottomGapElement.style.height=l+"px",this.topGapElementActive=Boolean(o),this.bottomGapElementActive=Boolean(l),this.contentElementInternal.style.setProperty("height","10000000px")}.bind(this)),this.contentElementInternal.style.removeProperty("height"),t&&this.restoreSelection(e),this.stickToBottomInternal&&(this.element.scrollTop=1e7)}partialViewportUpdate(e){const t=new Set;for(let e=this.firstActiveIndex;e<=this.lastActiveIndex;++e){const i=this.providerElement(e);console.assert(Boolean(i),"Expected provider element to be defined"),i&&t.add(i)}const i=this.renderedItems.filter((e=>!t.has(e)));for(let e=0;e<i.length;++e)i[e].willHide();e();let s=!1;for(let e=0;e<i.length;++e)s=s||i[e].element().hasFocus(),i[e].element().remove();const n=[];let o=this.contentElementInternal.firstChild;for(const e of t){const t=e.element();if(t!==o){!t.parentElement&&n.push(e),this.contentElementInternal.insertBefore(t,o)}else o=o.nextSibling}for(let e=0;e<n.length;++e)n[e].wasShown();this.renderedItems=Array.from(t),s&&this.contentElementInternal.focus(),this.updateFocusedItem()}selectedText(){if(this.updateSelectionModel(this.element.getComponentSelection()),!this.headSelection||!this.anchorSelection)return null;let e=null,t=null;this.selectionIsBackward?(e=this.headSelection,t=this.anchorSelection):(e=this.anchorSelection,t=this.headSelection);const i=[];for(let s=e.item;s<=t.item;++s){const e=this.providerElement(s);if(console.assert(Boolean(e)),!e)continue;const t=e.element().childTextNodes().map(Components.Linkifier.Linkifier.untruncatedNodeText).join("");i.push(t)}const s=this.providerElement(t.item),n=s&&s.element();if(n&&t.node&&t.node.isSelfOrDescendant(n)){const e=this.textOffsetInNode(n,t.node,t.offset);i.length>0&&(i[i.length-1]=i[i.length-1].substring(0,e))}const o=this.providerElement(e.item),l=o&&o.element();if(l&&e.node&&e.node.isSelfOrDescendant(l)){const t=this.textOffsetInNode(l,e.node,e.offset);i[0]=i[0].substring(t)}return i.join("\n")}textOffsetInNode(e,t,i){const s=t.textContent?t.textContent.length:0;t.nodeType!==Node.TEXT_NODE&&(i<t.childNodes.length?(t=t.childNodes.item(i),i=0):i=s);let n=0,o=e;for(;(o=o.traverseNextNode(e))&&o!==t;)o.nodeType!==Node.TEXT_NODE||o.parentNode&&("STYLE"===o.parentNode.nodeName||"SCRIPT"===o.parentNode.nodeName||"#document-fragment"===o.parentNode.nodeName)||(n+=Components.Linkifier.Linkifier.untruncatedNodeText(o).length);const l=Components.Linkifier.Linkifier.untruncatedNodeText(t).length;return i>0&&l!==s&&(i=l),n+i}onScroll(e){this.refresh()}firstVisibleIndex(){return this.cumulativeHeights.length?(this.rebuildCumulativeHeightsIfNeeded(),Platform.ArrayUtilities.lowerBound(this.cumulativeHeights,this.element.scrollTop+1,Platform.ArrayUtilities.DEFAULT_COMPARATOR)):-1}lastVisibleIndex(){if(!this.cumulativeHeights.length)return-1;this.rebuildCumulativeHeightsIfNeeded();const e=this.element.scrollTop+this.element.clientHeight,t=this.itemCount-1;return Platform.ArrayUtilities.lowerBound(this.cumulativeHeights,e,Platform.ArrayUtilities.DEFAULT_COMPARATOR,void 0,t)}renderedElementAt(e){return-1===e||e<this.firstActiveIndex||e>this.lastActiveIndex?null:this.renderedItems[e-this.firstActiveIndex].element()}scrollItemIntoView(e,t){const i=this.firstVisibleIndex(),s=this.lastVisibleIndex();e>i&&e<s||e===s&&this.cumulativeHeights[e]<=this.element.scrollTop+this.visibleHeight()||(t?this.forceScrollItemToBeLast(e):e<=i?this.forceScrollItemToBeFirst(e):e>=s&&this.forceScrollItemToBeLast(e))}forceScrollItemToBeFirst(e){console.assert(e>=0&&e<this.itemCount,"Cannot scroll item at invalid index"),this.setStickToBottom(!1),this.rebuildCumulativeHeightsIfNeeded(),this.element.scrollTop=e>0?this.cumulativeHeights[e-1]:0,UI.UIUtils.isScrolledToBottom(this.element)&&this.setStickToBottom(!0),this.refresh();const t=this.renderedElementAt(e);t&&t.scrollIntoView(!0)}forceScrollItemToBeLast(e){console.assert(e>=0&&e<this.itemCount,"Cannot scroll item at invalid index"),this.setStickToBottom(!1),this.rebuildCumulativeHeightsIfNeeded(),this.element.scrollTop=this.cumulativeHeights[e]-this.visibleHeight(),UI.UIUtils.isScrolledToBottom(this.element)&&this.setStickToBottom(!0),this.refresh();const t=this.renderedElementAt(e);t&&t.scrollIntoView(!1)}visibleHeight(){return this.element.offsetHeight}}