Skip to content

Commit

Permalink
Merge branch 'master' of github.com:laurent22/joplin
Browse files Browse the repository at this point in the history
  • Loading branch information
laurent22 committed Dec 13, 2019
2 parents 6654641 + 34f0a29 commit 48ce788
Show file tree
Hide file tree
Showing 36 changed files with 932 additions and 158 deletions.
6 changes: 5 additions & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,8 @@ Server/docs/
Server/dist/
Server/bin/
Server/node_modules/
ElectronClient/app/packageInfo.js
ElectronClient/app/packageInfo.js

# Ignore files generated from TypeScript files
ElectronClient/app/gui/ShareNoteDialog.js
ReactNativeClient/lib/JoplinServerApi.js
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,8 @@ ElectronClient/app/gui/note-viewer/fonts/
ElectronClient/app/gui/note-viewer/lib.js
Tools/commit_hook.txt
.vscode/*
*.map

# Ignore files generated from TypeScript files
ElectronClient/app/gui/ShareNoteDialog.js
ReactNativeClient/lib/JoplinServerApi.js
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,12 @@ before_install:
script:
- |
# Copy lib
rsync -aP --delete ReactNativeClient/lib/ ElectronClient/app/lib/
# Install tools
npm install
npm run typescript-compile
cd Tools
npm install
cd ..
Expand Down Expand Up @@ -110,5 +114,4 @@ script:
# Prepare the Electron app and build it
cd ElectronClient/app
rsync -aP --delete ../../ReactNativeClient/lib/ lib/
npm install && USE_HARD_LINKS=false yarn dist
31 changes: 23 additions & 8 deletions BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
- All the applications share the same library, which, for historical reasons, is in ReactNativeClient/lib. This library is copied to the relevant directories when building each app.
- In general, most of the backend (anything to do with the database, synchronisation, data import or export, etc.) is shared across all the apps, so when making a change please consider how it will affect all the apps.

# TypeScript

Most of the application is written in JavaScript, however new classes and files should generally be written in [TypeScript](https://www.typescriptlang.org/). Even if you don't write TypeScript code, you will need to build the existing .ts and .tsx files. This is done from the root of the project, by running `npm run typescript-compile`.

If you are modifying TypeScript code, the best is to have the compiler watch for changes from a terminal. To do so, run `npm run typescript-watch`.

All TypeScript files are generated next to the .ts or .tsx file. So for example, if there's a file "lib/MyClass.ts", there will be a generated "lib/MyClass.js" next to it. If you create a new TypeScript file, make sure you add the generated .js file to .gitignore. It is implemented that way as it requires minimal changes to integrate TypeScript in the existing JavaScript code base.

## macOS dependencies

brew install yarn node
Expand All @@ -14,7 +22,7 @@
## Linux and Windows (WSL) dependencies

- Install yarn - https://yarnpkg.com/lang/en/docs/install/
- Install node v8.x (check with `node --version`) - https://nodejs.org/en/
- Install node v10.x (check with `node --version`) - https://nodejs.org/en/
- If you get a node-gyp related error you might need to manually install it: `npm install -g node-gyp`

# Building the tools
Expand All @@ -28,8 +36,9 @@ npm install && cd Tools && npm install
# Building the Electron application

```
rsync --delete -a ReactNativeClient/lib/ ElectronClient/app/lib/
npm run typescript-compile
cd ElectronClient/app
rsync --delete -a ../../ReactNativeClient/lib/ lib/
npm install
yarn dist
```
Expand All @@ -47,10 +56,9 @@ From `/ElectronClient` you can also run `run.sh` to run the app for testing.
## Building Electron application on Windows

```
cd Tools
npm install
cd ..\ElectronClient\app
xcopy /C /I /H /R /Y /S ..\..\ReactNativeClient\lib lib
xcopy /C /I /H /R /Y /S ReactNativeClient\lib ElectronClient\app\lib
npm run typescript-compile
cd ElectronClient\app
npm install
yarn dist
```
Expand All @@ -67,15 +75,22 @@ The [building\_win32\_tips on this page](./readme/building_win32_tips.md) might

First you need to setup React Native to build projects with native code. For this, follow the instructions on the [Get Started](https://facebook.github.io/react-native/docs/getting-started.html) tutorial, in the "React Native CLI Quickstart" tab.

Then, from `/ReactNativeClient`, run `npm install`, then `react-native run-ios` or `react-native run-android`.
Then:

```
npm run typescript-compile
cd ReactNativeClient
npm install
react-native run-ios
# Or: react-native run-android
```

# Building the Terminal application

```
cd CliClient
npm install
./build.sh
rsync --delete -aP ../ReactNativeClient/locales/ build/locales/
```

Run `run.sh` to start the application for testing.
5 changes: 5 additions & 0 deletions CliClient/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,9 @@ rsync -a --exclude "node_modules/" "$ROOT_DIR/app/" "$BUILD_DIR/"
rsync -a --delete "$ROOT_DIR/../ReactNativeClient/lib/" "$BUILD_DIR/lib/"
rsync -a --delete "$ROOT_DIR/../ReactNativeClient/locales/" "$BUILD_DIR/locales/"
cp "$ROOT_DIR/package.json" "$BUILD_DIR"

cd $ROOT_DIR/..
npm run typescript-compile
cd $ROOT_DIR

chmod 755 "$BUILD_DIR/main.js"
95 changes: 86 additions & 9 deletions ElectronClient/app/gui/ConfigScreen.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,27 @@ class ConfigScreenComponent extends React.Component {
await shared.checkSyncConfig(this, this.state.settings);
};

this.checkNextcloudAppButton_click = async () => {
this.setState({ showNextcloudAppLog: true });
await shared.checkNextcloudApp(this, this.state.settings);
};

this.showLogButton_click = () => {
this.setState({ showNextcloudAppLog: true });
};

this.nextcloudAppHelpLink_click = () => {
bridge().openExternal('https://joplinapp.org/nextcloud_app');
};

this.rowStyle_ = {
marginBottom: 10,
};

this.configMenuBar_selectionChange = this.configMenuBar_selectionChange.bind(this);
}

componentWillMount() {
UNSAFE_componentWillMount() {
this.setState({ settings: this.props.settings });
}

Expand Down Expand Up @@ -93,14 +106,21 @@ class ConfigScreenComponent extends React.Component {

sectionToComponent(key, section, settings, selected) {
const theme = themeStyle(this.props.theme);
const settingComps = [];

for (let i = 0; i < section.metadatas.length; i++) {
const md = section.metadatas[i];
// const settingComps = [];

const createSettingComponents = (advanced) => {
const output = [];
for (let i = 0; i < section.metadatas.length; i++) {
const md = section.metadatas[i];
if (!!md.advanced !== advanced) continue;
const settingComp = this.settingToComponent(md.key, settings[md.key]);
output.push(settingComp);
}
return output;
};

const settingComp = this.settingToComponent(md.key, settings[md.key]);
settingComps.push(settingComp);
}
const settingComps = createSettingComponents(false);
const advancedSettingComps = createSettingComponents(true);

const sectionStyle = {
marginTop: 20,
Expand All @@ -117,10 +137,10 @@ class ConfigScreenComponent extends React.Component {

if (section.name === 'sync') {
const syncTargetMd = SyncTargetRegistry.idToMetadata(settings['sync.target']);
const statusStyle = Object.assign({}, theme.textStyle, { marginTop: 10 });

if (syncTargetMd.supportsConfigCheck) {
const messages = shared.checkSyncConfigMessages(this);
const statusStyle = Object.assign({}, theme.textStyle, { marginTop: 10 });
const statusComp = !messages.length ? null : (
<div style={statusStyle}>
{messages[0]}
Expand All @@ -137,12 +157,69 @@ class ConfigScreenComponent extends React.Component {
</div>
);
}

if (syncTargetMd.name === 'nextcloud') {
const syncTarget = settings['sync.5.syncTargets'][settings['sync.5.path']];

let status = _('Unknown');
let errorMessage = null;

if (this.state.checkNextcloudAppResult === 'checking') {
status = _('Checking...');
} else if (syncTarget) {
if (syncTarget.uuid) status = _('OK');
if (syncTarget.error) {
status = _('Error');
errorMessage = syncTarget.error;
}
}

const statusComp = !errorMessage || this.state.checkNextcloudAppResult === 'checking' || !this.state.showNextcloudAppLog ? null : (
<div style={statusStyle}>
<p style={theme.textStyle}>{_('The Joplin Nextcloud App is either not installed or misconfigured. Please see the full error message below:')}</p>
<pre>{errorMessage}</pre>
</div>
);

const showLogButton = !errorMessage || this.state.showNextcloudAppLog ? null : (
<a style={theme.urlStyle} href="#" onClick={this.showLogButton_click}>[{_('Show Log')}]</a>
);

const appStatusStyle = Object.assign({}, theme.textStyle, { fontWeight: 'bold' });

settingComps.push(
<div key="nextcloud_app_check" style={this.rowStyle_}>
<span style={theme.textStyle}>Beta: {_('Joplin Nextcloud App status:')} </span><span style={appStatusStyle}>{status}</span>
&nbsp;&nbsp;
{showLogButton}
&nbsp;&nbsp;
<button disabled={this.state.checkNextcloudAppResult === 'checking'} style={theme.buttonStyle} onClick={this.checkNextcloudAppButton_click}>
{_('Check Status')}
</button>
&nbsp;&nbsp;
<a style={theme.urlStyle} href="#" onClick={this.nextcloudAppHelpLink_click}>[{_('Help')}]</a>
{statusComp}
</div>
);
}
}

let advancedSettingsButton = null;
let advancedSettingsSectionStyle = { display: 'none' };

if (advancedSettingComps.length) {
const iconName = this.state.showAdvancedSettings ? 'fa fa-toggle-up' : 'fa fa-toggle-down';
const advancedSettingsButtonStyle = Object.assign({}, theme.buttonStyle, { marginBottom: 10 });
advancedSettingsButton = <button onClick={() => shared.advancedSettingsButton_click(this)} style={advancedSettingsButtonStyle}><i style={{fontSize: 14}} className={iconName}></i> {_('Show Advanced Settings')}</button>;
advancedSettingsSectionStyle.display = this.state.showAdvancedSettings ? 'block' : 'none';
}

return (
<div key={key} style={sectionStyle}>
{noteComp}
<div>{settingComps}</div>
{advancedSettingsButton}
<div style={advancedSettingsSectionStyle}>{advancedSettingComps}</div>
</div>
);
}
Expand Down
45 changes: 45 additions & 0 deletions ElectronClient/app/gui/DialogButtonRow.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
const React = require('react');
const { _ } = require('lib/locale.js');
const { themeStyle } = require('../theme.js');

function DialogButtonRow(props) {
const theme = themeStyle(props.theme);

const okButton_click = () => {
if (props.onClick) props.onClick({ buttonName: 'ok' });
};

const cancelButton_click = () => {
if (props.onClick) props.onClick({ buttonName: 'cancel' });
};

const onKeyDown = (event) => {
if (event.keyCode === 13) {
okButton_click();
} else if (event.keyCode === 27) {
cancelButton_click();
}
};

const buttonComps = [];

if (props.okButtonShow !== false) {
buttonComps.push(
<button key="ok" style={theme.buttonStyle} onClick={okButton_click} ref={props.okButtonRef} onKeyDown={onKeyDown}>
{_('OK')}
</button>
);
}

if (props.cancelButtonShow !== false) {
buttonComps.push(
<button key="cancel" style={Object.assign({}, theme.buttonStyle, { marginLeft: 10 })} onClick={cancelButton_click}>
{props.cancelButtonLabel ? props.cancelButtonLabel : _('Cancel')}
</button>
);
}

return <div style={{ textAlign: 'right', marginTop: 10 }}>{buttonComps}</div>;
}

module.exports = DialogButtonRow;
2 changes: 1 addition & 1 deletion ElectronClient/app/gui/DropboxLoginScreen.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class DropboxLoginScreenComponent extends React.Component {
this.shared_ = new Shared(this, msg => bridge().showInfoMessageBox(msg), msg => bridge().showErrorMessageBox(msg));
}

componentWillMount() {
UNSAFE_componentWillMount() {
this.shared_.refreshUrl();
}

Expand Down
4 changes: 2 additions & 2 deletions ElectronClient/app/gui/EncryptionConfigScreen.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ class EncryptionConfigScreenComponent extends React.Component {
return shared.refreshStats(this);
}

componentWillMount() {
UNSAFE_componentWillMount() {
this.initState(this.props);
}

componentWillReceiveProps(nextProps) {
UNSAFE_componentWillReceiveProps(nextProps) {
this.initState(nextProps);
}

Expand Down
2 changes: 1 addition & 1 deletion ElectronClient/app/gui/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class HeaderComponent extends React.Component {
};
}

async componentWillReceiveProps(nextProps) {
async UNSAFE_componentWillReceiveProps(nextProps) {
if (nextProps.windowCommand) {
this.doCommand(nextProps.windowCommand);
}
Expand Down
4 changes: 2 additions & 2 deletions ElectronClient/app/gui/ImportScreen.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ const { filename, basename } = require('lib/path-utils.js');
const { importEnex } = require('lib/import-enex');

class ImportScreenComponent extends React.Component {
componentWillMount() {
UNSAFE_componentWillMount() {
this.setState({
doImport: true,
filePath: this.props.filePath,
messages: [],
});
}

componentWillReceiveProps(newProps) {
UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.filePath) {
this.setState(
{
Expand Down
4 changes: 2 additions & 2 deletions ElectronClient/app/gui/ItemList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ class ItemList extends React.Component {
});
}

componentWillMount() {
UNSAFE_componentWillMount() {
this.updateStateItemIndexes();
}

componentWillReceiveProps(newProps) {
UNSAFE_componentWillReceiveProps(newProps) {
this.updateStateItemIndexes(newProps);
}

Expand Down
Loading

0 comments on commit 48ce788

Please sign in to comment.