fix(data-viewer): correct text line break in presence of <span>
This commit is contained in:
parent
a2b7026f54
commit
f0f11c0646
|
@ -137,7 +137,7 @@ function u8toHexdump(buffer: Uint8Array) {
|
||||||
function strToHTML(str: string) {
|
function strToHTML(str: string) {
|
||||||
return str.replace(/\n/g, '<br>') // Replace newline with <br> tag
|
return str.replace(/\n/g, '<br>') // Replace newline with <br> tag
|
||||||
.replace(/\t/g, ' ') // Replace tab with spaces (or you could use ' ' for single spaces)
|
.replace(/\t/g, ' ') // Replace tab with spaces (or you could use ' ' for single spaces)
|
||||||
.replace(/ /g, ' ');
|
.replace(/ /g, ' ');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isArrayContained(subArray: Uint8Array, mainArray: Uint8Array,
|
function isArrayContained(subArray: Uint8Array, mainArray: Uint8Array,
|
||||||
|
@ -376,11 +376,15 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
||||||
} else {
|
} else {
|
||||||
RxSegment = new Uint8Array();
|
RxSegment = new Uint8Array();
|
||||||
}
|
}
|
||||||
RxRemainHexdump.value = u8toHexdump(RxSegment);
|
|
||||||
|
|
||||||
for (let i = 0; i < frames.length; i++) {
|
for (let i = 0; i < frames.length; i++) {
|
||||||
addItem(frames[i], isRX, doSend);
|
addItem(frames[i], isRX, doSend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RxSegment.length > 8192) {
|
||||||
|
addItem(RxSegment, isRX, doSend);
|
||||||
|
RxSegment = new Uint8Array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const frameBreakRet = {
|
const frameBreakRet = {
|
||||||
|
@ -409,6 +413,11 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
||||||
const TxTotalByteCount = ref(0);
|
const TxTotalByteCount = ref(0);
|
||||||
const TxByteCount = ref(0);
|
const TxByteCount = ref(0);
|
||||||
|
|
||||||
|
let TxByteCountLocal = 0;
|
||||||
|
let TxTotalByteCountLocal = 0;
|
||||||
|
let RxByteCountLocal = 0;
|
||||||
|
let RxTotalByteCountLocal = 0;
|
||||||
|
|
||||||
const enableFilter = ref(true);
|
const enableFilter = ref(true);
|
||||||
const forceToBottom = ref(true);
|
const forceToBottom = ref(true);
|
||||||
const filterChanged = ref(false);
|
const filterChanged = ref(false);
|
||||||
|
@ -511,9 +520,19 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
||||||
}
|
}
|
||||||
}, {immediate: true});
|
}, {immediate: true});
|
||||||
|
|
||||||
|
/* delayed value update, prevent quick unnecessary update */
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
dataBufLength.value = dataBuf.length;
|
dataBufLength.value = dataBuf.length;
|
||||||
}, 500);
|
TxByteCount.value = TxByteCountLocal;
|
||||||
|
TxTotalByteCount.value = TxTotalByteCountLocal;
|
||||||
|
RxByteCount.value = RxByteCountLocal;
|
||||||
|
RxTotalByteCount.value = RxTotalByteCountLocal;
|
||||||
|
if (RxSegment.length) {
|
||||||
|
RxRemainHexdump.value = u8toHexdump(RxSegment);
|
||||||
|
} else {
|
||||||
|
RxRemainHexdump.value = "";
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
|
||||||
function addString(item: string, isRX: boolean = false, doSend: boolean = false, type: number = 0) {
|
function addString(item: string, isRX: boolean = false, doSend: boolean = false, type: number = 0) {
|
||||||
const encoder = new TextEncoder();
|
const encoder = new TextEncoder();
|
||||||
|
@ -594,8 +613,8 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
||||||
// });
|
// });
|
||||||
|
|
||||||
if (isRX) {
|
if (isRX) {
|
||||||
RxTotalByteCount.value += item.length;
|
RxTotalByteCountLocal += item.length;
|
||||||
RxByteCount.value = item.length;
|
RxByteCountLocal = item.length;
|
||||||
} else {
|
} else {
|
||||||
/* append prefix and suffix */
|
/* append prefix and suffix */
|
||||||
if (computedPrefixValue.value.length || computedSuffixValue.value.length) {
|
if (computedPrefixValue.value.length || computedSuffixValue.value.length) {
|
||||||
|
@ -614,8 +633,8 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
||||||
} else {
|
} else {
|
||||||
type = 1;
|
type = 1;
|
||||||
}
|
}
|
||||||
TxTotalByteCount.value += item.length;
|
TxTotalByteCountLocal += item.length;
|
||||||
TxByteCount.value = item.length;
|
TxByteCountLocal = item.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
let str = ""
|
let str = ""
|
||||||
|
@ -722,9 +741,9 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
||||||
|
|
||||||
function clearByteCount(isRX: boolean) {
|
function clearByteCount(isRX: boolean) {
|
||||||
if (isRX) {
|
if (isRX) {
|
||||||
RxTotalByteCount.value = 0;
|
RxTotalByteCountLocal = 0;
|
||||||
} else {
|
} else {
|
||||||
TxTotalByteCount.value = 0;
|
TxTotalByteCountLocal = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,11 +753,13 @@ export const useDataViewerStore = defineStore('text-viewer', () => {
|
||||||
dataBufLength.value = 0;
|
dataBufLength.value = 0;
|
||||||
batchStartIndex = 0;
|
batchStartIndex = 0;
|
||||||
|
|
||||||
RxByteCount.value = 0;
|
RxByteCountLocal = 0;
|
||||||
RxTotalByteCount.value = 0;
|
RxTotalByteCountLocal = 0;
|
||||||
|
TxByteCountLocal = 0;
|
||||||
|
TxTotalByteCountLocal = 0;
|
||||||
|
|
||||||
TxByteCount.value = 0;
|
RxSegment = new Uint8Array();
|
||||||
TxTotalByteCount.value = 0;
|
RxRemainHexdump.value = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearFilteredBuff() {
|
function clearFilteredBuff() {
|
||||||
|
|
|
@ -103,8 +103,8 @@
|
||||||
:class="[store.enableLineWrap ? 'break-all' : 'text-nowrap']"
|
:class="[store.enableLineWrap ? 'break-all' : 'text-nowrap']"
|
||||||
>
|
>
|
||||||
<template v-slot:default="{ item, }">
|
<template v-slot:default="{ item, }">
|
||||||
<div>
|
<div class="">
|
||||||
<div class="flex">
|
<div class="flex" :class="[store.enableLineWrap ? 'whitespace-pre-wrap' : 'whitespace-pre']">
|
||||||
<p class="text-nowrap text-sm text-lime-500" v-if="item.isRX" type="success" v-show="store.showTimestamp">
|
<p class="text-nowrap text-sm text-lime-500" v-if="item.isRX" type="success" v-show="store.showTimestamp">
|
||||||
<span>{{ item.time }}</span>◄-RX|</p>
|
<span>{{ item.time }}</span>◄-RX|</p>
|
||||||
<p class="text-nowrap text-sm text-sky-500" v-else-if="item.type === 0" type="primary" v-show="store.showTimestamp">
|
<p class="text-nowrap text-sm text-sky-500" v-else-if="item.type === 0" type="primary" v-show="store.showTimestamp">
|
||||||
|
@ -115,10 +115,10 @@
|
||||||
<p v-show="store.showText"
|
<p v-show="store.showText"
|
||||||
v-html="item.str"></p>
|
v-html="item.str"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex text-wrap">
|
<div class="flex">
|
||||||
<p v-show="store.showHex" class="">{{ item.hex }}</p>
|
<p v-show="store.showHex" class="">{{ item.hex }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex whitespace-pre">
|
||||||
<p v-show="store.showHexdump"
|
<p v-show="store.showHexdump"
|
||||||
class="text-nowrap"
|
class="text-nowrap"
|
||||||
:style="{ 'background-color': item.isRX ? store.RxHexdumpColor : store.TxHexdumpColor }"
|
:style="{ 'background-color': item.isRX ? store.RxHexdumpColor : store.TxHexdumpColor }"
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
>
|
>
|
||||||
<template v-slot:default="{ item, }">
|
<template v-slot:default="{ item, }">
|
||||||
<div>
|
<div>
|
||||||
<div class="flex">
|
<div class="flex" :class="[store.enableLineWrap ? 'whitespace-pre-wrap' : 'whitespace-pre']">
|
||||||
<p class="text-nowrap text-sm text-lime-500" v-if="item.isRX" type="success" v-show="store.showTimestamp">
|
<p class="text-nowrap text-sm text-lime-500" v-if="item.isRX" type="success" v-show="store.showTimestamp">
|
||||||
<span>{{ item.time }}</span>◄-RX|</p>
|
<span>{{ item.time }}</span>◄-RX|</p>
|
||||||
<p class="text-nowrap text-sm text-sky-500" v-else-if="item.type === 0" type="primary" v-show="store.showTimestamp">
|
<p class="text-nowrap text-sm text-sky-500" v-else-if="item.type === 0" type="primary" v-show="store.showTimestamp">
|
||||||
|
@ -148,10 +148,10 @@
|
||||||
<p v-show="store.showText"
|
<p v-show="store.showText"
|
||||||
v-html="item.str"></p>
|
v-html="item.str"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex text-wrap">
|
<div class="flex">
|
||||||
<p v-show="store.showHex" class="">{{ item.hex }}</p>
|
<p v-show="store.showHex" class="">{{ item.hex }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex">
|
<div class="flex whitespace-pre">
|
||||||
<p v-show="store.showHexdump"
|
<p v-show="store.showHexdump"
|
||||||
class="text-nowrap"
|
class="text-nowrap"
|
||||||
:style="{ 'background-color': item.isRX ? store.RxHexdumpColor : store.TxHexdumpColor }"
|
:style="{ 'background-color': item.isRX ? store.RxHexdumpColor : store.TxHexdumpColor }"
|
||||||
|
@ -165,7 +165,7 @@
|
||||||
|
|
||||||
<div class="shrink-0 flex max-h-14 mt-0.5 text-xs">
|
<div class="shrink-0 flex max-h-14 mt-0.5 text-xs">
|
||||||
<div class="flex shrink-0">
|
<div class="flex shrink-0">
|
||||||
<el-tooltip content="未满足断帧规则的数据(如:未超时),暂时实时显示在此区域。" effect="light">
|
<el-tooltip content="未满足断帧规则的数据(如:未超时),暂时实时显示在此区域。超过8192字节,自动断帧;" effect="light">
|
||||||
<InlineSvg name="help" class="w-3.5 h-3.5 text-gray-500 cursor-help"></InlineSvg>
|
<InlineSvg name="help" class="w-3.5 h-3.5 text-gray-500 cursor-help"></InlineSvg>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<p>►</p>
|
<p>►</p>
|
||||||
|
@ -209,12 +209,12 @@
|
||||||
<div class="flex gap-2">
|
<div class="flex gap-2">
|
||||||
<el-link>
|
<el-link>
|
||||||
<el-tag class="font-mono font-bold" size="small">
|
<el-tag class="font-mono font-bold" size="small">
|
||||||
{{ `TX:${store.TxByteCount}B/${store.TxTotalByteCount}B` }}
|
{{ `TX(B):${store.TxByteCount}/ ${store.TxTotalByteCount}` }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</el-link>
|
</el-link>
|
||||||
<el-link type="success">
|
<el-link type="success">
|
||||||
<el-tag class="font-mono font-bold" size="small" type="success">
|
<el-tag class="font-mono font-bold" size="small" type="success">
|
||||||
{{ `RX:${store.RxByteCount}B/${store.RxTotalByteCount}B` }}
|
{{ `RX(B):${store.RxByteCount}/ ${store.RxTotalByteCount}` }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</el-link>
|
</el-link>
|
||||||
<div class="flex align-center">
|
<div class="flex align-center">
|
||||||
|
@ -222,7 +222,7 @@
|
||||||
<el-link class="flex" @click="store.clearDataBuff" type="warning">
|
<el-link class="flex" @click="store.clearDataBuff" type="warning">
|
||||||
<InlineSvg class="h-5" name="trash"></InlineSvg>
|
<InlineSvg class="h-5" name="trash"></InlineSvg>
|
||||||
</el-link>
|
</el-link>
|
||||||
<span class="align-text-bottom">缓存帧数: {{ store.dataBufLength }}/20000</span>
|
<span class="align-text-bottom">缓存帧数: {{ store.dataBufLength }}/30000</span>
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -336,8 +336,7 @@ function addItem(nr: number) {
|
||||||
function scrollToBottom() {
|
function scrollToBottom() {
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const scrollerElement = vuetifyVirtualScrollBarRef.value; // Adjust according to your setup
|
const scrollerElement = vuetifyVirtualScrollBarRef.value; // Adjust according to your setup
|
||||||
// scrollerElement.scrollTop = scrollerElement.scrollHeight;
|
scrollerElement.scrollTop = scrollerElement.scrollHeight;
|
||||||
scrollerElement.scrollTo(scrollerElement.scrollLeft, scrollerElement.scrollHeight);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,6 +427,12 @@ watch(() => store.filterChanged, (value) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
watch(() => store.showVirtualScroll, () => {
|
||||||
|
if (store.forceToBottom) {
|
||||||
|
scrollToBottom();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const handleScroll = (ev: Event) => {
|
const handleScroll = (ev: Event) => {
|
||||||
if (store.forceToBottom) {
|
if (store.forceToBottom) {
|
||||||
if (vuetifyVirtualScrollBarRef.value.scrollTop - lastScrollHeight < 0) {
|
if (vuetifyVirtualScrollBarRef.value.scrollTop - lastScrollHeight < 0) {
|
||||||
|
|
Loading…
Reference in New Issue