1/* 2 * Copyright (C) 2024 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 */ 15import {BaseElement} from '../base-ui/BaseElement.js'; 16import '../base-ui/menu/LitMainMenu.js'; 17import '../base-ui/icon/LitIcon.js'; 18import '../base-ui/progress-bar/LitProgressBar.js'; 19import './component/WelcomePage.js'; 20import {error, info} from '../log/Log.js'; 21import {appHtml,} from './MainMemoryFunc.js'; 22import './component/MemoryDotting.js'; 23import './component/MemoryTree.js'; 24import { MemoryDotting } from './component/MemoryDotting.js'; 25 26export class MainMemory extends BaseElement { 27 static get observedAttributes() { 28 return ['subsection']; 29 } 30 31 initHtml() { 32 return appHtml; 33 } 34 35 initElements() { 36 this.rootEL = this.shadowRoot.querySelector('.root'); 37 this.welcomePage = this.shadowRoot.querySelector('#memory-welcome'); 38 this.table = this.shadowRoot.querySelector('#tabpane-summary'); 39 this.tree = this.shadowRoot.querySelector('#tab-pane-tree'); 40 this.mainMenu = this.shadowRoot.querySelector('#main-menu'); 41 this.menu = this.mainMenu.shadowRoot.querySelector('.menu-button'); 42 this.initElementsAttr(); 43 this.resetMenus(); 44 this.initGlobalEvents(); 45 this.downloadFile(); 46 } 47 48 initElementsAttr() { 49 this.mainMenu.setAttribute('main_menu', '1'); 50 this.childComponent = [ 51 this.table, 52 this.welcomePage, 53 this.tree 54 ]; 55 } 56 57 58 59 async downloadFile() { 60 let localUrl = `${window.location.origin}/get_filename`; 61 const response = await fetch(localUrl); 62 if (!response.ok) { 63 throw new Error('Failed to get filename: ' + response.statusText); 64 } 65 const filename = await response.text(); 66 console.log(filename); 67 const downloadRes = await fetch(`${window.location.origin}/download?filename=${encodeURIComponent(filename)}`); 68 if (!downloadRes.ok) { 69 throw new Error('Failed to download file: ' + downloadRes.statusText); 70 } 71 const blob = await downloadRes.blob(); 72 const file = new File([blob], filename, {type: blob.type}); 73 this.openTraceFile(file); 74 } 75 76 openTraceFile(file) { 77 this.openFileInit(); 78 let fileName = file.name; 79 let showFileName = fileName.lastIndexOf('.') === -1 ? fileName : fileName.substring(0, fileName.lastIndexOf('.')); 80 this.parseLogFile(file, showFileName, file.size, fileName); 81 } 82 83 initGlobalDropEvents() { 84 let body = document.querySelector('body'); 85 body.addEventListener('drop', (event) => { 86 let fileItem; 87 let dirItem; 88 event.preventDefault(); 89 event.stopPropagation(); 90 if (this.rootEL.classList.contains('filedrag')) { 91 this.rootEL.classList.remove('filedrag'); 92 } 93 if (event && event.dataTransfer && event.dataTransfer.items !== undefined && event.dataTransfer.items.length > 0) { 94 let item = event.dataTransfer.items[0]; 95 if ((fileItem = item.webkitGetAsEntry()) === null || fileItem === void 0 ? void 0 : fileItem.isFile) { 96 this.openTraceFile(item.getAsFile()); 97 } else if ((dirItem = item.webkitGetAsEntry()) === null || dirItem === void 0 ? void 0 : dirItem.isDirectory) { 98 this.freshMenuDisable(false); 99 } 100 } 101 }, false); 102 } 103 104 initGlobalEvents() { 105 let body = document.querySelector('body'); 106 body.addEventListener('dragover', (event) => { 107 event.preventDefault(); 108 event.stopPropagation(); 109 if (event && event.dataTransfer && event.dataTransfer.items.length > 0 && event.dataTransfer.items[0].kind === 'file') { 110 event.dataTransfer.dropEffect = 'copy'; 111 if (!this.rootEL.classList.contains('filedrag')) { 112 this.rootEL.classList.add('filedrag'); 113 } 114 } 115 }, false); 116 body.addEventListener('dragleave', (event) => { 117 event.stopPropagation(); 118 event.preventDefault(); 119 if (this.rootEL.classList.contains('filedrag')) { 120 this.rootEL.classList.remove('filedrag'); 121 } 122 }, false); 123 this.initGlobalDropEvents(); 124 } 125 126 initDocumentListener() { 127 document.addEventListener('file-error', () => { 128 }); 129 } 130 131 initNavigationMenu() { 132 return [ 133 { 134 collapsed: false, 135 title: 'Navigation', 136 second: false, 137 icon: 'caret-down', 138 describe: 'Import file', 139 children: [ 140 { 141 title: 'Import file', 142 icon: '', 143 fileChoose: true, 144 fileHandler: (ev) => { 145 this.openTraceFile(ev.detail); 146 }, 147 }, 148 { 149 title: 'Chart', 150 icon: '', 151 clickHandler: (item) => this.clickHandleChart(), 152 }, 153 { 154 title: 'Tree', 155 icon: '', 156 clickHandler: (item) => this.clickHandleTree(), 157 } 158 ], 159 } 160 ]; 161 } 162 163 clickHandleChart() { 164 this.showContent(this.table); 165 } 166 clickHandleTree() { 167 this.showContent(this.tree); 168 } 169 170 parseLogFile(file, showFileName, fileSize, fileName) { 171 let fileSizeStr = (fileSize / 1048576).toFixed(1); 172 document.title = `${showFileName} (${fileSizeStr}M)`; 173 console.log('fileName:' + fileName); 174 if (fileName.endsWith('.log') || fileName.endsWith('.txt')) { 175 let reader = new FileReader(); 176 reader.readAsArrayBuffer(file); 177 reader.onloadend = () => { 178 let arrayBuffer = reader.result; 179 let decoder = new TextDecoder('utf-8'); 180 let text = decoder.decode(arrayBuffer); 181 let modifiedText = `[${text.trim().replace(/,\s*$/, '')}]`; 182 let datas = JSON.parse(modifiedText); 183 this.freshMenuDisable(false); 184 let data = MemoryDotting.filterKeyPoints(datas, 10240); 185 this.table.data = data; 186 this.tree.data = data; 187 }; 188 } else { 189 this.freshMenuDisable(false); 190 } 191 } 192 193 resetMenus() { 194 this.mainMenu.menus = [...this.initNavigationMenu()]; 195 } 196 197 openFileInit() { 198 info('open memory File'); 199 this.resetMenus(); 200 this.freshMenuDisable(true); 201 this.showContent(this.table); 202 } 203 204 showContent(showNode) { 205 if (showNode === this.table) { 206 this.menu.style.pointerEvents = 'auto'; 207 } else { 208 this.menu.style.pointerEvents = 'none'; 209 } 210 this.childComponent.forEach((node) => { 211 if (node === showNode) { 212 showNode.style.visibility = 'visible'; 213 } else { 214 node.style.visibility = 'hidden'; 215 } 216 }); 217 } 218 219 freshMenuDisable(disable) { 220 let menu; 221 this.mainMenu.menus[0].children[0].disabled = disable; 222 if (this.mainMenu.menus.length > 2) { 223 (menu = this.mainMenu.menus) === null || menu === void 0 ? void 0 : menu[1].children.map((it) => (it.disabled = disable)); 224 } 225 this.mainMenu.menus = this.mainMenu.menus; 226 } 227} 228 229if (!customElements.get('main-memory')) { 230 customElements.define('main-memory', MainMemory); 231} 232