UNPKG

@yuebai008/cli

Version:

Command line interface for rapid qg-minigame development

1 lines 9.53 kB
import*as Common from"../../core/common/common.js";import*as i18n from"../../core/i18n/i18n.js";import*as Platform from"../../core/platform/platform.js";import*as UI from"../../ui/legacy/legacy.js";import{TimelineEventOverviewCPUActivity,TimelineEventOverviewNetwork,TimelineEventOverviewResponsiveness}from"./TimelineEventOverview.js";import timelineHistoryManagerStyles from"./timelineHistoryManager.css.js";const UIStrings={currentSessionSS:"Current Session: {PH1}. {PH2}",noRecordings:"(no recordings)",sAgo:"({PH1} ago)",moments:"moments",sM:"{PH1} m",sH:"{PH1} h",sD:"{PH1} #{PH2}",selectTimelineSession:"Select Timeline Session"},str_=i18n.i18n.registerUIStrings("panels/timeline/TimelineHistoryManager.ts",UIStrings),i18nString=i18n.i18n.getLocalizedString.bind(void 0,str_);export class TimelineHistoryManager{recordings;action;nextNumberByDomain;buttonInternal;allOverviews;totalHeight;enabled;lastActiveModel;constructor(){this.recordings=[],this.action=UI.ActionRegistry.ActionRegistry.instance().action("timeline.show-history"),this.nextNumberByDomain=new Map,this.buttonInternal=new ToolbarButton(this.action),UI.ARIAUtils.markAsMenuButton(this.buttonInternal.element),this.clear(),this.allOverviews=[{constructor:e=>new TimelineEventOverviewResponsiveness(e),height:3},{constructor:(e,t)=>new TimelineEventOverviewCPUActivity(t),height:20},{constructor:e=>new TimelineEventOverviewNetwork(e),height:8}],this.totalHeight=this.allOverviews.reduce(((e,t)=>e+t.height),0),this.enabled=!0,this.lastActiveModel=null}addRecording(e){const{legacyModel:t,traceParseDataIndex:n}=e.data,i=e.filmStripForPreview;this.lastActiveModel=t,this.recordings.unshift({legacyModel:t,traceParseDataIndex:n}),this.buildPreview(t,e.traceParsedData,i);const s=this.title(t);this.buttonInternal.setText(s);const o=this.action.title();if(UI.ARIAUtils.setLabel(this.buttonInternal.element,i18nString(UIStrings.currentSessionSS,{PH1:s,PH2:o})),this.updateState(),this.recordings.length<=maxRecordings)return;const r=this.recordings.reduce(((e,t)=>l(e.legacyModel)<l(t.legacyModel)?e:t));function l(e){const t=TimelineHistoryManager.dataForModel(e);if(!t)throw new Error("Unable to find data for model");return t.lastUsed}this.recordings.splice(this.recordings.indexOf(r),1)}setEnabled(e){this.enabled=e,this.updateState()}button(){return this.buttonInternal}clear(){this.recordings=[],this.lastActiveModel=null,this.updateState(),this.buttonInternal.setText(i18nString(UIStrings.noRecordings)),this.nextNumberByDomain.clear()}async showHistoryDropDown(){if(this.recordings.length<2||!this.enabled)return null;const e=await DropDown.show(this.recordings.map((e=>e.legacyModel)),this.lastActiveModel,this.buttonInternal.element);if(!e)return null;const t=this.recordings.findIndex((t=>t.legacyModel===e));return t<0?(console.assert(!1,"selected recording not found"),null):(this.setCurrentModel(e),this.recordings[t])}cancelIfShowing(){DropDown.cancelIfShowing()}navigate(e){if(!this.enabled||!this.lastActiveModel)return null;const t=this.recordings.findIndex((e=>e.legacyModel===this.lastActiveModel));if(t<0)return null;const n=Platform.NumberUtilities.clamp(t+e,0,this.recordings.length-1),i=this.recordings[n].legacyModel;return this.setCurrentModel(i),this.recordings[n]}setCurrentModel(e){const t=TimelineHistoryManager.dataForModel(e);if(!t)throw new Error("Unable to find data for model");t.lastUsed=Date.now(),this.lastActiveModel=e;const n=this.title(e),i=this.action.title();this.buttonInternal.setText(n),UI.ARIAUtils.setLabel(this.buttonInternal.element,i18nString(UIStrings.currentSessionSS,{PH1:n,PH2:i}))}updateState(){this.action.setEnabled(this.recordings.length>1&&this.enabled)}static previewElement(e){const t=TimelineHistoryManager.dataForModel(e);if(!t)throw new Error("Unable to find data for model");const n=e.recordStartTime();return t.time.textContent=n?i18nString(UIStrings.sAgo,{PH1:TimelineHistoryManager.coarseAge(n)}):"",t.preview}static coarseAge(e){const t=Math.round((Date.now()-e)/1e3);if(t<50)return i18nString(UIStrings.moments);const n=Math.round(t/60);if(n<50)return i18nString(UIStrings.sM,{PH1:n});const i=Math.round(n/60);return i18nString(UIStrings.sH,{PH1:i})}title(e){const t=TimelineHistoryManager.dataForModel(e);if(!t)throw new Error("Unable to find data for model");return t.title}buildPreview(e,t,n){const i=Common.ParsedURL.ParsedURL.fromString(e.timelineModel().pageURL()),s=i?i.host:"",o=e.tracingModel().title()||s,r=this.nextNumberByDomain.get(o)||1,l=i18nString(UIStrings.sD,{PH1:o,PH2:r});this.nextNumberByDomain.set(o,r+1);const a=document.createElement("span"),c=document.createElement("div");c.classList.add("preview-item"),c.classList.add("vbox");const d={preview:c,title:l,time:a,lastUsed:Date.now()};modelToPerformanceData.set(e,d),c.appendChild(this.buildTextDetails(e,o,a));const h=c.createChild("div","hbox");return h.appendChild(this.buildScreenshotThumbnail(n)),h.appendChild(this.buildOverview(e,t)),d.preview}buildTextDetails(e,t,n){const i=document.createElement("div");i.classList.add("text-details"),i.classList.add("hbox");const s=i.createChild("span","name");s.textContent=t,UI.ARIAUtils.setLabel(s,t);const o=e.tracingModel(),r=i18n.TimeUtilities.millisToString(o.maximumRecordTime()-o.minimumRecordTime(),!1),l=i.createChild("span","time");return l.appendChild(document.createTextNode(r)),l.appendChild(n),i}buildScreenshotThumbnail(e){const t=document.createElement("div");t.classList.add("screenshot-thumb");if(t.style.width=1.5*this.totalHeight+"px",t.style.height=this.totalHeight+"px",!e)return t;const n=e.frames.at(-1);return n?(UI.UIUtils.loadImageFromData(n.screenshotAsString).then((e=>{e&&t.appendChild(e)})),t):t}buildOverview(e,t){const n=document.createElement("div");n.style.width=previewWidth+"px",n.style.height=this.totalHeight+"px";const i=n.createChild("canvas");i.width=window.devicePixelRatio*previewWidth,i.height=window.devicePixelRatio*this.totalHeight;const s=i.getContext("2d");let o=0;for(const n of this.allOverviews){const i=n.constructor(t,e);i.setCanvasSize(previewWidth,n.height),i.update();const r=i.context(),l=r.getImageData(0,0,r.canvas.width,r.canvas.height);s&&s.putImageData(l,0,o),o+=n.height*window.devicePixelRatio}return n}static dataForModel(e){return modelToPerformanceData.get(e)||null}}export const maxRecordings=5;export const previewWidth=450;const modelToPerformanceData=new WeakMap;export class DropDown{glassPane;listControl;focusRestorer;selectionDone;constructor(e){this.glassPane=new UI.GlassPane.GlassPane,this.glassPane.setSizeBehavior("MeasureContent"),this.glassPane.setOutsideClickCallback((()=>this.close(null))),this.glassPane.setPointerEventsBehavior("BlockedByGlassPane"),this.glassPane.setAnchorBehavior("PreferBottom"),this.glassPane.element.addEventListener("blur",(()=>this.close(null)));const t=UI.Utils.createShadowRootWithCoreStyles(this.glassPane.contentElement,{cssFile:[timelineHistoryManagerStyles],delegatesFocus:void 0}).createChild("div","drop-down"),n=new UI.ListModel.ListModel;this.listControl=new UI.ListControl.ListControl(n,this,UI.ListControl.ListMode.NonViewport),this.listControl.element.addEventListener("mousemove",this.onMouseMove.bind(this),!1),n.replaceAll(e),UI.ARIAUtils.markAsMenu(this.listControl.element),UI.ARIAUtils.setLabel(this.listControl.element,i18nString(UIStrings.selectTimelineSession)),t.appendChild(this.listControl.element),t.addEventListener("keydown",this.onKeyDown.bind(this),!1),t.addEventListener("click",this.onClick.bind(this),!1),this.focusRestorer=new UI.UIUtils.ElementFocusRestorer(this.listControl.element),this.selectionDone=null}static show(e,t,n){if(DropDown.instance)return Promise.resolve(null);return new DropDown(e).show(n,t)}static cancelIfShowing(){DropDown.instance&&DropDown.instance.close(null)}show(e,t){return DropDown.instance=this,this.glassPane.setContentAnchorBox(e.boxInWindow()),this.glassPane.show(this.glassPane.contentElement.ownerDocument),this.listControl.element.focus(),this.listControl.selectItem(t),new Promise((e=>{this.selectionDone=e}))}onMouseMove(e){const t=e.target.enclosingNodeOrSelfWithClass("preview-item"),n=t&&this.listControl.itemForNode(t);n&&this.listControl.selectItem(n)}onClick(e){e.target.enclosingNodeOrSelfWithClass("preview-item")&&this.close(this.listControl.selectedItem())}onKeyDown(e){switch(e.key){case"Tab":case"Escape":this.close(null);break;case"Enter":this.close(this.listControl.selectedItem());break;default:return}e.consume(!0)}close(e){this.selectionDone&&this.selectionDone(e),this.focusRestorer.restore(),this.glassPane.hide(),DropDown.instance=null}createElementForItem(e){const t=TimelineHistoryManager.previewElement(e);return UI.ARIAUtils.markAsMenuItem(t),t.classList.remove("selected"),t}heightForItem(e){return console.assert(!1,"Should not be called"),0}isItemSelectable(e){return!0}selectedItemChanged(e,t,n,i){n&&n.classList.remove("selected"),i&&i.classList.add("selected")}updateSelectedItemARIA(e,t){return!1}static instance=null}export class ToolbarButton extends UI.Toolbar.ToolbarItem{contentElement;constructor(e){const t=document.createElement("button");t.classList.add("history-dropdown-button"),super(t),this.contentElement=this.element.createChild("span","content");const n=UI.Icon.Icon.create("triangle-down");this.element.appendChild(n),this.element.addEventListener("click",(()=>{e.execute()}),!1),this.setEnabled(e.enabled()),e.addEventListener("Enabled",(e=>this.setEnabled(e.data))),this.setTitle(e.title())}setText(e){this.contentElement.textContent=e}}