• 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.js";
17import "../base-ui/menu/LitMainMenu.js";
18import "../base-ui/icon/LitIcon.js";
19import {SpSystemTrace} from "./component/SpSystemTrace.js";
20import {LitMainMenu, MenuItem} from "../base-ui/menu/LitMainMenu.js";
21import "../base-ui/progress-bar/LitProgressBar.js";
22import {LitProgressBar} from "../base-ui/progress-bar/LitProgressBar.js";
23import {SpRecordTrace} from "./component/SpRecordTrace.js";
24import {SpWelcomePage} from "./component/SpWelcomePage.js";
25import {SpSearch} from "./component/trace/search/Search.js";
26import {threadPool} from "./database/SqlLite.js";
27import "./component/trace/search/Search.js";
28import "./component/SpWelcomePage.js";
29import "./component/SpSystemTrace.js";
30import "./component/SpWelcomePage.js";
31import "./component/SpRecordTrace.js";
32import {TraceRow} from "./component/trace/base/TraceRow.js";
33
34@element('sp-application')
35export class SpApplication extends BaseElement {
36    static skinChange: Function | null | undefined = null;
37    static skinChange2: Function | null | undefined = null;
38    skinChangeArray: Array<Function> = [];
39    private rootEL: HTMLDivElement | undefined | null
40
41    static get observedAttributes() {
42        return ["server", "sqlite", "wasm", "dark", "vs"]
43    }
44
45    get dark() {
46        return this.hasAttribute('dark');
47    }
48
49    set dark(value) {
50        if (value) {
51            this.rootEL!.classList.add('dark');
52            this.setAttribute('dark', '');
53        } else {
54            this.rootEL!.classList.remove('dark');
55            this.removeAttribute('dark');
56        }
57        if (this.skinChangeArray.length > 0) {
58            this.skinChangeArray.forEach((item) => item(value));
59        }
60        if (SpApplication.skinChange) {
61            SpApplication.skinChange(value);
62        }
63        if (SpApplication.skinChange2) {
64            SpApplication.skinChange2(value);
65        }
66    }
67
68    initHtml(): string {
69        return `
70<style>
71:host{
72
73}
74.dark{
75--dark-background: #272C34;
76--dark-background1: #424851;
77--dark-background2: #262f3c;
78--dark-background3: #292D33;
79--dark-background4: #323841;
80--dark-background5: #333840;
81--dark-background6: rgba(82,145,255,0.2);
82--dark-background7: #494d52;
83--dark-background8: #5291FF;
84--dark-color: rgba(255,255,255,0.6);
85--dark-color1: rgba(255,255,255,0.86);
86--dark-color2: rgba(255,255,255,0.9);
87--dark-border: #474F59;
88--dark-color3:#4694C2;
89--dark-color4:#5AADA0;
90--dark-border1: #454E5A;
91--bark-expansion:#0076FF;
92--bark-prompt:#9e9e9e;
93--dark-icon:#adafb3;
94--dark-img: url('img/dark_pic.png');
95    background: #272C34;
96    color: #FFFFFF;
97}
98.root{
99    display: grid;
100    grid-template-rows: min-content 1fr;
101    grid-template-columns: min-content 1fr;
102    grid-template-areas: 'm s'
103                         'm b';
104    height: 100vh;
105    width: 100vw;
106}
107.filedrag::after {
108            content: 'Drop the trace file to open it';
109            position: fixed;
110            z-index: 101;
111            top: 0;
112            left: 0;
113            right: 0;
114            bottom: 0;
115            border: 5px dashed var(--dark-color1,#404854);
116            text-align: center;
117            font-size: 3rem;
118            line-height: 100vh;
119            background: rgba(255, 255, 255, 0.5);
120            }
121.menu{
122    grid-area: m;
123    box-shadow: 4px 0px 20px rgba(0,0,0,0.05);
124    z-index: 101;
125}
126.search-container{
127    z-index: 10;
128    position: relative;
129}
130.progress{
131    bottom: 0;
132    position: absolute;
133    height: 1px;
134    left: 0;
135    right: 0;
136}
137:host(:not([search])) #sp-search  {
138   display: none;
139}
140
141:host(:not([search])) .search-container .search  {
142    background-color: var(--dark-background5,#F6F6F6);
143}
144.search{
145    grid-area: s;
146    background-color: var(--dark-background,#FFFFFF);
147    height: 48px;
148    display: flex;
149    justify-content: center;
150    align-items: center;
151
152}
153.search .search-bg{
154    background-color: var(--dark-background5,#fff);
155    border-radius: 40px;
156    padding: 3px 20px;
157    display: flex;
158    justify-content: center;
159    align-items: center;
160    border: 1px solid var(--dark-border,#c5c5c5);
161}
162.search input{
163    outline: none;
164    border: 0px;
165    background-color: transparent;
166    font-size: inherit;
167    color: var(--dark-color,#666666);
168    width: 30vw;
169    height: auto;
170    vertical-align:middle;
171    line-height:inherit;
172    height:inherit;
173    padding: 6px 6px 6px 6px};
174    max-height: inherit;
175    box-sizing: border-box;
176
177}
178::placeholder {
179  color: #b5b7ba;
180  font-size: 1em;
181}
182.search input::placeholder {
183  color: #b5b7ba;
184  font-size: 1em;
185}
186.content{
187    grid-area: b;
188    background-color: #ffffff;
189    height: 100%;
190    overflow: auto;
191    position:relative;
192}
193.sheet{
194
195}
196.sidebar-button{
197    position: absolute;
198    top: 0;
199    left: 0;
200    background-color: var(--dark-background1,#FFFFFF);
201    height: 100%;
202    border-radius: 0 5px 5px 0;
203    width: 48px;
204    display: flex;
205    align-content: center;
206    justify-content: center;
207    cursor: pointer;
208}
209:host{
210    font-size: inherit;
211    display: inline-block;
212    transition: .3s;
213 }
214 :host([spin]){
215    animation: rotate 1.75s linear infinite;
216 }
217 @keyframes rotate {
218    to{
219        transform: rotate(360deg);
220    }
221 }
222 .icon{
223    display: block;
224    width: 1em;
225    height: 1em;
226    margin: auto;
227    fill: currentColor;
228    overflow: hidden;
229    font-size: 20px;
230    color: var(--dark-color1,#4D4D4D);
231 }
232</style>
233<div class="root">
234    <lit-main-menu id="main-menu" class="menu" data=''>
235    </lit-main-menu>
236    <div class="search-container">
237        <div class="search" style="position: relative;">
238            <div class="sidebar-button" style="width: 0">
239                <svg class="icon" id="icon" aria-hidden="true" viewBox="0 0 1024 1024">
240                     <use id="use" xlink:href="./base-ui/icon.svg#icon-menu"></use>
241                </svg>
242            </div>
243            <sp-search id="sp-search"></sp-search>
244        </div>
245        <lit-progress-bar class="progress"></lit-progress-bar>
246    </div>
247
248    <div id="app-content" class="content">
249        <sp-welcome style="visibility:visible;top:0px;left:0px;position:absolute;z-index: 100" id="sp-welcome"></sp-welcome>
250        <sp-system-trace style="visibility:visible;" id="sp-system-trace"></sp-system-trace>
251        <sp-record-trace style="width:100%;height:100%;overflow:auto;visibility:hidden;top:0px;left:0px;right:0;bottom:0px;position:absolute;z-index: 102" id="sp-record-trace"></sp-record-trace>
252    </div>
253</div>`;
254    }
255
256    set vs(isVs: boolean) {
257        if (isVs) {
258            this.setAttribute("vs", "")
259        }
260    }
261
262    get vs(): boolean {
263        return this.hasAttribute("vs")
264    }
265
266    get sqlite(): boolean {
267        return this.hasAttribute("sqlite")
268    }
269
270    get wasm(): boolean {
271        return this.hasAttribute("wasm")
272    }
273
274    get server(): boolean {
275        return this.hasAttribute("server")
276    }
277
278    set server(s: boolean) {
279        if (s) {
280            this.setAttribute('server', '')
281        } else {
282            this.removeAttribute('server')
283        }
284    }
285
286    set search(search: boolean) {
287        if (search) {
288            this.setAttribute('search', '')
289        } else {
290            this.removeAttribute('search')
291        }
292    }
293
294    initElements() {
295        let that = this;
296        this.rootEL = this.shadowRoot!.querySelector<HTMLDivElement>(".root")
297        let spWelcomePage = this.shadowRoot!.querySelector("#sp-welcome") as SpWelcomePage
298        let spSystemTrace = this.shadowRoot!.querySelector<SpSystemTrace>("#sp-system-trace")
299        let spRecordTrace = this.shadowRoot!.querySelector<SpRecordTrace>("#sp-record-trace")
300        let mainMenu = this.shadowRoot?.querySelector('#main-menu') as LitMainMenu
301        let progressEL = this.shadowRoot?.querySelector('.progress') as LitProgressBar
302        let spSearch = this.shadowRoot?.querySelector('#sp-search') as SpSearch
303        let sidebarButton: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button')
304        let childNodes = [spSystemTrace, spRecordTrace, spWelcomePage]
305        spSearch.addEventListener("focus", () => {
306            spSystemTrace!.keyboardEnable = false
307        })
308        spSearch.addEventListener('blur', () => {
309            spSystemTrace!.keyboardEnable = true
310        })
311        spSearch.addEventListener("enter", (e: any) => {
312            spSystemTrace!.shadowRoot?.querySelectorAll<TraceRow<any>>('trace-row').forEach(item => {
313                if (e.detail.value == null || e.detail.value == undefined || e.detail.value == '') {
314                    if (item.rowType == TraceRow.ROW_TYPE_CPU ||
315                        item.rowType == TraceRow.ROW_TYPE_CPU_FREQ ||
316                        item.rowType == TraceRow.ROW_TYPE_FPS ||
317                        item.rowType == TraceRow.ROW_TYPE_PROCESS) {
318                        item.rowHidden = false;
319                    } else {
320                        item.rowHidden = true;
321                    }
322                } else {
323                    if (item.name.toLowerCase().indexOf(e.detail.value.toLowerCase()) >= 0) {
324                        item.rowHidden = false;
325                    } else {
326                        item.rowHidden = true;
327                    }
328                }
329            })
330        })
331        sidebarButton!.onclick = (event) => {
332            let menu: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector('#main-menu')
333            let menuButton: HTMLElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button')
334            if (menu) {
335                menu.style.width = `248px`
336                // @ts-ignore
337                menu.style.zIndex = 200;
338                menu.style.display = `flex`
339            }
340            if (menuButton) {
341                menuButton.style.width = `0px`
342            }
343        }
344        let icon: HTMLDivElement | undefined | null = this.shadowRoot?.querySelector("#main-menu")?.shadowRoot?.querySelector("div.header > div")
345        icon!.onclick = (mouseEvent) => {
346            let menu: HTMLElement | undefined | null = this.shadowRoot?.querySelector("#main-menu")
347            let menuButton: HTMLElement | undefined | null = this.shadowRoot?.querySelector('.sidebar-button')
348            if (menu) {
349                menu.style.width = `0px`
350                menu.style.display = `none`
351                // @ts-ignore
352                menu.style.zIndex = 0
353            }
354            if (menuButton) {
355                menuButton.style.width = `48px`
356            }
357        }
358
359        function showContent(showNode: HTMLElement) {
360            childNodes.forEach((node) => {
361                if (node === showNode) {
362                    showNode.style.visibility = 'visible'
363                } else {
364                    node!.style.visibility = 'hidden'
365                }
366            })
367        }
368
369        function openTraceFile(ev: any) {
370            showContent(spSystemTrace!)
371            that.search = true
372            progressEL.loading = true
373            let fileName = (ev as any).name
374            let fileSize = ((ev as any).size / 1000000).toFixed(1)
375            document.title = `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)`
376
377            if (that.server) {
378                threadPool.init("server").then(() => {
379                    spSearch.setPercent("parse trace", 1);
380                    const fd = new FormData()
381                    that.freshMenuDisable(true)
382                    fd.append('file', ev as any)
383                    let uploadPath = `https://${window.location.host.split(':')[0]}:9001/upload`
384                    if (that.vs) {
385                        uploadPath = `http://${window.location.host.split(':')[0]}:${window.location.port}/upload`
386                    }
387                    fetch(uploadPath, {
388                        method: 'POST',
389                        body: fd,
390                    }).then(res => {
391                        spSearch.setPercent("load database", 5);
392                        if (res.ok) {
393                            mainMenu.menus!.splice(1, 1, {
394                                collapsed: false,
395                                title: "Current Trace",
396                                describe: "Actions on the current trace",
397                                children: [
398                                    {
399                                        title: `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)`,
400                                        icon: "file-fill",
401                                        clickHandler: function () {
402                                            that.search = true
403                                            showContent(spSystemTrace!)
404                                        }
405                                    }
406                                ]
407                            })
408                            that.freshMenuDisable(true)
409                            return res.text();
410                        } else {
411                            if (res.status == 404) {
412                                spSearch.setPercent("This File is not supported!", -1)
413                                progressEL.loading = false;
414                                that.freshMenuDisable(false)
415                                return Promise.reject();
416                            }
417                        }
418                    }).then(res => {
419                        if (res != undefined) {
420                            let loadPath = `https://${window.location.host.split(':')[0]}:9001`
421                            if (that.vs) {
422                                loadPath = `http://${window.location.host.split(':')[0]}:${window.location.port}`
423                            }
424                            spSystemTrace!.loadDatabaseUrl(loadPath + res, (command: string, percent: number) => {
425                                spSearch.setPercent(command + '  ', percent);
426                            }, (res) => {
427                                spSearch.setPercent("", 101);
428                                progressEL.loading = false;
429                                that.freshMenuDisable(false)
430                            })
431                        } else {
432                            spSearch.setPercent("", 101)
433                            progressEL.loading = false;
434                            that.freshMenuDisable(false)
435                        }
436
437                    })
438                })
439                return;
440            }
441            if (that.sqlite) {
442                spSearch.setPercent("", 0);
443                threadPool.init("sqlite").then(res => {
444                    let reader = new FileReader();
445                    reader.readAsArrayBuffer(ev as any)
446                    reader.onloadend = function (event) {
447                        spSystemTrace!.loadDatabaseArrayBuffer(this.result as ArrayBuffer, (command: string, percent: number) => {
448                            spSearch.setPercent(command + '  ', percent);
449                        }, () => {
450                            spSearch.setPercent("", 101);
451                            progressEL.loading = false;
452                            that.freshMenuDisable(false)
453                        })
454                    }
455                })
456                return;
457            }
458            if (that.wasm) {
459                spSearch.setPercent("", 1);
460                threadPool.init("wasm").then(res => {
461                    let reader = new FileReader();
462                    reader.readAsArrayBuffer(ev as any)
463                    reader.onloadend = function (event) {
464                        spSearch.setPercent("ArrayBuffer loaded  ", 2);
465                        that.freshMenuDisable(true)
466                        mainMenu.menus!.splice(1, 1, {
467                            collapsed: false,
468                            title: "Current Trace",
469                            describe: "Actions on the current trace",
470                            children: [
471                                {
472                                    title: `${fileName.substring(0, fileName.lastIndexOf('.'))} (${fileSize}M)`,
473                                    icon: "file-fill",
474                                    clickHandler: function () {
475                                        that.search = true
476                                        showContent(spSystemTrace!)
477                                    }
478                                }
479                            ]
480                        })
481                        spSystemTrace!.loadDatabaseArrayBuffer(this.result as ArrayBuffer, (command: string, percent: number) => {
482                            spSearch.setPercent(command + '  ', percent);
483                        }, (res) => {
484                            if (res.status) {
485                                spSearch.setPercent("", 101);
486                                progressEL.loading = false;
487                                that.freshMenuDisable(false)
488                            } else {
489                                spSearch.setPercent("", 101);
490                                progressEL.loading = false;
491                                that.freshMenuDisable(false)
492                                alert(res.msg)
493                            }
494                        })
495                    }
496                })
497                return;
498            }
499        }
500
501        mainMenu.menus = [
502            {
503                collapsed: false,
504                title: 'Navigation',
505                describe: 'Open or record a new trace',
506                children: [
507                    {
508                        title: "Open trace file",
509                        icon: "folder",
510                        fileChoose: true,
511                        fileHandler: function (ev: InputEvent) {
512                            openTraceFile(ev.detail as any);
513                        }
514                    },
515                    {
516                        title: "Record new trace", icon: "copyhovered", clickHandler: function (item: MenuItem) {
517                            that.search = false
518                            showContent(spRecordTrace!)
519                        }
520                    }
521                ]
522            }
523        ]
524    }
525
526    freshMenuDisable(disable: boolean) {
527        let mainMenu = this.shadowRoot?.querySelector('#main-menu') as LitMainMenu
528        // @ts-ignore
529        mainMenu.menus[0].children[0].disabled = disable
530        mainMenu.menus = mainMenu.menus;
531    }
532}
533