Системные диалоги
Системные диалоги — стандартные окна операционной системы: выбор файла, сохранение файла, вопрос с кнопками. Пользователь видит привычное окно своей системы, а программа получает выбранный путь или нажатую кнопку. Диалоги открывает модуль dialog в главном процессе.
Сохранение в файл
Добавим экспорт всех заметок в текстовый файл. В main.js:
// main.js
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
ipcMain.handle('notes:export', async (event, notes) => {
const win = BrowserWindow.fromWebContents(event.sender);
const result = await dialog.showSaveDialog(win, {
title: 'Экспорт заметок',
defaultPath: 'notes.txt',
filters: [{ name: 'Текст', extensions: ['txt'] }],
});
if (result.canceled) {
return false;
}
await fs.writeFile(result.filePath, notes.join('\n\n'), 'utf8');
return true;
});BrowserWindow.fromWebContents(event.sender) находит окно, из которого пришёл запрос, — диалог привязывается к нему. Результат содержит canceled и filePath.
Вызов со страницы
// preload.js
contextBridge.exposeInMainWorld('notes', {
load: () => ipcRenderer.invoke('notes:load'),
save: (notes) => ipcRenderer.invoke('notes:save', notes),
exportText: (notes) => ipcRenderer.invoke('notes:export', notes),
});// renderer.js
document.querySelector('#export').addEventListener('click', () => {
window.notes.exportText(notes);
});Добавьте в index.html кнопку с id="export". По нажатию откроется системное окно сохранения с именем notes.txt.
Открытие файла
// main.js
ipcMain.handle('notes:import', async (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
const result = await dialog.showOpenDialog(win, {
properties: ['openFile'],
filters: [{ name: 'Текст', extensions: ['txt', 'md'] }],
});
if (result.canceled) {
return null;
}
return fs.readFile(result.filePaths[0], 'utf8');
});У диалога открытия результат — массив filePaths: с properties: ['openFile', 'multiSelections'] можно выбрать несколько файлов. Значение 'openDirectory' позволяет выбрать папку.
Вопрос пользователю
Перед удалением заметки спросим подтверждение:
// main.js
ipcMain.handle('notes:confirm-delete', async (event) => {
const win = BrowserWindow.fromWebContents(event.sender);
const result = await dialog.showMessageBox(win, {
type: 'question',
buttons: ['Удалить', 'Отмена'],
defaultId: 1,
cancelId: 1,
message: 'Удалить заметку?',
detail: 'Это действие нельзя отменить.',
});
return result.response === 0;
});response — номер нажатой кнопки в массиве buttons. defaultId выбирает кнопку по Enter, cancelId — кнопку, которая сработает при закрытии окна или нажатии Esc.
Методы dialog
| Метод | Что возвращает |
|---|---|
showOpenDialog | canceled, filePaths |
showSaveDialog | canceled, filePath |
showMessageBox | response — номер кнопки |
showErrorBox | Ничего, просто показывает ошибку |
Частая ошибка
Если не проверить canceled, то при нажатии «Отмена» программа попытается записать файл по пустому пути и упадёт с ошибкой. После каждого диалога файла сначала проверяйте result.canceled и только потом используйте путь.