mirror of
https://github.com/xlmnxp/extractify.zip.git
synced 2024-11-23 17:13:12 +03:00
add binary view
This commit is contained in:
parent
c8209c5799
commit
5a739b543d
9
app.vue
9
app.vue
@ -5,6 +5,7 @@ import { useDisplay } from 'vuetify/lib/framework.mjs';
|
||||
import { HistoryManager } from './composables/history-manager';
|
||||
import { FilesManager } from './composables/files-manager';
|
||||
import type { iFile } from "composables/worker/7zip-manager"
|
||||
import { videoExtensions, binaryExtensions } from '#imports';
|
||||
|
||||
let display = useDisplay();
|
||||
let drawer = ref(!display.mdAndDown.value);
|
||||
@ -57,6 +58,8 @@ watchEffect(async () => {
|
||||
const file = filesManager.getFile(selectedPath.value);
|
||||
filesGridList.value = file?.content;
|
||||
|
||||
console.log("Selected file", file);
|
||||
|
||||
selectedList.value = [];
|
||||
for (const selectedElement of document.querySelectorAll(".selectable.selected")) {
|
||||
selectedElement.classList.remove("selected");
|
||||
@ -193,9 +196,13 @@ function stepUp(path: string) {
|
||||
<MediaVideoPlayer :src="mediaBlobUrl"></MediaVideoPlayer>
|
||||
</template>
|
||||
<template
|
||||
v-if="!filesManager.getFile(selectedPath)?.isFolder && files.length && !videoExtensions.includes(filesManager.getFile(selectedPath)?.extension)">
|
||||
v-if="!filesManager.getFile(selectedPath)?.isFolder && files.length && !videoExtensions.includes(filesManager.getFile(selectedPath)?.extension) && !binaryExtensions.includes(filesManager.getFile(selectedPath)?.extension)">
|
||||
<TextEditor :file="filesManager.getFile(selectedPath)" :filesManager="filesManager"></TextEditor>
|
||||
</template>
|
||||
<template
|
||||
v-if="!filesManager.getFile(selectedPath)?.isFolder && files.length && binaryExtensions.includes(filesManager.getFile(selectedPath)?.extension)">
|
||||
<BinaryViewer :file="filesManager.getFile(selectedPath)" :filesManager="filesManager"></BinaryViewer>
|
||||
</template>
|
||||
<template v-if="!files.length">
|
||||
<!-- tutorial drag and drop zipped file here and review it securely -->
|
||||
<v-row align="center" justify="center">
|
||||
|
144
components/binary-viewer.vue
Normal file
144
components/binary-viewer.vue
Normal file
@ -0,0 +1,144 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, onMounted, computed } from 'vue'
|
||||
import { FilesManager } from '~/composables/files-manager';
|
||||
import { iFile } from '~/composables/worker/7zip-manager';
|
||||
|
||||
interface Props {
|
||||
file: iFile,
|
||||
filesManager: FilesManager
|
||||
}
|
||||
|
||||
const { file, filesManager } = defineProps<Props>()
|
||||
const buffer = ref<Uint8Array>()
|
||||
const containerRef = ref<HTMLElement>()
|
||||
const isLoading = ref(true)
|
||||
const rowHeight = 24 // pixels per row
|
||||
const visibleRows = ref(0)
|
||||
const scrollTop = ref(0)
|
||||
|
||||
// Calculate total rows and visible window
|
||||
const totalRows = computed(() => buffer.value ? Math.ceil(buffer.value.length / 16) : 0)
|
||||
const startRow = computed(() => Math.floor(scrollTop.value / rowHeight))
|
||||
const endRow = computed(() => Math.min(startRow.value + visibleRows.value + 5, totalRows.value))
|
||||
|
||||
// Get only the visible rows data
|
||||
const visibleData = computed(() => {
|
||||
if (!buffer.value) return []
|
||||
|
||||
const rows = []
|
||||
for (let i = startRow.value; i < endRow.value; i++) {
|
||||
const offset = i * 16
|
||||
const chunk = buffer.value.slice(offset, offset + 16)
|
||||
const hex = Array.from(chunk).map(b => b.toString(16).padStart(2, '0')).join(' ')
|
||||
const ascii = Array.from(chunk).map(b => b >= 32 && b <= 126 ? String.fromCharCode(b) : '.').join('')
|
||||
|
||||
rows.push({
|
||||
address: offset.toString(16).padStart(8, '0'),
|
||||
hex: hex.padEnd(48, ' '),
|
||||
ascii
|
||||
})
|
||||
}
|
||||
return rows
|
||||
})
|
||||
|
||||
// Handle scroll events
|
||||
function onScroll(event: Event) {
|
||||
const container = event.target as HTMLElement
|
||||
scrollTop.value = container.scrollTop
|
||||
}
|
||||
|
||||
// Calculate visible rows based on container height
|
||||
function updateVisibleRows() {
|
||||
if (containerRef.value) {
|
||||
visibleRows.value = Math.ceil(containerRef.value.clientHeight / rowHeight)
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
buffer.value = await filesManager.getFileContent(file.path, "binary") as Uint8Array
|
||||
updateVisibleRows()
|
||||
window.addEventListener('resize', updateVisibleRows)
|
||||
} finally {
|
||||
isLoading.value = false
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="binary-viewer">
|
||||
<div v-if="isLoading" class="loading">
|
||||
Loading...
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
ref="containerRef"
|
||||
class="hex-container"
|
||||
@scroll="onScroll"
|
||||
>
|
||||
<div
|
||||
class="scroll-content"
|
||||
:style="{
|
||||
height: `${totalRows * rowHeight}px`,
|
||||
paddingTop: `${startRow * rowHeight}px`
|
||||
}"
|
||||
>
|
||||
<div
|
||||
v-for="row in visibleData"
|
||||
:key="row.address"
|
||||
class="hex-line"
|
||||
>
|
||||
<span class="address">{{ row.address }}</span>
|
||||
<span class="hex">{{ row.hex }}</span>
|
||||
<span class="ascii">{{ row.ascii }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.binary-viewer {
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
padding: 1rem;
|
||||
background-color: var(--v-theme-surface);
|
||||
height: calc(100vh - 150px);
|
||||
}
|
||||
|
||||
.hex-container {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.scroll-content {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.hex-line {
|
||||
line-height: 1.5;
|
||||
height: v-bind(rowHeight + 'px');
|
||||
}
|
||||
|
||||
.address {
|
||||
color: #666;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.hex {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.ascii {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.loading {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
@ -10,7 +10,8 @@ import mime from 'mime';
|
||||
export const videoExtensions = ['mp4', 'avi', 'mov', 'mkv'];
|
||||
export const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
export const audioExtensions = ['mp3', 'wav', 'ogg', 'flac'];
|
||||
export const textExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'md', 'js', 'ts', 'php', 'c', 'cpp', 'py', 'html', 'css', 'scss', 'sass', 'less', 'json', 'xml', 'sql', 'java', 'go', 'rb', 'sh', 'bat', 'ps1', 'cmd', 'yml', 'yaml', 'ini', 'toml', 'csv', 'tsv', 'gitignore', 'lock', 'htaccess', 'htpasswd', 'env', 'dockerfile', 'gitattributes', 'gitmodules', 'editorconfig', 'babelrc', 'eslintrc', 'eslintignore', 'prettierrc', 'prettierignore', 'stylelintrc', 'stylelintignore', 'postcssrc', 'postcss.config', 'jsx', 'tsx', 'license']
|
||||
export const textExtensions = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'md', 'js', 'ts', 'php', 'c', 'cpp', 'py', 'html', 'css', 'scss', 'sass', 'less', 'json', 'xml', 'sql', 'java', 'go', 'rb', 'sh', 'bat', 'ps1', 'cmd', 'yml', 'yaml', 'ini', 'toml', 'csv', 'tsv', 'gitignore', 'lock', 'htaccess', 'htpasswd', 'env', 'dockerfile', 'gitattributes', 'gitmodules', 'editorconfig', 'babelrc', 'eslintrc', 'eslintignore', 'prettierrc', 'prettierignore', 'stylelintrc', 'stylelintignore', 'postcssrc', 'postcss.config', 'jsx', 'tsx', 'license'];
|
||||
export const binaryExtensions = ['exe', 'dll', 'so', 'dylib', 'bin', 'dat', 'db', 'sqlite', 'o', 'class', 'pyc'];
|
||||
|
||||
export class FilesManager {
|
||||
consoleOutputBuffer: string[] = [];
|
||||
|
6
package-lock.json
generated
6
package-lock.json
generated
@ -2662,9 +2662,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001487",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001487.tgz",
|
||||
"integrity": "sha512-83564Z3yWGqXsh2vaH/mhXfEM0wX+NlBCm1jYHOb97TrTWJEmPTccZgeLTPBUUb0PNVo+oomb7wkimZBIERClA==",
|
||||
"version": "1.0.30001677",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz",
|
||||
"integrity": "sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user