LiveSplit / LiveSplit/LiveSplitOne
Issues with multiple dialog boxes using showDialog
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 301
- Forks
- 55
- Avg merge
- 8m
- Merged PRs (30d)
- 1
Description
I was doing some work with importing comparisons other than the Personal Best comparison (LiveSplit/livesplit-core#889) and came across an issue when attempting to display multiple dialog boxes with `showDialog` right after each other.
In `src/ui/views/RunEditor.tsx`, I attempted to add another dialog box to the `importComparison` function like so:
```ts
const [dialogResult, runComparisonName] = await showDialog({
title: "Import Comparison",
description: "Specify the name of the comparison you want to import:",
textInput: true,
buttons: ["Ok", "Cancel"],
defaultText: file.name.replace(/\.[^/.]+$/, ""),
});
if (dialogResult !== 0) {
return;
}
const [dialogResult2, comparisonName] = await showDialog({
title: "Import Comparison",
description: "Specify the name the comparison should be saved as:",
textInput: true,
buttons: ["Import", "Cancel"],
defaultText: file.name.replace(/\.[^/.]+$/, ""),
});
if (dialogResult2 !== 0) {
return;
}
```
After doing this, I noticed that—while both dialog boxes would appear one after the other as expected—the second dialog box would handle its result before it was closed. That is, `dialogResult2` would have the value `true` and hit the `if (dialogResult2 !== 0) {` line as soon as the first dialog box was completed.
Out of curiosity about it being a possible race condition, I added `setTimeout` around the second dialog box (and all subsequent code) and found that it would work perfectly fine as expected. See the code below:
```ts
const [dialogResult, runComparisonName] = await showDialog({
title: "Import Comparison",
description: "Specify the name of the comparison you want to import:",
textInput: true,
buttons: ["Ok", "Cancel"],
defaultText: file.name.replace(/\.[^/.]+$/, ""),
});
if (dialogResult !== 0) {
return;
}
setTimeout(async () => {
const [dialogResult2, comparisonName] = await showDialog({
title: "Import Comparison",
description: "Specify the name the comparison should be saved as:",
textInput: true,
buttons: ["Import", "Cancel"],
defaultText: file.name.replace(/\.[^/.]+$/, ""),
});
console.log(dialogResult2);
if (dialogResult2 !== 0) {
return;
}
const valid = editor.importComparisonAsComparison(run, comparisonName, runComparisonName);
if (!valid) {
toast.error(
"The comparison could not be added. It may be a duplicate or a reserved name.",
);
} else {
update();
}
}, 0)
```
I couldn't make anything of the `showDialog` function when trying to identify the issue, so unfortunately could not continue without adding `setTimeout`, which should not be the fix I go with for what I'm trying to do.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/ui/views/RunEditor.tsx at importComparison and trace the showDialog entry point used by the two sequential calls. Reproduce the flow with the two dialogs, then inspect how each dialog resolves and closes. Done means the second dialog reports its own result only after it is closed, without requiring setTimeout, while the import flow still completes correctly.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- frontend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100