From 15c3d367d56691d4756f690fbbc3d36dc330c679 Mon Sep 17 00:00:00 2001 From: "Nanashi." Date: Sun, 5 Jan 2025 14:59:49 +0900 Subject: [PATCH 1/8] =?UTF-8?q?Change:=20Merge=20Queue=E3=81=AECI=E3=82=92?= =?UTF-8?q?1=E5=9B=9E=E3=81=A0=E3=81=91=E8=B5=B0=E3=82=89=E3=81=9B?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B=20(#2475?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/test.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b06a4b0dd0..5251fb0178 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,8 +5,6 @@ on: pull_request: branches: - "**" - merge_group: - types: [checks_requested] workflow_dispatch: env: From df4ad342c0f62eadeae1819eaf55c249307626aa Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Sun, 5 Jan 2025 15:15:31 +0900 Subject: [PATCH 2/8] =?UTF-8?q?fix:=20=E3=83=89=E3=83=A9=E3=83=83=E3=82=B0?= =?UTF-8?q?=E3=82=A2=E3=83=B3=E3=83=89=E3=83=89=E3=83=AD=E3=83=83=E3=83=97?= =?UTF-8?q?=E3=81=A7=E3=83=97=E3=83=AD=E3=82=B8=E3=82=A7=E3=82=AF=E3=83=88?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=84=E3=83=86=E3=82=AD?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=81=8C?= =?UTF-8?q?=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=82=81=E3=81=AA=E3=81=8B=E3=81=A3?= =?UTF-8?q?=E3=81=9F=E3=81=AE=E3=82=92=E7=9B=B4=E3=81=99=20(#2433)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/browser/sandbox.ts | 3 +++ src/backend/electron/preload.ts | 7 ++++- src/components/App.vue | 1 + src/components/Menu/MenuBar/MenuBar.vue | 3 ++- src/components/Talk/TalkEditor.vue | 19 ++++++++++++-- src/components/Talk/ToolBar.vue | 2 +- src/components/Talk/menuBarData.ts | 2 +- src/plugins/ipcMessageReceiverPlugin.ts | 7 +++-- src/store/audio.ts | 34 +++++++++++++++++-------- src/store/project.ts | 34 +++++++++++++++---------- src/store/type.ts | 14 ++++++++-- src/type/ipc.ts | 2 +- src/type/preload.ts | 1 + 13 files changed, 93 insertions(+), 36 deletions(-) diff --git a/src/backend/browser/sandbox.ts b/src/backend/browser/sandbox.ts index de3279fb63..f1ef8025ab 100644 --- a/src/backend/browser/sandbox.ts +++ b/src/backend/browser/sandbox.ts @@ -280,4 +280,7 @@ export const api: Sandbox = { reloadApp(/* obj: { isMultiEngineOffMode: boolean } */) { throw new Error(`Not supported on Browser version: reloadApp`); }, + getPathForFile(/* file: File */) { + throw new Error(`Not supported on Browser version: getPathForFile`); + }, }; diff --git a/src/backend/electron/preload.ts b/src/backend/electron/preload.ts index 878c8f6448..23a3370a4f 100644 --- a/src/backend/electron/preload.ts +++ b/src/backend/electron/preload.ts @@ -1,4 +1,4 @@ -import { contextBridge, ipcRenderer } from "electron"; +import { contextBridge, ipcRenderer, webUtils } from "electron"; import type { IpcRendererInvoke } from "./ipc"; import { ConfigType, @@ -228,6 +228,11 @@ const api: Sandbox = { reloadApp: async ({ isMultiEngineOffMode }) => { await ipcRendererInvokeProxy.RELOAD_APP({ isMultiEngineOffMode }); }, + + /** webUtils.getPathForFileを呼ぶ */ + getPathForFile: (file) => { + return webUtils.getPathForFile(file); + }, }; contextBridge.exposeInMainWorld(SandboxKey, api); diff --git a/src/components/App.vue b/src/components/App.vue index f49b89c372..51cdbfea1b 100644 --- a/src/components/App.vue +++ b/src/components/App.vue @@ -165,6 +165,7 @@ onMounted(async () => { // プロジェクトファイルが指定されていればロード if (typeof projectFilePath === "string" && projectFilePath !== "") { isProjectFileLoaded.value = await store.actions.LOAD_PROJECT_FILE({ + type: "path", filePath: projectFilePath, }); } else { diff --git a/src/components/Menu/MenuBar/MenuBar.vue b/src/components/Menu/MenuBar/MenuBar.vue index a94d5d6678..5df82f18d2 100644 --- a/src/components/Menu/MenuBar/MenuBar.vue +++ b/src/components/Menu/MenuBar/MenuBar.vue @@ -157,7 +157,7 @@ const saveProjectAs = async () => { const importProject = () => { if (!uiLocked.value) { - void store.actions.LOAD_PROJECT_FILE({}); + void store.actions.LOAD_PROJECT_FILE({ type: "dialog" }); } }; @@ -198,6 +198,7 @@ const updateRecentProjects = async () => { label: projectFilePath, onClick: () => { void store.actions.LOAD_PROJECT_FILE({ + type: "path", filePath: projectFilePath, }); }, diff --git a/src/components/Talk/TalkEditor.vue b/src/components/Talk/TalkEditor.vue index ecf68b6041..dda58caba7 100644 --- a/src/components/Talk/TalkEditor.vue +++ b/src/components/Talk/TalkEditor.vue @@ -143,6 +143,7 @@ import { actionPostfixSelectNthCharacter, HotkeyActionNameType, } from "@/domain/hotkeyAction"; +import { isElectron } from "@/helpers/platform"; const props = defineProps<{ isEnginesReady: boolean; @@ -574,13 +575,27 @@ const dragEventCounter = ref(0); const loadDraggedFile = (event: { dataTransfer: DataTransfer | null }) => { if (!event.dataTransfer || event.dataTransfer.files.length === 0) return; const file = event.dataTransfer.files[0]; + + // electronの場合のみファイルパスを取得できる + const filePath = isElectron ? window.backend.getPathForFile(file) : undefined; + switch (path.extname(file.name)) { case ".txt": - void store.actions.COMMAND_IMPORT_FROM_FILE({ filePath: file.path }); + if (filePath) { + void store.actions.COMMAND_IMPORT_FROM_FILE({ type: "path", filePath }); + } else { + void store.actions.COMMAND_IMPORT_FROM_FILE({ type: "file", file }); + } break; + case ".vvproj": - void store.actions.LOAD_PROJECT_FILE({ filePath: file.path }); + if (filePath) { + void store.actions.LOAD_PROJECT_FILE({ type: "path", filePath }); + } else { + void store.actions.LOAD_PROJECT_FILE({ type: "file", file }); + } break; + default: void store.actions.SHOW_ALERT_DIALOG({ title: "対応していないファイルです", diff --git a/src/components/Talk/ToolBar.vue b/src/components/Talk/ToolBar.vue index 5bbb6e1e2c..12b1bbbc86 100644 --- a/src/components/Talk/ToolBar.vue +++ b/src/components/Talk/ToolBar.vue @@ -145,7 +145,7 @@ const saveProject = async () => { await store.actions.SAVE_PROJECT_FILE({ overwrite: true }); }; const importTextFile = () => { - void store.actions.COMMAND_IMPORT_FROM_FILE({}); + void store.actions.COMMAND_IMPORT_FROM_FILE({ type: "dialog" }); }; const usableButtons: Record< diff --git a/src/components/Talk/menuBarData.ts b/src/components/Talk/menuBarData.ts index 5a9b73c2ea..cea0fd3a8c 100644 --- a/src/components/Talk/menuBarData.ts +++ b/src/components/Talk/menuBarData.ts @@ -46,7 +46,7 @@ export const useMenuBarData = () => { type: "button", label: "テキスト読み込み", onClick: () => { - void store.actions.COMMAND_IMPORT_FROM_FILE({}); + void store.actions.COMMAND_IMPORT_FROM_FILE({ type: "dialog" }); }, disableWhenUiLocked: true, }, diff --git a/src/plugins/ipcMessageReceiverPlugin.ts b/src/plugins/ipcMessageReceiverPlugin.ts index 1ae8393ca6..78313ee5f3 100644 --- a/src/plugins/ipcMessageReceiverPlugin.ts +++ b/src/plugins/ipcMessageReceiverPlugin.ts @@ -9,8 +9,11 @@ export const ipcMessageReceiver: Plugin = { options: { store: Store }, ) => { window.backend.onReceivedIPCMsg({ - LOAD_PROJECT_FILE: (_, { filePath } = {}) => - void options.store.actions.LOAD_PROJECT_FILE({ filePath }), + LOAD_PROJECT_FILE: (_, { filePath }) => + void options.store.actions.LOAD_PROJECT_FILE({ + type: "path", + filePath, + }), DETECT_MAXIMIZED: () => options.store.actions.DETECT_MAXIMIZED(), diff --git a/src/store/audio.ts b/src/store/audio.ts index d433b55ef6..371b0616f7 100644 --- a/src/store/audio.ts +++ b/src/store/audio.ts @@ -2886,24 +2886,36 @@ export const audioCommandStore = transformCommandStore( prevAudioKey: undefined, }); }, + /** + * セリフテキストファイルを読み込む。 + * ファイル選択ダイアログを表示するか、ファイルパス指定するか、Fileインスタンスを渡すか選べる。 + */ action: createUILockAction( - async ( - { state, mutations, actions, getters }, - { filePath }: { filePath?: string }, - ) => { - if (!filePath) { + async ({ state, mutations, actions, getters }, payload) => { + let filePath: undefined | string; + if (payload.type == "dialog") { filePath = await window.backend.showImportFileDialog({ title: "セリフ読み込み", }); if (!filePath) return; + } else if (payload.type == "path") { + filePath = payload.filePath; } - let body = new TextDecoder("utf-8").decode( - await window.backend.readFile({ filePath }).then(getValueOrThrow), - ); + + let buf: ArrayBuffer; + if (filePath != undefined) { + buf = await window.backend + .readFile({ filePath }) + .then(getValueOrThrow); + } else { + if (payload.type != "file") + throw new UnreachableError("payload.type != 'file'"); + buf = await payload.file.arrayBuffer(); + } + + let body = new TextDecoder("utf-8").decode(buf); if (body.includes("\ufffd")) { - body = new TextDecoder("shift-jis").decode( - await window.backend.readFile({ filePath }).then(getValueOrThrow), - ); + body = new TextDecoder("shift-jis").decode(buf); } const audioItems: AudioItem[] = []; let baseAudioItem: AudioItem | undefined = undefined; diff --git a/src/store/project.ts b/src/store/project.ts index 48da368714..3e5a0862d4 100755 --- a/src/store/project.ts +++ b/src/store/project.ts @@ -21,7 +21,7 @@ import { DEFAULT_TPQN, } from "@/sing/domain"; import { EditorType } from "@/type/preload"; -import { IsEqual } from "@/type/utility"; +import { IsEqual, UnreachableError } from "@/type/utility"; import { showAlertDialog, showMessageDialog, @@ -166,15 +166,13 @@ export const projectStore = createPartialStore({ LOAD_PROJECT_FILE: { /** * プロジェクトファイルを読み込む。読み込めたかの成否が返る。 + * ファイル選択ダイアログを表示するか、ファイルパス指定するか、Fileインスタンスを渡すか選べる。 * エラー発生時はダイアログが表示される。 */ action: createUILockAction( - async ( - { actions, mutations, getters }, - { filePath }: { filePath?: string }, - ) => { - if (!filePath) { - // Select and load a project File. + async ({ actions, mutations, getters }, payload) => { + let filePath: undefined | string; + if (payload.type == "dialog") { const ret = await window.backend.showProjectLoadDialog({ title: "プロジェクトファイルの選択", }); @@ -182,17 +180,25 @@ export const projectStore = createPartialStore({ return false; } filePath = ret[0]; + } else if (payload.type == "path") { + filePath = payload.filePath; } - let buf: ArrayBuffer; try { - buf = await window.backend - .readFile({ filePath }) - .then(getValueOrThrow); + let buf: ArrayBuffer; + if (filePath != undefined) { + buf = await window.backend + .readFile({ filePath }) + .then(getValueOrThrow); - await actions.APPEND_RECENTLY_USED_PROJECT({ - filePath, - }); + await actions.APPEND_RECENTLY_USED_PROJECT({ + filePath, + }); + } else { + if (payload.type != "file") + throw new UnreachableError("payload.type != 'file'"); + buf = await payload.file.arrayBuffer(); + } const text = new TextDecoder("utf-8").decode(buf).trim(); const parsedProjectData = await actions.PARSE_PROJECT_FILE({ diff --git a/src/store/type.ts b/src/store/type.ts index 1e83ab6a0b..a57e243881 100644 --- a/src/store/type.ts +++ b/src/store/type.ts @@ -690,7 +690,12 @@ export type AudioCommandStoreTypes = { mutation: { audioKeyItemPairs: { audioItem: AudioItem; audioKey: AudioKey }[]; }; - action(payload: { filePath?: string }): void; + action( + payload: + | { type: "dialog" } + | { type: "path"; filePath: string } + | { type: "file"; file: File }, + ): void; }; COMMAND_PUT_TEXTS: { @@ -1837,7 +1842,12 @@ export type ProjectStoreTypes = { }; LOAD_PROJECT_FILE: { - action(payload: { filePath?: string }): boolean; + action( + payload: + | { type: "dialog" } + | { type: "path"; filePath: string } + | { type: "file"; file: File }, + ): boolean; }; SAVE_PROJECT_FILE: { diff --git a/src/type/ipc.ts b/src/type/ipc.ts index 3414f186fd..8c35a089f5 100644 --- a/src/type/ipc.ts +++ b/src/type/ipc.ts @@ -241,7 +241,7 @@ export type IpcIHData = { */ export type IpcSOData = { LOAD_PROJECT_FILE: { - args: [obj: { filePath?: string }]; + args: [obj: { filePath: string }]; return: void; }; diff --git a/src/type/preload.ts b/src/type/preload.ts index f916bc7b29..a144d2c64d 100644 --- a/src/type/preload.ts +++ b/src/type/preload.ts @@ -141,6 +141,7 @@ export interface Sandbox { uninstallVvppEngine(engineId: EngineId): Promise; validateEngineDir(engineDir: string): Promise; reloadApp(obj: { isMultiEngineOffMode?: boolean }): Promise; + getPathForFile(file: File): string; } export type AppInfos = { From 10ce8dec6f7c9427c6519f241f926189997af13d Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Wed, 8 Jan 2025 01:21:58 +0900 Subject: [PATCH 3/8] =?UTF-8?q?refactor:=20vvppManager.extractVvpp?= =?UTF-8?q?=E3=81=AE=E5=87=A6=E7=90=86=E3=82=92=E9=96=A2=E6=95=B0=E5=88=87?= =?UTF-8?q?=E3=82=8A=E5=87=BA=E3=81=97=20(#2478)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/backend/electron/manager/vvppManager.ts | 241 +++++++++++--------- 1 file changed, 135 insertions(+), 106 deletions(-) diff --git a/src/backend/electron/manager/vvppManager.ts b/src/backend/electron/manager/vvppManager.ts index 9484a8476e..adaac308bc 100644 --- a/src/backend/electron/manager/vvppManager.ts +++ b/src/backend/electron/manager/vvppManager.ts @@ -33,6 +33,136 @@ export const isVvppFile = (filePath: string) => { const lockKey = "lock-key-for-vvpp-manager"; +/** VVPPファイルが分割されている場合、それらのファイルを取得する */ +async function getArchiveFileParts( + vvppLikeFilePath: string, +): Promise { + let archiveFileParts: string[]; + // 名前.数値.vvpppの場合は分割されているとみなして連結する + if (vvppLikeFilePath.match(/\.[0-9]+\.vvppp$/)) { + log.log("vvpp is split, finding other parts..."); + const vvpppPathGlob = vvppLikeFilePath + .replace(/\.[0-9]+\.vvppp$/, ".*.vvppp") + .replace(/\\/g, "/"); // node-globはバックスラッシュを使えないので、スラッシュに置換する + const filePaths: string[] = []; + for (const p of await glob(vvpppPathGlob)) { + if (!p.match(/\.[0-9]+\.vvppp$/)) { + continue; + } + log.log(`found ${p}`); + filePaths.push(p); + } + filePaths.sort((a, b) => { + const aMatch = a.match(/\.([0-9]+)\.vvppp$/); + const bMatch = b.match(/\.([0-9]+)\.vvppp$/); + if (aMatch == null || bMatch == null) { + throw new Error(`match is null: a=${a}, b=${b}`); + } + return parseInt(aMatch[1]) - parseInt(bMatch[1]); + }); + archiveFileParts = filePaths; + } else { + log.log("Not a split file"); + archiveFileParts = [vvppLikeFilePath]; + } + return archiveFileParts; +} + +/** 分割されているVVPPファイルを連結して返す */ +async function concatenateVvppFiles( + format: "zip" | "7z", + archiveFileParts: string[], +) { + // -siオプションでの7z解凍はサポートされていないため、 + // ファイルを連結した一次ファイルを作成し、それを7zで解凍する。 + log.log(`Concatenating ${archiveFileParts.length} files...`); + const tmpConcatenatedFile = path.join( + app.getPath("temp"), + `vvpp-${new Date().getTime()}.${format}`, + ); + log.log("Temporary file:", tmpConcatenatedFile); + await new Promise((resolve, reject) => { + if (!tmpConcatenatedFile) throw new Error("tmpFile is undefined"); + const inputStreams = archiveFileParts.map((f) => fs.createReadStream(f)); + const outputStream = fs.createWriteStream(tmpConcatenatedFile); + new MultiStream(inputStreams) + .pipe(outputStream) + .on("close", () => { + outputStream.close(); + resolve(); + }) + .on("error", reject); + }); + log.log("Concatenated"); + return tmpConcatenatedFile; +} + +/** 7zでファイルを解凍する */ +async function unarchive( + payload: { + archiveFile: string; + outputDir: string; + format: "zip" | "7z"; + }, + callbacks?: { onProgress?: ProgressCallback }, +) { + const { archiveFile, outputDir, format } = payload; + + const args = [ + "x", + "-o" + outputDir, + archiveFile, + "-t" + format, + "-bsp1", // 進捗出力 + ]; + + let sevenZipPath = import.meta.env.VITE_7Z_BIN_NAME; + if (!sevenZipPath) { + throw new Error("7z path is not defined"); + } + if (import.meta.env.PROD) { + sevenZipPath = path.join(path.dirname(app.getPath("exe")), sevenZipPath); + } + log.log("Spawning 7z:", sevenZipPath, args.join(" ")); + await new Promise((resolve, reject) => { + const child = spawn(sevenZipPath, args, { + stdio: ["pipe", "pipe", "pipe"], + }); + + child.stdout?.on("data", (data: Buffer) => { + const output = data.toString("utf-8"); + log.info(`7z STDOUT: ${output}`); + + // 進捗を取得 + // NOTE: ` 75% 106 - pyopenjtalk\open_jtalk_dic_utf_8-1.11\sys.dic` のような出力が来る + // TODO: 出力が変わるかもしれないのでテストが必要 + const progressMatch = output.match( + / *(?\d+)% ?(?\d+)? ?(?.*)/, + ); + if (progressMatch?.groups?.percent) { + callbacks?.onProgress?.({ + progress: parseInt(progressMatch.groups.percent), + }); + } + }); + + child.stderr?.on("data", (data: Buffer) => { + log.error(`7z STDERR: ${data.toString("utf-8")}`); + }); + + child.on("exit", (code) => { + if (code === 0) { + callbacks?.onProgress?.({ progress: 100 }); + resolve(); + } else { + reject(new Error(`7z exited with code ${code}`)); + } + }); + // FIXME: rejectが2回呼ばれることがある + child.on("error", reject); + }); +} + // # 軽い概要 // // フォルダ名:"エンジン名+UUID" @@ -117,34 +247,7 @@ export class VvppManager { const nonce = new Date().getTime().toString(); const outputDir = path.join(this.vvppEngineDir, ".tmp", nonce); - let archiveFileParts: string[]; - // 名前.数値.vvpppの場合は分割されているとみなして連結する - if (vvppLikeFilePath.match(/\.[0-9]+\.vvppp$/)) { - log.log("vvpp is split, finding other parts..."); - const vvpppPathGlob = vvppLikeFilePath - .replace(/\.[0-9]+\.vvppp$/, ".*.vvppp") - .replace(/\\/g, "/"); // node-globはバックスラッシュを使えないので、スラッシュに置換する - const filePaths: string[] = []; - for (const p of await glob(vvpppPathGlob)) { - if (!p.match(/\.[0-9]+\.vvppp$/)) { - continue; - } - log.log(`found ${p}`); - filePaths.push(p); - } - filePaths.sort((a, b) => { - const aMatch = a.match(/\.([0-9]+)\.vvppp$/); - const bMatch = b.match(/\.([0-9]+)\.vvppp$/); - if (aMatch == null || bMatch == null) { - throw new Error(`match is null: a=${a}, b=${b}`); - } - return parseInt(aMatch[1]) - parseInt(bMatch[1]); - }); - archiveFileParts = filePaths; - } else { - log.log("Not a split file"); - archiveFileParts = [vvppLikeFilePath]; - } + const archiveFileParts = await getArchiveFileParts(vvppLikeFilePath); const format = await this.detectFileFormat(archiveFileParts[0]); if (!format) { @@ -157,91 +260,17 @@ export class VvppManager { let archiveFile: string; try { if (archiveFileParts.length > 1) { - // -siオプションでの7z解凍はサポートされていないため、 - // ファイルを連結した一次ファイルを作成し、それを7zで解凍する。 - log.log(`Concatenating ${archiveFileParts.length} files...`); - tmpConcatenatedFile = path.join( - app.getPath("temp"), - `vvpp-${new Date().getTime()}.${format}`, + tmpConcatenatedFile = await concatenateVvppFiles( + format, + archiveFileParts, ); - log.log("Temporary file:", tmpConcatenatedFile); archiveFile = tmpConcatenatedFile; - await new Promise((resolve, reject) => { - if (!tmpConcatenatedFile) throw new Error("tmpFile is undefined"); - const inputStreams = archiveFileParts.map((f) => - fs.createReadStream(f), - ); - const outputStream = fs.createWriteStream(tmpConcatenatedFile); - new MultiStream(inputStreams) - .pipe(outputStream) - .on("close", () => { - outputStream.close(); - resolve(); - }) - .on("error", reject); - }); - log.log("Concatenated"); } else { archiveFile = archiveFileParts[0]; log.log("Single file, not concatenating"); } - const args = [ - "x", - "-o" + outputDir, - archiveFile, - "-t" + format, - "-bsp1", // 進捗出力 - ]; - - let sevenZipPath = import.meta.env.VITE_7Z_BIN_NAME; - if (!sevenZipPath) { - throw new Error("7z path is not defined"); - } - if (import.meta.env.PROD) { - sevenZipPath = path.join( - path.dirname(app.getPath("exe")), - sevenZipPath, - ); - } - log.log("Spawning 7z:", sevenZipPath, args.join(" ")); - await new Promise((resolve, reject) => { - const child = spawn(sevenZipPath, args, { - stdio: ["pipe", "pipe", "pipe"], - }); - - child.stdout?.on("data", (data: Buffer) => { - const output = data.toString("utf-8"); - log.info(`7z STDOUT: ${output}`); - - // 進捗を取得 - // NOTE: ` 75% 106 - pyopenjtalk\open_jtalk_dic_utf_8-1.11\sys.dic` のような出力が来る - // TODO: 出力が変わるかもしれないのでテストが必要 - const progressMatch = output.match( - / *(?\d+)% ?(?\d+)? ?(?.*)/, - ); - if (progressMatch?.groups?.percent) { - callbacks?.onProgress?.({ - progress: parseInt(progressMatch.groups.percent), - }); - } - }); - - child.stderr?.on("data", (data: Buffer) => { - log.error(`7z STDERR: ${data.toString("utf-8")}`); - }); - - child.on("exit", (code) => { - if (code === 0) { - callbacks?.onProgress?.({ progress: 100 }); - resolve(); - } else { - reject(new Error(`7z exited with code ${code}`)); - } - }); - // FIXME: rejectが2回呼ばれることがある - child.on("error", reject); - }); + await unarchive({ archiveFile, outputDir, format }, callbacks); } finally { if (tmpConcatenatedFile) { log.log("Removing temporary file", tmpConcatenatedFile); From 300fef16258732e068e9d614ea6a0a28507bb413 Mon Sep 17 00:00:00 2001 From: Sig <62321214+sigprogramming@users.noreply.github.com> Date: Wed, 15 Jan 2025 01:29:45 +0900 Subject: [PATCH 4/8] =?UTF-8?q?hotfix:=20[release-0.22]=20AudioCell?= =?UTF-8?q?=E3=81=8C0=E5=80=8B=E3=81=AE=E3=81=A8=E3=81=8D=E3=81=ABDEFAULT?= =?UTF-8?q?=5FPROJECT=5FFILE=5FBASE=5FNAME=E3=81=A7=E3=82=A8=E3=83=A9?= =?UTF-8?q?=E3=83=BC=E3=81=8C=E7=99=BA=E7=94=9F=E3=81=97=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E4=BF=AE=E6=AD=A3=20(#2484)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hiroshiba --- src/store/audio.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/store/audio.ts b/src/store/audio.ts index 8fc45d7c7b..4a3a067cf0 100644 --- a/src/store/audio.ts +++ b/src/store/audio.ts @@ -1226,6 +1226,12 @@ export const audioStore = createPartialStore({ DEFAULT_PROJECT_FILE_BASE_NAME: { getter: (state) => { + // NOTE: 起動時にソングエディタが開かれた場合、トークの初期化が行われずAudioCellが作成されない + // TODO: ソングエディタが開かれてい場合はこの関数を呼ばないようにし、warningを出す + if (state.audioKeys.length === 0) { + return DEFAULT_PROJECT_NAME; + } + const headItemText = state.audioItems[state.audioKeys[0]].text; const tailItemText = From a59600d196beb5852979ea3e224fe0b30895a0f2 Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Wed, 15 Jan 2025 01:43:57 +0900 Subject: [PATCH 5/8] add: [release-0.22] to 0.22.4 (#2486) --- public/updateInfos.json | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/public/updateInfos.json b/public/updateInfos.json index 451bf29abd..751f10f1f6 100644 --- a/public/updateInfos.json +++ b/public/updateInfos.json @@ -1,4 +1,11 @@ [ + { + "version": "0.22.4", + "descriptions": [ + "ソング:トークエディタを開かないと保存できない問題を修正" + ], + "contributors": ["sigprogramming"] + }, { "version": "0.22.3", "descriptions": ["キャラクター「ぞん子」を追加"], From 8e4eb03cea57c5404158cf0d47e02e0ad92072a6 Mon Sep 17 00:00:00 2001 From: Hiroshiba Date: Fri, 17 Jan 2025 23:34:33 +0900 Subject: [PATCH 6/8] =?UTF-8?q?refactor:=20createLogger=E3=82=92=E5=B0=91?= =?UTF-8?q?=E3=81=97=E3=83=AA=E3=83=95=E3=82=A1=E3=82=AF=E3=82=BF=E3=83=AA?= =?UTF-8?q?=E3=83=B3=E3=82=B0=20(#2489)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/domain/frontend/log.ts | 41 +++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/domain/frontend/log.ts b/src/domain/frontend/log.ts index 4cb2aa8598..d99ba23a23 100644 --- a/src/domain/frontend/log.ts +++ b/src/domain/frontend/log.ts @@ -1,22 +1,31 @@ +type LogLevel = "info" | "warn" | "error"; +type LogFunction = (...args: unknown[]) => void; + /** ログ出力用の関数を生成する。ブラウザ専用。 */ // TODO: window.backendをDIできるようにする -export function createLogger(scope: string) { - const createInner = - ( - method: "logInfo" | "logWarn" | "logError", - fallbackMethod: "info" | "warn" | "error", - ) => - (...args: unknown[]) => { - if (window.backend == undefined) { - // eslint-disable-next-line no-console - console[fallbackMethod](...args); +export function createLogger(scope: string): Record { + return { + info: createLogFunction("info"), + warn: createLogFunction("warn"), + error: createLogFunction("error"), + }; + + function createLogFunction(logType: LogLevel): LogFunction { + return (...args: unknown[]) => { + if (window.backend != undefined) { + const method = ( + { + info: "logInfo", + warn: "logWarn", + error: "logError", + } as const + )[logType]; + window.backend[method](`[${scope}]`, ...args); return; } - window.backend[method](`[${scope}]`, ...args); + + // eslint-disable-next-line no-console + console[logType](...args); }; - return { - info: createInner("logInfo", "info"), - warn: createInner("logWarn", "warn"), - error: createInner("logError", "error"), - }; + } } From 6602613fbdeb168be5ac6316f822752236856098 Mon Sep 17 00:00:00 2001 From: Takusea <53995265+takusea@users.noreply.github.com> Date: Sat, 18 Jan 2025 18:06:22 +0900 Subject: [PATCH 7/8] =?UTF-8?q?feat:=20=E3=83=97=E3=83=AA=E3=82=BB?= =?UTF-8?q?=E3=83=83=E3=83=88=E7=AE=A1=E7=90=86=E3=83=80=E3=82=A4=E3=82=A2?= =?UTF-8?q?=E3=83=AD=E3=82=B0=E3=82=92=E7=B7=A8=E9=9B=86=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E3=81=AB=E3=81=99=E3=82=8B=20(#2452)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hiroshiba Co-authored-by: Hiroshiba Kazuyuki Co-authored-by: github-actions[bot] --- src/components/Base/BaseListItem.vue | 1 + src/components/Base/BaseSlider.vue | 56 +++- src/components/Base/BaseTextField.vue | 7 +- src/components/Dialog/PresetManageDialog.vue | 268 ++++++++++++------ src/components/Talk/v2/ParameterSlider.vue | 89 ++++++ src/components/Talk/v2/README.md | 4 + src/helpers/timer.ts | 15 + ...eslider--default-dark-storybook-win32.png" | Bin 685 -> 600 bytes ...slider--default-light-storybook-win32.png" | Bin 680 -> 582 bytes ...slider--disabled-dark-storybook-win32.png" | Bin 638 -> 558 bytes ...lider--disabled-light-storybook-win32.png" | Bin 629 -> 548 bytes ...field--has-error-dark-storybook-win32.png" | Bin 2314 -> 2312 bytes ...ield--has-error-light-storybook-win32.png" | Bin 2224 -> 2262 bytes 13 files changed, 334 insertions(+), 106 deletions(-) create mode 100644 src/components/Talk/v2/ParameterSlider.vue create mode 100644 src/components/Talk/v2/README.md create mode 100644 src/helpers/timer.ts diff --git a/src/components/Base/BaseListItem.vue b/src/components/Base/BaseListItem.vue index e81e50bf39..0371091ed3 100644 --- a/src/components/Base/BaseListItem.vue +++ b/src/components/Base/BaseListItem.vue @@ -36,6 +36,7 @@ defineEmits<{ border: none; padding: vars.$padding-1 vars.$padding-2; border-radius: vars.$radius-1; + text-align: left; &:not(.selected):hover { background-color: colors.$clear-hovered; diff --git a/src/components/Base/BaseSlider.vue b/src/components/Base/BaseSlider.vue index 1c84e7fff1..ab19d9e53a 100644 --- a/src/components/Base/BaseSlider.vue +++ b/src/components/Base/BaseSlider.vue @@ -5,7 +5,7 @@ :max :step :disabled - :modelValue="[model]" + :modelValue="[modelValue]" @update:modelValue=" (value) => { if (value == undefined) { @@ -14,6 +14,8 @@ $emit('update:modelValue', value[0]); } " + @wheel="onWheel" + @valueCommit="$emit('valueCommit', $event[0])" > @@ -24,20 +26,52 @@ diff --git a/src/components/Talk/v2/README.md b/src/components/Talk/v2/README.md new file mode 100644 index 0000000000..4abb5ea163 --- /dev/null +++ b/src/components/Talk/v2/README.md @@ -0,0 +1,4 @@ +# このディレクトリは + +[トークエディタのリデザインプロジェクト](https://github.com/VOICEVOX/voicevox_project/issues/40)移行のための中間ファイルを配置するディレクトリです。 +デザイン的に合わないなどの問題がなければ、このディレクトリ内のファイルを使用しても問題ありません。 diff --git a/src/helpers/timer.ts b/src/helpers/timer.ts new file mode 100644 index 0000000000..969dc4a21a --- /dev/null +++ b/src/helpers/timer.ts @@ -0,0 +1,15 @@ +/** + * debounce関数を返す。 + * 最後に呼び出されてから指定した時間が経過した後にコールバックが実行される。 + */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function debounce unknown>( + callback: T, + delay: number, +): (...args: Parameters) => void { + let timeoutId: ReturnType; + return (...args) => { + clearTimeout(timeoutId); + timeoutId = setTimeout(() => callback(...args), delay); + }; +} diff --git "a/tests/e2e/storybook/\343\202\271\343\202\257\343\203\252\343\203\274\343\203\263\343\202\267\343\203\247\343\203\203\343\203\210.spec.mts-snapshots/components-base-baseslider--default-dark-storybook-win32.png" "b/tests/e2e/storybook/\343\202\271\343\202\257\343\203\252\343\203\274\343\203\263\343\202\267\343\203\247\343\203\203\343\203\210.spec.mts-snapshots/components-base-baseslider--default-dark-storybook-win32.png" index df4015cb8dc2279d6a75274737ce4c9cf2c430fc..26b8a6869a89e76d5788cc6b68717e34444bcac4 100644 GIT binary patch literal 600 zcmeAS@N?(olHy`uVBq!ia0y~yV0i#!OK>m&$vfeq4nT^rILO_JVcj{ImkbO{LY^*; zAr*7p-f{F6Nn|+waAsj)+2sjkJ}X~LkxXgiXk zGF^6ly3pzL)~PJh??#r~Unj-7u|2JA-g67)!|#8k-?NDM^Va6=V&=w+}|L4;t6PJZ{VfyPh7*?HiU}a!fAi@&@3pPhp9Y%?De}!)ARKD9@o!iX1F@-`|q`X{~oadnG*5x#fzsa zHQj3%85lHLQ(hmvowqx&em}gV}>vr_}ZQE*^ zxfq-aj)*fbGz1w0fHboLor;B%;IY?Fzwg}NwdQ?~;+BWU2r`7sZUpMhdM~$R>z6lE zw@lks&flfY)R1Kyz?k46z52EA%ZkNe{*P2TC%dh+o7k7XW}Wz5R)$d1OJ_DMl4e*i ziSPTZ`(^w5;%Dah#jJ8)Y;PyOuj<>U$FIK!iX1KcBhJsjaPB8(+|?RjD(JHWdW6B# L)z4*}Q$iB}X`J;g literal 685 zcmeAS@N?(olHy`uVBq!ia0y~yV0i#!D{wFYNt3z>4M2*qILO_JVcj{ImkbO{>7Fi* zAr*7p-Z}3T63B4;WAUb-5l1&8>d<`DV-xalQR-r&|_3{&L0#XjQ`&)YWhgDp*>w5jUPgwj z%wNBrMwjO;7w-LA63}w+<$$TsC-U}3(67;SVsD??D!RytW*CO}37MFJ&UR3-qWS=WTKt4z~tH1x>m*h;Y zmA2Q;ZRcQk<+}hFN&%ceDTW3wh>M#bE@sgJI)CbgJ)25$za6`ik*@Pyh+)O#hua^% zmy4Y{x7YCBZA+k;M-wjGy_K~h7^wDBR&URod9#X+h=a_^SYuyPcj5MVTV^2df4HGU zPWkS$;r?-Zsy-=wmta^ibIPT=?BDBtzIgg;*Z&1f4xB)b;dO~Z0ONus|LW}9ulasilid?QZ3mCoL9~ zUVQeOOLk3es_Az)CtHzqgxfS)Eq&D8;&`=I@5jKmIM=?jPSS zkknKEfr;S(dtp_Y+IKdF6-%dFn&{o3*dlRNlVQrWGqwy2ue6TM2>P|s9VDOzbe@eR j7eoETeicTLNA5G~8nmfTVo{RPx%07*naRCt{2+d)s$ za2&_sb{!p-AVUaKPvV5ckYF&r1rNSHPreclz6B!DgqVm^PU;e1AUd+rKlQqUUV5-? ze4gX4m+$qH{2O0~A_4#^8GZk;ACrX#mhlow^4AKr5AHxj#BsS?_1dS&}44l4Q%- z%6fl)bWoOM-Rl6Ll>{mPR8f}Y z0f08S3E^*_4i68LB>A^<0HEE{G~L+P=%`Zw008Qh=lOU%_QV$e0Dwm5Jiha&7o~O2 z0002s|COfcU@+)z54N@kTXl~CfR+g%ygYvO$4@&uI|u$j1%L`X@sq&;8-D-*8bP1} zKt*Y?a1+A(cjGv&dmR9@QhXhXx;Fqo`;=u_6vgP<=Y!+-lj(UBMXOnV m@4@cy-otLUt5E@Px%Vo5|nRCt{2+|6ne zQ2>VF`AMfWr8c$Fs4Hu%AcacBTX5m^x$;U}cnig%Py}nVE484ewVIMNXO0U&ve3;S z&I~@!^33MjzRa0PFTyMV004lxWpxh#004kQpaK8@&=dj{0Dl00M(ET%003HS`0?G| z@cHMnQIaImCIFZI${-5&%?l_GAQgE4}~#05n2&_sZ?Xq^Nra04)Fj|F5Db`u%?APJio8f2-~> z0MIfagvUoue*0*9d)qgt08oJ|z5oCKG=e~rn*ketsHn&n$`IyH$`Fctp}s``&~5@1 z04nM&_a^7l`IE`{w71-=ZxH~rn?MDCD$+FF-P}3-bTU30hY-RnjL*iWpH6l+chWSi zdmR9@QhE_)b#DNG_K7jhX0zdkxBEvgN8^(uN!Gf(-J3gu>$f_cjz$H53Ir+uR8*E_ z2%#)Z%NXO&cdA*I<$0cEE+_#&6`i^V06<%1S(c`0jPX~X{#5ra0B9?L3INq9QULgi g+(7~W0H6_m0QPU9U0*(PVgLXD07*qoM6N<$g0KA=i~s-t diff --git "a/tests/e2e/storybook/\343\202\271\343\202\257\343\203\252\343\203\274\343\203\263\343\202\267\343\203\247\343\203\203\343\203\210.spec.mts-snapshots/components-base-baseslider--disabled-dark-storybook-win32.png" "b/tests/e2e/storybook/\343\202\271\343\202\257\343\203\252\343\203\274\343\203\263\343\202\267\343\203\247\343\203\203\343\203\210.spec.mts-snapshots/components-base-baseslider--disabled-dark-storybook-win32.png" index 58b784bc074d668d77d0810d58ae2d993cd81765..c4280dc1127390128fccb03a652a725931825148 100644 GIT binary patch delta 546 zcmeyzvW{hfc)bJ%69WUoop4bHAjMc5Cb8P7e7wSD|Yq8emd|}nk<=f+p zd=Ga|*XL$PQ0zB%oBa0VgNqw9x_)MsZm2H!^wZ+I2E&V0^+ly7r}i>3SY>{Fd299D z>nr8gb?wrdwc}EJ{l383)#vt~FZO3{@O$-Cj)5U|>rUI9EA(H#wpuzRXw~}H-M@;8 zt0z^9Gn7nqU~O<+GKGzwt#nns+_mdpA3QWzIwc<{GXp5YI`wbFpGk|J2F*<8Whj~N zz{mDATnr2j+8iN3u_(oLw$k=DZ*^#U@0`xyF#XTNc%#Q3 zE&kj#ED!w9$M{d%_wt#v&G#y@W9I@xZbD$>w8IZCh{l6-E;O(GztnF3DO+X+hKAj% zGiR+@_2}ZgFB$o>s(Bbne7rKBzny*GZkFHjgW{7IK75b)$jVTUa0;eN92YPhXqvV9 z*|c_s1GzxQMO^r^rfYA-XO(Y{{;WB*or7VQFGvMn`SP#N#B#_d$;z;qCbUI|32PrUq8RknL~Q#bw&sEzbrSc W%I-%pv=#up!QkoY=d#Wzp$PyE&g@_S literal 638 zcmeAS@N?(olHy`uVBq!ia0y~yV0i#!D{wFYNt3z>4M2*qILO_JVcj{ImkbO{7M?DS zAr*7p-u3ktc4RpIaPGT+C0|v8f)09oNnm&!{@}s#56RWXX3Y2?WXjv65Y191$sgyT z!q#0__O!C^vfRIyZ>Rf|AO5^`E69SP*H7hu6ho^6D+9vt)};7`uw#a z@vA52U%qphVZr2>kE{)nwl^be*PegXZMAet&?@~`mw&xEc`WN)EW?FRCQ*j8i9u3# zq_3>pR}&F`rTO>aDM9;yGKnCWkZ;K!y}PCrr_M8FxKIleVQ2^wSOIk0mL{-EMIkO# z2w-Gj$Y|a1rQ}aWt*YLcr*TXSv7cs_pX@pQ_(T5jJ8lQ_c|OEv&U*Ia#}4zj_^{(IVuh^^M&udx>f$?iq8Wj9(>E1wQSX@9s6x>-k~y5pe3*Ya#y|$lqDc=ny`&dvV}9UWN;{iY+fMZn3hEyC=){PUpy? zKXnzK{+->eFK^c_P_&-8!H?_w^=sfL@Y0N})B_r6_EG9SBg486#xDBlt4vrMW&;DO nKzWe}!#^>8PoSF@h}JQLXV+#~@K`bfy~^O}>gTe~DWM4fSh)Pj diff --git "a/tests/e2e/storybook/\343\202\271\343\202\257\343\203\252\343\203\274\343\203\263\343\202\267\343\203\247\343\203\203\343\203\210.spec.mts-snapshots/components-base-baseslider--disabled-light-storybook-win32.png" "b/tests/e2e/storybook/\343\202\271\343\202\257\343\203\252\343\203\274\343\203\263\343\202\267\343\203\247\343\203\203\343\203\210.spec.mts-snapshots/components-base-baseslider--disabled-light-storybook-win32.png" index d5dc4060ed85a8ad66a3ee693652ccf1bdc820ef..58758e8b7a3a98b78ab5b64e31252dee720da8ae 100644 GIT binary patch delta 536 zcmey$vV>)Vc)bJ%69WUoop4bHAjMc525wvETc7h4l~a5Se(u;gAP+?)k#UNj@cx$(O?Br&sR!x$XTEpV?*3^BEWx z->KXGyQui0%~sDzSM*nHe{HU=-@jarmBD)|R|tc|^JjIx>tBBQ>=-MWI#0#(K5xJ8 z?|*;p{(4dJDwAP@$IUCu3<)dswoSj97%DduaFay~=)KJf0gMa` zGguqB7#I%daD)Jb>eCz-00Y2)`{>tq&vxDYc2S$1@quI#M}1XEY3bCzzslnOS;c>1 z{Bb;`vTjS1==HPP{I6&N^-bnHT(JN4&PUuJlTy;ZW=?z-d>$zN;Q!apUGHyZ)ozRO zw`F4xQ#(~y|EIiY-?e6WGz-INus1(H_WgaKtUs1VvF(Cw*<0u8x;-;NffIU* z_wN;HhJ=Yu9JlYjy?#4C_qv*A(A2B1CxgTe~DWM4f0J!I% literal 629 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 NEX-`6m8KpK{|!W3D#ZW* literal 2314 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 U#$$yIK@YPl){gCBs~D zTROBcHe;ke8q>nWay#XAG&Y&hZ1}g;`@HY-ywCUh{d}I!^ZmZh=Y6;L#ooteKq$=4 z)+?@HVGIc8NkCnnht|VIEVZHP7Sh#n6V&tr9eQ|rUDMtCD_VJu=8((xx5Dl}#=dFV zx}lQ$ko^auLQ8%`PO(nc2_5DkLtHe=k3c%9DfsK#{s`gb(9{;PS87@UM>j&qS>E9w zjKx}le1OT7MTuA=n*j`2!W&?}+wtf=_nwEWJr{64HkE=3*>`P!Q2DwrG~XKxs`}2a z`~2#}q>sCK!!7L{Rphu*8O?&bj&1cI*T31JsC;6^sc0VDGgIq}qWZS(s`}dvrDM}~ zoGqTzYZ9?u`9LO!`2-Anw66bC)C)45ce=mUlCger^Yh@$2SVjNG|QMAH*&VjQ&H50Ju6^3 zr!{!N)HkNleV(A4^p2gWek15Lc1!#oo5w=FqDtlLqePtPcvMW4B>DvQpk&7ko1rrw;cvahH26(+83f#Le&XGRZXAFnRod|R2kX-yQ8 zzu|hMoo;Ho_00Gv#-33`gLG+W$mS?{J*5!or6>Ttb_Mgr@tPLPnAf zAvnjl`o-bu7j03SP~5g)gkVzjgd(Lf7v#FCyr}$@q@2O){ack%e!YCSSlRnC_pW%H zIjD>CZwjen&YQ#1>{S;^gnuD>h<;N`TE3dG|3kbKoA~!VnObUcmZz>$8=jg%;^kK5 z0bKyH{2{b!LF>P6Uz+m!$R8<~aCtrd6w{vK$Ppg8(E0WnM@S8%C$#G4&8Lc&@|5p$ z4w(k##++}7F9vgwO!`a{wDLysMET-f;sDz4HU-|FLPAh(FrUWwu`gb-?pwj2noHY5 z3HxCXh=C@$Ks@iS3+tD5!mY!!0a{r*3GGQwq?;i}d=h)of-3d>OJ)sJB}Hh!)CiX8 z*C>!x=OiuXFPe`JLu6@A0dCc_aRtQi28!$~~}lIhWfaafw|`?SEDp zb*^X+Xt%S+1V0PPMLOcKy(`ky_}cYWO+_P5U-32~;i--Cl4v$CO|!Es?a0XS9y4Ep z^e=bMEy(VnYsDu>>ax0_a6@fa@|Bk>l||~h^sze5&zA1{h7nV|b@JiZdRXLQbl1wn z*5x3+dhN6m)YPmo@?~{4p69>GUt1}FTW}cl+NP0%Ht?wdOIEjBqT$cntuapz%PAAC zku1{2(4#p9fVBF~Y_5JGU+Pm8Eh{}R<)Kjc+HSxy`P0cj;sF~g-Z{$0UPkT7@zGO- z+lA`ZVb41I$@-6~M?vo2gx%!60>eFV6!}eMl}Q2sgmFi zPf6!2R&4~agQ!TiTChU&;oi$zLSuT1z$Dx3G8W=ex~ksXA3;V!x2uo>>LqcQkv>S=k5IH0`+Q?jY%UA6_9}3Gwr>LG*(Zv`HM~ zI&tk|_AyOu19(epLKmPmyYjsG&-&9bFb{g&ji^`zgW3LiiT>Mzj6%5deym+G#oV`h zEO1B+47LKZ#pp{BSh#~k;E&Ch7uar7P;TmZLX$)Dn7qY#0jgjzz4Xkj04%z+rUc&K z?)0GY2rpXdJAf=U>-YY!Ha;!Nx`XAS%U0c2Z_Unwdw_I?vG_#B{ZBaiTGv2@#5T!k zi8DSjp}HF(g6wuN^f~BlU2n=e$_}Il2M2YDQN1N!Izs6*7FHlz0l9qvOZ7$Yl>!!K zmNdqe=*SuPDgQe5yBBqJ(JM@@XwMV4O(BZ2{LWdOOc`Q=#^tUs`Q8QU;KYA2zZoM)c41?1AkY&j@~#a=_F-kct%ibOe_*4$n~wmV z8FPaym6BdNe)ZW1ly#T$(c}n159VsVP@yzQheO+`{LxfgUh%l!+zq3#*Ij8lT6e$u b-}cRI*RS>NS~jncC{QqaSG$^v*Y5ovqa+Un From 14f9a3de58e835d5ee3b865c007daad30ce37052 Mon Sep 17 00:00:00 2001 From: madosuki Date: Sat, 18 Jan 2025 21:18:38 +0900 Subject: [PATCH 8/8] =?UTF-8?q?Arch=20Linux=E3=81=8Cp7zip=E3=82=927zip?= =?UTF-8?q?=E3=81=AB=E7=BD=AE=E3=81=8D=E6=8F=9B=E3=81=88=E3=81=9F=E3=81=AE?= =?UTF-8?q?=E3=81=A7=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=80=82=E3=81=9D=E3=82=8C=E3=81=A87zz?= =?UTF-8?q?=E3=82=92=E8=A8=B1=E5=AE=B9=E3=81=99=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB=E3=80=82=20(#2493)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Hiroshiba --- build/installer_linux.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/build/installer_linux.sh b/build/installer_linux.sh index dc1d05ac48..14ce3e4286 100755 --- a/build/installer_linux.sh +++ b/build/installer_linux.sh @@ -95,9 +95,12 @@ elif command -v 7zr &> /dev/null; then elif command -v 7za &> /dev/null; then # CentOS/Fedora COMMAND_7Z=7za +elif command -v 7zz &> /dev/null; then + # Official 7zip + COMMAND_7Z=7zz else cat << 'EOS' && exit 1 -[!] Command '7z', '7zr' or '7za' not found +[!] Command '7z', '7zr', '7za' or '7zz' not found Required to extract compressed files @@ -115,7 +118,7 @@ Or sudo yum install p7zip Arch Linux: - sudo pacman -S p7zip + sudo pacman -S 7zip MacOS: brew install p7zip