Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c404ecd8c | |||
| e30d7418df |
@@ -1133,20 +1133,47 @@ function downloadFinalResourcepack() {
|
|||||||
section.innerHTML =
|
section.innerHTML =
|
||||||
'<h2>' + tt('resourcepack.downloadHeading') + '</h2>' +
|
'<h2>' + tt('resourcepack.downloadHeading') + '</h2>' +
|
||||||
'<div class="formMessage" id="rpMsg">' + tt('resourcepack.downloading') + '</div>' +
|
'<div class="formMessage" id="rpMsg">' + tt('resourcepack.downloading') + '</div>' +
|
||||||
|
'<div id="rpBarWrap" style="margin-top:10px;height:16px;background:rgba(255,255,255,0.08);border:1px solid var(--border,#30363d);border-radius:8px;overflow:hidden;">' +
|
||||||
|
' <div id="rpBar" style="height:100%;width:0%;background:var(--accent,#6cf);transition:width 0.15s;"></div>' +
|
||||||
|
'</div>' +
|
||||||
|
'<div class="formMessage" id="rpPercent" style="margin-top:6px;">0%</div>' +
|
||||||
'<div class="actionRow" id="rpActions" hidden></div>'
|
'<div class="actionRow" id="rpActions" hidden></div>'
|
||||||
pageHost.appendChild(section)
|
pageHost.appendChild(section)
|
||||||
var msg = section.querySelector('#rpMsg')
|
var msg = section.querySelector('#rpMsg')
|
||||||
var actions = section.querySelector('#rpActions')
|
var actions = section.querySelector('#rpActions')
|
||||||
|
var bar = section.querySelector('#rpBar')
|
||||||
|
var barWrap = section.querySelector('#rpBarWrap')
|
||||||
|
var percentEl = section.querySelector('#rpPercent')
|
||||||
|
|
||||||
function proceed() { state.finalRpHandled = true; renderStep5() }
|
// 다운로드 진행률(퍼센트) 구독. 완료/실패 시 해제.
|
||||||
|
var unsubscribe = null
|
||||||
|
if (installerApi.onFinalResourcepackProgress) {
|
||||||
|
unsubscribe = installerApi.onFinalResourcepackProgress(function (info) {
|
||||||
|
if (info && info.percent >= 0) {
|
||||||
|
bar.style.width = info.percent + '%'
|
||||||
|
percentEl.textContent = info.percent + '%'
|
||||||
|
} else if (info) {
|
||||||
|
// 전체 크기를 모르면 받은 용량(MB)만 표시.
|
||||||
|
percentEl.textContent = (info.loaded / 1048576).toFixed(1) + ' MB'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function stopProgress() { if (unsubscribe) { unsubscribe(); unsubscribe = null } }
|
||||||
|
|
||||||
|
function proceed() { stopProgress(); state.finalRpHandled = true; renderStep5() }
|
||||||
|
|
||||||
installerApi.installFinalResourcepack().then(function (res) {
|
installerApi.installFinalResourcepack().then(function (res) {
|
||||||
|
stopProgress()
|
||||||
if (res && res.ok) {
|
if (res && res.ok) {
|
||||||
|
bar.style.width = '100%'
|
||||||
|
percentEl.textContent = '100%'
|
||||||
msg.textContent = tt('resourcepack.downloadDone')
|
msg.textContent = tt('resourcepack.downloadDone')
|
||||||
msg.classList.add('success')
|
msg.classList.add('success')
|
||||||
actions.innerHTML = '<button class="primaryBtn" id="rpNext">' + tt('common.next') + '</button>'
|
actions.innerHTML = '<button class="primaryBtn" id="rpNext">' + tt('common.next') + '</button>'
|
||||||
actions.querySelector('#rpNext').addEventListener('click', proceed)
|
actions.querySelector('#rpNext').addEventListener('click', proceed)
|
||||||
} else {
|
} else {
|
||||||
|
barWrap.hidden = true
|
||||||
|
percentEl.hidden = true
|
||||||
msg.textContent = tt('resourcepack.downloadFailed', { message: (res && res.message) || 'unknown' })
|
msg.textContent = tt('resourcepack.downloadFailed', { message: (res && res.message) || 'unknown' })
|
||||||
msg.classList.add('error')
|
msg.classList.add('error')
|
||||||
actions.innerHTML =
|
actions.innerHTML =
|
||||||
@@ -1157,6 +1184,9 @@ function downloadFinalResourcepack() {
|
|||||||
}
|
}
|
||||||
actions.hidden = false
|
actions.hidden = false
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
|
stopProgress()
|
||||||
|
barWrap.hidden = true
|
||||||
|
percentEl.hidden = true
|
||||||
msg.textContent = tt('resourcepack.downloadFailed', { message: (err && err.message) ? err.message : String(err) })
|
msg.textContent = tt('resourcepack.downloadFailed', { message: (err && err.message) ? err.message : String(err) })
|
||||||
msg.classList.add('error')
|
msg.classList.add('error')
|
||||||
actions.innerHTML =
|
actions.innerHTML =
|
||||||
|
|||||||
@@ -241,6 +241,7 @@
|
|||||||
"modDownload": "모드 다운로드: {{file}}",
|
"modDownload": "모드 다운로드: {{file}}",
|
||||||
"skipResourcepack": "resourcepackPath가 비어 있어 리소스팩 다운로드를 건너뜁니다.",
|
"skipResourcepack": "resourcepackPath가 비어 있어 리소스팩 다운로드를 건너뜁니다.",
|
||||||
"resourcepackDownload": "리소스팩 다운로드: {{url}}",
|
"resourcepackDownload": "리소스팩 다운로드: {{url}}",
|
||||||
|
"skipBaseForFinal": "최종 리소스팩이 등록돼 있어 베이스 리소스팩은 건너뜁니다(설치 마지막에 최종 리소스팩만 받음).",
|
||||||
"finalResourcepackDownload": "최종 리소스팩 다운로드: {{url}}",
|
"finalResourcepackDownload": "최종 리소스팩 다운로드: {{url}}",
|
||||||
"finalResourcepackSaved": "최종 리소스팩 저장: {{path}}",
|
"finalResourcepackSaved": "최종 리소스팩 저장: {{path}}",
|
||||||
"serverInstallPath": "서버 설치 경로: {{path}}",
|
"serverInstallPath": "서버 설치 경로: {{path}}",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "minecraft-music-quiz-installer",
|
"name": "minecraft-music-quiz-installer",
|
||||||
"version": "0.4.17",
|
"version": "0.4.19",
|
||||||
"description": "마인크래프트 음악퀴즈 간편설치기 + 관리 사이트",
|
"description": "마인크래프트 음악퀴즈 간편설치기 + 관리 사이트",
|
||||||
"main": "dist/installer/main.js",
|
"main": "dist/installer/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -290,8 +290,20 @@ ipcMain.handle('finalResourcepack:install', async (): Promise<{ ok: boolean; pat
|
|||||||
const url = `${state.baseUrl}/file/resourcepacks/outputs/${encodeURIComponent(cleaned)}`
|
const url = `${state.baseUrl}/file/resourcepacks/outputs/${encodeURIComponent(cleaned)}`
|
||||||
const destDir = path.join(getAppDataDir(), getMcCustomDirName(), 'resourcepacks')
|
const destDir = path.join(getAppDataDir(), getMcCustomDirName(), 'resourcepacks')
|
||||||
const dest = path.join(destDir, cleaned)
|
const dest = path.join(destDir, cleaned)
|
||||||
|
await fsp.mkdir(destDir, { recursive: true })
|
||||||
sendLog(t('log.finalResourcepackDownload', { url }))
|
sendLog(t('log.finalResourcepackDownload', { url }))
|
||||||
await downloadFile(url, dest)
|
// 진행률(퍼센트)을 렌더러로 흘려보내며 스트리밍 다운로드.
|
||||||
|
let lastPct = -1
|
||||||
|
const controller = new AbortController()
|
||||||
|
await downloadStream(url, dest, controller.signal, (loaded, total) => {
|
||||||
|
const percent = total > 0 ? Math.min(100, Math.max(0, Math.floor((loaded / total) * 100))) : -1
|
||||||
|
if (percent !== lastPct) {
|
||||||
|
lastPct = percent
|
||||||
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
|
mainWindow.webContents.send('finalResourcepack:progress', { loaded, total, percent })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
sendLog(t('log.finalResourcepackSaved', { path: dest }))
|
sendLog(t('log.finalResourcepackSaved', { path: dest }))
|
||||||
return { ok: true, path: dest }
|
return { ok: true, path: dest }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1340,7 +1352,13 @@ ipcMain.handle('client:install', async (_event, payload: ClientInstallPayload) =
|
|||||||
}
|
}
|
||||||
|
|
||||||
await downloadModsFolder(pack.pack, customRoot)
|
await downloadModsFolder(pack.pack, customRoot)
|
||||||
await downloadResourcepackZip(pack.pack, customRoot)
|
// 최종 리소스팩이 등록돼 있으면(finalResourcepackPath !== "."), 완성본을 설치 마지막에
|
||||||
|
// 따로 받으므로 베이스 리소스팩은 받지 않는다("최종 리소스팩만 다운로드").
|
||||||
|
if (pack.pack.finalResourcepackPath && pack.pack.finalResourcepackPath !== '.') {
|
||||||
|
sendLog(t('log.skipBaseForFinal'))
|
||||||
|
} else {
|
||||||
|
await downloadResourcepackZip(pack.pack, customRoot)
|
||||||
|
}
|
||||||
|
|
||||||
if (payload.skipMap) {
|
if (payload.skipMap) {
|
||||||
// 참가자 모드: 이전 설치 흐름에서 설치러가 풀어둔 맵이 있다면 제거한다.
|
// 참가자 모드: 이전 설치 흐름에서 설치러가 풀어둔 맵이 있다면 제거한다.
|
||||||
|
|||||||
@@ -74,6 +74,15 @@ const api = {
|
|||||||
const listener = (_event: unknown, line: string) => handler(line)
|
const listener = (_event: unknown, line: string) => handler(line)
|
||||||
ipcRenderer.on('log', listener)
|
ipcRenderer.on('log', listener)
|
||||||
return () => ipcRenderer.removeListener('log', listener)
|
return () => ipcRenderer.removeListener('log', listener)
|
||||||
|
},
|
||||||
|
|
||||||
|
// 최종 리소스팩 다운로드 진행률 구독. 반환값을 호출하면 구독 해제.
|
||||||
|
onFinalResourcepackProgress: (
|
||||||
|
handler: (info: { loaded: number; total: number; percent: number }) => void
|
||||||
|
): (() => void) => {
|
||||||
|
const listener = (_event: unknown, info: { loaded: number; total: number; percent: number }) => handler(info)
|
||||||
|
ipcRenderer.on('finalResourcepack:progress', listener)
|
||||||
|
return () => ipcRenderer.removeListener('finalResourcepack:progress', listener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user