UNPKG

@yuebai008/cli

Version:

Command line interface for rapid qg-minigame development

1 lines 13.2 kB
import*as Common from"../../core/common/common.js";import networkWaterfallColumnStyles from"./networkWaterfallColumn.css.js";import*as PerfUI from"../../ui/legacy/components/perf_ui/perf_ui.js";import*as Coordinator from"../../ui/components/render_coordinator/render_coordinator.js";import*as UI from"../../ui/legacy/legacy.js";import*as ThemeSupport from"../../ui/legacy/theme_support/theme_support.js";import{RequestTimeRangeNameToColor}from"./NetworkOverview.js";import{RequestTimeRangeNames,RequestTimingView}from"./RequestTimingView.js";import networkingTimingTableStyles from"./networkTimingTable.css.js";const BAR_SPACING=1,coordinator=Coordinator.RenderCoordinator.RenderCoordinator.instance();export class NetworkWaterfallColumn extends UI.Widget.VBox{canvas;canvasPosition;leftPadding;fontSize;rightPadding;scrollTop;headerHeight;calculator;rawRowHeight;rowHeight;offsetWidth;offsetHeight;startTime;endTime;popoverHelper;nodes;hoveredNode;eventDividers;styleForTimeRangeName;styleForWaitingResourceType;styleForDownloadingResourceType;wiskerStyle;hoverDetailsStyle;pathForStyle;textLayers;constructor(e){super(!1),this.canvas=this.contentElement.createChild("canvas"),this.canvas.tabIndex=-1,this.setDefaultFocusedElement(this.canvas),this.canvasPosition=this.canvas.getBoundingClientRect(),this.leftPadding=5,this.fontSize=10,this.rightPadding=0,this.scrollTop=0,this.headerHeight=0,this.calculator=e,this.rawRowHeight=0,this.rowHeight=0,this.offsetWidth=0,this.offsetHeight=0,this.startTime=this.calculator.minimumBoundary(),this.endTime=this.calculator.maximumBoundary(),this.popoverHelper=new UI.PopoverHelper.PopoverHelper(this.element,this.getPopoverRequest.bind(this)),this.popoverHelper.setHasPadding(!0),this.popoverHelper.setTimeout(300,300),this.nodes=[],this.hoveredNode=null,this.eventDividers=new Map,this.element.addEventListener("mousemove",this.onMouseMove.bind(this),!0),this.element.addEventListener("mouseleave",(e=>this.setHoveredNode(null,!1)),!0),this.element.addEventListener("click",this.onClick.bind(this),!0),this.styleForTimeRangeName=NetworkWaterfallColumn.buildRequestTimeRangeStyle();const t=NetworkWaterfallColumn.buildResourceTypeStyle();this.styleForWaitingResourceType=t[0],this.styleForDownloadingResourceType=t[1];const i=ThemeSupport.ThemeSupport.instance().getComputedValue("--color-text-disabled");this.wiskerStyle={borderColor:i,lineWidth:1,fillStyle:void 0},this.hoverDetailsStyle={fillStyle:i,lineWidth:1,borderColor:i},this.pathForStyle=new Map,this.textLayers=[]}static buildRequestTimeRangeStyle(){const e=RequestTimeRangeNames,t=new Map;return t.set(e.Connecting,{fillStyle:RequestTimeRangeNameToColor[e.Connecting]}),t.set(e.SSL,{fillStyle:RequestTimeRangeNameToColor[e.SSL]}),t.set(e.DNS,{fillStyle:RequestTimeRangeNameToColor[e.DNS]}),t.set(e.Proxy,{fillStyle:RequestTimeRangeNameToColor[e.Proxy]}),t.set(e.Blocking,{fillStyle:RequestTimeRangeNameToColor[e.Blocking]}),t.set(e.Push,{fillStyle:RequestTimeRangeNameToColor[e.Push]}),t.set(e.Queueing,{fillStyle:RequestTimeRangeNameToColor[e.Queueing],lineWidth:2,borderColor:"lightgrey"}),t.set(e.Receiving,{fillStyle:RequestTimeRangeNameToColor[e.Receiving],lineWidth:2,borderColor:"#03A9F4"}),t.set(e.Waiting,{fillStyle:RequestTimeRangeNameToColor[e.Waiting]}),t.set(e.ReceivingPush,{fillStyle:RequestTimeRangeNameToColor[e.ReceivingPush]}),t.set(e.ServiceWorker,{fillStyle:RequestTimeRangeNameToColor[e.ServiceWorker]}),t.set(e.ServiceWorkerPreparation,{fillStyle:RequestTimeRangeNameToColor[e.ServiceWorkerPreparation]}),t.set(e.ServiceWorkerRespondWith,{fillStyle:RequestTimeRangeNameToColor[e.ServiceWorkerRespondWith]}),t}static buildResourceTypeStyle(){const e=new Map([["document","hsl(215, 100%, 80%)"],["font","hsl(8, 100%, 80%)"],["media","hsl(90, 50%, 80%)"],["image","hsl(90, 50%, 80%)"],["script","hsl(31, 100%, 80%)"],["stylesheet","hsl(272, 64%, 80%)"],["texttrack","hsl(8, 100%, 80%)"],["websocket","hsl(0, 0%, 95%)"],["xhr","hsl(53, 100%, 80%)"],["fetch","hsl(53, 100%, 80%)"],["other","hsl(0, 0%, 95%)"]]),t=new Map,i=new Map;for(const r of Object.values(Common.ResourceType.resourceTypes)){let a=e.get(r.name());a||(a=e.get("other"));const l=s(a);t.set(r,{fillStyle:o(a),lineWidth:1,borderColor:l}),i.set(r,{fillStyle:a,lineWidth:1,borderColor:l})}return[t,i];function s(e){const t=Common.Color.parse(e)?.as("hsl");if(!t)return"";let{s:i,l:s}=t;return i/=2,s-=Math.min(s,.2),new Common.Color.HSL(t.h,i,s,t.alpha).asString()}function o(e){const t=Common.Color.parse(e)?.as("hsl");if(!t)return"";let{l:i}=t;return i*=1.1,new Common.Color.HSL(t.h,t.s,i,t.alpha).asString()}}resetPaths(){this.pathForStyle.clear(),this.pathForStyle.set(this.wiskerStyle,new Path2D),this.styleForTimeRangeName.forEach((e=>this.pathForStyle.set(e,new Path2D))),this.styleForWaitingResourceType.forEach((e=>this.pathForStyle.set(e,new Path2D))),this.styleForDownloadingResourceType.forEach((e=>this.pathForStyle.set(e,new Path2D))),this.pathForStyle.set(this.hoverDetailsStyle,new Path2D)}willHide(){this.popoverHelper.hidePopover()}wasShown(){this.update(),this.registerCSSFiles([networkWaterfallColumnStyles])}onMouseMove(e){this.setHoveredNode(this.getNodeFromPoint(e.offsetX,e.offsetY),e.shiftKey)}onClick(e){this.setSelectedNode(this.getNodeFromPoint(e.offsetX,e.offsetY))&&e.consume(!0)}getPopoverRequest(e){if(!this.hoveredNode)return null;const t=this.hoveredNode.request();if(!t)return null;let i,s,o;if(!Common.Settings.Settings.instance().moduleSetting("networkColorCodeResourceTypes").get()&&!this.calculator.startAtZero?(i=RequestTimingView.calculateRequestTimeRanges(t,0).find((e=>e.name===RequestTimeRangeNames.Total)),s=this.timeToPosition(i.start),o=this.timeToPosition(i.end)):(i=this.getSimplifiedBarRange(t,0),s=i.start,o=i.end),o-s<50){const e=(o-s)/2;s=s+e-25,o=o-e+25}if(e.clientX<this.canvasPosition.left+s||e.clientX>this.canvasPosition.left+o)return null;const r=this.nodes.findIndex((e=>e.hovered())),a=this.getBarHeight(i.name),l=this.headerHeight+(this.rowHeight*r-this.scrollTop)+(this.rowHeight-a)/2;if(e.clientY<this.canvasPosition.top+l||e.clientY>this.canvasPosition.top+l+a)return null;const n=this.element.boxInWindow();return n.x+=s,n.y+=l,n.width=o-s,n.height=a,{box:n,show:e=>{const i=RequestTimingView.createTimingTable(t,this.calculator);return e.registerCSSFiles([networkingTimingTableStyles]),e.contentElement.appendChild(i),Promise.resolve(!0)},hide:void 0}}setHoveredNode(e,t){this.hoveredNode&&this.hoveredNode.setHovered(!1,!1),this.hoveredNode=e,this.hoveredNode&&this.hoveredNode.setHovered(!0,t)}setSelectedNode(e){return!(!e||!e.dataGrid)&&(e.select(),e.dataGrid.element.focus(),!0)}setRowHeight(e){this.rawRowHeight=e,this.updateRowHeight()}updateRowHeight(){this.rowHeight=Math.round(this.rawRowHeight*window.devicePixelRatio)/window.devicePixelRatio}setHeaderHeight(e){this.headerHeight=e}setRightPadding(e){this.rightPadding=e,this.calculateCanvasSize()}setCalculator(e){this.calculator=e}getNodeFromPoint(e,t){return t<=this.headerHeight?null:this.nodes[Math.floor((this.scrollTop+t-this.headerHeight)/this.rowHeight)]}scheduleDraw(){coordinator.write("NetworkWaterfallColumn.render",(()=>this.update()))}update(e,t,i){void 0!==e&&this.scrollTop!==e&&(this.popoverHelper.hidePopover(),this.scrollTop=e),i&&(this.nodes=i,this.calculateCanvasSize()),void 0!==t&&(this.eventDividers=t),this.startTime=this.calculator.minimumBoundary(),this.endTime=this.calculator.maximumBoundary(),this.resetCanvas(),this.resetPaths(),this.textLayers=[],this.draw()}resetCanvas(){const e=window.devicePixelRatio;this.canvas.width=this.offsetWidth*e,this.canvas.height=this.offsetHeight*e,this.canvas.style.width=this.offsetWidth+"px",this.canvas.style.height=this.offsetHeight+"px"}onResize(){super.onResize(),this.updateRowHeight(),this.calculateCanvasSize(),this.scheduleDraw()}calculateCanvasSize(){this.offsetWidth=this.contentElement.offsetWidth-this.rightPadding,this.offsetHeight=this.contentElement.offsetHeight,this.calculator.setDisplayWidth(this.offsetWidth),this.canvasPosition=this.canvas.getBoundingClientRect()}timeToPosition(e){const t=(this.offsetWidth-this.leftPadding)/(this.endTime-this.startTime);return Math.floor(this.leftPadding+(e-this.startTime)*t)}didDrawForTest(){}draw(){const e=!Common.Settings.Settings.instance().moduleSetting("networkColorCodeResourceTypes").get()&&!this.calculator.startAtZero,t=this.nodes,i=this.canvas.getContext("2d");if(!i)return;i.save(),i.scale(window.devicePixelRatio,window.devicePixelRatio),i.translate(0,this.headerHeight),i.rect(0,0,this.offsetWidth,this.offsetHeight),i.clip();const s=Math.floor(this.scrollTop/this.rowHeight),o=Math.min(t.length,s+Math.ceil(this.offsetHeight/this.rowHeight));for(let r=s;r<o;r++){const s=this.rowHeight*r,o=t[r];this.decorateRow(i,o,s-this.scrollTop);let a=[];o.hasChildren()&&!o.expanded&&(a=o.flatChildren()),a.push(o);for(const t of a)e?this.buildTimingBarLayers(t,s-this.scrollTop):this.buildSimplifiedBarLayers(i,t,s-this.scrollTop)}this.drawLayers(i,e),i.save(),i.fillStyle=ThemeSupport.ThemeSupport.instance().getComputedValue("--color-text-disabled");for(const e of this.textLayers)i.fillText(e.text,e.x,e.y);i.restore(),this.drawEventDividers(i),i.restore();const r=PerfUI.TimelineGrid.TimelineGrid.calculateGridOffsets(this.calculator);PerfUI.TimelineGrid.TimelineGrid.drawCanvasGrid(i,r),PerfUI.TimelineGrid.TimelineGrid.drawCanvasHeaders(i,r,(e=>this.calculator.formatValue(e,r.precision)),this.fontSize,this.headerHeight,75),i.save(),i.scale(window.devicePixelRatio,window.devicePixelRatio),i.clearRect(this.offsetWidth-18,0,18,this.headerHeight),i.restore(),this.didDrawForTest()}drawLayers(e,t){for(const i of this.pathForStyle){const s=i[0],o=i[1];e.save(),e.beginPath(),s.lineWidth&&(e.lineWidth=s.lineWidth,s.borderColor&&(e.strokeStyle=s.borderColor),e.stroke(o)),s.fillStyle&&(e.fillStyle=t?ThemeSupport.ThemeSupport.instance().getComputedValue(s.fillStyle):s.fillStyle,e.fill(o)),e.restore()}}drawEventDividers(e){e.save(),e.lineWidth=1;for(const t of this.eventDividers.keys()){e.strokeStyle=t;for(const i of this.eventDividers.get(t)||[]){e.beginPath();const t=this.timeToPosition(i);e.moveTo(t,0),e.lineTo(t,this.offsetHeight)}e.stroke()}e.restore()}getBarHeight(e){const t=RequestTimeRangeNames;switch(e){case t.Connecting:case t.SSL:case t.DNS:case t.Proxy:case t.Blocking:case t.Push:case t.Queueing:return 7;default:return 13}}getSimplifiedBarRange(e,t){const i=this.offsetWidth-this.leftPadding,s=this.calculator.computeBarGraphPercentages(e);return{start:this.leftPadding+Math.floor(s.start/100*i)+t,mid:this.leftPadding+Math.floor(s.middle/100*i)+t,end:this.leftPadding+Math.floor(s.end/100*i)+t}}buildSimplifiedBarLayers(e,t,i){const s=t.request();if(!s)return;const o=.5,r=this.getSimplifiedBarRange(s,o),a=this.getBarHeight();i+=Math.floor(this.rowHeight/2-a/2+1)-.5;const l=this.styleForWaitingResourceType.get(s.resourceType());this.pathForStyle.get(l).rect(r.start,i,r.mid-r.start,a-1);const n=Math.max(2,r.end-r.mid),h=this.styleForDownloadingResourceType.get(s.resourceType());this.pathForStyle.get(h).rect(r.mid,i,n,a-1);let d=null;if(t.hovered()){d=this.calculator.computeBarGraphLabels(s);const t=10,l=e.measureText(d.left).width,h=e.measureText(d.right).width,c=this.pathForStyle.get(this.hoverDetailsStyle);if(l<r.mid-r.start){const e=r.start+(r.mid-r.start-l)/2;this.textLayers.push({text:d.left,x:e,y:i+this.fontSize})}else t+l+this.leftPadding<r.start&&(this.textLayers.push({text:d.left,x:r.start-l-t-1,y:i+this.fontSize}),c.moveTo(r.start-t,i+Math.floor(a/2)),c.arc(r.start,i+Math.floor(a/2),2,0,2*Math.PI),c.moveTo(r.start-t,i+Math.floor(a/2)),c.lineTo(r.start,i+Math.floor(a/2)));const m=r.mid+n+o;if(h<m-r.mid){const e=r.mid+(m-r.mid-h)/2;this.textLayers.push({text:d.right,x:e,y:i+this.fontSize})}else m+t+h<this.offsetWidth-this.leftPadding&&(this.textLayers.push({text:d.right,x:m+t+1,y:i+this.fontSize}),c.moveTo(m,i+Math.floor(a/2)),c.arc(m,i+Math.floor(a/2),2,0,2*Math.PI),c.moveTo(m,i+Math.floor(a/2)),c.lineTo(m+t,i+Math.floor(a/2)))}if(!this.calculator.startAtZero){const t=RequestTimingView.calculateRequestTimeRanges(s,0).find((e=>e.name===RequestTimeRangeNames.Total)),l=d?e.measureText(d.left).width:0,n=l<r.mid-r.start,h=d&&!n?l+13:0,c=this.timeToPosition(t.start);if(r.start-h>c){const e=this.pathForStyle.get(this.wiskerStyle);e.moveTo(c,i+Math.floor(a/2)),e.lineTo(r.start-h,i+Math.floor(a/2));const t=a/2;e.moveTo(c+o,i+t/2),e.lineTo(c+o,i+a-t/2-1)}}}buildTimingBarLayers(e,t){const i=e.request();if(!i)return;const s=RequestTimingView.calculateRequestTimeRanges(i,0);let o=0;for(const e of s){if(e.name===RequestTimeRangeNames.Total||e.name===RequestTimeRangeNames.Sending||e.end-e.start==0)continue;const i=this.styleForTimeRangeName.get(e.name),s=this.pathForStyle.get(i),r=i.lineWidth||0,a=this.getBarHeight(e.name),l=t+Math.floor(this.rowHeight/2-a/2)+r/2,n=this.timeToPosition(e.start),h=this.timeToPosition(e.end);s.rect(n+1*o,l,h-n,a-r),o++}}decorateRow(e,t,i){const s=t.backgroundColor();e.save(),e.beginPath(),e.fillStyle=ThemeSupport.ThemeSupport.instance().getComputedValue(s),e.rect(0,i,this.offsetWidth,this.rowHeight),e.fill(),e.restore()}}