diff --git a/src/provider/handlers/zipHandler.ts b/src/provider/handlers/zipHandler.ts new file mode 100644 index 0000000..02d6d34 --- /dev/null +++ b/src/provider/handlers/zipHandler.ts @@ -0,0 +1,71 @@ +import { Output } from "@/common/Output"; +import { FileUtil } from "@/common/fileUtil"; +import { Handler } from "@/common/handler"; +import { parseZipAsTree } from "@/service/zip/zipUtils"; +import { existsSync, mkdirSync, rm, writeFileSync } from "fs"; +import { tmpdir } from "os"; +import { basename, extname, join, parse, resolve } from "path"; +import { Uri, commands, env, window, workspace } from "vscode"; + +export async function handleZip(uri: Uri, handler: Handler) { + // delete update + handler.on('init', async () => { + const data = (await workspace.fs.readFile(uri)) as Buffer + const basePath = `${tmpdir()}/officeZip.${new Date().getTime()}`; + const { zip, files, folderMap, fileMap } = parseZipAsTree(data) + handler.emit('data', { + files, folderMap, + fileName: basename(uri.fsPath) + }).on('openPath', async info => { + const { entryName, isDirectory } = info + if (isDirectory) { + handler.emit('openDir', entryName) + } else { + await commands.executeCommand('workbench.action.keepEditor') + const file = fileMap[entryName] + const tempPath = `${basePath}/${entryName}` + mkdirSync(resolve(tempPath, '..'), { recursive: true }) + writeFileSync(tempPath, file.getData()) + const url = Uri.file(tempPath); + if (['.xlsx', '.csv'].includes(extname(tempPath)?.toLowerCase())) { + return env.openExternal(url); + } + commands.executeCommand('vscode.open', url); + } + }).on('autoExtract', () => { + window.showInformationMessage("Start extracting...") + let target = resolve(uri.fsPath, '..'); + if (files.length > 1) { + target = join(target, parse(uri.fsPath).name) + mkdirSync(target, { recursive: true }) + } + zip.extractAllToAsync(target, true, false, (err) => { + if (err) { + Output.debug(err) + window.showErrorMessage(err.message) + } else { + setTimeout(() => { + window.showInformationMessage("Extract success!") + commands.executeCommand('revealFileInOS', Uri.file(target)) + }, 100); + } + }); + }).on('addFile', async (currentDir = '') => { + const defaultUri = FileUtil.getLastPath('connectChoose') + const uris = await window.showOpenDialog({ defaultUri }) + if (!uris) return; + const uri = uris[0] + const buf = await workspace.fs.readFile(uri) as Buffer + const prefix = currentDir ? `${currentDir}/` : ''; + zip.addFile(`${prefix}${basename(uri.fsPath)}`, buf) + await workspace.fs.writeFile(uri, zip.toBuffer()) + handler.emit('zipChange') + }).on('removeFile', async entryName => { + zip.deleteFile(entryName) + await workspace.fs.writeFile(uri, zip.toBuffer()) + handler.emit('zipChange') + }).on('dispose', () => { + if (existsSync(basePath)) rm(basePath, { recursive: true, force: true }, null) + }) + }) +} \ No newline at end of file diff --git a/src/provider/officeViewerProvider.ts b/src/provider/officeViewerProvider.ts index b0b64ca..e17938c 100644 --- a/src/provider/officeViewerProvider.ts +++ b/src/provider/officeViewerProvider.ts @@ -1,15 +1,15 @@ -import { ZipService } from '@/service/zip/zipService'; +import { ReactApp } from '@/common/reactApp'; import { spawn } from 'child_process'; import { existsSync, mkdirSync, readFileSync } from 'fs'; import { tmpdir } from 'os'; import { extname, parse } from 'path'; import { TextEncoder } from 'util'; import * as vscode from 'vscode'; -import { Handler } from '../common/handler'; import { Output } from '../common/Output'; +import { Handler } from '../common/handler'; import { Util } from '../common/util'; -import { ReactApp } from '@/common/reactApp'; import { handleImage, isImage } from './handlers/imageHanlder'; +import { handleZip } from './handlers/zipHandler'; /** * support view office files @@ -72,12 +72,10 @@ export class OfficeViewerProvider implements vscode.CustomReadonlyEditorProvider case ".csv": case ".ods": route = 'excel'; - this.handleXlsx(uri, handler) handler.on("fileChange", send) break; case ".docx": case ".dotx": - htmlPath = 'word.html' route = 'word' handler.on("fileChange", send) break; @@ -86,7 +84,7 @@ export class OfficeViewerProvider implements vscode.CustomReadonlyEditorProvider case ".apk": case ".vsix": route = 'zip'; - this.handleZip(uri, handler); + handleZip(uri, handler); break; case ".pdf": this.handlePdf(webview); @@ -119,10 +117,6 @@ export class OfficeViewerProvider implements vscode.CustomReadonlyEditorProvider } - async handleZip(uri: vscode.Uri, handler: Handler) { - new ZipService(uri, handler).bind(); - } - private handlePdf(webview: vscode.Webview) { const baseUrl = this.getBaseUrl(webview, 'pdf') webview.html = readFileSync(this.extensionPath + "/resource/pdf/viewer.html", 'utf8').replace("{{baseUrl}}", baseUrl) @@ -141,20 +135,6 @@ export class OfficeViewerProvider implements vscode.CustomReadonlyEditorProvider return baseUrl; } - private handleXlsx(uri: vscode.Uri, handler: Handler) { - const enc = new TextEncoder(); - handler.on("save", async (content) => { - Util.confirm(`Save confirm`, 'Are you sure you want to save? this will lose all formatting.', async () => { - await vscode.workspace.fs.writeFile(uri, new Uint8Array(content)) - handler.emit("saveDone") - }) - }).on("saveCsv", async (content) => { - await vscode.workspace.fs.writeFile(uri, enc.encode(content)) - handler.emit("saveDone") - }) - } - - private async handleClass(uri: vscode.Uri, panel: vscode.WebviewPanel) { if (uri.scheme != "file") { vscode.commands.executeCommand('vscode.openWith', uri, "default"); diff --git a/src/service/zip/zipService.ts b/src/service/zip/zipService.ts deleted file mode 100644 index 9efeade..0000000 --- a/src/service/zip/zipService.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { Handler } from "@/common/handler"; -import { existsSync, mkdirSync, rm, writeFileSync } from "fs"; -import { tmpdir } from "os"; -import { basename, extname, join, parse, resolve } from "path"; -import { Uri, commands, env, extensions, window, workspace } from "vscode"; -import { parseZipAsTree } from "./zipUtils"; -import { Output } from "@/common/Output"; -import { FileUtil } from "@/common/fileUtil"; - -export class ZipService { - - constructor(private uri: Uri, private handler: Handler) { } - - public async bind() { - - // delete update - const handler = this.handler; - handler.on('init', async () => { - const data = (await workspace.fs.readFile(this.uri)) as Buffer - const basePath = `${tmpdir()}/officeZip.${new Date().getTime()}`; - const { zip, files, folderMap, fileMap } = parseZipAsTree(data) - handler.emit('data', { - files, folderMap, - fileName: basename(this.uri.fsPath) - }).on('openPath', async info => { - const { entryName, isDirectory } = info - if (isDirectory) { - handler.emit('openDir', entryName) - } else { - await commands.executeCommand('workbench.action.keepEditor') - const file = fileMap[entryName] - const tempPath = `${basePath}/${entryName}` - mkdirSync(resolve(tempPath, '..'), { recursive: true }) - writeFileSync(tempPath, file.getData()) - const url = Uri.file(tempPath); - if (['.xlsx', '.csv'].includes(extname(tempPath)?.toLowerCase())) { - return env.openExternal(url); - } - commands.executeCommand('vscode.open', url); - } - }).on('autoExtract', () => { - window.showInformationMessage("Start extracting...") - let target = resolve(this.uri.fsPath, '..'); - if (files.length > 1) { - target = join(target, parse(this.uri.fsPath).name) - mkdirSync(target, { recursive: true }) - } - zip.extractAllToAsync(target, true, false, (err) => { - if (err) { - Output.debug(err) - window.showErrorMessage(err.message) - } else { - setTimeout(() => { - window.showInformationMessage("Extract success!") - commands.executeCommand('revealFileInOS', Uri.file(target)) - }, 100); - } - }); - }).on('addFile', async (currentDir = '') => { - const defaultUri = FileUtil.getLastPath('connectChoose') - const uris = await window.showOpenDialog({ defaultUri }) - if (!uris) return; - const uri = uris[0] - const buf = await workspace.fs.readFile(uri) as Buffer - const prefix = currentDir ? `${currentDir}/` : ''; - zip.addFile(`${prefix}${basename(uri.fsPath)}`, buf) - await workspace.fs.writeFile(this.uri, zip.toBuffer()) - handler.emit('zipChange') - }).on('removeFile', async entryName => { - zip.deleteFile(entryName) - await workspace.fs.writeFile(this.uri, zip.toBuffer()) - handler.emit('zipChange') - }).on('dispose', () => { - if (existsSync(basePath)) rm(basePath, { recursive: true, force: true }, null) - }) - }) - } - -} \ No newline at end of file