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 1 commit
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
124 changes: 70 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,63 @@ 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'
// Rsync outputs either the file currently being transferred or a
CommandMC marked this conversation as resolved.
Show resolved Hide resolved
// progress report. To know which one of those `data` 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 =
!data.includes('%') && !data.includes(':') && !data.startsWith(' ')

if (isFilenameOutput) {
// If we have a filename output, we've started copying a new
// file (we thus start at 0%, with 0 bytes moved, and with no ETA)

// Data will be a multiline string, potentially with directory names,
// finally the file name, and ending with an empty line
currentFile = data.trim().split('\n').at(-1)!
} else {
// If we got the progress update, try to read out the bytes, ETA and
// percent
const bytesMatch = data.match(/^\s*(\d+)/)?.[1]
CommandMC marked this conversation as resolved.
Show resolved Hide resolved
const etaMatch = data.match(/(\d+:\d+:\d+)/)?.[1]
CommandMC marked this conversation as resolved.
Show resolved Hide resolved
const percentMatch = data.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