Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Системные диалоги

Системные диалоги — стандартные окна операционной системы: выбор файла, сохранение файла, вопрос с кнопками. Пользователь видит привычное окно своей системы, а программа получает выбранный путь или нажатую кнопку. Диалоги открывает модуль 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

МетодЧто возвращает
showOpenDialogcanceled, filePaths
showSaveDialogcanceled, filePath
showMessageBoxresponse — номер кнопки
showErrorBoxНичего, просто показывает ошибку

Частая ошибка

Если не проверить canceled, то при нажатии «Отмена» программа попытается записать файл по пустому пути и упадёт с ошибкой. После каждого диалога файла сначала проверяйте result.canceled и только потом используйте путь.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.