mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-24 10:27:10 +02:00
Clipper: Added Clipper config screen and improved server
This commit is contained in:
parent
d11ecd8fac
commit
e15f84716a
@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Joplin Web Clipper",
|
||||
"version": "1.0",
|
||||
"version": "1.0.1",
|
||||
|
||||
"description": "Gets and saves content from your browser to Joplin.",
|
||||
|
||||
|
32
Clipper/joplin-webclipper/package-lock.json
generated
32
Clipper/joplin-webclipper/package-lock.json
generated
@ -4,10 +4,42 @@
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"fs-extra": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-6.0.1.tgz",
|
||||
"integrity": "sha512-GnyIkKhhzXZUWFCaJzvyDLEEgDkPfb4/TPvJCJVuS8MWZgoSsErf++QpiAlDnKFcqhRlm+tIOcencCjyJE6ZCA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
|
||||
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=",
|
||||
"dev": true
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"readability-node": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/readability-node/-/readability-node-0.1.0.tgz",
|
||||
"integrity": "sha1-DUBacMLCFZRKf0qbX3UGzQWpsao="
|
||||
},
|
||||
"universalify": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz",
|
||||
"integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,5 +10,8 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"readability-node": "^0.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"fs-extra": "^6.0.1"
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import React, { Component } from 'react';
|
||||
import './App.css';
|
||||
|
||||
const { connect } = require('react-redux');
|
||||
const Global = require('./Global');
|
||||
const { bridge } = require('./bridge');
|
||||
|
||||
class AppComponent extends Component {
|
||||
|
@ -3,7 +3,7 @@ import ReactDOM from 'react-dom';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
|
||||
const { connect, Provider } = require('react-redux');
|
||||
const { Provider } = require('react-redux');
|
||||
const { bridge } = require('./bridge');
|
||||
const { createStore } = require('redux');
|
||||
|
||||
|
@ -34,9 +34,6 @@ const reservedPorts = [1024, 1027, 1028, 1029, 1058, 1059, 1080, 1085, 1098, 109
|
||||
|
||||
// From https://github.com/coverslide/node-alea
|
||||
const AleaModule = function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
// importState to sync generator states
|
||||
Alea.importState = function(i){
|
||||
var random = new Alea();
|
||||
@ -54,8 +51,8 @@ const AleaModule = function () {
|
||||
var s2 = 0;
|
||||
var c = 1;
|
||||
|
||||
if (args.length == 0) {
|
||||
args = [+new Date];
|
||||
if (args.length === 0) {
|
||||
args = [+new Date()];
|
||||
}
|
||||
var mash = Mash();
|
||||
s0 = mash(' ');
|
||||
|
@ -23,6 +23,7 @@ const DecryptionWorker = require('lib/services/DecryptionWorker');
|
||||
const InteropService = require('lib/services/InteropService');
|
||||
const InteropServiceHelper = require('./InteropServiceHelper.js');
|
||||
const ResourceService = require('lib/services/ResourceService');
|
||||
const ClipperServer = require('lib/ClipperServer');
|
||||
|
||||
const { bridge } = require('electron').remote.require('./bridge');
|
||||
const Menu = bridge().Menu;
|
||||
@ -459,6 +460,14 @@ class Application extends BaseApplication {
|
||||
}, {
|
||||
type: 'separator',
|
||||
screens: ['Main'],
|
||||
},{
|
||||
label: _('Web clipper options'),
|
||||
click: () => {
|
||||
this.dispatch({
|
||||
type: 'NAV_GO',
|
||||
routeName: 'ClipperConfig',
|
||||
});
|
||||
}
|
||||
},{
|
||||
label: _('Encryption options'),
|
||||
click: () => {
|
||||
@ -662,6 +671,17 @@ class Application extends BaseApplication {
|
||||
DecryptionWorker.instance().scheduleStart();
|
||||
});
|
||||
}
|
||||
|
||||
const clipperLogger = new Logger();
|
||||
clipperLogger.addTarget('file', { path: Setting.value('profileDir') + '/log-clipper.txt' });
|
||||
clipperLogger.addTarget('console');
|
||||
|
||||
ClipperServer.instance().setLogger(clipperLogger);
|
||||
ClipperServer.instance().setDispatch(this.store().dispatch);
|
||||
|
||||
if (Setting.value('clipperServer.autoStart')) {
|
||||
ClipperServer.instance().start();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
106
ElectronClient/app/gui/ClipperConfigScreen.jsx
Normal file
106
ElectronClient/app/gui/ClipperConfigScreen.jsx
Normal file
File diff suppressed because one or more lines are too long
@ -13,6 +13,7 @@ const { StatusScreen } = require('./StatusScreen.min.js');
|
||||
const { ImportScreen } = require('./ImportScreen.min.js');
|
||||
const { ConfigScreen } = require('./ConfigScreen.min.js');
|
||||
const { EncryptionConfigScreen } = require('./EncryptionConfigScreen.min.js');
|
||||
const { ClipperConfigScreen } = require('./ClipperConfigScreen.min.js');
|
||||
const { Navigator } = require('./Navigator.min.js');
|
||||
|
||||
const { app } = require('../app');
|
||||
@ -86,6 +87,7 @@ class RootComponent extends React.Component {
|
||||
Config: { screen: ConfigScreen, title: () => _('Options') },
|
||||
Status: { screen: StatusScreen, title: () => _('Synchronisation Status') },
|
||||
EncryptionConfig: { screen: EncryptionConfigScreen, title: () => _('Encryption Options') },
|
||||
ClipperConfig: { screen: ClipperConfigScreen, title: () => _('Clipper Options') },
|
||||
};
|
||||
|
||||
return (
|
||||
|
5
ElectronClient/app/package-lock.json
generated
5
ElectronClient/app/package-lock.json
generated
@ -5452,6 +5452,11 @@
|
||||
"semver": "5.4.1"
|
||||
}
|
||||
},
|
||||
"server-destroy": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/server-destroy/-/server-destroy-1.0.1.tgz",
|
||||
"integrity": "sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0="
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
|
@ -114,6 +114,7 @@
|
||||
"read-chunk": "^2.1.0",
|
||||
"readability-node": "^0.1.0",
|
||||
"redux": "^3.7.2",
|
||||
"server-destroy": "^1.0.1",
|
||||
"smalltalk": "^2.5.1",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"sqlite3": "^3.1.13",
|
||||
|
@ -34,7 +34,6 @@ const SyncTargetDropbox = require('lib/SyncTargetDropbox.js');
|
||||
const EncryptionService = require('lib/services/EncryptionService');
|
||||
const DecryptionWorker = require('lib/services/DecryptionWorker');
|
||||
const BaseService = require('lib/services/BaseService');
|
||||
const ClipperServer = require('lib/ClipperServer');
|
||||
|
||||
SyncTargetRegistry.addClass(SyncTargetFilesystem);
|
||||
SyncTargetRegistry.addClass(SyncTargetOneDrive);
|
||||
@ -493,13 +492,6 @@ class BaseApplication {
|
||||
|
||||
// await this.testing();process.exit();
|
||||
|
||||
const clipperLogger = new Logger();
|
||||
clipperLogger.addTarget('file', { path: profileDir + '/log-clipper.txt' });
|
||||
clipperLogger.addTarget('console');
|
||||
this.clipperServer_ = new ClipperServer();
|
||||
this.clipperServer_.setLogger(clipperLogger);
|
||||
this.clipperServer_.start();
|
||||
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
@ -12,11 +12,21 @@ const { Logger } = require('lib/logger.js');
|
||||
const markdownUtils = require('lib/markdownUtils');
|
||||
const mimeUtils = require('lib/mime-utils.js').mime;
|
||||
const randomClipperPort = require('lib/randomClipperPort');
|
||||
const enableServerDestroy = require('server-destroy');
|
||||
|
||||
class ClipperServer {
|
||||
|
||||
constructor() {
|
||||
this.logger_ = new Logger();
|
||||
this.startState_ = 'idle';
|
||||
this.server_ = null;
|
||||
this.port_ = null;
|
||||
}
|
||||
|
||||
static instance() {
|
||||
if (this.instance_) return this.instance_;
|
||||
this.instance_ = new ClipperServer();
|
||||
return this.instance_;
|
||||
}
|
||||
|
||||
setLogger(l) {
|
||||
@ -27,6 +37,41 @@ class ClipperServer {
|
||||
return this.logger_;
|
||||
}
|
||||
|
||||
setDispatch(d) {
|
||||
this.dispatch_ = d;
|
||||
}
|
||||
|
||||
dispatch(action) {
|
||||
if (!this.dispatch_) throw new Error('dispatch not set!');
|
||||
this.dispatch_(action);
|
||||
}
|
||||
|
||||
setStartState(v) {
|
||||
if (this.startState_ === v) return;
|
||||
this.startState_ = v;
|
||||
this.dispatch({
|
||||
type: 'CLIPPER_SERVER_SET',
|
||||
startState: v,
|
||||
});
|
||||
}
|
||||
|
||||
setPort(v) {
|
||||
if (this.port_ === v) return;
|
||||
this.port_ = v;
|
||||
this.dispatch({
|
||||
type: 'CLIPPER_SERVER_SET',
|
||||
port: v,
|
||||
});
|
||||
}
|
||||
|
||||
// startState() {
|
||||
// return this.startState_;
|
||||
// }
|
||||
|
||||
// port() {
|
||||
// return this.port_;
|
||||
// }
|
||||
|
||||
htmlToMdParser() {
|
||||
if (this.htmlToMdParser_) return this.htmlToMdParser_;
|
||||
this.htmlToMdParser_ = new HtmlToMd();
|
||||
@ -167,18 +212,22 @@ class ClipperServer {
|
||||
}
|
||||
|
||||
async start() {
|
||||
let port = null;
|
||||
this.setPort(null);
|
||||
|
||||
this.setStartState('starting');
|
||||
|
||||
try {
|
||||
port = await this.findAvailablePort();
|
||||
const p = await this.findAvailablePort();
|
||||
this.setPort(p);
|
||||
} catch (error) {
|
||||
this.setStartState('idle');
|
||||
this.logger().error(error);
|
||||
return;
|
||||
}
|
||||
|
||||
const server = require('http').createServer();
|
||||
this.server_ = require('http').createServer();
|
||||
|
||||
server.on('request', (request, response) => {
|
||||
this.server_.on('request', (request, response) => {
|
||||
|
||||
const writeCorsHeaders = (code) => {
|
||||
response.writeHead(code, {
|
||||
@ -253,13 +302,24 @@ class ClipperServer {
|
||||
}
|
||||
});
|
||||
|
||||
server.on('close', () => {
|
||||
this.server_.on('close', () => {
|
||||
|
||||
});
|
||||
|
||||
this.logger().info('Starting Clipper server on port ' + port);
|
||||
enableServerDestroy(this.server_);
|
||||
|
||||
server.listen(port);
|
||||
this.logger().info('Starting Clipper server on port ' + this.port_);
|
||||
|
||||
this.server_.listen(this.port_);
|
||||
|
||||
this.setStartState('started');
|
||||
}
|
||||
|
||||
async stop() {
|
||||
this.server_.destroy();
|
||||
this.server_ = null;
|
||||
this.setStartState('idle');
|
||||
this.setPort(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -102,6 +102,7 @@ class Setting extends BaseModel {
|
||||
'style.zoom': {value: "100", type: Setting.TYPE_INT, public: true, appTypes: ['desktop'], label: () => _('Global zoom percentage'), minimum: "50", maximum: "500", step: "10"},
|
||||
'style.editor.fontFamily': {value: "", type: Setting.TYPE_STRING, public: true, appTypes: ['desktop'], label: () => _('Editor font family'), description: () => _('The font name will not be checked. If incorrect or empty, it will default to a generic monospace font.')},
|
||||
'autoUpdateEnabled': { value: true, type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Automatically update the application') },
|
||||
'clipperServer.autoStart': { value: false, type: Setting.TYPE_BOOL, public: false },
|
||||
'sync.interval': { value: 300, type: Setting.TYPE_INT, isEnum: true, public: true, label: () => _('Synchronisation interval'), options: () => {
|
||||
return {
|
||||
0: _('Disabled'),
|
||||
|
@ -34,9 +34,6 @@ const reservedPorts = [1024, 1027, 1028, 1029, 1058, 1059, 1080, 1085, 1098, 109
|
||||
|
||||
// From https://github.com/coverslide/node-alea
|
||||
const AleaModule = function () {
|
||||
|
||||
'use strict';
|
||||
|
||||
// importState to sync generator states
|
||||
Alea.importState = function(i){
|
||||
var random = new Alea();
|
||||
@ -54,8 +51,8 @@ const AleaModule = function () {
|
||||
var s2 = 0;
|
||||
var c = 1;
|
||||
|
||||
if (args.length == 0) {
|
||||
args = [+new Date];
|
||||
if (args.length === 0) {
|
||||
args = [+new Date()];
|
||||
}
|
||||
var mash = Mash();
|
||||
s0 = mash(' ');
|
||||
|
@ -27,6 +27,10 @@ const defaultState = {
|
||||
hasDisabledSyncItems: false,
|
||||
newNote: null,
|
||||
collapsedFolderIds: [],
|
||||
clipperServer: {
|
||||
startState: 'idle',
|
||||
port: null,
|
||||
},
|
||||
};
|
||||
|
||||
const stateUtils = {};
|
||||
@ -525,7 +529,16 @@ const reducer = (state = defaultState, action) => {
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
newState.newNote = action.item;
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'CLIPPER_SERVER_SET':
|
||||
|
||||
newState = Object.assign({}, state);
|
||||
const clipperServer = Object.assign({}, newState.clipperServer);
|
||||
if ('startState' in action) clipperServer.startState = action.startState;
|
||||
if ('port' in action) clipperServer.port = action.port;
|
||||
newState.clipperServer = clipperServer;
|
||||
break;
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
|
46
Tools/release-clipper.js
Normal file
46
Tools/release-clipper.js
Normal file
@ -0,0 +1,46 @@
|
||||
const fs = require('fs-extra');
|
||||
const { execCommand } = require('./tool-utils.js');
|
||||
|
||||
const clipperDir = __dirname + '/../Clipper/joplin-webclipper';
|
||||
|
||||
async function copyDir(baseSourceDir, sourcePath, baseDestDir) {
|
||||
await fs.mkdirp(baseDestDir + '/' + sourcePath);
|
||||
await fs.copy(baseSourceDir + '/' + sourcePath, baseDestDir + '/' + sourcePath);
|
||||
}
|
||||
|
||||
async function copyToDist(distDir) {
|
||||
await copyDir(clipperDir, 'popup/build', distDir);
|
||||
await copyDir(clipperDir, 'content_scripts', distDir);
|
||||
await copyDir(clipperDir, 'icons', distDir);
|
||||
await fs.copy(clipperDir + '/background.js', distDir + '/background.js');
|
||||
await fs.copy(clipperDir + '/main.js', distDir + '/main.js');
|
||||
await fs.copy(clipperDir + '/manifest.json', distDir + '/manifest.json');
|
||||
|
||||
await fs.remove(distDir + '/popup/build/manifest.json');
|
||||
}
|
||||
|
||||
async function main() {
|
||||
process.chdir(clipperDir + '/popup');
|
||||
|
||||
console.info(await execCommand('npm run build'));
|
||||
|
||||
const dists = [
|
||||
{
|
||||
dir: clipperDir + '/dist/chrometest',
|
||||
name: 'chrome',
|
||||
}
|
||||
];
|
||||
|
||||
for (let i = 0; i < dists.length; i++) {
|
||||
const dist = dists[i];
|
||||
await copyToDist(dist.dir);
|
||||
process.chdir(dist.dir);
|
||||
console.info(await execCommand('7z a -tzip ' + dist.name + '.zip *'));
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Fatal error');
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
Loading…
Reference in New Issue
Block a user