Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add progress perc to loading win for import-db module #449

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@
},
"modalDialog": {
"title": "Database import"
},
"loadingWindow": {
"description": "Importing DB ...",
"unzippedBytes": "DB size {{prettyUnzippedBytes}}"
}
}
},
Expand Down
4 changes: 4 additions & 0 deletions build/locales/ru/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,10 @@
},
"modalDialog": {
"title": "Импорт базы данных"
},
"loadingWindow": {
"description": "Импортирование БД ...",
"unzippedBytes": "размер БД {{prettyUnzippedBytes}}"
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"new-github-issue-url": "0.2.1",
"showdown": "2.0.3",
"truncate-utf8-bytes": "1.0.2",
"yauzl": "2.10.0"
"yauzl": "3.2.0"
},
"devDependencies": {
"@mapbox/node-pre-gyp": "1.0.11",
Expand Down
129 changes: 93 additions & 36 deletions src/archiver.js
Original file line number Diff line number Diff line change
Expand Up @@ -140,83 +140,140 @@ const zip = async (
const unzip = (
zipPath,
folderPath,
params = {}
params
) => {
const { extractFiles } = { ...params }
const extractedfileNames = []
let isClosedByError = false
const {
extractFiles,
progressHandler
} = params ?? {}
return new Promise((_resolve, _reject) => {
const entryStates = []
let totalUncompressedSize = 0
let unzippedBytes = 0
let lastProgressEventMts = Date.now()

const asyncProgressHandler = async () => {
try {
if (typeof progressHandler !== 'function') {
return
}

if (
!Number.isFinite(totalUncompressedSize) ||
totalUncompressedSize === 0 ||
!Number.isFinite(unzippedBytes)
) {
return
}

const progress = unzippedBytes / totalUncompressedSize
const prettyUnzippedBytes = bytesToSize(unzippedBytes)

await progressHandler({
progress,
unzippedBytes,
prettyUnzippedBytes
})
} catch (err) {
console.debug(err)
}
}
const resolve = (entryState) => {
if (entryState) {
entryState.isClosedSuccessfully = true
}
if (
entryStates.some((state) => state?.isClosedWithError) ||
entryStates.some((state) => !state?.isClosedSuccessfully)
) {
return
}

asyncProgressHandler()

return _resolve(entryStates.map((state) => state?.entry?.fileName))
}
const reject = (err, zipfile, entryState) => {
if (entryState) {
entryState.isClosedWithError = true
}
if (zipfile) {
zipfile.close()
}

return _reject(err)
}

return new Promise((resolve, reject) => {
try {
yauzl.open(zipPath, { lazyEntries: true }, (err, zipfile) => {
yauzl.open(zipPath, { lazyEntries: false }, (err, zipfile) => {
if (err) {
reject(err)

return
}

zipfile.on('error', reject)
zipfile.on('end', () => {
if (isClosedByError) {
return
}

resolve(extractedfileNames)
})
zipfile.readEntry()

zipfile.on('end', () => resolve())
zipfile.on('entry', (entry) => {
const { fileName } = entry
const filePath = path.join(folderPath, fileName)
const errorMessage = yauzl.validateFileName(fileName)

if (/\/$/.test(fileName)) {
zipfile.readEntry()

return
}
if (
Array.isArray(extractFiles) &&
extractFiles.every(file => file !== fileName)
) {
zipfile.readEntry()

return
}

const entryState = {
isClosedWithError: false,
isClosedSuccessfully: false,
entry
}
totalUncompressedSize += entry?.uncompressedSize ?? 0
entryStates.push(entryState)

if (errorMessage) {
isClosedByError = true
zipfile.close()
reject(new InvalidFileNameInArchiveError(errorMessage))
reject(
new InvalidFileNameInArchiveError(errorMessage),
zipfile,
entryState
)

return
}

zipfile.openReadStream(entry, (err, readStream) => {
if (err) {
isClosedByError = true
zipfile.close()
reject(err)
reject(err, zipfile, entryState)

return
}

const output = fs.createWriteStream(filePath)

output.on('close', () => {
extractedfileNames.push(fileName)

zipfile.readEntry()
})
output.on('close', () => resolve(entryState))
output.on('error', (err) => {
isClosedByError = true
zipfile.close()
reject(err)
reject(err, zipfile, entryState)
})

readStream.on('error', (err) => {
isClosedByError = true
zipfile.close()
reject(err)
reject(err, zipfile, entryState)
})
readStream.on('data', (chunk) => {
unzippedBytes += chunk.length
const currMts = Date.now()

if (currMts - lastProgressEventMts < 500) {
return
}

lastProgressEventMts = currMts
asyncProgressHandler()
})

readStream.pipe(output)
Expand Down
39 changes: 36 additions & 3 deletions src/import-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const pauseApp = require('./pause-app')
const relaunch = require('./relaunch')
const { rm, isMainWinAvailable } = require('./helpers')
const wins = require('./window-creators/windows')
const {
setLoadingDescription
} = require('./window-creators/change-loading-win-visibility-state')
const {
DB_FILE_NAME,
DB_SHM_FILE_NAME,
Expand Down Expand Up @@ -78,7 +81,33 @@ module.exports = ({
throw new InvalidFilePathError()
}

await pauseApp()
const progressHandler = async (args) => {
const {
progress,
prettyUnzippedBytes
} = args ?? {}

const _description = i18next
.t('common.importDB.loadingWindow.description')
const _unzipped = i18next.t(
'common.importDB.loadingWindow.unzippedBytes',
{ prettyUnzippedBytes }
)

const unzipped = prettyUnzippedBytes
? `<br><small style="color:#808b93">${_unzipped}</small>`
: ''
const description = `${_description}${unzipped}`

await setLoadingDescription({ progress, description })
}

await pauseApp({
loadingWinParams: {
description: i18next
.t('common.importDB.loadingWindow.description')
}
})
await _rmDbExcludeMain(pathToUserData, DB_FILE_NAME)
const extractedfileNames = await unzip(
filePaths[0],
Expand All @@ -89,7 +118,8 @@ module.exports = ({
DB_SHM_FILE_NAME,
DB_WAL_FILE_NAME,
SECRET_KEY_FILE_NAME
]
],
progressHandler
}
)

Expand All @@ -100,8 +130,11 @@ module.exports = ({
relaunch()
} catch (err) {
try {
const _win = isMainWinAvailable(wins.loadingWindow)
? wins.loadingWindow
: win
await showErrorModalDialog(
win,
_win,
i18next.t('common.importDB.modalDialog.title'),
err
)
Expand Down
12 changes: 8 additions & 4 deletions src/pause-app.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,16 @@ const _closeServer = () => {
})
}

module.exports = async (opts = {}) => {
module.exports = async (opts) => {
const {
beforeClosingServHook = () => {}
} = opts
beforeClosingServHook = () => {},
loadingWinParams
} = opts ?? {}

await showLoadingWindow({ isRequiredToCloseAllWins: true })
await showLoadingWindow({
isRequiredToCloseAllWins: true,
...loadingWinParams
})

await beforeClosingServHook()

Expand Down