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

[Feat] Improve the "Move Game" experience a bit #3648

Merged
merged 2 commits into from
Mar 26, 2024
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
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
Loading