2
0
mirror of https://github.com/frappe/books.git synced 2024-11-14 01:14:03 +00:00

Merge pull request #331 from 18alantom/auto-updation

feat: notification based updation
This commit is contained in:
Alan 2022-02-03 15:37:43 +05:30 committed by GitHub
commit da9c677fc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 164 additions and 58 deletions

View File

@ -88,15 +88,6 @@ module.exports = {
'Hides the Get Started section from the sidebar. Change will be visible on restart or refreshing the app.' 'Hides the Get Started section from the sidebar. Change will be visible on restart or refreshing the app.'
), ),
}, },
{
fieldname: 'autoUpdate',
label: 'Auto Update',
fieldtype: 'Check',
default: 1,
description: t(
'Automatically checks for updates and download them if available. The update will be applied after you restart the app.'
),
},
{ {
fieldname: 'autoReportErrors', fieldname: 'autoReportErrors',
label: 'Hide & Auto Report Errors', label: 'Hide & Auto Report Errors',
@ -112,7 +103,6 @@ module.exports = {
'locale', 'locale',
'displayPrecision', 'displayPrecision',
'hideGetStarted', 'hideGetStarted',
'autoUpdate',
'autoReportErrors', 'autoReportErrors',
], ],
}; };

View File

@ -39,7 +39,7 @@ import {
postSetup, postSetup,
purgeCache, purgeCache,
} from '@/initialization'; } from '@/initialization';
import { routeTo } from './utils'; import { checkForUpdates, routeTo } from './utils';
import fs from 'fs/promises'; import fs from 'fs/promises';
import { showErrorDialog } from './errorHandling'; import { showErrorDialog } from './errorHandling';
@ -106,7 +106,7 @@ export default {
this.activeScreen = 'SetupWizard'; this.activeScreen = 'SetupWizard';
} else { } else {
this.activeScreen = 'Desk'; this.activeScreen = 'Desk';
this.checkForUpdates(); checkForUpdates(false);
} }
if (!resetRoute) { if (!resetRoute) {
@ -122,9 +122,6 @@ export default {
routeTo('/get-started'); routeTo('/get-started');
} }
}, },
checkForUpdates() {
frappe.events.trigger('check-for-updates');
},
changeDbFile() { changeDbFile() {
config.set('lastSelectedFilePath', null); config.set('lastSelectedFilePath', null);
purgeCache(true); purgeCache(true);

View File

@ -16,7 +16,7 @@ import fs from 'fs/promises';
import path from 'path'; import path from 'path';
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'; import { createProtocol } from 'vue-cli-plugin-electron-builder/lib';
import { sendError } from './contactMothership'; import { sendError } from './contactMothership';
import { IPC_ACTIONS, IPC_MESSAGES } from './messages'; import { IPC_ACTIONS, IPC_CHANNELS, IPC_MESSAGES } from './messages';
import saveHtmlAsPdf from './saveHtmlAsPdf'; import saveHtmlAsPdf from './saveHtmlAsPdf';
const isDevelopment = process.env.NODE_ENV !== 'production'; const isDevelopment = process.env.NODE_ENV !== 'production';
@ -37,6 +37,10 @@ protocol.registerSchemesAsPrivileged([
{ scheme: 'app', privileges: { secure: true, standard: true } }, { scheme: 'app', privileges: { secure: true, standard: true } },
]); ]);
if (isDevelopment) {
autoUpdater.logger = console;
}
Store.initRenderer(); Store.initRenderer();
/* ----------------------------- /* -----------------------------
@ -104,7 +108,7 @@ function createWindow() {
}); });
mainWindow.webContents.on('did-finish-load', () => { mainWindow.webContents.on('did-finish-load', () => {
mainWindow.webContents.send('store-on-window', { mainWindow.webContents.send(IPC_CHANNELS.STORE_ON_WINDOW, {
appVersion: app.getVersion(), appVersion: app.getVersion(),
}); });
}); });
@ -114,13 +118,6 @@ function createWindow() {
* Register ipcMain message handlers * Register ipcMain message handlers
* ---------------------------------*/ * ---------------------------------*/
ipcMain.on(IPC_MESSAGES.CHECK_FOR_UPDATES, () => {
if (!isDevelopment && !checkedForUpdate) {
autoUpdater.checkForUpdatesAndNotify();
checkedForUpdate = true;
}
});
ipcMain.on(IPC_MESSAGES.OPEN_MENU, (event) => { ipcMain.on(IPC_MESSAGES.OPEN_MENU, (event) => {
const window = event.sender.getOwnerBrowserWindow(); const window = event.sender.getOwnerBrowserWindow();
const menu = Menu.getApplicationMenu(); const menu = Menu.getApplicationMenu();
@ -154,6 +151,14 @@ ipcMain.on(IPC_MESSAGES.SHOW_ITEM_IN_FOLDER, (event, filePath) => {
return shell.showItemInFolder(filePath); return shell.showItemInFolder(filePath);
}); });
ipcMain.on(IPC_MESSAGES.DOWNLOAD_UPDATE, (event) => {
autoUpdater.downloadUpdate();
});
ipcMain.on(IPC_MESSAGES.INSTALL_UPDATE, (event) => {
autoUpdater.quitAndInstall(true, true);
});
/* ---------------------------------- /* ----------------------------------
* Register ipcMain function handlers * Register ipcMain function handlers
* ----------------------------------*/ * ----------------------------------*/
@ -207,6 +212,45 @@ ipcMain.handle(IPC_ACTIONS.SEND_ERROR, (event, bodyJson) => {
sendError(bodyJson); sendError(bodyJson);
}); });
ipcMain.handle(IPC_ACTIONS.CHECK_FOR_UPDATES, (event, force) => {
if (!isDevelopment && !checkedForUpdate) {
autoUpdater.checkForUpdates();
checkedForUpdate = true;
} else if (force) {
autoUpdater.checkForUpdates();
}
});
/* ------------------------------
* Register autoUpdater events lis
* ------------------------------*/
autoUpdater.autoDownload = false;
autoUpdater.autoInstallOnAppQuit = false;
autoUpdater.on('checking-for-update', () => {
if (!checkedForUpdate) {
return;
}
mainWindow.webContents.send(IPC_CHANNELS.CHECKING_FOR_UPDATE);
});
autoUpdater.on('update-available', (info) => {
mainWindow.webContents.send(IPC_CHANNELS.UPDATE_AVAILABLE, info.version);
});
autoUpdater.on('update-not-available', () => {
mainWindow.webContents.send(IPC_CHANNELS.UPDATE_NOT_AVAILABLE);
});
autoUpdater.on('update-downloaded', () => {
mainWindow.webContents.send(IPC_CHANNELS.UPDATE_DOWNLOADED);
});
autoUpdater.on('error', (error) => {
mainWindow.webContents.send(IPC_CHANNELS.UPDATE_ERROR, error);
});
/* ------------------------------ /* ------------------------------
* Register app lifecycle methods * Register app lifecycle methods
* ------------------------------*/ * ------------------------------*/

View File

@ -11,7 +11,7 @@
mb-3 mb-3
w-80 w-80
" "
:class="bgColor + (action ? ' cursor-pointer' : '')" :class="bgColor + (actionText ? ' cursor-pointer' : '')"
style="transition: opacity 150ms ease-in" style="transition: opacity 150ms ease-in"
:style="{ opacity }" :style="{ opacity }"
@click="action" @click="action"
@ -37,9 +37,9 @@ export default {
return { opacity: 0, show: true }; return { opacity: 0, show: true };
}, },
props: { props: {
message: String, message: { type: String, required: true },
action: Function, action: { type: Function, default: () => {} },
actionText: String, actionText: { type: String, default: '' },
type: { type: String, default: 'info' }, type: { type: String, default: 'info' },
duration: { type: Number, default: 5000 }, duration: { type: Number, default: 5000 },
}, },

View File

@ -58,6 +58,16 @@ function getToastProps(errorLogObj: ErrorLog, cb?: Function) {
return props; return props;
} }
export function getErrorLogObject(error: Error, more: object = {}): ErrorLog {
const { name, stack, message } = error;
const errorLogObj = { name, stack, message, more };
// @ts-ignore
frappe.errorLog.push(errorLogObj);
return errorLogObj;
}
export function handleError( export function handleError(
shouldLog: boolean, shouldLog: boolean,
error: Error, error: Error,
@ -72,11 +82,7 @@ export function handleError(
return; return;
} }
const { name, stack, message } = error; const errorLogObj = getErrorLogObject(error, more);
const errorLogObj: ErrorLog = { name, stack, message, more };
// @ts-ignore
frappe.errorLog.push(errorLogObj);
// @ts-ignore // @ts-ignore
if (frappe.SystemSettings?.autoReportErrors) { if (frappe.SystemSettings?.autoReportErrors) {

View File

@ -5,10 +5,10 @@ import models from '../models';
import App from './App'; import App from './App';
import FeatherIcon from './components/FeatherIcon'; import FeatherIcon from './components/FeatherIcon';
import { getErrorHandled, handleError } from './errorHandling'; import { getErrorHandled, handleError } from './errorHandling';
import { IPC_MESSAGES } from './messages'; import { IPC_CHANNELS, IPC_MESSAGES } from './messages';
import router from './router'; import router from './router';
import { outsideClickDirective } from './ui'; import { outsideClickDirective } from './ui';
import { stringifyCircular } from './utils'; import { showToast, stringifyCircular } from './utils';
(async () => { (async () => {
frappe.isServer = true; frappe.isServer = true;
@ -23,19 +23,10 @@ import { stringifyCircular } from './utils';
ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW); ipcRenderer.send(IPC_MESSAGES.RELOAD_MAIN_WINDOW);
}); });
frappe.events.on('check-for-updates', () => {
let { autoUpdate } = frappe.SystemSettings;
if (autoUpdate == null || autoUpdate === 1) {
ipcRenderer.send(IPC_MESSAGES.CHECK_FOR_UPDATES);
}
});
window.frappe = frappe; window.frappe = frappe;
window.frappe.store = {}; window.frappe.store = {};
ipcRenderer.on('store-on-window', (event, message) => { registerIpcRendererListeners();
Object.assign(window.frappe.store, message);
});
Vue.config.productionTip = false; Vue.config.productionTip = false;
Vue.component('feather-icon', FeatherIcon); Vue.component('feather-icon', FeatherIcon);
@ -60,17 +51,19 @@ import { stringifyCircular } from './utils';
}); });
Vue.config.errorHandler = (err, vm, info) => { Vue.config.errorHandler = (err, vm, info) => {
const { fullPath, params } = vm.$route; const more = {
const data = stringifyCircular(vm.$data, true, true);
const props = stringifyCircular(vm.$props, true, true);
handleError(false, err, {
fullPath,
params: stringifyCircular(params),
data,
props,
info, info,
}); };
if (vm) {
const { fullPath, params } = vm.$route;
more.fullPath = fullPath;
more.params = stringifyCircular(params ?? {});
more.data = stringifyCircular(vm.$data ?? {}, true, true);
more.props = stringifyCircular(vm.$props ?? {}, true, true);
}
handleError(false, err, more);
console.error(err, vm, info); console.error(err, vm, info);
}; };
@ -97,3 +90,52 @@ import { stringifyCircular } from './utils';
template: '<App/>', template: '<App/>',
}); });
})(); })();
function registerIpcRendererListeners() {
ipcRenderer.on(IPC_CHANNELS.STORE_ON_WINDOW, (event, message) => {
Object.assign(window.frappe.store, message);
});
ipcRenderer.on(IPC_CHANNELS.CHECKING_FOR_UPDATE, (_) => {
showToast({ message: frappe.t`Checking for updates` });
});
ipcRenderer.on(IPC_CHANNELS.UPDATE_AVAILABLE, (_, version) => {
const message = version
? frappe.t`Version ${version} available`
: frappe.t`New version available`;
const action = () => {
ipcRenderer.send(IPC_MESSAGES.DOWNLOAD_UPDATE);
};
showToast({
message,
action,
actionText: frappe.t`Download Update`,
duration: 10_000,
type: 'success',
});
});
ipcRenderer.on(IPC_CHANNELS.UPDATE_NOT_AVAILABLE, (_) => {
showToast({ message: frappe.t`No updates available` });
});
ipcRenderer.on(IPC_CHANNELS.UPDATE_DOWNLOADED, (_) => {
const action = () => {
ipcRenderer.send(IPC_MESSAGES.INSTALL_UPDATE);
};
showToast({
message: frappe.t`Update downloaded`,
action,
actionText: frappe.t`Install Update`,
duration: 10_000,
type: 'success',
});
});
ipcRenderer.on(IPC_CHANNELS.UPDATE_ERROR, (_, error) => {
error.name = 'Updation Error';
handleError(true, error);
});
}

View File

@ -1,15 +1,18 @@
// ipcRenderer.send(...)
export const IPC_MESSAGES = { export const IPC_MESSAGES = {
OPEN_MENU: 'open-menu', OPEN_MENU: 'open-menu',
OPEN_SETTINGS: 'open-settings', OPEN_SETTINGS: 'open-settings',
OPEN_EXTERNAL: 'open-external', OPEN_EXTERNAL: 'open-external',
SHOW_ITEM_IN_FOLDER: 'show-item-in-folder', SHOW_ITEM_IN_FOLDER: 'show-item-in-folder',
CHECK_FOR_UPDATES: 'check-for-updates',
RELOAD_MAIN_WINDOW: 'reload-main-window', RELOAD_MAIN_WINDOW: 'reload-main-window',
RESIZE_MAIN_WINDOW: 'resize-main-window', RESIZE_MAIN_WINDOW: 'resize-main-window',
CLOSE_CURRENT_WINDOW: 'close-current-window', CLOSE_CURRENT_WINDOW: 'close-current-window',
MINIMIZE_CURRENT_WINDOW: 'minimize-current-window', MINIMIZE_CURRENT_WINDOW: 'minimize-current-window',
DOWNLOAD_UPDATE: 'download-update',
INSTALL_UPDATE: 'install-update',
}; };
// ipcRenderer.invoke(...)
export const IPC_ACTIONS = { export const IPC_ACTIONS = {
TOGGLE_MAXIMIZE_CURRENT_WINDOW: 'toggle-maximize-current-window', TOGGLE_MAXIMIZE_CURRENT_WINDOW: 'toggle-maximize-current-window',
GET_OPEN_FILEPATH: 'open-dialog', GET_OPEN_FILEPATH: 'open-dialog',
@ -20,6 +23,17 @@ export const IPC_ACTIONS = {
SAVE_DATA: 'save-data', SAVE_DATA: 'save-data',
SHOW_ERROR: 'show-error', SHOW_ERROR: 'show-error',
SEND_ERROR: 'send-error', SEND_ERROR: 'send-error',
CHECK_FOR_UPDATES: 'check-for-updates',
};
// ipcMain.send(...)
export const IPC_CHANNELS = {
STORE_ON_WINDOW: 'store-on-window',
CHECKING_FOR_UPDATE: 'checking-for-update',
UPDATE_AVAILABLE: 'update-available',
UPDATE_NOT_AVAILABLE: 'update-not-available',
UPDATE_DOWNLOADED: 'update-downloaded',
UPDATE_ERROR: 'update-error',
}; };
export const DB_CONN_FAILURE = { export const DB_CONN_FAILURE = {

View File

@ -8,12 +8,21 @@
:emit-change="true" :emit-change="true"
@change="forwardChangeEvent" @change="forwardChangeEvent"
/> />
<div class="flex flex-row justify-end my-4">
<button
class="text-gray-900 text-sm hover:bg-gray-100 rounded-md px-4 py-1.5"
@click="checkForUpdates(true)"
>
Check for Updates
</button>
</div>
</div> </div>
</template> </template>
<script> <script>
import frappe from 'frappe'; import frappe from 'frappe';
import TwoColumnForm from '@/components/TwoColumnForm'; import TwoColumnForm from '@/components/TwoColumnForm';
import { checkForUpdates } from '@/utils';
export default { export default {
name: 'TabSystem', name: 'TabSystem',
@ -36,6 +45,7 @@ export default {
}, },
}, },
methods: { methods: {
checkForUpdates,
forwardChangeEvent(...args) { forwardChangeEvent(...args) {
this.$emit('change', ...args); this.$emit('change', ...args);
}, },

View File

@ -2,8 +2,7 @@ import Avatar from '@/components/Avatar';
import Toast from '@/components/Toast'; import Toast from '@/components/Toast';
import router from '@/router'; import router from '@/router';
import { ipcRenderer } from 'electron'; import { ipcRenderer } from 'electron';
import frappe from 'frappe'; import frappe, { t } from 'frappe';
import { t } from 'frappe';
import { isPesa } from 'frappe/utils'; import { isPesa } from 'frappe/utils';
import lodash from 'lodash'; import lodash from 'lodash';
import Vue from 'vue'; import Vue from 'vue';
@ -414,3 +413,7 @@ export function stringifyCircular(
return value; return value;
}); });
} }
export function checkForUpdates(force = false) {
ipcRenderer.invoke(IPC_ACTIONS.CHECK_FOR_UPDATES, force);
}