Show save/execution error dialogs on desktop #264

This commit introduces system-native error dialogs on desktop
application for code save or execution failures, addressing user confusion
described in issue #264.

This commit adds informative feedback when script execution or saving
fails.

Changes:

- Implement support for system-native error dialogs.
- Refactor `CodeRunner` and `Dialog` interfaces and their
  implementations to improve error handling and provide better type
  safety.
- Introduce structured error handling, allowing UI to display detailed
  error messages.
- Replace error throwing with an error object interface for controlled
  handling. This ensures that errors are propagated to the renderer
  process without being limited by Electron's error object
  serialization limitations as detailed in electron/electron#24427.
- Add logging for dialog actions to aid in troubleshooting.
- Rename `fileName` to `defaultFilename` in `saveFile` functions
  to clarify its purpose.
- Centralize message assertion in `LoggerStub` for consistency.
- Introduce `expectTrue` in tests for clearer boolean assertions.
- Standardize `filename` usage across the codebase.
- Enhance existing test names and organization for clarity.
- Update related documentation.
This commit is contained in:
undergroundwires
2024-01-14 22:35:53 +01:00
parent c546a33eff
commit e09db0f1bd
48 changed files with 1986 additions and 578 deletions

View File

@@ -19,8 +19,8 @@ import { injectKey } from '@/presentation/injectionSymbols';
import ModalDialog from '@/presentation/components/Shared/Modal/ModalDialog.vue';
import { ScriptingLanguage } from '@/domain/ScriptingLanguage';
import { IScriptingDefinition } from '@/domain/IScriptingDefinition';
import { ScriptFileName } from '@/application/CodeRunner/ScriptFileName';
import { FileType } from '@/presentation/common/Dialog';
import { ScriptFilename } from '@/application/CodeRunner/ScriptFilename';
import { Dialog, FileType } from '@/presentation/common/Dialog';
import IconButton from '../IconButton.vue';
import InstructionList from './Instructions/InstructionList.vue';
import { IInstructionListData } from './Instructions/InstructionListData';
@@ -38,25 +38,28 @@ export default defineComponent({
const { dialog } = injectKey((keys) => keys.useDialog);
const areInstructionsVisible = ref(false);
const fileName = computed<string>(() => buildFileName(currentState.value.collection.scripting));
const filename = computed<string>(() => buildFilename(currentState.value.collection.scripting));
const instructions = computed<IInstructionListData | undefined>(() => getInstructions(
currentState.value.collection.os,
fileName.value,
filename.value,
));
async function saveCode() {
await dialog.saveFile(
const { success, error } = await dialog.saveFile(
currentState.value.code.current,
fileName.value,
filename.value,
getType(currentState.value.collection.scripting.language),
);
if (!success) {
showScriptSaveError(dialog, `${error.type}: ${error.message}`);
return;
}
areInstructionsVisible.value = true;
}
return {
isRunningAsDesktopApplication,
instructions,
fileName,
areInstructionsVisible,
saveCode,
};
@@ -74,10 +77,30 @@ function getType(language: ScriptingLanguage) {
}
}
function buildFileName(scripting: IScriptingDefinition) {
function buildFilename(scripting: IScriptingDefinition) {
if (scripting.fileExtension) {
return `${ScriptFileName}.${scripting.fileExtension}`;
return `${ScriptFilename}.${scripting.fileExtension}`;
}
return ScriptFileName;
return ScriptFilename;
}
function showScriptSaveError(dialog: Dialog, technicalDetails: string) {
dialog.showError(
'Error Saving Script',
[
'An error occurred while saving the script.',
'This issue may arise from insufficient permissions, limited disk space, or interference from security software.',
'\n',
'To address this:',
'- Verify your permissions for the selected save directory.',
'- Check available disk space.',
'- Review your antivirus or security settings; adding an exclusion for privacy.sexy might be necessary.',
'- Try saving the script to a different location or modifying your selection.',
'- If the problem persists, reach out to the community for further assistance.',
'\n',
'Technical Details:',
technicalDetails,
].join('\n'),
);
}
</script>