Skip to content

Commit

Permalink
[Feat] Improve the "Move Game" experience a bit (#3648)
Browse files Browse the repository at this point in the history
  • Loading branch information
CommandMC authored Mar 26, 2024
1 parent 8a150c3 commit c62820d
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 61 deletions.
2 changes: 1 addition & 1 deletion public/locales/en/gamepage.json
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@
"installing": "Installing",
"launching": "Launching",
"moving": "Moving Installation, please wait",
"moving-files": "Moving file '{{file}}': {{percent}} ",
"moving-files": "Moving file '{{file}}': {{percent}}%",
"notinstalled": "This game is not installed",
"notSupported": "Not supported",
"notSupportedGame": "Not Supported",
Expand Down
133 changes: 79 additions & 54 deletions src/backend/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -996,41 +996,33 @@ export async function moveOnWindows(
newInstallPath = join(newInstallPath, basename(install_path))

let currentFile = ''
let currentPercent = ''

// move using robocopy and show progress of the current file being copied
const { code, stderr } = await spawnAsync(
'robocopy',
[install_path, newInstallPath, '/MOVE', '/MIR'],
[install_path, newInstallPath, '/MOVE', '/MIR', '/NJH', '/NJS', '/NDL'],
{ stdio: 'pipe' },
(data) => {
data = data.replaceAll(/\s/g, ' ')

const match = data.split(' ').filter(Boolean)
// current percentage
const percent = match.filter((m) => m.includes('%'))[0]
// current file
const file = match[match.length - 1]
if (percent) {
currentPercent = percent
}

if (file && file.includes('.') && !file.includes('%')) {
currentPercent = '0%'
currentFile = file
}

if (match) {
sendFrontendMessage(`progressUpdate-${gameInfo.app_name}`, {
appName: gameInfo.app_name,
runner: gameInfo.runner,
status: 'moving',
progress: {
percent: currentPercent,
file: currentFile
}
})
}
let percent = 0
const percentMatch = data.match(/(\d+)(?:\.\d+)?%/)?.[1]
if (percentMatch) percent = Number(percentMatch)

const filenameMatch = data.match(/([\w.:\\]+)$/)?.[1]
if (filenameMatch) currentFile = filenameMatch

sendFrontendMessage(`progressUpdate-${gameInfo.app_name}`, {
appName: gameInfo.app_name,
runner: gameInfo.runner,
status: 'moving',
progress: {
percent,
file: currentFile,
// FIXME: Robocopy does not report bytes moved / an ETA, so we have to
// leave these blank for now
bytes: '',
eta: ''
}
})
}
)
if (code !== 0) {
Expand Down Expand Up @@ -1058,7 +1050,6 @@ export async function moveOnUnix(
const destination = join(newInstallPath, basename(install_path))

let currentFile = ''
let currentPercent = ''

let rsyncExists = false
try {
Expand All @@ -1070,38 +1061,72 @@ export async function moveOnUnix(
if (rsyncExists) {
const origin = install_path + '/'
logInfo(
`moving command: rsync -az --progress ${origin} ${destination} `,
`moving command: rsync --archive --compress --no-human-readable --remove-source-files --info=name,progress ${origin} ${destination} `,
LogPrefix.Backend
)
const { code, stderr } = await spawnAsync(
'rsync',
['-az', '--progress', origin, destination],
[
'--archive',
'--compress',
'--no-human-readable',
'--remove-source-files',
'--info=name,progress',
origin,
destination
],
{ stdio: 'pipe' },
(data) => {
const split =
data
.split('\n')
.find((d) => d.includes('/') && !d.includes('%'))
?.split('/') || []
const file = split.at(-1) || ''

if (file) {
currentFile = file
let percent = 0
let eta = ''
let bytes = '0'

// Multiple output lines might be buffered into a single `data`, so
// we have to iterate over every line (we can't just look at the last
// one since that might skip new files)
for (const outLine of data.trim().split('\n')) {
// Rsync outputs either the file currently being transferred or a
// progress report. To know which one of those `outLine` is, we check
// if it includes a %, :, and starts with a space
// If all of these aren't the case, it's *most likely* a filename
// FIXME: This is pretty hacky, but I don't see an obvious way to
// "divide" the two output types other than that
const isFilenameOutput =
!outLine.includes('%') &&
!outLine.includes(':') &&
!outLine.startsWith(' ')

if (isFilenameOutput) {
// If we have a filename output, set `lastFile` and reset all
// other metrics. Either there'll be a progress update in the next
// line of `data`, or we've just started copying and thus start at 0
currentFile = outLine
percent = 0
eta = ''
bytes = '0'
} else {
// If we got the progress update, try to read out the bytes, ETA and
// percent
const bytesMatch = outLine.match(/^\s+(\d+)/)?.[1]
const etaMatch = outLine.match(/(\d+:\d{2}:\d{2})/)?.[1]
const percentMatch = outLine.match(/(\d+)%/)?.[1]
if (bytesMatch) bytes = getFileSize(Number(bytesMatch))
if (etaMatch) eta = etaMatch
if (percentMatch) percent = Number(percentMatch)
}
}

const percent = data.match(/(\d+)%/)
if (percent) {
currentPercent = percent[0]
sendFrontendMessage(`progressUpdate-${gameInfo.app_name}`, {
appName: gameInfo.app_name,
runner: gameInfo.runner,
status: 'moving',
progress: {
percent: currentPercent,
file: currentFile
}
})
}
sendFrontendMessage(`progressUpdate-${gameInfo.app_name}`, {
appName: gameInfo.app_name,
runner: gameInfo.runner,
status: 'moving',
progress: {
percent,
eta,
bytes,
file: currentFile
}
})
}
)
if (code !== 1) {
Expand Down
11 changes: 5 additions & 6 deletions src/frontend/screens/Game/GamePage/components/GameStatus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,12 @@ const GameStatus = ({ gameInfo, progress, handleUpdate, hasUpdate }: Props) => {
}

if (is.moving) {
if (file && percent) {
return `${t(
if (file && percent !== undefined) {
return t(
'status.moving-files',
`Moving file '{{file}}': {{percent}} `,
{ file, percent }
)}
`
`Moving file '{{file}}': {{percent}}%`,
{ file, percent: percent.toFixed(0) }
)
}

return `${t('status.moving', 'Moving Installation, please wait')} ...`
Expand Down

0 comments on commit c62820d

Please sign in to comment.