1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-06-24 23:26:50 +02:00

Desktop: Allow updating a plugin

This commit is contained in:
Laurent Cozic
2021-01-19 22:58:09 +00:00
parent 63e30f6ccb
commit f37d37e613
25 changed files with 447 additions and 69 deletions

View File

@ -8,6 +8,7 @@ import { filename, dirname, rtrimSlashes } from '../../path-utils';
import Setting from '../../models/Setting';
import Logger from '../../Logger';
import RepositoryApi from './RepositoryApi';
import produce from 'immer';
const compareVersions = require('compare-versions');
const uslug = require('uslug');
const md5File = require('md5-file/promise');
@ -31,12 +32,19 @@ export interface Plugins {
export interface PluginSetting {
enabled: boolean;
deleted: boolean;
// After a plugin has been updated, the user needs to restart the app before
// loading the new version. In the meantime, we set this property to `true`
// so that we know the plugin has been updated. It is used for example to
// disable the Update button.
hasBeenUpdated: boolean;
}
export function defaultPluginSetting(): PluginSetting {
return {
enabled: true,
deleted: false,
hasBeenUpdated: false,
};
}
@ -92,6 +100,10 @@ export default class PluginService extends BaseService {
delete this.plugins_[pluginId];
}
private async deletePluginFiles(plugin: Plugin) {
await shim.fsDriver().remove(plugin.baseDir);
}
public pluginById(id: string): Plugin {
if (!this.plugins_[id]) throw new Error(`Plugin not found: ${id}`);
@ -173,7 +185,7 @@ export default class PluginService extends BaseService {
const fname = filename(path);
const hash = await md5File(path);
const unpackDir = `${Setting.value('tempDir')}/${fname}`;
const unpackDir = `${Setting.value('cacheDir')}/${fname}`;
const manifestFilePath = `${unpackDir}/manifest.json`;
let manifest: any = await this.loadManifestToObject(manifestFilePath);
@ -194,7 +206,7 @@ export default class PluginService extends BaseService {
manifest._package_hash = hash;
await shim.fsDriver().writeFile(manifestFilePath, JSON.stringify(manifest), 'utf8');
await shim.fsDriver().writeFile(manifestFilePath, JSON.stringify(manifest, null, '\t'), 'utf8');
}
return this.loadPluginFromPath(unpackDir);
@ -345,6 +357,10 @@ export default class PluginService extends BaseService {
return plugin;
}
public async updatePluginFromRepo(repoApi: RepositoryApi, pluginId: string): Promise<Plugin> {
return this.installPluginFromRepo(repoApi, pluginId);
}
public async installPlugin(jplPath: string): Promise<Plugin> {
logger.info(`Installing plugin: "${jplPath}"`);
@ -352,6 +368,7 @@ export default class PluginService extends BaseService {
// from where it is now to check that it is valid and to retrieve
// the plugin ID.
const preloadedPlugin = await this.loadPluginFromPath(jplPath);
await this.deletePluginFiles(preloadedPlugin);
const destPath = `${Setting.value('pluginDir')}/${preloadedPlugin.id}.jpl`;
await shim.fsDriver().copy(jplPath, destPath);
@ -402,6 +419,16 @@ export default class PluginService extends BaseService {
return newSettings;
}
// On startup the "hasBeenUpdated" prop can be cleared since the new version
// of the plugin has now been loaded.
public clearUpdateState(settings: PluginSettings): PluginSettings {
return produce(settings, (draft: PluginSettings) => {
for (const pluginId in draft) {
if (draft[pluginId].hasBeenUpdated) draft[pluginId].hasBeenUpdated = false;
}
});
}
public async destroy() {
await this.runner_.waitForSandboxCalls();
}