• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16import { BaseElement, element } from '../../base-ui/BaseElement';
17import './trace/TimerShaftElement';
18import './trace/base/TraceRow';
19import { threadPool } from '../database/SqlLite';
20import { TraceRow } from './trace/base/TraceRow';
21import { TimerShaftElement } from './trace/TimerShaftElement';
22import './trace/base/TraceSheet';
23import { TraceSheet } from './trace/base/TraceSheet';
24import { RangeSelect } from './trace/base/RangeSelect';
25import { SelectionParam } from '../bean/BoxSelection';
26import { procedurePool } from '../database/Procedure';
27import { SpApplication } from '../SpApplication';
28import { Flag } from './trace/timer-shaft/Flag';
29import { SlicesTime, SportRuler } from './trace/timer-shaft/SportRuler';
30import { SpHiPerf } from './chart/SpHiPerf';
31import { SearchSdkBean } from '../bean/SearchFuncBean';
32import { info } from '../../log/Log';
33import {
34  drawFlagLineSegment,
35  drawLines,
36  drawLinkLines,
37  drawLogsLineSegment,
38  drawWakeUp,
39  drawWakeUpList,
40  LineType,
41  ns2x,
42  ns2xByTimeShaft,
43  PairPoint,
44  Rect,
45} from '../database/ui-worker/ProcedureWorkerCommon';
46import { SpChartManager } from './chart/SpChartManager';
47import { CpuStruct, WakeupBean } from '../database/ui-worker/cpu/ProcedureWorkerCPU';
48import { ProcessStruct } from '../database/ui-worker/ProcedureWorkerProcess';
49import { CpuFreqStruct } from '../database/ui-worker/ProcedureWorkerFreq';
50import { CpuFreqLimitsStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuFreqLimits';
51import { ThreadStruct } from '../database/ui-worker/ProcedureWorkerThread';
52import { FuncStruct } from '../database/ui-worker/ProcedureWorkerFunc';
53import { CpuStateStruct } from '../database/ui-worker/cpu/ProcedureWorkerCpuState';
54import { HiPerfCpuStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCPU2';
55import { HiPerfProcessStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfProcess2';
56import { HiPerfThreadStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfThread2';
57import { HiPerfEventStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfEvent';
58import { HiPerfReportStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfReport';
59import { FpsStruct } from '../database/ui-worker/ProcedureWorkerFPS';
60import { CpuAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerCpuAbility';
61import { DiskAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerDiskIoAbility';
62import { MemoryAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerMemoryAbility';
63import { NetworkAbilityMonitorStruct } from '../database/ui-worker/ProcedureWorkerNetworkAbility';
64import { ClockStruct } from '../database/ui-worker/ProcedureWorkerClock';
65import { Utils } from './trace/base/Utils';
66import { IrqStruct } from '../database/ui-worker/ProcedureWorkerIrq';
67import { JankStruct } from '../database/ui-worker/ProcedureWorkerJank';
68import { TabPaneCurrent } from './trace/sheet/TabPaneCurrent';
69import { HeapStruct } from '../database/ui-worker/ProcedureWorkerHeap';
70import { SpStatisticsHttpUtil } from '../../statistics/util/SpStatisticsHttpUtil';
71import { HeapSnapshotStruct } from '../database/ui-worker/ProcedureWorkerHeapSnapshot';
72import { HeapDataInterface } from '../../js-heap/HeapDataInterface';
73import { LitTabs } from '../../base-ui/tabs/lit-tabs';
74import { TraceRowConfig } from './trace/base/TraceRowConfig';
75import { TabPaneCurrentSelection } from './trace/sheet/TabPaneCurrentSelection';
76import { SpChartList } from './trace/SpChartList';
77import './trace/SpChartList';
78import { AppStartupStruct } from '../database/ui-worker/ProcedureWorkerAppStartup';
79import { AllAppStartupStruct } from '../database/ui-worker/ProcedureWorkerAllAppStartup';
80import { SoStruct } from '../database/ui-worker/ProcedureWorkerSoInit';
81import { FrameDynamicStruct } from '../database/ui-worker/ProcedureWorkerFrameDynamic';
82import { FrameAnimationStruct } from '../database/ui-worker/ProcedureWorkerFrameAnimation';
83import { FrameSpacingStruct } from '../database/ui-worker/ProcedureWorkerFrameSpacing';
84import { JsCpuProfilerStruct } from '../database/ui-worker/ProcedureWorkerCpuProfiler';
85import { FileInfo } from '../../js-heap/model/UiStruct';
86import { SnapshotStruct } from '../database/ui-worker/ProcedureWorkerSnapshot';
87import { TabPaneFrequencySample } from './trace/sheet/cpu/TabPaneFrequencySample';
88import { TabPaneCounterSample } from './trace/sheet/cpu/TabPaneCounterSample';
89import { TabPaneFlag } from './trace/timer-shaft/TabPaneFlag';
90import { LitTabpane } from '../../base-ui/tabs/lit-tabpane';
91import { HiPerfCallChartStruct } from '../database/ui-worker/hiperf/ProcedureWorkerHiPerfCallChart';
92import { InitAnalysis } from '../database/logic-worker/ProcedureLogicWorkerCommon';
93import { searchCpuDataSender } from '../database/data-trafic/CpuDataSender';
94import { resetVSync } from './chart/VSync';
95import { QueryEnum } from '../database/data-trafic/utils/QueryEnum';
96import { SpSystemTraceHtml } from './SpSystemTrace.html';
97import { querySceneSearchFunc, querySearchFunc } from '../database/sql/Func.sql';
98import { queryCpuKeyPathData } from '../database/sql/Cpu.sql';
99import { LtpoStruct } from '../database/ui-worker/ProcedureWorkerLTPO';
100import { HitchTimeStruct } from '../database/ui-worker/ProcedureWorkerHitchTime';
101import {
102  spSystemTraceInit,
103  spSystemTraceInitElement,
104  spSystemTraceInitPointToEvent,
105  spSystemTraceParentRowSticky,
106  spSystemTraceShowStruct,
107} from './SpSystemTrace.init';
108import {
109  spSystemTraceDrawJankLine,
110  spSystemTraceDrawTaskPollLine,
111  spSystemTraceDrawThreadLine,
112} from './SpSystemTrace.line';
113import spSystemTraceOnClickHandler, {
114  spSystemTraceDocumentOnClick,
115  spSystemTraceDocumentOnKeyDown,
116  spSystemTraceDocumentOnKeyPress,
117  spSystemTraceDocumentOnKeyUp,
118  spSystemTraceDocumentOnMouseDown,
119  spSystemTraceDocumentOnMouseMove,
120  spSystemTraceDocumentOnMouseOut,
121  spSystemTraceDocumentOnMouseUp,
122} from './SpSystemTrace.event';
123import { SampleStruct } from '../database/ui-worker/ProcedureWorkerBpftrace';
124import { readTraceFileBuffer } from '../SpApplicationPublicFunc';
125import { PerfToolStruct } from '../database/ui-worker/ProcedureWorkerPerfTool';
126import { BaseStruct } from '../bean/BaseStruct';
127
128function dpr(): number {
129  return window.devicePixelRatio || 1;
130}
131
132export class CurrentSlicesTime {
133  startTime: number | undefined;
134  endTime: number | undefined;
135}
136
137type HTMLDivElementAlias = HTMLDivElement | undefined | null;
138type FlagAlias = Flag | undefined | null;
139type SlicesTimeAlias = SlicesTime | undefined | null;
140
141@element('sp-system-trace')
142export class SpSystemTrace extends BaseElement {
143  mouseCurrentPosition = 0;
144  static isKeyUp: boolean = true;
145  offsetMouse = 0;
146  static isMouseLeftDown = false;
147  static scrollViewWidth = 0;
148  static isCanvasOffScreen = true;
149  static DATA_DICT: Map<number, string> = new Map<number, string>();
150  static DATA_TASK_POOL_CALLSTACK: Map<number, { id: number; ts: number; dur: number; name: string }> = new Map<
151    number,
152    { id: number; ts: number; dur: number; name: string }
153  >();
154  static SDK_CONFIG_MAP: unknown;
155  static sliceRangeMark: unknown;
156  static wakeupList: Array<WakeupBean> = [];
157  static keyPathList: Array<CpuStruct> = [];
158  static keyboardFlar: Boolean = true;
159  static jsProfilerMap: Map<number, unknown> = new Map<number, unknown>();
160  times: Set<number> = new Set<number>();
161  currentSlicesTime: CurrentSlicesTime = new CurrentSlicesTime();
162  intersectionObserver: IntersectionObserver | undefined;
163  tipEL: HTMLDivElementAlias;
164  rowsEL: HTMLDivElementAlias;
165  rowsPaneEL: HTMLDivElementAlias;
166  stateRowsId: Array<object> = [];
167  spacerEL: HTMLDivElementAlias; // @ts-ignore
168  visibleRows: Array<TraceRow<unknown>> = []; // @ts-ignore
169  invisibleRows: Array<TraceRow<unknown>> = []; // @ts-ignore
170  collectRows: Array<TraceRow<unknown>> = []; // @ts-ignore
171  currentRow: TraceRow<unknown> | undefined | null;
172  keyboardEnable = true;
173  mouseEventEnable = true;
174  currentRowType = ''; /*保存当前鼠标所在行的类型*/
175  observerScrollHeightEnable: boolean = false;
176  observerScrollHeightCallback: Function | undefined;
177  favoriteChartListEL: SpChartList | undefined | null;
178  // @ts-ignore
179  observer = new ResizeObserver((entries) => {
180    if (this.observerScrollHeightEnable && this.observerScrollHeightCallback) {
181      this.observerScrollHeightCallback();
182    }
183  });
184  static btnTimer: unknown = null;
185  isMousePointInSheet = false;
186  hoverFlag: FlagAlias;
187  selectFlag: FlagAlias;
188  slicestime: SlicesTimeAlias;
189  public timerShaftEL: TimerShaftElement | null | undefined;
190  public traceSheetEL: TraceSheet | undefined | null;
191  public rangeSelect!: RangeSelect;
192  chartManager: SpChartManager | undefined | null;
193  loadTraceCompleted: boolean = false; // @ts-ignore
194  rangeTraceRow: Array<TraceRow<unknown>> | undefined = [];
195  canvasFavoritePanelCtx: CanvasRenderingContext2D | null | undefined;
196  canvasPanel: HTMLCanvasElement | null | undefined; //绘制取消收藏后泳道图
197  canvasPanelCtx: CanvasRenderingContext2D | undefined | null;
198  linkNodes: PairPoint[][] = [];
199  public currentClickRow: HTMLDivElement | undefined | null;
200  private litTabs: LitTabs | undefined | null;
201  eventMap: unknown = {};
202  isSelectClick: boolean = false;
203  selectionParam: SelectionParam | undefined;
204  snapshotFiles: FileInfo | null | undefined;
205  tabCpuFreq: TabPaneFrequencySample | undefined | null;
206  tabCpuState: TabPaneCounterSample | undefined | null;
207  collapseAll: boolean = false;
208  currentCollectGroup: string = '1';
209  private _list: Array<SlicesTime> = [];
210  static isHiddenMenu: boolean = false; // @ts-ignore
211  expandRowList: Array<TraceRow<unknown>> = [];
212  _slicesList: Array<SlicesTime> = [];
213  _flagList: Array<unknown> = [];
214  static currentStartTime: number = 0;
215  static retargetIndex: number = 0;
216  private prevScrollY: number = 0;
217
218  set snapshotFile(data: FileInfo) {
219    this.snapshotFiles = data;
220  }
221
222  set slicesList(list: Array<SlicesTime>) {
223    this._slicesList = list;
224  }
225
226  set flagList(list: Array<unknown>) {
227    this._flagList = list;
228  }
229
230  //节流处理
231  throttle(fn: Function, t: number, ev?: unknown): Function {
232    let timerId: unknown = null;
233    return (): void => {
234      if (!timerId) {
235        timerId = setTimeout(function (): void {
236          if (ev) {
237            fn(ev);
238          } else {
239            fn();
240          }
241          timerId = null;
242        }, t); // @ts-ignore
243        this.times.add(timerId);
244      }
245    };
246  }
247
248  // 防抖处理
249  debounce(fn: Function, ms: number, ev?: unknown): Function {
250    let timerId: undefined | number;
251    return (): void => {
252      if (timerId) {
253        window.clearTimeout(timerId);
254      } else {
255        timerId = window.setTimeout((): void => {
256          if (ev) {
257            fn(ev);
258          } else {
259            fn();
260          }
261          timerId = undefined;
262        }, ms);
263        this.times.add(timerId);
264      }
265    };
266  }
267
268  addPointPair(startPoint: PairPoint, endPoint: PairPoint): void {
269    if (startPoint.rowEL.collect) {
270      if (this.timerShaftEL?._checkExpand) {
271        startPoint.rowEL.translateY =
272          startPoint.rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!;
273      } else {
274        startPoint.rowEL.translateY = startPoint.rowEL.getBoundingClientRect().top - 195;
275      }
276    } else {
277      startPoint.rowEL.translateY = startPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
278    }
279    if (endPoint.rowEL.collect) {
280      endPoint.rowEL.translateY = endPoint.rowEL.getBoundingClientRect().top - 195;
281    } else {
282      endPoint.rowEL.translateY = endPoint.rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
283    }
284    startPoint.y = startPoint.rowEL!.translateY! + startPoint.offsetY;
285    endPoint.y = endPoint.rowEL!.translateY! + endPoint.offsetY;
286    startPoint.backrowEL = startPoint.rowEL;
287    endPoint.backrowEL = endPoint.rowEL;
288    this.linkNodes.push([startPoint, endPoint]);
289  }
290
291  clearPointPair(): void {
292    this.linkNodes.length = 0;
293  }
294
295  removeLinkLinesByBusinessType(...businessTypes: string[]): void {
296    this.linkNodes = this.linkNodes.filter((pointPair) => {
297      return businessTypes.indexOf(pointPair[0].business) <= -1;
298    });
299  }
300
301  hiddenLinkLinesByBusinessType(...businessTypes: string[]): void {
302    this.linkNodes.map((value) => {
303      if (businessTypes.indexOf(value[0].business) !== -1) {
304        value[0].hidden = true;
305        value[1].hidden = true;
306      }
307    });
308  }
309
310  showLinkLinesByBusinessType(...businessTypes: string[]): void {
311    this.linkNodes.map((value) => {
312      if (businessTypes.indexOf(value[0].business) !== -1) {
313        value[0].hidden = false;
314        value[1].hidden = false;
315      }
316    });
317  }
318
319  initElements(): void {
320    spSystemTraceInitElement(this);
321  }
322
323  // 清除上一次点击调用栈产生的三角旗子
324  clearTriangle(flagList: Array<Flag>): void {
325    this.timerShaftEL!.sportRuler!.times = [];
326    for (let i = 0; i < flagList.length; i++) {
327      if (flagList[i].type === 'triangle') {
328        flagList.splice(i, 1);
329        i--;
330      }
331    }
332  }
333
334  pushPidToSelection(selection: SelectionParam, id: string): void {
335    let pid = parseInt(id);
336    if (!selection.processIds.includes(pid)) {
337      selection.processIds.push(pid);
338    }
339  }
340  // @ts-ignore
341  getCollectRows(condition: (row: TraceRow<unknown>) => boolean): Array<TraceRow<unknown>> {
342    return this.favoriteChartListEL!.getCollectRows(condition);
343  }
344  // @ts-ignore
345  createPointEvent(it: TraceRow<unknown>): unknown {
346    // @ts-ignore
347    let event = this.eventMap[`${it.rowType}`];
348    if (event) {
349      return event;
350    } else {
351      if (it.rowType === TraceRow.ROW_TYPE_HEAP) {
352        event = it.name;
353      } else if (it.rowType === TraceRow.ROW_TYPE_HIPERF_CPU) {
354        event = 'HiPerf Cpu';
355        if (it.rowId === 'HiPerf-cpu-merge') {
356          event = 'HiPerf';
357        }
358      } else if (it.rowType === TraceRow.ROW_TYPE_FILE_SYSTEM) {
359        event = this.handleFileSystemType(it, event);
360      } else if (it.rowType === TraceRow.ROW_TYPE_STATE_ENERGY) {
361        event = it.name;
362      } else if (it.rowType === TraceRow.ROW_TYPE_VM_TRACKER) {
363        if (it.rowParentId === '') {
364          event = 'VM Tracker';
365        } else {
366          event = it.name;
367        }
368      } else if (it.rowType === TraceRow.ROW_TYPE_JANK) {
369        if (it.rowId === 'frameTime' || it.rowParentId === 'frameTime') {
370          event = 'FrameTimeLine';
371        } else if (it.hasAttribute('frame_type')) {
372          event = `${it.getAttribute('frame_type')}`;
373        }
374      } else if (it.rowType === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) {
375        event = 'DeliverInputEvent';
376        if (it.rowParentId === TraceRow.ROW_TYPE_DELIVER_INPUT_EVENT) {
377          event = 'DeliverInputEvent Func';
378        }
379      } else {
380        event = it.name;
381      }
382      return event;
383    }
384  }
385  // @ts-ignore
386  private handleFileSystemType(it: TraceRow<unknown>, event: unknown): void {
387    if (it.rowId === 'FileSystemLogicalWrite') {
388      event = 'FileSystem Logical Write';
389    } else if (it.rowId === 'FileSystemLogicalRead') {
390      event = 'FileSystem Logical Read';
391    } else if (it.rowId === 'FileSystemVirtualMemory') {
392      event = 'Page Fault Trace';
393    } else if (it.rowId!.startsWith('FileSystemDiskIOLatency')) {
394      event = 'Disk I/O Latency';
395      if (it.rowId!.startsWith('FileSystemDiskIOLatency-')) {
396        event = 'Bio Process';
397      }
398    } // @ts-ignore
399    return event;
400  }
401
402  refreshFavoriteCanvas(): void {
403    this.favoriteChartListEL!.refreshFavoriteCanvas();
404  }
405  // @ts-ignore
406  expansionAllParentRow(currentRow: TraceRow<unknown>): void {
407    // @ts-ignore
408    let parentRow = this.rowsEL!.querySelector<TraceRow<unknown>>(
409      `trace-row[row-id='${currentRow.rowParentId}'][folder][scene]`
410    );
411    if (parentRow) {
412      parentRow.expansion = true; // @ts-ignore
413      if (this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${parentRow.rowParentId}'][folder]`)) {
414        this.expansionAllParentRow(parentRow);
415      }
416    }
417  }
418
419  canvasPanelConfig(): void {
420    this.canvasPanel!.style.left = `${this.timerShaftEL!.canvas!.offsetLeft!}px`;
421    this.canvasPanel!.width = this.canvasPanel!.offsetWidth * dpr();
422    this.canvasPanel!.height = this.canvasPanel!.offsetHeight * dpr();
423    this.canvasPanelCtx!.scale(dpr(), dpr());
424  }
425
426  getScrollWidth(): number {
427    let overflowDiv = document.createElement('div');
428    overflowDiv.style.cssText = 'position:absolute; top:-2000px;width:200px; height:200px; overflow:hidden;';
429    let totalScrollDiv = document.body.appendChild(overflowDiv).clientWidth;
430    overflowDiv.style.overflowY = 'scroll';
431    let scrollDiv = overflowDiv.clientWidth;
432    document.body.removeChild(overflowDiv);
433    return totalScrollDiv - scrollDiv;
434  }
435
436  getShowTab(): Array<string> {
437    let tabpane = this.traceSheetEL!.shadowRoot!.querySelectorAll('lit-tabpane') as NodeListOf<LitTabpane>;
438    let showTab: Array<string> = [];
439    for (let pane of tabpane) {
440      if (pane.getAttribute('hidden') === 'false') {
441        showTab.push(pane.getAttribute('id') || '');
442      }
443    }
444    return showTab;
445  }
446
447  timerShaftELFlagClickHandler = (flag: FlagAlias): void => {
448    if (flag) {
449      setTimeout(() => {
450        if (TraceRow.rangeSelectObject) {
451          let showTab = this.getShowTab();
452          this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag', ...showTab).setCurrentFlag(flag);
453        } else {
454          this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag').setCurrentFlag(flag);
455        }
456      }, 100);
457    }
458  };
459
460  timerShaftELFlagChange = (hoverFlag: FlagAlias, selectFlag: FlagAlias): void => {
461    this.hoverFlag = hoverFlag;
462    this.selectFlag = selectFlag;
463    this.refreshCanvas(true, 'flagChange');
464  };
465
466  timerShaftELRangeClick = (sliceTime: SlicesTimeAlias): void => {
467    if (sliceTime) {
468      setTimeout(() => {
469        if (TraceRow.rangeSelectObject) {
470          let showTab = this.getShowTab();
471          this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current', ...showTab).setCurrentSlicesTime(sliceTime);
472        } else {
473          this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current').setCurrentSlicesTime(sliceTime);
474        }
475      }, 0);
476    }
477  };
478
479  timerShaftELRangeChange = (e: unknown): void => {
480    // @ts-ignore
481    TraceRow.range = e;
482    if (TraceRow.rangeSelectObject) {
483      TraceRow.rangeSelectObject!.startX = Math.floor(
484        ns2x(
485          TraceRow.rangeSelectObject!.startNS!,
486          TraceRow.range?.startNS!,
487          TraceRow.range?.endNS!,
488          TraceRow.range?.totalNS!,
489          this.timerShaftEL!.sportRuler!.frame
490        )
491      );
492      TraceRow.rangeSelectObject!.endX = Math.floor(
493        ns2x(
494          TraceRow.rangeSelectObject!.endNS!,
495          TraceRow.range?.startNS!,
496          TraceRow.range?.endNS!,
497          TraceRow.range?.totalNS!,
498          this.timerShaftEL!.sportRuler!.frame
499        )
500      );
501    }
502    //在rowsEL显示范围内的 trace-row组件将收到时间区间变化通知
503    this.linkNodes.forEach((it) => {
504      it[0].x = ns2xByTimeShaft(it[0].ns, this.timerShaftEL!);
505      it[1].x = ns2xByTimeShaft(it[1].ns, this.timerShaftEL!);
506    });
507    this.invisibleRows.forEach((it) => (it.needRefresh = true));
508    this.visibleRows.forEach((it) => (it.needRefresh = true));
509    this.refreshCanvas(false, 'rangeChange');
510  };
511  top: number = 0;
512  handler: number = -1;
513  rowsElOnScroll = (e: unknown): void => {
514    // @ts-ignore
515    const currentScrollY = e.target.scrollTop;
516    const deltaY = currentScrollY - this.prevScrollY;
517    this.linkNodes.forEach((itln) => {
518      if (itln[0].rowEL.collect) {
519        if (this.timerShaftEL?._checkExpand) {
520          itln[0].rowEL.translateY =
521            itln[0].rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!;
522        } else {
523          itln[0].rowEL.translateY = itln[0].rowEL.getBoundingClientRect().top - 195;
524        }
525      } else {
526        itln[0].rowEL.translateY = itln[0].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
527      }
528      if (itln[1].rowEL.collect) {
529        if (this.timerShaftEL?._checkExpand) {
530          itln[1].rowEL.translateY =
531            itln[1].rowEL.getBoundingClientRect().top - 195 + this.timerShaftEL._usageFoldHeight!;
532        } else {
533          itln[1].rowEL.translateY = itln[1].rowEL.getBoundingClientRect().top - 195;
534        }
535      } else {
536        itln[1].rowEL.translateY = itln[1].rowEL.offsetTop - this.rowsPaneEL!.scrollTop;
537      }
538      itln[0].y = itln[0].rowEL.translateY + itln[0].offsetY;
539      itln[1].y = itln[1].rowEL.translateY + itln[1].offsetY;
540    });
541    this.hoverStructNull();
542    if (this.scrollTimer) {
543      // @ts-ignore
544      clearTimeout(this.scrollTimer);
545    }
546    this.scrollTimer = setTimeout(() => {
547      TraceRow.range!.refresh = true;
548      requestAnimationFrame(() => this.refreshCanvas(false));
549    }, 200);
550    requestAnimationFrame(() => this.refreshCanvas(false));
551    spSystemTraceParentRowSticky(this, deltaY);
552    this.prevScrollY = currentScrollY;
553  };
554
555  private scrollTimer: unknown;
556
557  favoriteRowsElOnScroll = (e: unknown): void => {
558    this.rowsElOnScroll(e);
559  };
560
561  offset = 147;
562
563  getRowsContentHeight(): number {
564    // @ts-ignore
565    return [...this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row:not([sleeping])')]
566      .map((it) => it.clientHeight)
567      .reduce((acr, cur) => acr + cur, 0);
568  }
569
570  // refresh main canvas and favorite canvas
571  refreshCanvas(cache: boolean, from?: string): void {
572    if (this.visibleRows.length === 0) {
573      return;
574    }
575    //clear main canvas
576    this.canvasPanelCtx!.clearRect(0, 0, this.canvasPanel!.offsetWidth, this.canvasPanel!.offsetHeight);
577    this.favoriteChartListEL!.clearRect();
578    //draw lines for main canvas
579    let rowsContentHeight = this.getRowsContentHeight();
580    let canvasHeight =
581      rowsContentHeight > this.canvasPanel!.clientHeight ? this.canvasPanel!.clientHeight : rowsContentHeight;
582    drawLines(this.canvasPanelCtx!, TraceRow.range?.xs || [], canvasHeight, this.timerShaftEL!.lineColor());
583    //draw lines for favorite canvas
584    this.favoriteChartListEL?.drawLines(TraceRow.range?.xs, this.timerShaftEL!.lineColor()); // chart list
585
586    //canvas translate
587    this.canvasPanel!.style.transform = `translateY(${this.rowsPaneEL!.scrollTop}px)`;
588    //draw trace row
589    this.visibleRows.forEach((v, i) => {
590      if (v.collect) {
591        v.translateY =
592          v.getBoundingClientRect().top -
593          this.timerShaftEL?.clientHeight! -
594          this.parentElement!.previousElementSibling!.clientHeight -
595          1;
596      } else {
597        v.translateY = v.offsetTop - this.rowsPaneEL!.scrollTop;
598      }
599      v.draw(cache);
600    });
601    this.drawAllLines();
602  }
603
604  drawWakeUpLine(): void {
605    //draw wakeup for main canvas
606    drawWakeUp(
607      this.canvasPanelCtx,
608      CpuStruct.wakeupBean,
609      TraceRow.range!.startNS,
610      TraceRow.range!.endNS,
611      TraceRow.range!.totalNS,
612      {
613        x: 0,
614        y: 0,
615        width: TraceRow.FRAME_WIDTH,
616        height: this.canvasPanel!.clientHeight!,
617      } as Rect
618    );
619    this.favoriteChartListEL?.drawWakeUp();
620    // draw wakeuplist for main canvas
621    for (let i = 0; i < SpSystemTrace.wakeupList.length; i++) {
622      if (i + 1 === SpSystemTrace.wakeupList.length) {
623        return;
624      }
625      drawWakeUpList(
626        this.canvasPanelCtx,
627        SpSystemTrace.wakeupList[i + 1],
628        TraceRow.range!.startNS,
629        TraceRow.range!.endNS,
630        TraceRow.range!.totalNS,
631        {
632          x: 0,
633          y: 0,
634          width: this.timerShaftEL!.canvas!.clientWidth,
635          height: this.canvasPanel!.clientHeight!,
636        } as Rect
637      );
638      this.favoriteChartListEL?.drawWakeUpList(SpSystemTrace.wakeupList[i + 1]);
639    }
640  }
641
642  drawAllLines(): void {
643    // draw flag line segment for canvas
644    drawFlagLineSegment(
645      this.canvasPanelCtx,
646      this.hoverFlag,
647      this.selectFlag,
648      {
649        x: 0,
650        y: 0,
651        width: this.timerShaftEL?.canvas?.clientWidth,
652        height: this.canvasPanel?.clientHeight,
653      } as Rect,
654      this.timerShaftEL!
655    );
656    this.favoriteChartListEL?.drawFlagLineSegment(this.hoverFlag, this.selectFlag, this.timerShaftEL!);
657    this.drawWakeUpLine();
658    //draw system logs line segment for canvas
659    drawLogsLineSegment(
660      this.canvasPanelCtx,
661      this.traceSheetEL?.systemLogFlag,
662      {
663        x: 0,
664        y: 0,
665        width: this.timerShaftEL?.canvas?.clientWidth,
666        height: this.canvasPanel?.clientHeight,
667      },
668      this.timerShaftEL!
669    );
670    this.favoriteChartListEL?.drawLogsLineSegment(this.traceSheetEL!.systemLogFlag, this.timerShaftEL!);
671
672    // Draw the connection curve
673    if (this.linkNodes && this.linkNodes.length > 0) {
674      drawLinkLines(
675        this.canvasPanelCtx!,
676        this.linkNodes,
677        this.timerShaftEL!,
678        false,
679        this.favoriteChartListEL!.clientHeight
680      );
681      this.favoriteChartListEL?.drawLinkLines(
682        this.linkNodes,
683        this.timerShaftEL!,
684        true,
685        this.favoriteChartListEL!.clientHeight
686      );
687    }
688  }
689
690  documentOnMouseDown = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseDown(this, ev);
691
692  onContextMenuHandler = (e: Event): void => {
693    setTimeout(() => {
694      for (let key of this.keyPressMap.keys()) {
695        if (this.keyPressMap.get(key)) {
696          this.timerShaftEL?.stopWASD({ key: key });
697          this.keyPressMap.set(key, false);
698        }
699      }
700    }, 100);
701  };
702
703  documentOnMouseUp = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseUp(this, ev);
704
705  cancelDrag(): void {
706    this.rangeSelect.drag = false;
707    this.rangeSelect.isMouseDown = false;
708    TraceRow.rangeSelectObject = {
709      startX: 0,
710      endX: 0,
711      startNS: 0,
712      endNS: 0,
713    };
714  }
715
716  documentOnMouseOut = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseOut(this, ev);
717
718  keyPressMap: Map<string, boolean> = new Map([
719    ['w', false],
720    ['s', false],
721    ['a', false],
722    ['d', false],
723    ['f', false],
724  ]);
725
726  documentOnKeyDown = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyDown(this, ev);
727
728  documentOnKeyPress = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyPress(this, ev);
729
730  verticalScrollToRow(): void {
731    if (this.currentRow) {
732      //@ts-ignore
733      this.currentRow.scrollIntoViewIfNeeded();
734    }
735  }
736
737  setCurrentSlicesTime(): void {
738    if (CpuStruct.selectCpuStruct) {
739      if (CpuStruct.selectCpuStruct.startTime && CpuStruct.selectCpuStruct.dur) {
740        this.currentSlicesTime.startTime = CpuStruct.selectCpuStruct.startTime;
741        this.currentSlicesTime.endTime = CpuStruct.selectCpuStruct.startTime + CpuStruct.selectCpuStruct.dur;
742      }
743    } else if (ThreadStruct.selectThreadStruct) {
744      if (ThreadStruct.selectThreadStruct.startTime && ThreadStruct.selectThreadStruct.dur) {
745        this.currentSlicesTime.startTime = ThreadStruct.selectThreadStruct.startTime;
746        this.currentSlicesTime.endTime =
747          ThreadStruct.selectThreadStruct.startTime + ThreadStruct.selectThreadStruct.dur;
748      }
749    } else if (FuncStruct.selectFuncStruct) {
750      if (FuncStruct.selectFuncStruct.startTs && FuncStruct.selectFuncStruct.dur) {
751        this.currentSlicesTime.startTime = FuncStruct.selectFuncStruct.startTs;
752        this.currentSlicesTime.endTime = FuncStruct.selectFuncStruct.startTs + FuncStruct.selectFuncStruct.dur;
753      }
754    } else if (IrqStruct.selectIrqStruct) {
755      if (IrqStruct.selectIrqStruct.startNS && IrqStruct.selectIrqStruct.dur) {
756        this.currentSlicesTime.startTime = IrqStruct.selectIrqStruct.startNS;
757        this.currentSlicesTime.endTime = IrqStruct.selectIrqStruct.startNS + IrqStruct.selectIrqStruct.dur;
758      }
759    } else if (TraceRow.rangeSelectObject) {
760      this.currentRow = undefined;
761      if (TraceRow.rangeSelectObject.startNS && TraceRow.rangeSelectObject.endNS) {
762        this.currentSlicesTime.startTime = TraceRow.rangeSelectObject.startNS;
763        this.currentSlicesTime.endTime = TraceRow.rangeSelectObject.endNS;
764      }
765    } else if (JankStruct.selectJankStruct) {
766      if (JankStruct.selectJankStruct.ts && JankStruct.selectJankStruct.dur) {
767        this.currentSlicesTime.startTime = JankStruct.selectJankStruct.ts;
768        this.currentSlicesTime.endTime = JankStruct.selectJankStruct.ts + JankStruct.selectJankStruct.dur;
769      }
770    } else if (SampleStruct.selectSampleStruct) {
771      if (SampleStruct.selectSampleStruct.begin && SampleStruct.selectSampleStruct.end) {
772        this.currentSlicesTime.startTime =
773          SampleStruct.selectSampleStruct.begin - SampleStruct.selectSampleStruct.startTs!;
774        this.currentSlicesTime.endTime = SampleStruct.selectSampleStruct.end - SampleStruct.selectSampleStruct.startTs!;
775      }
776    } else {
777      this.currentSlicesTime.startTime = 0;
778      this.currentSlicesTime.endTime = 0;
779    }
780  }
781
782  public setSLiceMark = (shiftKey: boolean): SlicesTime | null | undefined => {
783    const selectedStruct: unknown =
784      CpuStruct.selectCpuStruct ||
785      ThreadStruct.selectThreadStruct ||
786      TraceRow.rangeSelectObject ||
787      FuncStruct.selectFuncStruct ||
788      IrqStruct.selectIrqStruct ||
789      JankStruct.selectJankStruct ||
790      AppStartupStruct.selectStartupStruct ||
791      SoStruct.selectSoStruct ||
792      SampleStruct.selectSampleStruct ||
793      AllAppStartupStruct.selectStartupStruct ||
794      FrameAnimationStruct.selectFrameAnimationStruct ||
795      JsCpuProfilerStruct.selectJsCpuProfilerStruct;
796    this.calculateSlicesTime(selectedStruct, shiftKey);
797
798    return this.slicestime;
799  };
800
801  private calculateSlicesTime(selectedStruct: unknown, shiftKey: boolean): void {
802    if (selectedStruct) {
803      let startTs = 0; // @ts-ignore
804      if (selectedStruct.begin && selectedStruct.end) {
805        // @ts-ignore
806        startTs = selectedStruct.begin - selectedStruct.startTs; // @ts-ignore
807        let end = selectedStruct.end - selectedStruct.startTs;
808        this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, end, shiftKey);
809      } else {
810        startTs = // @ts-ignore
811          selectedStruct.startTs || selectedStruct.startTime || selectedStruct.startNS || selectedStruct.ts || 0; // @ts-ignore
812        let dur = selectedStruct.dur || selectedStruct.totalTime || selectedStruct.endNS - selectedStruct.startNS || 0;
813        this.slicestime = this.timerShaftEL?.setSlicesMark(startTs, startTs + dur, shiftKey);
814      }
815    } else {
816      this.slicestime = this.timerShaftEL?.setSlicesMark();
817    }
818  }
819
820  stopWASD = (): void => {
821    setTimeout((): void => {
822      for (let key of this.keyPressMap.keys()) {
823        if (this.keyPressMap.get(key)) {
824          this.timerShaftEL?.stopWASD({ key: key });
825          this.keyPressMap.set(key, false);
826        }
827      }
828    }, 100);
829  };
830
831  // 一直按着回车键的时候执行搜索功能
832  continueSearch = (ev: KeyboardEvent): void => {
833    if (ev.key === 'Enter') {
834      if (ev.shiftKey) {
835        this.dispatchEvent(
836          new CustomEvent('trace-previous-data', {
837            detail: { down: true },
838            composed: false,
839          })
840        );
841      } else {
842        this.dispatchEvent(
843          new CustomEvent('trace-next-data', {
844            detail: { down: true },
845            composed: false,
846          })
847        );
848      }
849    }
850  };
851
852  documentOnKeyUp = (ev: KeyboardEvent): void => spSystemTraceDocumentOnKeyUp(this, ev);
853
854  /**
855   * 根据传入的参数实现卡尺和旗子的快捷跳转
856   * @param list 要跳转的数组
857   * @param type 标记类型(卡尺和旗子)
858   * @param direction 跳转方向(前一个/后一个)
859   */
860  MarkJump(list: Array<unknown>, type: string, direction: string, ev: KeyboardEvent): void {
861    this.traceSheetEL = this.shadowRoot?.querySelector('.trace-sheet'); // @ts-ignore
862    let find = list.find((it) => it.selected);
863    if (!find) {
864      // 如果当前没有选中的,就选中第一个
865      // @ts-ignore
866      list.forEach((it) => (it.selected = false));
867      this.ifSliceInView(list[0], type, ev); // @ts-ignore
868      list[0].selected = true;
869    } else {
870      for (let i = 0; i < list.length; i++) {
871        // 将当前数组中选中的那条数据改为未选中
872        // @ts-ignore
873        if (list[i].selected) {
874          // @ts-ignore
875          list[i].selected = false;
876          if (direction === 'previous') {
877            if (i === 0) {
878              // 如果当前选中的是第一个,就循环到最后一个上
879              this.ifSliceInView(list[list.length - 1], type, ev); // @ts-ignore
880              list[list.length - 1].selected = true;
881              break;
882            } else {
883              // 选中当前的上一个
884              this.ifSliceInView(list[i - 1], type, ev); // @ts-ignore
885              list[i - 1].selected = true;
886              break;
887            }
888          } else if (direction === 'next') {
889            if (i === list.length - 1) {
890              // 如果当前选中的是最后一个,就循环到第一个上
891              this.ifSliceInView(list[0], type, ev); // @ts-ignore
892              list[0].selected = true;
893              break;
894            } else {
895              // 选中当前的下一个
896              this.ifSliceInView(list[i + 1], type, ev); // @ts-ignore
897              list[i + 1].selected = true;
898              break;
899            }
900          }
901        }
902      }
903    }
904
905    if (type === 'flag') {
906      let currentPane = this.traceSheetEL?.displayTab<TabPaneFlag>('box-flag');
907      list.forEach((flag, index) => {
908        // @ts-ignore
909        this.timerShaftEL!.sportRuler!.drawTriangle(flag.time, flag.type); // @ts-ignore
910        if (flag.selected) {
911          // 修改当前选中的旗子对应的表格中某行的背景
912          currentPane!.setTableSelection(index + 1);
913        }
914      });
915    } else if (type === 'slice') {
916      this.refreshCanvas(true);
917      let currentPane = this.traceSheetEL?.displayTab<TabPaneCurrent>('tabpane-current');
918      list.forEach((slice, index) => {
919        // @ts-ignore
920        if (slice.selected) {
921          // 修改当前选中的卡尺对应的表格中某行的背景
922          currentPane!.setTableSelection(index + 1);
923        }
924      });
925    }
926  }
927
928  ifSliceInView(data: unknown, type: string, ev: KeyboardEvent): void {
929    let timeRangeEndNS = this.timerShaftEL?.getRangeRuler()?.range.endNS;
930    let timeRangeStartNS = this.timerShaftEL?.getRangeRuler()?.range.startNS;
931    if (type === 'flag') {
932      // @ts-ignore
933      data.startTime = data.time; // @ts-ignore
934      data.endTime = data.time;
935    } // @ts-ignore
936    let endTime = data.endTime; // @ts-ignore
937    let startTime = data.startTime;
938    if (endTime > timeRangeEndNS! || startTime < timeRangeStartNS!) {
939      // @ts-ignore
940      this.timerShaftEL!.documentOnKeyPress(ev, data);
941      setTimeout(() => {
942        this.timerShaftEL!.documentOnKeyUp(ev);
943      }, 1000);
944    }
945  }
946
947  isMouseInSheet = (ev: MouseEvent): boolean => {
948    this.isMousePointInSheet =
949      this.traceSheetEL?.getAttribute('mode') !== 'hidden' &&
950      ev.offsetX > this.traceSheetEL!.offsetLeft &&
951      ev.offsetY > this.traceSheetEL!.offsetTop;
952    return this.isMousePointInSheet;
953  };
954  // @ts-ignore
955  favoriteChangeHandler = (row: TraceRow<unknown>): void => {
956    info('favoriteChangeHandler', row.frame, row.offsetTop, row.offsetHeight);
957  };
958
959  /**
960   * 根据选择的traceRow 处理foler
961   * @param currentRow 当前点击checkbox的row
962   */
963  // @ts-ignore
964  setParentCheckStatus(currentRow: TraceRow<unknown>): void {
965    if (currentRow.parentRowEl?.folder && currentRow.parentRowEl?.childrenList) {
966      const parent = currentRow.parentRowEl;
967      const childrenList = parent.childrenList;
968      const selectList = [];
969      const unSelectList = [];
970      for (const child of childrenList) {
971        if (child.offsetParent === null) {
972          continue;
973        }
974        if (child.checkType === '2') {
975          selectList.push(child);
976        } else {
977          unSelectList.push(child);
978        }
979      }
980      if (unSelectList.length === 0) {
981        parent.setAttribute('check-type', '2');
982        parent.rangeSelect = true;
983        parent.checkBoxEL!.checked = true;
984        parent.checkBoxEL!.indeterminate = false;
985      } else if (selectList.length === 0) {
986        parent.setAttribute('check-type', '0');
987        parent.rangeSelect = false;
988        parent.checkBoxEL!.checked = false;
989        parent.checkBoxEL!.indeterminate = false;
990      } else {
991        parent.setAttribute('check-type', '1');
992        parent.rangeSelect = false;
993        parent.checkBoxEL!.checked = false;
994        parent.checkBoxEL!.indeterminate = true;
995      }
996    }
997  }
998
999  /**
1000   * 处理点击checkbox的逻辑
1001   * @param row 当前点击checkbox的row
1002   */
1003  // @ts-ignore
1004  selectChangeHandler = (row: TraceRow<unknown>): void => {
1005    this.setParentCheckStatus(row);
1006    const rows = [
1007      // @ts-ignore
1008      ...this.shadowRoot!.querySelectorAll<TraceRow<unknown>>("trace-row[check-type='2']"),
1009      ...this.favoriteChartListEL!.getAllSelectCollectRows(),
1010    ];
1011    this.isSelectClick = true;
1012    this.rangeSelect.rangeTraceRow = rows; // @ts-ignore
1013    let changeTraceRows: Array<TraceRow<unknown>> = [];
1014    if (this.rangeTraceRow!.length < rows.length) {
1015      // @ts-ignore
1016      rows!.forEach((currentTraceRow: TraceRow<unknown>) => {
1017        let changeFilter = this.rangeTraceRow!.filter(
1018          // @ts-ignore
1019          (prevTraceRow: TraceRow<unknown>) => prevTraceRow === currentTraceRow
1020        );
1021        if (changeFilter.length < 1) {
1022          changeTraceRows.push(currentTraceRow);
1023        }
1024      });
1025      if (changeTraceRows.length > 0) {
1026        // @ts-ignore
1027        changeTraceRows!.forEach((changeTraceRow: TraceRow<unknown>) => {
1028          let pointEvent = this.createPointEvent(changeTraceRow);
1029          SpStatisticsHttpUtil.addOrdinaryVisitAction({
1030            action: 'trace_row', // @ts-ignore
1031            event: pointEvent,
1032          });
1033        });
1034      }
1035    }
1036    this.rangeTraceRow = rows;
1037    this.rangeSelect.selectHandler?.(this.rangeSelect.rangeTraceRow, false);
1038  };
1039  inFavoriteArea: boolean | undefined;
1040  documentOnMouseMove = (ev: MouseEvent): void => spSystemTraceDocumentOnMouseMove(this, ev);
1041
1042  hoverStructNull(): SpSystemTrace {
1043    CpuStruct.hoverCpuStruct = undefined;
1044    CpuFreqStruct.hoverCpuFreqStruct = undefined;
1045    ThreadStruct.hoverThreadStruct = undefined;
1046    FuncStruct.hoverFuncStruct = undefined;
1047    HiPerfCpuStruct.hoverStruct = undefined;
1048    HiPerfProcessStruct.hoverStruct = undefined;
1049    HiPerfThreadStruct.hoverStruct = undefined;
1050    HiPerfEventStruct.hoverStruct = undefined;
1051    HiPerfReportStruct.hoverStruct = undefined;
1052    CpuStateStruct.hoverStateStruct = undefined;
1053    CpuAbilityMonitorStruct.hoverCpuAbilityStruct = undefined;
1054    DiskAbilityMonitorStruct.hoverDiskAbilityStruct = undefined;
1055    MemoryAbilityMonitorStruct.hoverMemoryAbilityStruct = undefined;
1056    NetworkAbilityMonitorStruct.hoverNetworkAbilityStruct = undefined;
1057    CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = undefined;
1058    FpsStruct.hoverFpsStruct = undefined;
1059    ClockStruct.hoverClockStruct = undefined;
1060    IrqStruct.hoverIrqStruct = undefined;
1061    HeapStruct.hoverHeapStruct = undefined;
1062    JankStruct.hoverJankStruct = undefined;
1063    AppStartupStruct.hoverStartupStruct = undefined;
1064    SoStruct.hoverSoStruct = undefined;
1065    HeapSnapshotStruct.hoverSnapshotStruct = undefined;
1066    FrameAnimationStruct.hoverFrameAnimationStruct = undefined;
1067    FrameDynamicStruct.hoverFrameDynamicStruct = undefined;
1068    FrameSpacingStruct.hoverFrameSpacingStruct = undefined;
1069    JsCpuProfilerStruct.hoverJsCpuProfilerStruct = undefined;
1070    SnapshotStruct.hoverSnapshotStruct = undefined;
1071    HiPerfCallChartStruct.hoverPerfCallCutStruct = undefined;
1072    SampleStruct.hoverSampleStruct = undefined;
1073    PerfToolStruct.hoverPerfToolStruct = undefined;
1074    this.tipEL!.style.display = 'none';
1075    return this;
1076  }
1077
1078  selectStructNull(): SpSystemTrace {
1079    CpuStruct.selectCpuStruct = undefined;
1080    CpuStruct.wakeupBean = null;
1081    CpuFreqStruct.selectCpuFreqStruct = undefined;
1082    ThreadStruct.selectThreadStruct = undefined;
1083    FuncStruct.selectFuncStruct = undefined;
1084    SpHiPerf.selectCpuStruct = undefined;
1085    CpuStateStruct.selectStateStruct = undefined;
1086    CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = undefined;
1087    ClockStruct.selectClockStruct = undefined;
1088    IrqStruct.selectIrqStruct = undefined;
1089    JankStruct.selectJankStruct = undefined;
1090    HeapStruct.selectHeapStruct = undefined;
1091    AppStartupStruct.selectStartupStruct = undefined;
1092    SoStruct.selectSoStruct = undefined;
1093    HeapSnapshotStruct.selectSnapshotStruct = undefined;
1094    FrameSpacingStruct.selectFrameSpacingStruct = undefined;
1095    FrameAnimationStruct.selectFrameAnimationStruct = undefined;
1096    FrameDynamicStruct.selectFrameDynamicStruct = undefined;
1097    JsCpuProfilerStruct.selectJsCpuProfilerStruct = undefined;
1098    SnapshotStruct.selectSnapshotStruct = undefined;
1099    HiPerfCallChartStruct.selectStruct = undefined;
1100    AllAppStartupStruct.selectStartupStruct = undefined;
1101    LtpoStruct.selectLtpoStruct = undefined;
1102    HitchTimeStruct.selectHitchTimeStruct = undefined;
1103    SampleStruct.selectSampleStruct = undefined;
1104    PerfToolStruct.selectPerfToolStruct = undefined;
1105    return this;
1106  }
1107
1108  isWASDKeyPress(): boolean | undefined {
1109    return (
1110      this.keyPressMap.get('w') || this.keyPressMap.get('a') || this.keyPressMap.get('d') || this.keyPressMap.get('s')
1111    );
1112  }
1113
1114  documentOnClick = (ev: MouseEvent): void => spSystemTraceDocumentOnClick(this, ev);
1115
1116  clickEmptyArea(): void {
1117    this.queryAllTraceRow().forEach((it) => {
1118      it.checkType = '-1';
1119      it.rangeSelect = false;
1120    });
1121    this.rangeSelect.rangeTraceRow = [];
1122    TraceRow.rangeSelectObject = undefined;
1123    this.selectStructNull();
1124    this.wakeupListNull();
1125    this.observerScrollHeightEnable = false;
1126    this.selectFlag = null;
1127    this.timerShaftEL?.removeTriangle('inverted');
1128    //   如果鼠标在SportRuler区域不隐藏tab页
1129    if (!SportRuler.isMouseInSportRuler) {
1130      this.traceSheetEL?.setMode('hidden');
1131    }
1132    this.removeLinkLinesByBusinessType('task', 'thread');
1133    this.refreshCanvas(true);
1134    JankStruct.delJankLineFlag = true;
1135  }
1136
1137  //泳道图点击判定条件
1138  traceRowClickJudgmentConditions: Map<string, () => boolean> = new Map<string, () => boolean>([
1139    [TraceRow.ROW_TYPE_CPU, (): boolean => CpuStruct.hoverCpuStruct !== null && CpuStruct.hoverCpuStruct !== undefined],
1140    [
1141      TraceRow.ROW_TYPE_THREAD,
1142      (): boolean => ThreadStruct.hoverThreadStruct !== null && ThreadStruct.hoverThreadStruct !== undefined,
1143    ],
1144    [
1145      TraceRow.ROW_TYPE_FUNC,
1146      (): boolean => FuncStruct.hoverFuncStruct !== null && FuncStruct.hoverFuncStruct !== undefined,
1147    ],
1148    [
1149      TraceRow.ROW_TYPE_SAMPLE,
1150      (): boolean => SampleStruct.hoverSampleStruct !== null && SampleStruct.hoverSampleStruct !== undefined,
1151    ],
1152    [
1153      TraceRow.ROW_TYPE_CPU_FREQ,
1154      (): boolean => CpuFreqStruct.hoverCpuFreqStruct !== null && CpuFreqStruct.hoverCpuFreqStruct !== undefined,
1155    ],
1156    [
1157      TraceRow.ROW_TYPE_CPU_STATE,
1158      (): boolean => CpuStateStruct.hoverStateStruct !== null && CpuStateStruct.hoverStateStruct !== undefined,
1159    ],
1160    [
1161      TraceRow.ROW_TYPE_CPU_FREQ_LIMIT,
1162      (): boolean =>
1163        CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct !== null &&
1164        CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct !== undefined,
1165    ],
1166    [
1167      TraceRow.ROW_TYPE_CLOCK,
1168      (): boolean => ClockStruct.hoverClockStruct !== null && ClockStruct.hoverClockStruct !== undefined,
1169    ],
1170    [TraceRow.ROW_TYPE_IRQ, (): boolean => IrqStruct.hoverIrqStruct !== null && IrqStruct.hoverIrqStruct !== undefined],
1171    [
1172      TraceRow.ROW_TYPE_APP_STARTUP,
1173      (): boolean => AppStartupStruct.hoverStartupStruct !== null && AppStartupStruct.hoverStartupStruct !== undefined,
1174    ],
1175    [
1176      TraceRow.ROW_TYPE_ALL_APPSTARTUPS,
1177      (): boolean =>
1178        AllAppStartupStruct.hoverStartupStruct !== null && AllAppStartupStruct.hoverStartupStruct !== undefined,
1179    ],
1180    [
1181      TraceRow.ROW_TYPE_STATIC_INIT,
1182      (): boolean => SoStruct.hoverSoStruct !== null && SoStruct.hoverSoStruct !== undefined,
1183    ],
1184    [
1185      TraceRow.ROW_TYPE_JANK,
1186      (): boolean => JankStruct.hoverJankStruct !== null && JankStruct.hoverJankStruct !== undefined,
1187    ],
1188    [
1189      TraceRow.ROW_TYPE_HEAP,
1190      (): boolean => HeapStruct.hoverHeapStruct !== null && HeapStruct.hoverHeapStruct !== undefined,
1191    ],
1192    [
1193      TraceRow.ROW_TYPE_SYS_MEMORY_GPU_TOTAL,
1194      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1195    ],
1196    [
1197      TraceRow.ROW_TYPE_SYS_MEMORY_GPU_WINDOW,
1198      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1199    ],
1200    [
1201      TraceRow.ROW_TYPE_HEAP_SNAPSHOT,
1202      (): boolean =>
1203        HeapSnapshotStruct.hoverSnapshotStruct !== null && HeapSnapshotStruct.hoverSnapshotStruct !== undefined,
1204    ],
1205    [
1206      TraceRow.ROW_TYPE_FRAME_ANIMATION,
1207      (): boolean =>
1208        FrameAnimationStruct.hoverFrameAnimationStruct !== null &&
1209        FrameAnimationStruct.hoverFrameAnimationStruct !== undefined,
1210    ],
1211    [
1212      TraceRow.ROW_TYPE_FRAME_DYNAMIC,
1213      (): boolean =>
1214        FrameDynamicStruct.hoverFrameDynamicStruct !== null && FrameDynamicStruct.hoverFrameDynamicStruct !== undefined,
1215    ],
1216    [
1217      TraceRow.ROW_TYPE_FRAME_SPACING,
1218      (): boolean =>
1219        FrameSpacingStruct.hoverFrameSpacingStruct !== null && FrameSpacingStruct.hoverFrameSpacingStruct !== undefined,
1220    ],
1221    [
1222      TraceRow.ROW_TYPE_JS_CPU_PROFILER,
1223      (): boolean =>
1224        JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== null &&
1225        JsCpuProfilerStruct.hoverJsCpuProfilerStruct !== undefined,
1226    ],
1227    [
1228      TraceRow.ROW_TYPE_PURGEABLE_TOTAL_ABILITY,
1229      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1230    ],
1231    [
1232      TraceRow.ROW_TYPE_PURGEABLE_PIN_ABILITY,
1233      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1234    ],
1235    [
1236      TraceRow.ROW_TYPE_PURGEABLE_TOTAL_VM,
1237      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1238    ],
1239    [
1240      TraceRow.ROW_TYPE_PURGEABLE_PIN_VM,
1241      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1242    ],
1243    [
1244      TraceRow.ROW_TYPE_DMA_ABILITY,
1245      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1246    ],
1247    [
1248      TraceRow.ROW_TYPE_DMA_VMTRACKER,
1249      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1250    ],
1251    [
1252      TraceRow.ROW_TYPE_GPU_MEMORY_ABILITY,
1253      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1254    ],
1255    [
1256      TraceRow.ROW_TYPE_GPU_MEMORY_VMTRACKER,
1257      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1258    ],
1259    [
1260      TraceRow.ROW_TYPE_GPU_RESOURCE_VMTRACKER,
1261      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1262    ],
1263    [
1264      TraceRow.ROW_TYPE_VMTRACKER_SHM,
1265      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1266    ],
1267    [
1268      TraceRow.ROW_TYPE_VM_TRACKER_SMAPS,
1269      (): boolean => SnapshotStruct.hoverSnapshotStruct !== null && SnapshotStruct.hoverSnapshotStruct !== undefined,
1270    ],
1271  ]);
1272  // @ts-ignore
1273  onClickHandler(clickRowType: string, row?: TraceRow<unknown>, entry?: unknown): void {
1274    spSystemTraceOnClickHandler(this, clickRowType, row, entry);
1275  }
1276
1277  makePoint(
1278    ts: number,
1279    dur: number,
1280    translateY: number,
1281    rowStruct: unknown,
1282    offsetY: number,
1283    business: string,
1284    lineType: LineType,
1285    isRight: boolean
1286  ): PairPoint {
1287    return {
1288      x: ns2xByTimeShaft(ts + dur, this.timerShaftEL!),
1289      y: translateY!,
1290      offsetY: offsetY,
1291      ns: ts + dur, // @ts-ignore
1292      rowEL: rowStruct!,
1293      isRight: isRight,
1294      business: business,
1295      lineType: lineType,
1296    };
1297  }
1298  // @ts-ignore
1299  drawTaskPollLine(row?: TraceRow<unknown>): void {
1300    spSystemTraceDrawTaskPollLine(this, row);
1301  }
1302  drawJankLine(
1303    endParentRow: unknown,
1304    selectJankStruct: JankStruct,
1305    data: unknown,
1306    isBinderClick: boolean = false
1307  ): void {
1308    spSystemTraceDrawJankLine(this, endParentRow, selectJankStruct, data, isBinderClick);
1309  }
1310
1311  drawThreadLine(endParentRow: unknown, selectThreadStruct: ThreadStruct | undefined, data: unknown): void {
1312    spSystemTraceDrawThreadLine(this, endParentRow, selectThreadStruct, data);
1313  }
1314
1315  getStartRow(selectRowId: number | undefined, collectList: unknown[]): unknown {
1316    let startRow = this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>(
1317      `trace-row[row-id='${selectRowId}'][row-type='thread']`
1318    );
1319    if (!startRow) {
1320      for (let collectChart of collectList) {
1321        // @ts-ignore
1322        if (collectChart.rowId === selectRowId?.toString() && collectChart.rowType === 'thread') {
1323          // @ts-ignore
1324          startRow = collectChart;
1325          break;
1326        }
1327      }
1328    }
1329    return startRow;
1330  }
1331
1332  calculateStartY(startRow: unknown, selectThreadStruct: ThreadStruct): [number, unknown, number] {
1333    // @ts-ignore
1334    let startY = startRow!.translateY!;
1335    let startRowEl = startRow;
1336    let startOffSetY = 20 * 0.5;
1337    const startParentRow = this.shadowRoot?.querySelector<TraceRow<ThreadStruct>>( // @ts-ignore
1338      `trace-row[row-id='${startRow.rowParentId}'][folder]`
1339    );
1340    const expansionFlag = this.collectionHasThread(startRow);
1341    if (startParentRow && !startParentRow.expansion && expansionFlag) {
1342      startY = startParentRow.translateY!;
1343      startRowEl = startParentRow;
1344      startOffSetY = 10 * 0.5;
1345    }
1346    return [startY, startRowEl, startOffSetY];
1347  }
1348
1349  calculateEndY(endParentRow: unknown, endRowStruct: unknown): [number, unknown, number] {
1350    // @ts-ignore
1351    let endY = endRowStruct.translateY!;
1352    let endRowEl = endRowStruct;
1353    let endOffSetY = 20 * 0.5;
1354    const expansionFlag = this.collectionHasThread(endRowStruct); // @ts-ignore
1355    if (!endParentRow.expansion && expansionFlag) {
1356      // @ts-ignore
1357      endY = endParentRow.translateY!;
1358      endRowEl = endParentRow;
1359      endOffSetY = 10 * 0.5;
1360    }
1361    return [endY, endRowEl, endOffSetY];
1362  }
1363
1364  collectionHasThread(threadRow: unknown): boolean {
1365    const collectList = this.favoriteChartListEL!.getCollectRows();
1366    for (let item of collectList!) {
1367      // @ts-ignore
1368      if (item.rowId === threadRow.rowId && item.rowType === threadRow.rowType) {
1369        return false;
1370      }
1371    }
1372    return true;
1373  }
1374
1375  translateByMouseMove(ev: MouseEvent): void {
1376    ev.preventDefault();
1377    let offset = 0;
1378    if (this.offsetMouse === 0) {
1379      this.offsetMouse = ev.clientX;
1380      offset = ev.clientX - this.mouseCurrentPosition;
1381    } else {
1382      offset = ev.clientX - this.offsetMouse;
1383    }
1384    this.offsetMouse = ev.clientX;
1385    const rangeRuler = this.timerShaftEL?.getRangeRuler()!;
1386    rangeRuler.translate(offset);
1387  }
1388
1389  private eventListener(): void {
1390    /**
1391     * 监听时间轴区间变化
1392     */
1393    this.timerShaftEL!.rangeChangeHandler = this.timerShaftELRangeChange;
1394    this.timerShaftEL!.rangeClickHandler = this.timerShaftELRangeClick;
1395    this.timerShaftEL!.flagChangeHandler = this.timerShaftELFlagChange;
1396    this.timerShaftEL!.flagClickHandler = this.timerShaftELFlagClickHandler;
1397    /**
1398     * 监听rowsEL的滚动时间,刷新可见区域的trace-row组件的时间区间(将触发trace-row组件重绘)
1399     */
1400    this.rowsPaneEL?.addEventListener('scroll', this.rowsElOnScroll, {
1401      passive: true,
1402    });
1403    this.favoriteChartListEL?.addEventListener('scroll', this.favoriteRowsElOnScroll, {
1404      passive: true,
1405    });
1406    /**
1407     * 监听document的mousemove事件 坐标通过换算后找到当前鼠标所在的trace-row组件,将坐标传入
1408     */
1409    this.addEventListener('mousemove', this.documentOnMouseMove);
1410    this.addEventListener('click', this.documentOnClick);
1411    this.addEventListener('mousedown', this.documentOnMouseDown);
1412    this.addEventListener('mouseup', this.documentOnMouseUp);
1413    this.addEventListener('mouseout', this.documentOnMouseOut);
1414    document.addEventListener('keydown', this.documentOnKeyDown);
1415    document.addEventListener('keypress', this.documentOnKeyPress);
1416    document.addEventListener('keyup', this.documentOnKeyUp);
1417    document.addEventListener('contextmenu', this.onContextMenuHandler);
1418    this.wheelListener();
1419  }
1420
1421  private subRecordExportListener(): void {
1422    window.subscribe(window.SmartEvent.UI.ExportRecord, (params) => {
1423      let range = this.timerShaftEL?.rangeRuler?.range;
1424      if (range) {
1425        let expandRows =
1426          Array.from(this.rowsEL!.querySelectorAll<TraceRow<BaseStruct>>('trace-row[folder][expansion]')) || [];
1427        let data = JSON.stringify({
1428          leftNS: range.startNS,
1429          rightNS: range.endNS,
1430          G1: this.favoriteChartListEL!.getCollectRowsInfo('1'),
1431          G2: this.favoriteChartListEL!.getCollectRowsInfo('2'),
1432          expand: expandRows.map((row) => {
1433            return {
1434              type: row.rowType,
1435              name: row.name,
1436              id: row.rowId,
1437            };
1438          }),
1439          scrollTop: this.rowsEL!.scrollTop,
1440          favoriteScrollTop: this.favoriteChartListEL!.scrollTop,
1441        });
1442        this.downloadRecordFile(data).then(() => {});
1443      }
1444    });
1445  }
1446
1447  private async downloadRecordFile(jsonStr: string): Promise<void> {
1448    let a = document.createElement('a');
1449    let buffer = await readTraceFileBuffer();
1450    if (buffer) {
1451      let str = `MarkPositionJSON->${jsonStr}\n`;
1452      let mark = new Blob([str]);
1453      let markBuf = await mark.arrayBuffer();
1454      a.href = URL.createObjectURL(new Blob([`${markBuf.byteLength}`, mark, buffer])); // @ts-ignore
1455      a.download = (window as unknown).traceFileName || `${new Date().getTime()}`;
1456      a.click();
1457    }
1458    window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Downloading trace file with mark' });
1459  }
1460
1461  private subRecordImportListener(): void {
1462    //@ts-ignore
1463    window.subscribe(window.SmartEvent.UI.ImportRecord, (data: string) => {
1464      let record = JSON.parse(data);
1465      if (record.leftNS !== undefined && record.rightNS !== undefined) {
1466        this.favoriteChartListEL?.removeAllCollectRow();
1467        let currentGroup = this.currentCollectGroup;
1468        if (record.G1) {
1469          this.currentCollectGroup = '1';
1470          this.restoreRecordCollectRows(record.G1);
1471        }
1472        if (record.G2) {
1473          this.currentCollectGroup = '2';
1474          this.restoreRecordCollectRows(record.G2);
1475        }
1476        if (record.expand) {
1477          let expandRows = // @ts-ignore
1478            Array.from(this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row[folder][expansion]')) || [];
1479          let expands: Array<unknown> = record.expand;
1480          //关闭不在记录中的父泳道
1481          for (let expandRow of expandRows) {
1482            if (
1483              !expands.includes(
1484                (it: unknown) =>
1485                  // @ts-ignore
1486                  it.id === expandRow.rowId && it.name === expandRow.name && it.type === expandRow.rowType
1487              )
1488            ) {
1489              expandRow.expansion = false;
1490            }
1491          }
1492          //展开记录的泳道
1493          for (let it of record.expand) {
1494            // @ts-ignore
1495            let traceRow = this.rowsEL!.querySelector<TraceRow<unknown>>(
1496              `trace-row[folder][row-id='${it.id}'][row-type='${it.type}']`
1497            );
1498            if (traceRow && !traceRow.expansion) {
1499              traceRow.expansion = true;
1500            }
1501          }
1502        }
1503        this.currentCollectGroup = currentGroup;
1504        this.timerShaftEL?.setRangeNS(record.leftNS, record.rightNS);
1505        TraceRow.range!.refresh = true;
1506        this.refreshCanvas(true);
1507        this.restoreRecordScrollTop(record.scrollTop, record.favoriteScrollTop);
1508      }
1509    });
1510  }
1511
1512  private restoreRecordScrollTop(mainScrollTop: number, favoriteScrollTop: number): void {
1513    if (mainScrollTop && mainScrollTop > 0) {
1514      this.rowsPaneEL!.scroll({
1515        top: mainScrollTop,
1516        left: 0,
1517        behavior: 'smooth',
1518      });
1519    }
1520    if (favoriteScrollTop && favoriteScrollTop > 0) {
1521      this.favoriteChartListEL?.scroll({
1522        top: favoriteScrollTop,
1523        left: 0,
1524        behavior: 'smooth',
1525      });
1526    }
1527  }
1528
1529  private restoreRecordCollectRows(group: Array<unknown>): void {
1530    group.forEach((it: unknown) => {
1531      // @ts-ignore
1532      let traceRow: TraceRow<unknown> | undefined | null = this.rowsEL!.querySelector<TraceRow<unknown>>( // @ts-ignore
1533        `trace-row[row-id='${it.id}'][row-type='${it.type}']`
1534      );
1535      if (traceRow === null || traceRow === undefined) {
1536        // @ts-ignore
1537        if (it.parents.length > 0) {
1538          // @ts-ignore
1539          let rootFolder = it.parents[0]; // @ts-ignore
1540          let folderRow: TraceRow<unknown> | undefined | null = this.rowsEL!.querySelector<TraceRow<unknown>>(
1541            `trace-row[row-id='${rootFolder.id}'][row-type='${rootFolder.type}']`
1542          );
1543          if (folderRow) {
1544            if (!folderRow!.expansion) {
1545              folderRow!.expansion = true;
1546            } // @ts-ignore
1547            for (let i = 1; i < it.parents.length; i++) {
1548              folderRow = folderRow!.childrenList.find(
1549                // @ts-ignore
1550                (child) => child.rowId === it.parents[i].id && child.rowType === it.parents[i].type
1551              );
1552              if (!folderRow!.expansion) {
1553                folderRow!.expansion = true;
1554              }
1555            }
1556          }
1557          if (folderRow) {
1558            // @ts-ignore
1559            traceRow = folderRow.childrenList.find((child) => child.rowId === it.id && child.rowType === it.type);
1560          }
1561        }
1562      }
1563      if (traceRow) {
1564        traceRow.collectEL?.click();
1565      }
1566    });
1567  }
1568
1569  private wheelListener(): void {
1570    document.addEventListener(
1571      'wheel',
1572      (e): void => {
1573        if (e.ctrlKey) {
1574          if (e.deltaY > 0) {
1575            e.preventDefault();
1576            e.stopPropagation();
1577            let eventS = new KeyboardEvent('keypress', {
1578              key: 's',
1579              code: '83',
1580              keyCode: 83,
1581            });
1582            this.timerShaftEL!.documentOnKeyPress(eventS);
1583            setTimeout(() => this.timerShaftEL!.documentOnKeyUp(eventS), 200);
1584          }
1585          if (e.deltaY < 0) {
1586            e.preventDefault();
1587            e.stopPropagation();
1588            let eventW = new KeyboardEvent('keypress', {
1589              key: 'w',
1590              code: '87',
1591              keyCode: 87,
1592            });
1593            this.timerShaftEL!.documentOnKeyPress(eventW);
1594            setTimeout(() => this.timerShaftEL!.documentOnKeyUp(eventW), 200);
1595          }
1596        }
1597      },
1598      { passive: false }
1599    );
1600  }
1601
1602  connectedCallback(): void {
1603    this.initPointToEvent();
1604    this.eventListener();
1605    this.subRecordExportListener();
1606    this.subRecordImportListener();
1607    /**
1608     * 泳道图中添加ctrl+鼠标滚轮事件,对泳道图进行放大缩小。
1609     * 鼠标滚轮事件转化为键盘事件,keyPress和keyUp两个事件需要配合使用,
1610     * 否则泳道图会一直放大或一直缩小。
1611     * setTimeout()函数中的时间参数可以控制鼠标滚轮的频率。
1612     */
1613    SpApplication.skinChange2 = (val: boolean): void => {
1614      this.timerShaftEL?.render();
1615    };
1616    window.subscribe(window.SmartEvent.UI.UploadSOFile, (data): void => {
1617      this.chartManager?.importSoFileUpdate().then(() => {
1618        window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Import So File' });
1619        let updateCanvas = this.traceSheetEL?.updateRangeSelect();
1620        if (updateCanvas) {
1621          this.refreshCanvas(true);
1622        }
1623      });
1624    });
1625    window.subscribe(window.SmartEvent.UI.KeyPath, (data): void => {
1626      this.invisibleRows.forEach((it) => (it.needRefresh = true));
1627      this.visibleRows.forEach((it) => (it.needRefresh = true)); //@ts-ignore
1628      if (data.length === 0) {
1629        // clear
1630        SpSystemTrace.keyPathList = [];
1631        this.refreshCanvas(false);
1632      } else {
1633        // draw
1634        //@ts-ignore
1635        queryCpuKeyPathData(data).then((res): void => {
1636          SpSystemTrace.keyPathList = res;
1637          this.refreshCanvas(false);
1638        });
1639      }
1640    });
1641    window.subscribe(window.SmartEvent.UI.CheckALL, (data): void => {
1642      //@ts-ignore
1643      this.getCollectRows((row) => row.rowParentId === data.rowId).forEach((it) => {
1644        //@ts-ignore
1645        it.checkType = data.isCheck ? '2' : '0';
1646      });
1647    });
1648    window.subscribe(window.SmartEvent.UI.HoverNull, () => this.hoverStructNull());
1649    this.subscribeBottomTabVisibleEvent();
1650  }
1651
1652  private scrollH: number = 0;
1653
1654  subscribeBottomTabVisibleEvent(): void {
1655    //@ts-ignore
1656    window.subscribe(window.SmartEvent.UI.ShowBottomTab, (data: { show: number; delta: number }): void => {
1657      if (data.show === 1) {
1658        //显示底部tab
1659        this.scrollH = this.rowsEL!.scrollHeight;
1660      } else {
1661        // 底部 tab 为 最小化 或者隐藏 时候
1662        if (this.rowsEL!.scrollHeight > this.scrollH) {
1663          this.rowsEL!.scrollTop = this.rowsEL!.scrollTop - data.delta;
1664        }
1665      }
1666    });
1667  }
1668  // @ts-ignore
1669  favoriteAreaSearchHandler(row: TraceRow<unknown>): void {
1670    if (this.timerShaftEL!.collecBtn!.hasAttribute('close')) {
1671      this.timerShaftEL!.collecBtn!.removeAttribute('close');
1672      this.favoriteChartListEL!.showCollectArea();
1673    }
1674    this.favoriteChartListEL?.expandSearchRowGroup(row);
1675  }
1676
1677  scrollToProcess(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true): void {
1678    let traceRow = // @ts-ignore
1679      this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) ||
1680      this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType);
1681    if (traceRow?.collect) {
1682      this.favoriteChartListEL!.scroll({
1683        top:
1684          (traceRow?.offsetTop || 0) -
1685          this.favoriteChartListEL!.getCanvas()!.offsetHeight +
1686          (traceRow?.offsetHeight || 0),
1687        left: 0,
1688        behavior: smooth ? 'smooth' : undefined,
1689      });
1690    } else {
1691      // @ts-ignore
1692      let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}'][folder]`);
1693      if (row && !row.expansion) {
1694        row.expansion = true;
1695      }
1696      if (traceRow && traceRow.offsetTop >= 0 && traceRow.offsetHeight >= 0) {
1697        this.rowsPaneEL!.scroll({
1698          top: (traceRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + (traceRow?.offsetHeight || 0),
1699          left: 0,
1700          behavior: smooth ? 'smooth' : undefined,
1701        });
1702      }
1703    }
1704  }
1705
1706  scrollToDepth(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true, depth: number): void {
1707    let rootRow = // @ts-ignore
1708      this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowId}'][row-type='${rowType}']`) ||
1709      this.favoriteChartListEL!.getCollectRow((row) => row.rowId === rowId && row.rowType === rowType);
1710    if (rootRow && rootRow!.collect) {
1711      this.favoriteAreaSearchHandler(rootRow);
1712      rootRow.expandFunc();
1713      if (!this.isInViewport(rootRow)) {
1714        setTimeout(() => {
1715          rootRow!.scrollIntoView({ behavior: 'smooth' });
1716        }, 500);
1717      }
1718    } else {
1719      // @ts-ignore
1720      let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}'][folder]`);
1721      if (row && !row.expansion) {
1722        row.expansion = true;
1723      }
1724      if (rootRow) {
1725        rootRow.expandFunc();
1726      }
1727      setTimeout(() => {
1728        rootRow!.scrollIntoView({ behavior: 'smooth', block: 'center' });
1729      }, 500);
1730    }
1731  }
1732
1733  isInViewport(e: unknown): boolean {
1734    // @ts-ignore
1735    const rect = e.getBoundingClientRect();
1736    return (
1737      rect.top >= 0 &&
1738      rect.left >= 0 &&
1739      rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
1740      rect.right <= (window.innerWidth || document.documentElement.clientWidth)
1741    );
1742  }
1743
1744  scrollToFunction(rowId: string, rowParentId: string, rowType: string, smooth: boolean = true): void {
1745    let condition = `trace-row[row-id='${rowId}'][row-type='${rowType}'][row-parent-id='${rowParentId}']`;
1746    let rootRow = // @ts-ignore
1747      this.rowsEL!.querySelector<TraceRow<unknown>>(condition) ||
1748      this.favoriteChartListEL!.getCollectRow((row) => {
1749        return row.rowId === rowId && row.rowType === rowType && row.rowParentId === rowParentId;
1750      });
1751    if (rootRow?.collect) {
1752      this.favoriteAreaSearchHandler(rootRow);
1753      this.favoriteChartListEL!.scroll({
1754        top:
1755          (rootRow?.offsetTop || 0) -
1756          this.favoriteChartListEL!.getCanvas()!.offsetHeight +
1757          (rootRow?.offsetHeight || 0),
1758        left: 0,
1759        behavior: smooth ? 'smooth' : undefined,
1760      });
1761    } else {
1762      // @ts-ignore
1763      let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${rowParentId}'][folder]`);
1764      if (row && !row.expansion) {
1765        row.expansion = true;
1766      }
1767      if (rootRow && rootRow.offsetTop >= 0 && rootRow.offsetHeight >= 0) {
1768        this.rowsPaneEL!.scroll({
1769          top: (rootRow?.offsetTop || 0) - this.canvasPanel!.offsetHeight + 20,
1770          left: 0,
1771          behavior: smooth ? 'smooth' : undefined,
1772        });
1773      }
1774    }
1775  }
1776
1777  disconnectedCallback(): void {
1778    this.timerShaftEL?.removeEventListener('range-change', this.timerShaftELRangeChange);
1779    this.rowsPaneEL?.removeEventListener('scroll', this.rowsElOnScroll);
1780    this.favoriteChartListEL?.removeEventListener('scroll', this.favoriteRowsElOnScroll);
1781    this.removeEventListener('mousemove', this.documentOnMouseMove);
1782    this.removeEventListener('click', this.documentOnClick);
1783    this.removeEventListener('mousedown', this.documentOnMouseDown);
1784    this.removeEventListener('mouseup', this.documentOnMouseUp);
1785    this.removeEventListener('mouseout', this.documentOnMouseOut);
1786    document.removeEventListener('keypress', this.documentOnKeyPress);
1787    document.removeEventListener('keydown', this.documentOnKeyDown);
1788    document.removeEventListener('keyup', this.documentOnKeyUp);
1789    document.removeEventListener('contextmenu', this.onContextMenuHandler);
1790    window.unsubscribe(window.SmartEvent.UI.SliceMark, this.sliceMarkEventHandler.bind(this));
1791  }
1792
1793  sliceMarkEventHandler(ev: unknown): void {
1794    SpSystemTrace.sliceRangeMark = ev; // @ts-ignore
1795    let startNS = ev.timestamp - (window as unknown).recordStartNS; // @ts-ignore
1796    let endNS = ev.maxDuration + startNS;
1797    TraceRow.rangeSelectObject = {
1798      startX: 0,
1799      startNS: startNS,
1800      endNS: endNS,
1801      endX: 0,
1802    };
1803    window.publish(window.SmartEvent.UI.MenuTrace, {});
1804    window.publish(window.SmartEvent.UI.TimeRange, {
1805      // @ts-ignore
1806      startNS: startNS - ev.maxDuration, // @ts-ignore
1807      endNS: endNS + ev.maxDuration,
1808    });
1809    this.queryAllTraceRow().forEach((it) => (it.checkType = '-1'));
1810    this.rangeSelect.rangeTraceRow = [];
1811    this.selectStructNull();
1812    this.wakeupListNull();
1813    this.traceSheetEL?.setMode('hidden');
1814    this.removeLinkLinesByBusinessType('janks');
1815    TraceRow.range!.refresh = true;
1816    this.refreshCanvas(false);
1817  }
1818
1819  loadDatabaseUrl(
1820    url: string,
1821    progress: Function,
1822    complete?: ((res: { status: boolean; msg: string }) => void) | undefined
1823  ): void {
1824    this.observerScrollHeightEnable = false;
1825    this.init({ url: url }, '', progress).then((res) => {
1826      if (complete) {
1827        // @ts-ignore
1828        complete(res);
1829        window.publish(window.SmartEvent.UI.MouseEventEnable, {
1830          mouseEnable: true,
1831        });
1832      }
1833    });
1834  }
1835
1836  loadDatabaseArrayBuffer(
1837    buf: ArrayBuffer,
1838    thirdPartyWasmConfigUrl: string,
1839    progress: (name: string, percent: number) => void,
1840    complete?: ((res: { status: boolean; msg: string }) => void) | undefined
1841  ): void {
1842    this.observerScrollHeightEnable = false;
1843    this.init({ buf }, thirdPartyWasmConfigUrl, progress).then((res) => {
1844      // @ts-ignore
1845      this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it));
1846      if (complete) {
1847        // @ts-ignore
1848        complete(res);
1849        window.publish(window.SmartEvent.UI.MouseEventEnable, {
1850          mouseEnable: true,
1851        });
1852      }
1853    });
1854  }
1855
1856  loadSample = async (ev: File): Promise<void> => {
1857    this.observerScrollHeightEnable = false;
1858    await this.initSample(ev); // @ts-ignore
1859    this.rowsEL?.querySelectorAll('trace-row').forEach((it: unknown) => this.observer.observe(it));
1860    window.publish(window.SmartEvent.UI.MouseEventEnable, {
1861      mouseEnable: true,
1862    });
1863  };
1864
1865  initSample = async (ev: File): Promise<void> => {
1866    this.rowsPaneEL!.scroll({
1867      top: 0,
1868      left: 0,
1869    });
1870    this.chartManager?.initSample(ev).then((): void => {
1871      this.loadTraceCompleted = true; // @ts-ignore
1872      this.rowsEL!.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((it): void => {
1873        this.intersectionObserver?.observe(it);
1874      });
1875    });
1876  };
1877  // @ts-ignore
1878  queryAllTraceRow<T>(selectors?: string, filter?: (row: TraceRow<unknown>) => boolean): TraceRow<unknown>[] {
1879    return [
1880      // @ts-ignore
1881      ...this.rowsEL!.querySelectorAll<TraceRow<unknown>>(selectors ?? 'trace-row'),
1882      ...this.favoriteChartListEL!.getCollectRows(filter),
1883    ];
1884  }
1885
1886  search(query: string): void {
1887    this.queryAllTraceRow().forEach((item): void => {
1888      if (query === null || query === undefined || query === '') {
1889        if (
1890          item.rowType === TraceRow.ROW_TYPE_CPU ||
1891          item.rowType === TraceRow.ROW_TYPE_CPU_FREQ ||
1892          item.rowType === TraceRow.ROW_TYPE_NATIVE_MEMORY ||
1893          item.rowType === TraceRow.ROW_TYPE_FPS ||
1894          item.rowType === TraceRow.ROW_TYPE_PROCESS ||
1895          item.rowType === TraceRow.ROW_TYPE_CPU_ABILITY ||
1896          item.rowType === TraceRow.ROW_TYPE_MEMORY_ABILITY ||
1897          item.rowType === TraceRow.ROW_TYPE_DISK_ABILITY ||
1898          item.rowType === TraceRow.ROW_TYPE_NETWORK_ABILITY
1899        ) {
1900          item.expansion = false;
1901          item.rowHidden = false;
1902        } else {
1903          item.rowHidden = true;
1904        }
1905      } else {
1906        item.rowHidden = item.name.toLowerCase().indexOf(query.toLowerCase()) < 0;
1907      }
1908    });
1909    this.visibleRows.forEach((it) => (it.rowHidden = false && it.draw(true)));
1910  }
1911
1912  async searchCPU(query: string): Promise<Array<unknown>> {
1913    let pidArr: Array<number> = [];
1914    let tidArr: Array<number> = [];
1915    for (let key of Utils.PROCESS_MAP.keys()) {
1916      if (`${key}`.includes(query) || (Utils.PROCESS_MAP.get(key) || '').includes(query)) {
1917        pidArr.push(key);
1918      }
1919    }
1920    for (let key of Utils.THREAD_MAP.keys()) {
1921      if (`${key}`.includes(query) || (Utils.THREAD_MAP.get(key) || '').includes(query)) {
1922        tidArr.push(key);
1923      }
1924    }
1925    return await searchCpuDataSender(pidArr, tidArr);
1926  }
1927
1928  async searchFunction(cpuList: Array<unknown>, query: string): Promise<Array<unknown>> {
1929    let processList: Array<string> = [];
1930    let traceRow = // @ts-ignore
1931      this.shadowRoot!.querySelector<TraceRow<unknown>>('trace-row[scene]') ||
1932      this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene'));
1933    if (traceRow) {
1934      // @ts-ignore
1935      this.shadowRoot!.querySelectorAll<TraceRow<unknown>>("trace-row[row-type='process'][scene]").forEach(
1936        (row): void => {
1937          processList.push(row.rowId!);
1938        }
1939      );
1940      if (query.includes('_')) {
1941        query = query.replace(/_/g, '\\_');
1942      }
1943      if (query.includes('%')) {
1944        query = query.replace(/%/g, '\\%');
1945      }
1946      let list = await querySceneSearchFunc(query, processList);
1947      cpuList = cpuList.concat(list); // @ts-ignore
1948      cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
1949      return cpuList;
1950    } else {
1951      let list = await querySearchFunc(query);
1952      cpuList = cpuList.concat(list); // @ts-ignore
1953      cpuList.sort((a, b) => (a.startTime || 0) - (b.startTime || 0));
1954      return cpuList;
1955    }
1956  }
1957
1958  searchSdk(dataList: Array<unknown>, query: string): Array<unknown> {
1959    let traceRow = // @ts-ignore
1960      this.shadowRoot!.querySelector<TraceRow<unknown>>('trace-row[scene]') ||
1961      this.favoriteChartListEL!.getCollectRow((row) => row.hasAttribute('scene'));
1962    let dataAll = "trace-row[row-type^='sdk']";
1963    if (traceRow) {
1964      dataAll = "trace-row[row-type^='sdk'][scene]";
1965    }
1966    let allTraceRow: unknown = []; // @ts-ignore
1967    let parentRows = this.shadowRoot!.querySelectorAll<TraceRow<unknown>>(`${dataAll}`); // @ts-ignore
1968    parentRows.forEach((parentRow: TraceRow<unknown>): void => {
1969      // @ts-ignore
1970      allTraceRow.push(parentRow);
1971      if (parentRow.childrenList && parentRow.childrenList.length > 0) {
1972        // @ts-ignore
1973        allTraceRow.push(...parentRow.childrenList);
1974      }
1975    }); // @ts-ignore
1976    allTraceRow.forEach((row: unknown): void => {
1977      // @ts-ignore
1978      if (row!.name.indexOf(query) >= 0) {
1979        let searchSdkBean = new SearchSdkBean();
1980        searchSdkBean.startTime = TraceRow.range!.startNS;
1981        searchSdkBean.dur = TraceRow.range!.totalNS; // @ts-ignore
1982        searchSdkBean.name = row.name; // @ts-ignore
1983        searchSdkBean.rowId = row.rowId;
1984        searchSdkBean.type = 'sdk'; // @ts-ignore
1985        searchSdkBean.rowType = row.rowType; // @ts-ignore
1986        searchSdkBean.rowParentId = row.rowParentId;
1987        dataList.push(searchSdkBean);
1988      }
1989    });
1990    return dataList;
1991  }
1992
1993  showStruct(previous: boolean, currentIndex: number, structs: Array<unknown>, retargetIndex?: number): number {
1994    return spSystemTraceShowStruct(this, previous, currentIndex, structs, retargetIndex);
1995  }
1996
1997  private toTargetDepth = (entry: unknown, funcRowID: string, funcStract: unknown): void => {
1998    if (entry) {
1999      this.hoverStructNull();
2000      this.selectStructNull();
2001      this.wakeupListNull();
2002      // @ts-ignore
2003      FuncStruct.hoverFuncStruct = entry; // @ts-ignore
2004      FuncStruct.selectFuncStruct = entry;
2005      // 鼠标左键点击不需要触发点击事件
2006      if (FuncStruct.funcSelect) {
2007        this.onClickHandler(TraceRow.ROW_TYPE_FUNC, undefined, entry);
2008      } // @ts-ignore
2009      this.scrollToDepth(`${funcRowID}`, `${funcStract.pid}`, 'func', true, entry.depth || 0);
2010      FuncStruct.funcSelect = true;
2011    }
2012  };
2013
2014  scrollToActFunc(funcStract: unknown, highlight: boolean): void {
2015    if (!Utils.isBinder(funcStract)) {
2016      // @ts-ignore
2017      if (funcStract.dur === -1 || funcStract.dur === null || funcStract.dur === undefined) {
2018        // @ts-ignore
2019        funcStract.dur = (TraceRow.range?.totalNS || 0) - (funcStract.startTs || 0); // @ts-ignore
2020        funcStract.flag = 'Did not end';
2021      }
2022    } // @ts-ignore
2023    let funcRowID = !funcStract.cookie ? `${funcStract.tid}` : `${funcStract.funName}-${funcStract.pid}`;
2024    let targetRow = this.favoriteChartListEL?.getCollectRow((row) => {
2025      return row.rowId === funcRowID && row.rowType === 'func';
2026    });
2027    if (targetRow) {
2028      targetRow.fixedList[0] = funcStract;
2029      targetRow.highlight = highlight;
2030      //如果目标泳道图在收藏上面,则跳转至收藏
2031      this.toTargetDepth(funcStract, funcRowID, funcStract);
2032      return;
2033    } // @ts-ignore
2034    let parentRow = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${funcStract.pid}'][folder]`);
2035    if (!parentRow) {
2036      return;
2037    }
2038    let filterRow = parentRow.childrenList.filter((child) => child.rowId === funcRowID && child.rowType === 'func')[0];
2039    if (!filterRow) {
2040      // @ts-ignore
2041      let funcRow = this.rowsEL?.querySelector<TraceRow<unknown>>(`trace-row[row-id='${funcRowID}'][row-type='func']`);
2042      if (funcRow) {
2043        filterRow = funcRow;
2044      } else {
2045        return;
2046      }
2047    }
2048    filterRow.fixedList = [funcStract];
2049    filterRow!.highlight = highlight; // @ts-ignore
2050    let row = this.rowsEL!.querySelector<TraceRow<unknown>>(`trace-row[row-id='${funcStract.pid}'][folder]`);
2051    this.currentRow = row;
2052    if (row && !row.expansion) {
2053      row.expansion = true;
2054    }
2055    const completeEntry = (): void => {
2056      this.toTargetDepth(filterRow.fixedList[0], funcRowID, funcStract);
2057    };
2058    if (filterRow!.isComplete) {
2059      completeEntry();
2060    } else {
2061      // @ts-ignore
2062      this.scrollToProcess(`${funcStract.tid}`, `${funcStract.pid}`, 'thread', false); // @ts-ignore
2063      this.scrollToFunction(`${funcStract.tid}`, `${funcStract.pid}`, 'func', true);
2064      filterRow!.onComplete = completeEntry;
2065    }
2066  }
2067
2068  closeAllExpandRows(pid: string): void {
2069    let expandRows = this.rowsEL?.querySelectorAll<TraceRow<ProcessStruct>>("trace-row[row-type='process'][expansion]");
2070    expandRows?.forEach((row): void => {
2071      if (row.rowId !== pid) {
2072        row.expansion = false;
2073      }
2074    });
2075  }
2076
2077  moveRangeToLeft(startTime: number, dur: number): void {
2078    let startNS = this.timerShaftEL?.getRange()?.startNS || 0;
2079    let endNS = this.timerShaftEL?.getRange()?.endNS || 0;
2080    let harfDur = Math.trunc(endNS - startNS - dur / 2);
2081    let leftNs = startTime;
2082    let rightNs = startTime + dur + harfDur;
2083    if (startTime - harfDur < 0) {
2084      leftNs = 0;
2085      rightNs += harfDur - startTime;
2086    }
2087    this.timerShaftEL?.setRangeNS(leftNs, rightNs);
2088    TraceRow.range!.refresh = true;
2089    this.refreshCanvas(true);
2090  }
2091
2092  moveRangeToCenter(startTime: number, dur: number): void {
2093    let startNS = this.timerShaftEL?.getRange()?.startNS || 0;
2094    let endNS = this.timerShaftEL?.getRange()?.endNS || 0;
2095    let harfDur = Math.trunc((endNS - startNS) / 2 - dur / 2);
2096    let leftNs = startTime - harfDur;
2097    let rightNs = startTime + dur + harfDur;
2098    if (startTime - harfDur < 0) {
2099      leftNs = 0;
2100      rightNs += harfDur - startTime;
2101    }
2102    this.timerShaftEL?.setRangeNS(leftNs, rightNs);
2103    TraceRow.range!.refresh = true;
2104    this.refreshCanvas(true);
2105  }
2106
2107  rechargeCpuData(it: CpuStruct, next: CpuStruct | undefined): void {
2108    let p = Utils.PROCESS_MAP.get(it.processId!);
2109    let t = Utils.THREAD_MAP.get(it.tid!);
2110    let slice = Utils.SCHED_SLICE_MAP.get(`${it.id}-${it.startTime}`);
2111    if (slice) {
2112      it.end_state = slice.endState;
2113      it.priority = slice.priority;
2114    }
2115    it.processName = p;
2116    it.processCmdLine = p;
2117    it.name = t;
2118    it.type = 'thread';
2119    if (next) {
2120      if (it.startTime! + it.dur! > next!.startTime! || it.dur === -1 || it.dur === null || it.dur === undefined) {
2121        it.dur = next!.startTime! - it.startTime!;
2122        it.nofinish = true;
2123      }
2124    } else {
2125      if (it.dur === -1 || it.dur === null || it.dur === undefined) {
2126        it.dur = TraceRow.range!.endNS - it.startTime!;
2127        it.nofinish = true;
2128      }
2129    }
2130  }
2131
2132  reset(progress: Function | undefined | null): void {
2133    this.visibleRows.length = 0;
2134    this.tipEL!.style.display = 'none';
2135    this.canvasPanelCtx?.clearRect(0, 0, this.canvasPanel!.clientWidth, this.canvasPanel!.offsetHeight);
2136    this.loadTraceCompleted = false;
2137    this.collectRows = [];
2138    this.visibleRows = [];
2139    TraceRowConfig.allTraceRowList.forEach((it) => {
2140      it.clearMemory();
2141    });
2142    TraceRowConfig.allTraceRowList = [];
2143    this.favoriteChartListEL!.reset();
2144    if (this.rowsEL) {
2145      // @ts-ignore
2146      this.rowsEL.querySelectorAll<TraceRow<unknown>>('trace-row').forEach((row) => {
2147        row.clearMemory();
2148        this.rowsEL!.removeChild(row);
2149      });
2150    }
2151    this.traceSheetEL?.clearMemory();
2152    this.spacerEL!.style.height = '0px';
2153    this.rangeSelect.rangeTraceRow = [];
2154    SpSystemTrace.SDK_CONFIG_MAP = undefined;
2155    SpSystemTrace.sliceRangeMark = undefined;
2156    this.timerShaftEL?.displayCollect(false);
2157    this.timerShaftEL!.collecBtn!.removeAttribute('close');
2158    CpuStruct.wakeupBean = undefined;
2159    this.selectStructNull();
2160    this.hoverStructNull();
2161    this.wakeupListNull();
2162    this.traceSheetEL?.setMode('hidden');
2163    progress?.('rest timershaft', 8);
2164    this.timerShaftEL?.reset();
2165    progress?.('clear cache', 10);
2166    HeapDataInterface.getInstance().clearData();
2167    procedurePool.clearCache();
2168    Utils.clearData();
2169    InitAnalysis.getInstance().isInitAnalysis = true;
2170    procedurePool.submitWithName('logic0', 'clear', {}, undefined, (res: unknown) => {});
2171    if (threadPool) {
2172      threadPool.submitProto(QueryEnum.ClearMemoryCache, {}, (res: unknown, len: number): void => {});
2173    }
2174    this.times.clear();
2175    resetVSync();
2176    SpSystemTrace.keyPathList = [];
2177    Utils.isTransformed = false;
2178  }
2179
2180  init = async (
2181    param: { buf?: ArrayBuffer; url?: string },
2182    wasmConfigUri: string,
2183    progress: Function
2184  ): Promise<unknown> => {
2185    return spSystemTraceInit(this, param, wasmConfigUri, progress);
2186  };
2187  // @ts-ignore
2188  extracted(it: TraceRow<unknown>) {
2189    return (): void => {
2190      if (it.hasAttribute('expansion')) {
2191        it.childrenList.forEach((child): void => {
2192          if (child.hasAttribute('scene') && !child.collect) {
2193            child.rowHidden = false;
2194          }
2195          if (child.folder) {
2196            child.addEventListener('expansion-change', this.extracted(child));
2197          }
2198          this.intersectionObserver?.observe(child);
2199        });
2200      } else {
2201        it.childrenList.forEach((child): void => {
2202          if (child.hasAttribute('scene') && !child.collect) {
2203            child.rowHidden = true;
2204            this.intersectionObserver?.unobserve(child);
2205          }
2206          if (child.folder) {
2207            child.removeEventListener('expansion-change', this.extracted(child));
2208          }
2209        });
2210        this.linkNodes.map((value): void => {
2211          if ('task' === value[0].business && value[0].rowEL.parentRowEl?.rowId === it.rowId) {
2212            value[0].hidden = true;
2213            value[1].hidden = true;
2214            this.clickEmptyArea();
2215          }
2216        });
2217      }
2218      if (!this.collapseAll) {
2219        this.refreshCanvas(false);
2220      }
2221    };
2222  }
2223  // @ts-ignore
2224  displayTip(row: TraceRow<unknown>, struct: unknown, html: string): void {
2225    let x = row.hoverX + 248;
2226    let y = row.getBoundingClientRect().top - this.getBoundingClientRect().top;
2227    if ((struct === undefined || struct === null) && this.tipEL) {
2228      this.tipEL.style.display = 'none';
2229      return;
2230    }
2231    if (this.tipEL) {
2232      this.tipEL.innerHTML = html;
2233      if (
2234        row.rowType === TraceRow.ROW_TYPE_JS_CPU_PROFILER ||
2235        row.rowType === TraceRow.ROW_TYPE_PERF_CALLCHART ||
2236        row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT
2237      ) {
2238        this.tipEL.style.maxWidth = `${row.clientWidth / 3} px`;
2239        this.tipEL.style.wordBreak = ' break-all';
2240        this.tipEL.style.height = 'unset';
2241        this.tipEL.style.display = 'block'; // @ts-ignore
2242        y = y + struct.depth * 20;
2243        if (row.rowType === TraceRow.ROW_TYPE_BINDER_COUNT) {
2244          this.tipEL.style.height = '40px';
2245          y = row.hoverY + row.getBoundingClientRect().top - this.getBoundingClientRect().top;
2246        }
2247      } else {
2248        this.tipEL.style.display = 'flex';
2249        this.tipEL.style.height = row.style.height;
2250      }
2251      if (x + this.tipEL.clientWidth > (this.canvasPanel!.clientWidth ?? 0)) {
2252        this.tipEL.style.transform = `translateX(${x - this.tipEL.clientWidth - 1}px) translateY(${y}px)`;
2253      } else {
2254        this.tipEL.style.transform = `translateX(${x}px) translateY(${y}px)`;
2255      }
2256    }
2257  }
2258
2259  queryCPUWakeUpList(data: WakeupBean): void {
2260    TabPaneCurrentSelection.queryCPUWakeUpListFromBean(data).then((a: unknown) => {
2261      if (a === null) {
2262        window.publish(window.SmartEvent.UI.WakeupList, SpSystemTrace.wakeupList);
2263      } // @ts-ignore
2264      SpSystemTrace.wakeupList.push(a); // @ts-ignore
2265      this.queryCPUWakeUpList(a);
2266    });
2267  }
2268
2269  wakeupListNull(): SpSystemTrace {
2270    SpSystemTrace.wakeupList = [];
2271    return this;
2272  }
2273
2274  initPointToEvent(): void {
2275    spSystemTraceInitPointToEvent(this);
2276  }
2277
2278  initHtml(): string {
2279    return SpSystemTraceHtml;
2280  }
2281}
2282