1fb726d48Sopenharmony_ci/* 2fb726d48Sopenharmony_ci * Copyright (C) 2022 Huawei Device Co., Ltd. 3fb726d48Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4fb726d48Sopenharmony_ci * you may not use this file except in compliance with the License. 5fb726d48Sopenharmony_ci * You may obtain a copy of the License at 6fb726d48Sopenharmony_ci * 7fb726d48Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8fb726d48Sopenharmony_ci * 9fb726d48Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10fb726d48Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11fb726d48Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fb726d48Sopenharmony_ci * See the License for the specific language governing permissions and 13fb726d48Sopenharmony_ci * limitations under the License. 14fb726d48Sopenharmony_ci */ 15fb726d48Sopenharmony_ci 16fb726d48Sopenharmony_ciimport { BaseElement, element } from '../../../base-ui/BaseElement'; 17fb726d48Sopenharmony_ciimport { HdcDeviceManager } from '../../../hdc/HdcDeviceManager'; 18fb726d48Sopenharmony_ciimport { SpRecordTrace } from '../SpRecordTrace'; 19fb726d48Sopenharmony_ciimport { DataMessage } from '../../../hdc/message/DataMessage'; 20fb726d48Sopenharmony_ci 21fb726d48Sopenharmony_ci@element('sp-web-hdc-shell') 22fb726d48Sopenharmony_ciexport class SpWebHdcShell extends BaseElement { 23fb726d48Sopenharmony_ci private static MAX_DISPLAY_ROWS = 1000; 24fb726d48Sopenharmony_ci private static MAX_SAVE_SIZE = 2097152; 25fb726d48Sopenharmony_ci shellDiv: HTMLDivElement | null | undefined; 26fb726d48Sopenharmony_ci currentScreenRemain: number = 0; 27fb726d48Sopenharmony_ci private shellCanvas: HTMLCanvasElement | null | undefined; 28fb726d48Sopenharmony_ci private shellCanvasCtx: CanvasRenderingContext2D | null | undefined; 29fb726d48Sopenharmony_ci private resultStr = ''; 30fb726d48Sopenharmony_ci private sendCallBack: ((keyboardEvent: KeyboardEvent | string) => void | undefined) | undefined; 31fb726d48Sopenharmony_ci private startShellDevice = ''; 32fb726d48Sopenharmony_ci private intervalId: number | undefined; 33fb726d48Sopenharmony_ci private skipFlag: number[] = [7]; 34fb726d48Sopenharmony_ci private clearFlag: number[] = [27, 91, 50, 74, 27, 91, 72]; 35fb726d48Sopenharmony_ci private CRLFFlag: number[] = [13, 13, 10]; 36fb726d48Sopenharmony_ci private startRealTimeFlag: number[] = [27, 91, 115]; 37fb726d48Sopenharmony_ci private endRealTimeFlag: number[] = [27, 91, 117]; 38fb726d48Sopenharmony_ci private clearRealTimeFlag: number[] = [27, 91, 72, 27, 91, 74]; 39fb726d48Sopenharmony_ci private ctrlCFlag: number[] = [13, 10, 35, 32]; 40fb726d48Sopenharmony_ci private points: Point | undefined; 41fb726d48Sopenharmony_ci private forwardFlag: boolean = false; 42fb726d48Sopenharmony_ci private cursorIndex: number = 3; 43fb726d48Sopenharmony_ci private shellStrLength: number = 0; 44fb726d48Sopenharmony_ci private textY: number = 0; 45fb726d48Sopenharmony_ci private cursorRow: string = ''; 46fb726d48Sopenharmony_ci private textDecoder: TextDecoder = new TextDecoder(); 47fb726d48Sopenharmony_ci private isDragging: boolean = false; 48fb726d48Sopenharmony_ci private static TOP_OFFSET = 48; 49fb726d48Sopenharmony_ci private static FIRST_ROW_OFFSET = 32; 50fb726d48Sopenharmony_ci private static LAST_ROW_OFFSET = 40; 51fb726d48Sopenharmony_ci private static MULTI_LINE_FLAG = '<\b'; 52fb726d48Sopenharmony_ci private static LINE_BREAK_LENGTH = 2; 53fb726d48Sopenharmony_ci private static LEFT_OFFSET = 48; 54fb726d48Sopenharmony_ci private realTimeResult: string | null | undefined = ''; 55fb726d48Sopenharmony_ci private startRealTime: boolean = false; 56fb726d48Sopenharmony_ci private prevTextY: number = 0; 57fb726d48Sopenharmony_ci 58fb726d48Sopenharmony_ci public initElements(): void { 59fb726d48Sopenharmony_ci this.shellCanvas = this.shadowRoot!.querySelector<HTMLCanvasElement>('#shell_cmd'); 60fb726d48Sopenharmony_ci this.shellCanvasCtx = this.shellCanvas!.getContext('2d'); 61fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillStyle = '#000'; 62fb726d48Sopenharmony_ci 63fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(0, 0, this.shellCanvas!.width, this.shellCanvas!.height); 64fb726d48Sopenharmony_ci this.shellDiv = this.shadowRoot!.querySelector<HTMLDivElement>('.shell_cmd_div'); 65fb726d48Sopenharmony_ci this.shellCanvasAddMouseListener(); 66fb726d48Sopenharmony_ci this.shellCanvas!.addEventListener('contextmenu', (event) => { 67fb726d48Sopenharmony_ci event.preventDefault(); 68fb726d48Sopenharmony_ci event.stopPropagation(); 69fb726d48Sopenharmony_ci }); 70fb726d48Sopenharmony_ci this.shellCanvas!.addEventListener('keydown', async (keyboardEvent) => { 71fb726d48Sopenharmony_ci keyboardEvent.preventDefault(); 72fb726d48Sopenharmony_ci if (keyboardEvent.ctrlKey && keyboardEvent.code === 'KeyC' && this.points) { 73fb726d48Sopenharmony_ci let rowText: string = this.getSelectedText(); 74fb726d48Sopenharmony_ci this.points = undefined; 75fb726d48Sopenharmony_ci await navigator.clipboard.writeText(rowText); 76fb726d48Sopenharmony_ci } else { 77fb726d48Sopenharmony_ci if (this.sendCallBack) { 78fb726d48Sopenharmony_ci this.sendCallBack(keyboardEvent); 79fb726d48Sopenharmony_ci } 80fb726d48Sopenharmony_ci } 81fb726d48Sopenharmony_ci }); //@ts-ignore 82fb726d48Sopenharmony_ci window.subscribe(window.SmartEvent.UI.DeviceConnect, (deviceName: string) => { 83fb726d48Sopenharmony_ci if (deviceName) { 84fb726d48Sopenharmony_ci this.hdcShellFocus(); 85fb726d48Sopenharmony_ci } 86fb726d48Sopenharmony_ci }); 87fb726d48Sopenharmony_ci window.subscribe(window.SmartEvent.UI.DeviceDisConnect, () => { 88fb726d48Sopenharmony_ci this.clear(); 89fb726d48Sopenharmony_ci }); 90fb726d48Sopenharmony_ci this.shellCanvas!.addEventListener('blur', () => { 91fb726d48Sopenharmony_ci if (this.intervalId) { 92fb726d48Sopenharmony_ci window.clearInterval(this.intervalId); 93fb726d48Sopenharmony_ci } 94fb726d48Sopenharmony_ci this.shellCanvasCtx!.clearRect(this.shellStrLength, this.textY, 12, 3); 95fb726d48Sopenharmony_ci }); 96fb726d48Sopenharmony_ci new ResizeObserver(() => { 97fb726d48Sopenharmony_ci this.resizeCanvas(); 98fb726d48Sopenharmony_ci this.refreshShellPage(true); 99fb726d48Sopenharmony_ci }).observe(this); 100fb726d48Sopenharmony_ci } 101fb726d48Sopenharmony_ci 102fb726d48Sopenharmony_ci resizeCanvas(): void { 103fb726d48Sopenharmony_ci if (this.shellCanvas !== null && this.shellCanvas !== undefined) { 104fb726d48Sopenharmony_ci this.shellCanvas.width = this.shellCanvas.clientWidth; 105fb726d48Sopenharmony_ci this.shellCanvas.height = this.shellCanvas.clientHeight; 106fb726d48Sopenharmony_ci } 107fb726d48Sopenharmony_ci } 108fb726d48Sopenharmony_ci 109fb726d48Sopenharmony_ci clear(): void { 110fb726d48Sopenharmony_ci this.sendCallBack = undefined; 111fb726d48Sopenharmony_ci this.resultStr = ''; 112fb726d48Sopenharmony_ci this.cursorRow = ''; 113fb726d48Sopenharmony_ci this.shellCanvasCtx!.clearRect(0, 0, this.shellCanvas!.width, this.shellCanvas!.height); 114fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillStyle = '#000'; 115fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(0, 0, this.shellCanvas!.width, this.shellCanvas!.height); 116fb726d48Sopenharmony_ci window.clearInterval(this.intervalId); 117fb726d48Sopenharmony_ci } 118fb726d48Sopenharmony_ci 119fb726d48Sopenharmony_ci public hdcShellFocus(): void { 120fb726d48Sopenharmony_ci HdcDeviceManager.connect(SpRecordTrace.serialNumber).then((connected) => { 121fb726d48Sopenharmony_ci if (connected) { 122fb726d48Sopenharmony_ci if (this.sendCallBack && this.startShellDevice === SpRecordTrace.serialNumber) { 123fb726d48Sopenharmony_ci this.shellCanvas!.focus(); 124fb726d48Sopenharmony_ci this.refreshShellPage(true); 125fb726d48Sopenharmony_ci } else { 126fb726d48Sopenharmony_ci this.clear(); 127fb726d48Sopenharmony_ci this.sendCallBack = HdcDeviceManager.startShell((result: DataMessage) => { 128fb726d48Sopenharmony_ci if (result.channelClose) { 129fb726d48Sopenharmony_ci this.clear(); 130fb726d48Sopenharmony_ci return; 131fb726d48Sopenharmony_ci } 132fb726d48Sopenharmony_ci this.startShellDevice = SpRecordTrace.serialNumber; 133fb726d48Sopenharmony_ci this.handleHdcRecvData(result); 134fb726d48Sopenharmony_ci }); 135fb726d48Sopenharmony_ci this.shellCanvas!.focus(); 136fb726d48Sopenharmony_ci this.refreshShellPage(true); 137fb726d48Sopenharmony_ci } 138fb726d48Sopenharmony_ci } else { 139fb726d48Sopenharmony_ci this.clear(); 140fb726d48Sopenharmony_ci } 141fb726d48Sopenharmony_ci }); 142fb726d48Sopenharmony_ci } 143fb726d48Sopenharmony_ci 144fb726d48Sopenharmony_ci arrayBufferCompare(compareA: ArrayBuffer, compareB: number[]): boolean { 145fb726d48Sopenharmony_ci const arrayA = new Uint8Array(compareA); 146fb726d48Sopenharmony_ci if (arrayA.length === compareB.length) { 147fb726d48Sopenharmony_ci for (let i = 0; i < arrayA.length; i++) { 148fb726d48Sopenharmony_ci const dd = arrayA[i]; 149fb726d48Sopenharmony_ci if (dd !== compareB[i]) { 150fb726d48Sopenharmony_ci return false; 151fb726d48Sopenharmony_ci } 152fb726d48Sopenharmony_ci } 153fb726d48Sopenharmony_ci return true; 154fb726d48Sopenharmony_ci } 155fb726d48Sopenharmony_ci return false; 156fb726d48Sopenharmony_ci } 157fb726d48Sopenharmony_ci 158fb726d48Sopenharmony_ci getSelectedText(): string { 159fb726d48Sopenharmony_ci let selectedText = ''; 160fb726d48Sopenharmony_ci let textLines = [...this.finalArr]; 161fb726d48Sopenharmony_ci let startX = this.points!.startX < SpWebHdcShell.LEFT_OFFSET ? SpWebHdcShell.LEFT_OFFSET : this.points!.startX; 162fb726d48Sopenharmony_ci let startY = this.points!.startY; 163fb726d48Sopenharmony_ci let endX = this.points!.endX < SpWebHdcShell.LEFT_OFFSET ? SpWebHdcShell.LEFT_OFFSET : this.points!.endX; 164fb726d48Sopenharmony_ci let endY = this.points!.endY; 165fb726d48Sopenharmony_ci let endTop = Math.ceil((endY - SpWebHdcShell.TOP_OFFSET) / 16); 166fb726d48Sopenharmony_ci let startTop = Math.floor((startY - SpWebHdcShell.TOP_OFFSET - 2) / 16); 167fb726d48Sopenharmony_ci let selectRangeList = textLines.slice(startTop + 1, endTop); 168fb726d48Sopenharmony_ci let charWidth = this.shellCanvasCtx!.measureText(selectRangeList[0].split('')[0]).width; 169fb726d48Sopenharmony_ci for (let index = 0; index < selectRangeList.length; index++) { 170fb726d48Sopenharmony_ci let currentIndexLine = selectRangeList[index]; 171fb726d48Sopenharmony_ci if (index === 0) { 172fb726d48Sopenharmony_ci let startNum = Math.floor((startX - SpWebHdcShell.LEFT_OFFSET) / charWidth); 173fb726d48Sopenharmony_ci selectedText = currentIndexLine.slice(startNum); 174fb726d48Sopenharmony_ci } else if (index === selectRangeList.length - 1) { 175fb726d48Sopenharmony_ci let endNum = Math.ceil((endX - SpWebHdcShell.LEFT_OFFSET) / charWidth); 176fb726d48Sopenharmony_ci selectedText += currentIndexLine.slice(0, endNum); 177fb726d48Sopenharmony_ci } else { 178fb726d48Sopenharmony_ci selectedText += `${currentIndexLine}\n`; 179fb726d48Sopenharmony_ci } 180fb726d48Sopenharmony_ci } 181fb726d48Sopenharmony_ci return selectedText.trim(); 182fb726d48Sopenharmony_ci } 183fb726d48Sopenharmony_ci 184fb726d48Sopenharmony_ci forwardSelected(startX: number, startY: number, endX: number, endY: number): void { 185fb726d48Sopenharmony_ci //左边界x为SpWebHdcShell.LEFT_OFFSET,右边界为this.shellCanvas!.width 186fb726d48Sopenharmony_ci let depth = Math.ceil((endY - startY) / 16); 187fb726d48Sopenharmony_ci let startPointX = 0; 188fb726d48Sopenharmony_ci let startPointY = 0; 189fb726d48Sopenharmony_ci let endPointX = 0; 190fb726d48Sopenharmony_ci let endPointY = 0; 191fb726d48Sopenharmony_ci if (depth <= 1) { 192fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(startX, startY, endX - startX, endY - startY); 193fb726d48Sopenharmony_ci startPointX = startX; 194fb726d48Sopenharmony_ci startPointY = startY; 195fb726d48Sopenharmony_ci endPointX = endX; 196fb726d48Sopenharmony_ci endPointY = endY; 197fb726d48Sopenharmony_ci } else { 198fb726d48Sopenharmony_ci //绘制多行 199fb726d48Sopenharmony_ci for (let index = 1; index <= depth; index++) { 200fb726d48Sopenharmony_ci //第一行,绘起始点到canvas右边界矩形 201fb726d48Sopenharmony_ci if (index === 1) { 202fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(startX, startY, this.shellCanvas!.width - startX, index * 16); 203fb726d48Sopenharmony_ci startPointX = startX; 204fb726d48Sopenharmony_ci startPointY = startY; 205fb726d48Sopenharmony_ci } else if (index === depth) { 206fb726d48Sopenharmony_ci //最后一行,canvas左边界到结束点矩形 207fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect( 208fb726d48Sopenharmony_ci SpWebHdcShell.LEFT_OFFSET, 209fb726d48Sopenharmony_ci startY + (index - 1) * 16, 210fb726d48Sopenharmony_ci endX - SpWebHdcShell.LEFT_OFFSET, 211fb726d48Sopenharmony_ci endY - (startY + (index - 1) * 16) 212fb726d48Sopenharmony_ci ); 213fb726d48Sopenharmony_ci endPointX = endX; 214fb726d48Sopenharmony_ci endPointY = endY; 215fb726d48Sopenharmony_ci } else { 216fb726d48Sopenharmony_ci //中间行,canvas的左边界到右边界的矩形 217fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect( 218fb726d48Sopenharmony_ci SpWebHdcShell.LEFT_OFFSET, 219fb726d48Sopenharmony_ci startY + (index - 1) * 16, 220fb726d48Sopenharmony_ci this.shellCanvas!.width, 221fb726d48Sopenharmony_ci 16 222fb726d48Sopenharmony_ci ); 223fb726d48Sopenharmony_ci } 224fb726d48Sopenharmony_ci } 225fb726d48Sopenharmony_ci } 226fb726d48Sopenharmony_ci this.points = { startX: startPointX, startY: startPointY, endX: endPointX, endY: endPointY }; 227fb726d48Sopenharmony_ci } 228fb726d48Sopenharmony_ci 229fb726d48Sopenharmony_ci getCurrentLineBackSize(currentLine: string, maxBackSize: number, isStart: boolean): number { 230fb726d48Sopenharmony_ci let fillText = ''; 231fb726d48Sopenharmony_ci let strings = currentLine.split(''); 232fb726d48Sopenharmony_ci for (let index = 0; index < strings.length; index++) { 233fb726d48Sopenharmony_ci let text = strings[index]; 234fb726d48Sopenharmony_ci if ( 235fb726d48Sopenharmony_ci this.shellCanvasCtx!.measureText(fillText).width < maxBackSize && 236fb726d48Sopenharmony_ci this.shellCanvasCtx!.measureText(fillText + text).width >= maxBackSize 237fb726d48Sopenharmony_ci ) { 238fb726d48Sopenharmony_ci if (!isStart) { 239fb726d48Sopenharmony_ci fillText += text; 240fb726d48Sopenharmony_ci } 241fb726d48Sopenharmony_ci break; 242fb726d48Sopenharmony_ci } 243fb726d48Sopenharmony_ci fillText += text; 244fb726d48Sopenharmony_ci } 245fb726d48Sopenharmony_ci return fillText.length; 246fb726d48Sopenharmony_ci } 247fb726d48Sopenharmony_ci 248fb726d48Sopenharmony_ci reverseSelected(startX: number, startY: number, endX: number, endY: number): void { 249fb726d48Sopenharmony_ci //左边界x为SpWebHdcShell.LEFT_OFFSET,右边界为this.shellCanvas!.width 250fb726d48Sopenharmony_ci let depth = Math.ceil((startY - endY) / 16); 251fb726d48Sopenharmony_ci let startPointX = 0; 252fb726d48Sopenharmony_ci let startPointY = 0; 253fb726d48Sopenharmony_ci let endPointX = 0; 254fb726d48Sopenharmony_ci let endPointY = 0; 255fb726d48Sopenharmony_ci if (depth <= 1) { 256fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(endX, endY, startX - endX, startY - endY); 257fb726d48Sopenharmony_ci startPointX = endX; 258fb726d48Sopenharmony_ci startPointY = endY; 259fb726d48Sopenharmony_ci endPointX = startX; 260fb726d48Sopenharmony_ci endPointY = startY; 261fb726d48Sopenharmony_ci } else { 262fb726d48Sopenharmony_ci //绘制多行 263fb726d48Sopenharmony_ci for (let index = 1; index <= depth; index++) { 264fb726d48Sopenharmony_ci //第一行,绘起始点到canvas左边界矩形 265fb726d48Sopenharmony_ci if (index === 1) { 266fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(SpWebHdcShell.LEFT_OFFSET, startY - 16, startX - SpWebHdcShell.LEFT_OFFSET, 16); 267fb726d48Sopenharmony_ci endPointX = startX; 268fb726d48Sopenharmony_ci endPointY = startY; 269fb726d48Sopenharmony_ci } else if (index === depth) { 270fb726d48Sopenharmony_ci //最后一行,canvas右边界到结束点矩形 271fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(endX, endY, this.shellCanvas!.width - endX, startY - (index - 1) * 16 - endY); 272fb726d48Sopenharmony_ci startPointX = endX; 273fb726d48Sopenharmony_ci startPointY = endY; 274fb726d48Sopenharmony_ci } else { 275fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(SpWebHdcShell.LEFT_OFFSET, startY - index * 16, this.shellCanvas!.width, 16); 276fb726d48Sopenharmony_ci this.shellCanvasCtx!.textBaseline = 'middle'; 277fb726d48Sopenharmony_ci } 278fb726d48Sopenharmony_ci } 279fb726d48Sopenharmony_ci } 280fb726d48Sopenharmony_ci this.points = { startX: startPointX, startY: startPointY, endX: endPointX, endY: endPointY }; 281fb726d48Sopenharmony_ci } 282fb726d48Sopenharmony_ci 283fb726d48Sopenharmony_ci private singleLineToMultiLine(shellStr: string, foundationWidth: number, maxWidth: number): string[] { 284fb726d48Sopenharmony_ci let result = []; 285fb726d48Sopenharmony_ci while (shellStr.length * foundationWidth > maxWidth) { 286fb726d48Sopenharmony_ci let bfb = maxWidth / (shellStr.length * foundationWidth); 287fb726d48Sopenharmony_ci let cutIndex = Math.floor(shellStr.length * bfb); 288fb726d48Sopenharmony_ci let ss = shellStr.substring(0, cutIndex); 289fb726d48Sopenharmony_ci result.push(ss); 290fb726d48Sopenharmony_ci shellStr = shellStr.substring(cutIndex); 291fb726d48Sopenharmony_ci } 292fb726d48Sopenharmony_ci if (shellStr.length > 0) { 293fb726d48Sopenharmony_ci result.push(shellStr); 294fb726d48Sopenharmony_ci } 295fb726d48Sopenharmony_ci return result; 296fb726d48Sopenharmony_ci } 297fb726d48Sopenharmony_ci 298fb726d48Sopenharmony_ci private finalArr: Array<string> = []; 299fb726d48Sopenharmony_ci 300fb726d48Sopenharmony_ci private drawShellPage(resultStrArr: string[]): void { 301fb726d48Sopenharmony_ci let maxWidth = this.shellCanvas!.width; 302fb726d48Sopenharmony_ci let foundationWidth = Math.ceil(this.shellCanvasCtx!.measureText(' ').width); 303fb726d48Sopenharmony_ci for (let index = 0; index < resultStrArr.length - 1; index++) { 304fb726d48Sopenharmony_ci let shellStr = resultStrArr[index]; 305fb726d48Sopenharmony_ci let strWidth = this.shellCanvasCtx!.measureText(shellStr).width; 306fb726d48Sopenharmony_ci if (strWidth > maxWidth) { 307fb726d48Sopenharmony_ci let lines = this.singleLineToMultiLine(shellStr, foundationWidth, maxWidth - SpWebHdcShell.LEFT_OFFSET); 308fb726d48Sopenharmony_ci this.finalArr.push(...lines); 309fb726d48Sopenharmony_ci } else { 310fb726d48Sopenharmony_ci this.finalArr.push(shellStr); 311fb726d48Sopenharmony_ci } 312fb726d48Sopenharmony_ci } 313fb726d48Sopenharmony_ci if (this.finalArr.length > SpWebHdcShell.MAX_DISPLAY_ROWS) { 314fb726d48Sopenharmony_ci this.finalArr.splice(0, this.finalArr.length - SpWebHdcShell.MAX_DISPLAY_ROWS + 1); 315fb726d48Sopenharmony_ci } 316fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillStyle = '#fff'; 317fb726d48Sopenharmony_ci this.shellCanvasCtx!.font = '16px serif'; 318fb726d48Sopenharmony_ci this.textY = SpWebHdcShell.TOP_OFFSET; 319fb726d48Sopenharmony_ci this.finalArr.push(this.cursorRow); 320fb726d48Sopenharmony_ci for (let index: number = 0; index < this.finalArr.length; index++) { 321fb726d48Sopenharmony_ci let shellStr: string = this.finalArr[index]; 322fb726d48Sopenharmony_ci this.textY = SpWebHdcShell.TOP_OFFSET + index * 16; 323fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillText(shellStr, SpWebHdcShell.LEFT_OFFSET, this.textY); 324fb726d48Sopenharmony_ci } 325fb726d48Sopenharmony_ci } 326fb726d48Sopenharmony_ci 327fb726d48Sopenharmony_ci private drawCursorStyle(): void { 328fb726d48Sopenharmony_ci if (this.intervalId) { 329fb726d48Sopenharmony_ci window.clearInterval(this.intervalId); 330fb726d48Sopenharmony_ci } 331fb726d48Sopenharmony_ci let needClear = false; 332fb726d48Sopenharmony_ci this.intervalId = window.setInterval(() => { 333fb726d48Sopenharmony_ci if (needClear) { 334fb726d48Sopenharmony_ci needClear = false; 335fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillStyle = '#000'; 336fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(this.shellStrLength, this.textY, 12, 3); 337fb726d48Sopenharmony_ci } else { 338fb726d48Sopenharmony_ci needClear = true; 339fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillStyle = '#fff'; 340fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(this.shellStrLength, this.textY, 12, 3); 341fb726d48Sopenharmony_ci } 342fb726d48Sopenharmony_ci }, 500); 343fb726d48Sopenharmony_ci } 344fb726d48Sopenharmony_ci 345fb726d48Sopenharmony_ci refreshShellPage(scroller: boolean): void { 346fb726d48Sopenharmony_ci try { 347fb726d48Sopenharmony_ci if (this.resultStr.length === 0 && this.cursorRow.length === 0) { 348fb726d48Sopenharmony_ci return; 349fb726d48Sopenharmony_ci } 350fb726d48Sopenharmony_ci this.shellCanvasCtx!.clearRect(0, 0, this.shellCanvas!.width, this.shellCanvas!.height); 351fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillStyle = '#000'; 352fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillRect(0, 0, this.shellCanvas!.width, this.shellCanvas!.height); 353fb726d48Sopenharmony_ci let resultStrArr = this.resultStr.split('\r\n'); 354fb726d48Sopenharmony_ci if (this.realTimeResult !== '') { 355fb726d48Sopenharmony_ci resultStrArr = (this.resultStr + this.realTimeResult).split('\r\n'); 356fb726d48Sopenharmony_ci } 357fb726d48Sopenharmony_ci this.finalArr = []; 358fb726d48Sopenharmony_ci if (this.shellCanvas!.width > 0) { 359fb726d48Sopenharmony_ci this.drawShellPage(resultStrArr); 360fb726d48Sopenharmony_ci this.shellStrLength = 361fb726d48Sopenharmony_ci this.shellCanvasCtx!.measureText(this.cursorRow.slice(0, this.cursorIndex)).width + SpWebHdcShell.LEFT_OFFSET; 362fb726d48Sopenharmony_ci // 记录前一次滚动条的位置 363fb726d48Sopenharmony_ci this.prevTextY = this.shellDiv!.scrollTop + this.shellDiv!.clientHeight - 3; 364fb726d48Sopenharmony_ci if (scroller && this.textY > this.shellDiv!.clientHeight && this.textY > this.prevTextY) { 365fb726d48Sopenharmony_ci this.shellDiv!.scrollTop = this.textY - this.shellDiv!.clientHeight + 3; 366fb726d48Sopenharmony_ci this.currentScreenRemain = this.shellDiv!.scrollTop; 367fb726d48Sopenharmony_ci } 368fb726d48Sopenharmony_ci this.drawCursorStyle(); 369fb726d48Sopenharmony_ci } 370fb726d48Sopenharmony_ci } catch (e) { } 371fb726d48Sopenharmony_ci } 372fb726d48Sopenharmony_ci 373fb726d48Sopenharmony_ci public initHtml(): string { 374fb726d48Sopenharmony_ci return ` 375fb726d48Sopenharmony_ci <style> 376fb726d48Sopenharmony_ci :host{ 377fb726d48Sopenharmony_ci display: block; 378fb726d48Sopenharmony_ci border-radius: 0 16px 16px 0; 379fb726d48Sopenharmony_ci width: 100%; 380fb726d48Sopenharmony_ci position: relative; 381fb726d48Sopenharmony_ci } 382fb726d48Sopenharmony_ci .shell_cmd_div { 383fb726d48Sopenharmony_ci width: 90%; 384fb726d48Sopenharmony_ci margin-left: 5%; 385fb726d48Sopenharmony_ci margin-top: 3%; 386fb726d48Sopenharmony_ci overflow-y: scroll; 387fb726d48Sopenharmony_ci height: 40rem; 388fb726d48Sopenharmony_ci background: #000; 389fb726d48Sopenharmony_ci border: 1px solid var(--dark-color1,#4D4D4D); 390fb726d48Sopenharmony_ci border-radius: 16px; 391fb726d48Sopenharmony_ci } 392fb726d48Sopenharmony_ci ::-webkit-scrollbar{ 393fb726d48Sopenharmony_ci width: 13px; 394fb726d48Sopenharmony_ci height: 10px; 395fb726d48Sopenharmony_ci background-color: #FFFFFF; 396fb726d48Sopenharmony_ci } 397fb726d48Sopenharmony_ci ::-webkit-scrollbar-track{ 398fb726d48Sopenharmony_ci border-top-right-radius: 16px; 399fb726d48Sopenharmony_ci border-bottom-right-radius: 16px; 400fb726d48Sopenharmony_ci background-color: #000000; 401fb726d48Sopenharmony_ci } 402fb726d48Sopenharmony_ci ::-webkit-scrollbar-thumb{ 403fb726d48Sopenharmony_ci background: #5A5A5A; 404fb726d48Sopenharmony_ci border-radius: 6px; 405fb726d48Sopenharmony_ci } 406fb726d48Sopenharmony_ci canvas { 407fb726d48Sopenharmony_ci display: inline-block; 408fb726d48Sopenharmony_ci outline: none; 409fb726d48Sopenharmony_ci } 410fb726d48Sopenharmony_ci 411fb726d48Sopenharmony_ci </style> 412fb726d48Sopenharmony_ci <div class="shell_cmd_div"> 413fb726d48Sopenharmony_ci <canvas id="shell_cmd" style="width: 100%;height:${16000 + SpWebHdcShell.TOP_OFFSET}px;" tabindex="0"></canvas> 414fb726d48Sopenharmony_ci </div> 415fb726d48Sopenharmony_ci `; 416fb726d48Sopenharmony_ci } 417fb726d48Sopenharmony_ci 418fb726d48Sopenharmony_ci private refreshCurrentRow(): void { 419fb726d48Sopenharmony_ci let lastRow: string = this.resultStr; 420fb726d48Sopenharmony_ci if (this.resultStr.lastIndexOf('\r\n') !== -1) { 421fb726d48Sopenharmony_ci lastRow = this.resultStr.substring(this.resultStr.lastIndexOf('\r\n') + 2); 422fb726d48Sopenharmony_ci } 423fb726d48Sopenharmony_ci let currentRow: string[] = [...lastRow]; 424fb726d48Sopenharmony_ci let result: string[] = []; 425fb726d48Sopenharmony_ci this.cursorIndex = 0; 426fb726d48Sopenharmony_ci for (let index: number = 0; index < currentRow.length; index++) { 427fb726d48Sopenharmony_ci let currentResult: string = currentRow[index]; 428fb726d48Sopenharmony_ci if (currentResult === '\b') { 429fb726d48Sopenharmony_ci this.cursorIndex--; 430fb726d48Sopenharmony_ci } else { 431fb726d48Sopenharmony_ci result[this.cursorIndex] = currentResult; 432fb726d48Sopenharmony_ci this.cursorIndex++; 433fb726d48Sopenharmony_ci } 434fb726d48Sopenharmony_ci } 435fb726d48Sopenharmony_ci this.cursorRow = result.join(''); 436fb726d48Sopenharmony_ci } 437fb726d48Sopenharmony_ci 438fb726d48Sopenharmony_ci private handleHdcRecvData(result: DataMessage): void { 439fb726d48Sopenharmony_ci const resData = result.getData(); 440fb726d48Sopenharmony_ci if (resData) { 441fb726d48Sopenharmony_ci if (this.arrayBufferCompare(resData, this.skipFlag)) { 442fb726d48Sopenharmony_ci return; 443fb726d48Sopenharmony_ci } else if (this.arrayBufferCompare(resData, this.clearFlag)) { 444fb726d48Sopenharmony_ci this.resultStr = ''; 445fb726d48Sopenharmony_ci this.shellDiv!.scrollTop = 0; 446fb726d48Sopenharmony_ci this.cursorIndex = 3; 447fb726d48Sopenharmony_ci } else if (this.arrayBufferCompare(resData, this.CRLFFlag)) { 448fb726d48Sopenharmony_ci if (this.resultStr.lastIndexOf('\r\n') !== -1) { 449fb726d48Sopenharmony_ci this.resultStr = this.resultStr.substring(0, this.resultStr.lastIndexOf('\r\n') + 2) + this.cursorRow; 450fb726d48Sopenharmony_ci } else { 451fb726d48Sopenharmony_ci this.resultStr = this.cursorRow; 452fb726d48Sopenharmony_ci } 453fb726d48Sopenharmony_ci this.resultStr += result.getDataToString(); 454fb726d48Sopenharmony_ci this.cursorIndex = 3; 455fb726d48Sopenharmony_ci } else { 456fb726d48Sopenharmony_ci if (this.resultStr.length > SpWebHdcShell.MAX_SAVE_SIZE) { 457fb726d48Sopenharmony_ci this.resultStr = this.resultStr.substring(this.resultStr.length / 2); 458fb726d48Sopenharmony_ci } 459fb726d48Sopenharmony_ci const arrayA = new Uint8Array(resData); 460fb726d48Sopenharmony_ci if (arrayA[0] === 13 && arrayA[1] !== 10 && arrayA[1] !== 13) { 461fb726d48Sopenharmony_ci this.hdcRecvEnterAndBracket(arrayA, result); 462fb726d48Sopenharmony_ci } else if (this.isStartWidthArrayBuffer(arrayA, this.startRealTimeFlag)) { 463fb726d48Sopenharmony_ci let lastIndex = this.getLastRestorationIndex(arrayA, this.endRealTimeFlag); 464fb726d48Sopenharmony_ci this.realTimeResult = this.removeTextAndColorSequenceStr( 465fb726d48Sopenharmony_ci this.textDecoder.decode(arrayA.slice(lastIndex, arrayA.length)) 466fb726d48Sopenharmony_ci ); 467fb726d48Sopenharmony_ci this.startRealTime = true; 468fb726d48Sopenharmony_ci } else if (this.isStartWidthArrayBuffer(arrayA, this.clearRealTimeFlag)) { 469fb726d48Sopenharmony_ci this.realTimeResult = this.removeTextAndColorSequenceStr( 470fb726d48Sopenharmony_ci this.textDecoder.decode(arrayA.slice(6, arrayA.length)) 471fb726d48Sopenharmony_ci ); 472fb726d48Sopenharmony_ci this.startRealTime = true; 473fb726d48Sopenharmony_ci } else { 474fb726d48Sopenharmony_ci if (this.isStartWidthArrayBuffer(arrayA, this.ctrlCFlag)) { 475fb726d48Sopenharmony_ci this.resultStr += this.realTimeResult; 476fb726d48Sopenharmony_ci this.startRealTime = false; 477fb726d48Sopenharmony_ci } 478fb726d48Sopenharmony_ci this.hdcRecvRealMessage(result); 479fb726d48Sopenharmony_ci } 480fb726d48Sopenharmony_ci } 481fb726d48Sopenharmony_ci this.resultStr = this.removeTextAndColorSequenceStr(this.resultStr); 482fb726d48Sopenharmony_ci this.refreshCurrentRow(); 483fb726d48Sopenharmony_ci this.refreshShellPage(true); 484fb726d48Sopenharmony_ci } 485fb726d48Sopenharmony_ci } 486fb726d48Sopenharmony_ci 487fb726d48Sopenharmony_ci private hdcRecvEnterAndBracket(arrayA: Uint8Array, result: DataMessage): void { 488fb726d48Sopenharmony_ci const index = this.resultStr.lastIndexOf('\n'); 489fb726d48Sopenharmony_ci const resultStrLength = this.resultStr.length; 490fb726d48Sopenharmony_ci if (index > -1 && resultStrLength > index) { 491fb726d48Sopenharmony_ci this.resultStr = this.resultStr.substring(0, index + 1) + this.textDecoder.decode(arrayA.slice(1, arrayA.length)); 492fb726d48Sopenharmony_ci } else { 493fb726d48Sopenharmony_ci if (this.resultStr.split('\n').length === 1) { 494fb726d48Sopenharmony_ci const index = this.cursorRow.lastIndexOf('\n'); 495fb726d48Sopenharmony_ci this.cursorRow = 496fb726d48Sopenharmony_ci this.cursorRow.substring(0, index + 1) + this.textDecoder.decode(arrayA.slice(1, arrayA.length)); 497fb726d48Sopenharmony_ci this.resultStr = this.cursorRow; 498fb726d48Sopenharmony_ci } else { 499fb726d48Sopenharmony_ci this.resultStr += result.getDataToString(); 500fb726d48Sopenharmony_ci } 501fb726d48Sopenharmony_ci } 502fb726d48Sopenharmony_ci this.realTimeResult = ''; 503fb726d48Sopenharmony_ci } 504fb726d48Sopenharmony_ci 505fb726d48Sopenharmony_ci private hdcRecvRealMessage(result: DataMessage): void { 506fb726d48Sopenharmony_ci if (this.startRealTime) { 507fb726d48Sopenharmony_ci if (result.getDataToString().includes(SpWebHdcShell.MULTI_LINE_FLAG)) { 508fb726d48Sopenharmony_ci this.realTimeResult += result.getDataToString().substring(result.getDataToString().indexOf('\r')); 509fb726d48Sopenharmony_ci } else { 510fb726d48Sopenharmony_ci this.realTimeResult += result.getDataToString(); 511fb726d48Sopenharmony_ci } 512fb726d48Sopenharmony_ci this.realTimeResult = this.removeTextAndColorSequenceStr(this.realTimeResult!); 513fb726d48Sopenharmony_ci } else { 514fb726d48Sopenharmony_ci this.realTimeResult = ''; 515fb726d48Sopenharmony_ci if (result.getDataToString().includes(SpWebHdcShell.MULTI_LINE_FLAG)) { 516fb726d48Sopenharmony_ci // 获取所有内容,不包括最后一行数据 517fb726d48Sopenharmony_ci this.resultStr = this.resultStr.substring( 518fb726d48Sopenharmony_ci 0, 519fb726d48Sopenharmony_ci this.resultStr.lastIndexOf('\r\n') + SpWebHdcShell.LINE_BREAK_LENGTH 520fb726d48Sopenharmony_ci ); 521fb726d48Sopenharmony_ci // 多行情况不能直接拼接返回数据 522fb726d48Sopenharmony_ci this.resultStr += result.getDataToString().substring(result.getDataToString().indexOf('\r')); 523fb726d48Sopenharmony_ci } else { 524fb726d48Sopenharmony_ci this.resultStr += result.getDataToString(); 525fb726d48Sopenharmony_ci } 526fb726d48Sopenharmony_ci } 527fb726d48Sopenharmony_ci } 528fb726d48Sopenharmony_ci 529fb726d48Sopenharmony_ci private removeTextAndColorSequenceStr(currentStr: string): string { 530fb726d48Sopenharmony_ci return currentStr.replace(new RegExp(/\x1B\[[0-9;]*[a-zA-Z]/g), ''); 531fb726d48Sopenharmony_ci } 532fb726d48Sopenharmony_ci 533fb726d48Sopenharmony_ci private isStartWidthArrayBuffer(sourceArray: Uint8Array, compareArray: number[]): boolean { 534fb726d48Sopenharmony_ci for (let index = 0; index < compareArray.length; index++) { 535fb726d48Sopenharmony_ci if (sourceArray[index] !== compareArray[index]) { 536fb726d48Sopenharmony_ci return false; 537fb726d48Sopenharmony_ci } 538fb726d48Sopenharmony_ci } 539fb726d48Sopenharmony_ci return true; 540fb726d48Sopenharmony_ci } 541fb726d48Sopenharmony_ci 542fb726d48Sopenharmony_ci private getLastRestorationIndex(sourceArray: Uint8Array, compareArray: number[]): number { 543fb726d48Sopenharmony_ci let lastIndex = -1; 544fb726d48Sopenharmony_ci for (let index = sourceArray.length - 1; index >= 0; index--) { 545fb726d48Sopenharmony_ci if (sourceArray[index] === compareArray[0]) { 546fb726d48Sopenharmony_ci let isLast = true; 547fb726d48Sopenharmony_ci for (let j = 1; j < compareArray.length; j++) { 548fb726d48Sopenharmony_ci if (sourceArray[index + j] !== compareArray[j]) { 549fb726d48Sopenharmony_ci isLast = false; 550fb726d48Sopenharmony_ci break; 551fb726d48Sopenharmony_ci } 552fb726d48Sopenharmony_ci } 553fb726d48Sopenharmony_ci if (isLast) { 554fb726d48Sopenharmony_ci lastIndex = index; 555fb726d48Sopenharmony_ci break; 556fb726d48Sopenharmony_ci } 557fb726d48Sopenharmony_ci } 558fb726d48Sopenharmony_ci } 559fb726d48Sopenharmony_ci return lastIndex + compareArray.length; 560fb726d48Sopenharmony_ci } 561fb726d48Sopenharmony_ci 562fb726d48Sopenharmony_ci private shellCanvasAddMouseListener(): void { 563fb726d48Sopenharmony_ci let startX: number; 564fb726d48Sopenharmony_ci let startY: number; 565fb726d48Sopenharmony_ci let endX: number; 566fb726d48Sopenharmony_ci let endY: number; 567fb726d48Sopenharmony_ci this.shellCanvas!.addEventListener('mousedown', (event) => { 568fb726d48Sopenharmony_ci if (this.resultStr.length === 0 && this.cursorRow.length === 0) { 569fb726d48Sopenharmony_ci return; 570fb726d48Sopenharmony_ci } 571fb726d48Sopenharmony_ci this.isDragging = true; 572fb726d48Sopenharmony_ci startX = event.offsetX; 573fb726d48Sopenharmony_ci startY = event.offsetY; 574fb726d48Sopenharmony_ci this.refreshShellPage(false); 575fb726d48Sopenharmony_ci }); 576fb726d48Sopenharmony_ci this.shellCanvas!.addEventListener('mousemove', (event) => { 577fb726d48Sopenharmony_ci if (!this.isDragging) { 578fb726d48Sopenharmony_ci return; 579fb726d48Sopenharmony_ci } 580fb726d48Sopenharmony_ci if (this.resultStr.length === 0 && this.cursorRow.length === 0) { 581fb726d48Sopenharmony_ci return; 582fb726d48Sopenharmony_ci } 583fb726d48Sopenharmony_ci endX = event.offsetX; 584fb726d48Sopenharmony_ci endY = event.offsetY; 585fb726d48Sopenharmony_ci this.refreshShellPage(false); 586fb726d48Sopenharmony_ci this.points = undefined; 587fb726d48Sopenharmony_ci this.shellCanvasCtx!.fillStyle = 'rgba(128, 128, 128, 0.5)'; 588fb726d48Sopenharmony_ci if (endY > startY) { 589fb726d48Sopenharmony_ci this.forwardFlag = true; 590fb726d48Sopenharmony_ci this.forwardSelected(startX, startY, endX, endY); 591fb726d48Sopenharmony_ci } else { 592fb726d48Sopenharmony_ci this.forwardFlag = false; 593fb726d48Sopenharmony_ci this.reverseSelected(startX, startY, endX, endY); 594fb726d48Sopenharmony_ci } 595fb726d48Sopenharmony_ci }); 596fb726d48Sopenharmony_ci this.shellCanvasAddMouseUpListener(); 597fb726d48Sopenharmony_ci } 598fb726d48Sopenharmony_ci 599fb726d48Sopenharmony_ci private shellCanvasAddMouseUpListener(): void { 600fb726d48Sopenharmony_ci this.shellCanvas!.addEventListener('mouseup', async (event)=> { 601fb726d48Sopenharmony_ci if (!this.isDragging) { 602fb726d48Sopenharmony_ci return; 603fb726d48Sopenharmony_ci } 604fb726d48Sopenharmony_ci if (this.resultStr.length === 0 && this.cursorRow.length === 0) { 605fb726d48Sopenharmony_ci return; 606fb726d48Sopenharmony_ci } 607fb726d48Sopenharmony_ci this.isDragging = false; 608fb726d48Sopenharmony_ci //右键 609fb726d48Sopenharmony_ci if (event.button === 2) { 610fb726d48Sopenharmony_ci let text: string = await navigator.clipboard.readText(); 611fb726d48Sopenharmony_ci if (text) { 612fb726d48Sopenharmony_ci if (this.sendCallBack) { 613fb726d48Sopenharmony_ci this.sendCallBack(text); 614fb726d48Sopenharmony_ci } 615fb726d48Sopenharmony_ci return; 616fb726d48Sopenharmony_ci } 617fb726d48Sopenharmony_ci } 618fb726d48Sopenharmony_ci }); 619fb726d48Sopenharmony_ci } 620fb726d48Sopenharmony_ci} 621fb726d48Sopenharmony_ci 622fb726d48Sopenharmony_ciexport class Point { 623fb726d48Sopenharmony_ci startX: number = 0; 624fb726d48Sopenharmony_ci startY: number = 0; 625fb726d48Sopenharmony_ci endX: number = 0; 626fb726d48Sopenharmony_ci endY: number = 0; 627fb726d48Sopenharmony_ci} 628