Запрос на сохранение/закрытие перед закрытием окна

  • Я делаю письменное выражение. Пользователи могут открыть приложение, написать текст, сохранить свою работу и т.д.
  • Я пытаюсь сделать так, чтобы при нажатии кнопки window close пользователю предлагалось (а) сохранить свою работу (при необходимости) или (б) просто выйти.
  • Я пытаюсь использовать window.beforeunload для достижения этой цели, но обнаруживаю, что застреваю в цикле, где при попытке "выйти" появляется одно и то же приглашение до бесконечности.

Вот некоторый код:

windowCloseCheck() {
window.onbeforeunload = function(e) {
  e.returnValue = false;
// window.alert('try to close me');    
if(file.isUnsaved() || file.hasChanged()) {
  // prompt - save or just quit?
  file.fileWarning('You have unsaveeed work.', 'Save', 'Quit', function(){
    // OPTION A - save
    file.save();
  }, function() {
    // OPTION B: Quit.
    ipcRenderer.send('quitter')
  })
} 

else {
  // file is saved and no new work has been done:
  ipcRenderer.send('quitter')
}

windowCloseCheck вызывается при настройке приложения, инициируя прослушиватель событий для закрытия окна. Мое условие проверяет, является ли файл несохраненным или изменился с оригинала.

fileWarning - это функция, которая просто оборачивает электронное диалоговое окно, в результате чего появляется всплывающее окно с двумя вариантами и соответствующими функциями для вызова для каждого варианта.

Остальная часть кода доступна, если я (возможно) опускаю необходимую информацию. Был бы рад уточнить, если я не очень ясно.

Ответ 1

Пожалуйста, добавьте следующий блок внутри функции, где вы определили окно браузера (в моем случае функция createWindow() объявлена ​​в main.js)

  // Create the browser window.
  mainWindow = new BrowserWindow({width: 400, height: 400})


  mainWindow.on('close', function(e){
    var choice = require('electron').dialog.showMessageBox(this,
        {
          type: 'question',
          buttons: ['Yes', 'No'],
          title: 'Confirm',
          message: 'Are you sure you want to quit?'
       });
       if(choice == 1){
         e.preventDefault();
       }
    });

Ответ 2

Вы можете добавить локальную переменную, чтобы избежать mainWindow.destroy(), например:

  let showExitPrompt = true;

  // ask renderer process whether should close the app (mainWindow)
  mainWindow.on('close', e => {
    if (showExitPrompt) {
      e.preventDefault(); // Prevents the window from closing
      mainWindow.webContents.send('on-app-closing');
    }
  });

  // renderer allows the app to close
  ipcMain.on('quitter', (e) => {
    showExitPrompt = false;
    mainWindow.close();
  })

Ответ 3

В итоге я использовал window.destroy(), чтобы разбить процесс визуализации на биты (из основного процесса):

ipcMain.on('quitter', (e) => {
  mainWindow.destroy(); // necessary to bypass the repeat-quit-check in the render process.
  app.quit()
})

Не уверен, что это рекомендуется, поскольку, похоже, есть лучшие способы правильно выйти из электронного приложения. Все еще рады получить любую обратную связь, если вы знаете лучший ответ!

/пожав плечами!

Ответ 4

Решение Awijeet просто отлично! Bth, спасибо Awijeet: он спас мне часы!; -)

Кроме того, если вам нужно идти дальше, знайте, что e.preventDefault() распространяется повсюду в коде. После правильного управления preventDefault() вам нужно повернуть переменную e.defaultPrevented = false, чтобы вернуться к естественному поведению вашего приложения.

На самом деле, кажется, что функция e.preventDefault() отключает переменную e.defaultPrevented до true, пока вы не измените ее значение.

Ответ 5

Если пользователь выберет кнопку сохранения, мы должны сохранить данные и закрыть окно, используя window.close(). Но, с этим подходом мы получим бесконечный цикл, который запрашивает сохранение несохраненной работы, потому что window.close() будет снова генерировать событие окна close.

Чтобы решить эту проблему, мы должны объявить новый логический тип var forceQuit, для которого изначально установлено значение false, затем мы установили его на true после сохранения данных или если пользователь решил просто закрыть, не сохраняя данные.

import { app, BrowserWindow, dialog } from 'electron';

let win = null;
let forceQuit = false;

app.on('ready', () => {
    win = new BrowserWindow({
        // Your window options..
    });

    mainWindow.on('close', e => {
        if (!forceQuit) {
            const clickedButtonId = dialog.showMessageBox(mainWindow, {
                type: 'warning',
                buttons: ['Save', 'Cancel', 'Don't save'],
                cancelId: 1,
                title: 'Confirm',
                message: 'You have unsaved work!'
            });
            if (clickedButtonId === 0) {
                e.preventDefault();

                console.log('Saving...');
                /** Here do your data saving logic */

                forceQuit = true;
                win.close();
            } else if (clickedButtonId === 1) {
                e.preventDefault();
            } else if (clickedButtonId === 2) {
                forceQuit = true;
                win.close();
            }
        }
    });
});