1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-30 20:39:46 +02:00

Compare commits

...

40 Commits

Author SHA1 Message Date
Laurent Cozic
7b85c33213 CLI v1.0.117 2018-10-29 23:24:19 +00:00
Laurent Cozic
4b4d0e8b25 Update website 2018-10-24 21:14:38 +01:00
Laurent Cozic
4fb6af3c62 Android release v1.0.175 2018-10-24 19:59:37 +01:00
Laurent Cozic
d7ffe7e294 Electron release v1.0.114 2018-10-24 19:52:07 +01:00
Laurent Cozic
3ff139d445 Merge branch 'master' of github.com:laurent22/joplin 2018-10-24 19:51:16 +01:00
Laurent Cozic
40443e0134 Android v153 2018-10-24 19:50:26 +01:00
Laurent Cozic
1f927c1285 iOS v26 2018-10-24 19:48:09 +01:00
Andros Fenollosa
5e82e62335 Linux script install: implement previous updates (#905)
Avoid an erroneous update and prevent installation icon only on gnome.
2018-10-24 19:17:18 +01:00
Yannis Mitsos
de954827df Support FreeBSD in terminal (#896) 2018-10-24 19:16:15 +01:00
Laurent Cozic
2cb24bf198 Mobile: Fixes #902: Don't change existing note when sharing with mobile app 2018-10-24 19:10:05 +01:00
Laurent Cozic
739a6a4a9c Documentation 2018-10-24 18:47:04 +01:00
Laurent Cozic
dfcf1193dc Electron: Handle internal anchors 2018-10-17 08:01:18 +01:00
Laurent Cozic
c72f92e22f Additional info 2018-10-15 18:40:11 +01:00
Laurent Cozic
f6d01ce7e1 Android release v1.0.174 2018-10-15 00:01:36 +01:00
Laurent Cozic
fed9700587 Merge branch 'master' of github.com:laurent22/joplin 2018-10-15 00:00:13 +01:00
Laurent Cozic
12a3a9a89e android release 2018-10-14 23:59:42 +01:00
Laurent Cozic
590c62c371 Merge branch 'fixing_android_build' 2018-10-14 23:56:42 +01:00
Laurent Cozic
df41f64b3c Revert "trying to fix android build"
This reverts commit 621d0260f4.
2018-10-14 21:47:12 +01:00
Laurent Cozic
1849355245 Android: Tryinc to fix release builkd 2018-10-14 21:42:34 +01:00
Laurent Cozic
fa1b471ea4 Android: Tryinc to fix release builkd 2018-10-14 21:41:29 +01:00
Laurent Cozic
0a67f8c947 Revert "Android: Updated project to build on macOS"
This reverts commit b547f9aa13.
2018-10-14 20:44:05 +01:00
Laurent Cozic
621d0260f4 trying to fix android build 2018-10-14 19:57:30 +01:00
Laurent Cozic
f93fca7c5b Revert "Android: Updated project to build on macOS"
This reverts commit b547f9aa13.
2018-10-13 11:35:21 +01:00
Laurent Cozic
f4d830c2ef Android release v1.0.151 2018-10-13 11:09:03 +01:00
Laurent Cozic
1aa2844efa Android release v1.0.148 2018-10-13 10:39:55 +01:00
Laurent Cozic
f22b2adaad Mobile: Improved camera attachment 2018-10-13 10:32:44 +01:00
Laurent Cozic
b547f9aa13 Android: Updated project to build on macOS 2018-10-13 00:30:41 +01:00
Laurent Cozic
e4166e9da7 Electron: Fixes #312 (maybe): Removed power saving feature, which wasn\'t doing anything and added a possible fix to the UI freezing issue on Linux 2018-10-12 23:44:00 +01:00
Laurent Cozic
1634fdb421 Merge branch 'master' of github.com:laurent22/joplin 2018-10-12 23:26:11 +01:00
Laurent Cozic
7f51035f91 Mobile: Reload note when resource got downloaded. Also fixed Android build script to make it work in macOS. 2018-10-12 23:25:11 +01:00
ebayer
70e71cbc2a Mobile: Fixes #856: Add option to open source url (#872)
* Mobile: Fixes #856: Add option to open source url

* Mobile: Fixes #856: Change menu wording for opening source url
2018-10-12 19:30:00 +01:00
Laurent Cozic
ffd03bf34c Merge branch 'master' of github.com:laurent22/joplin 2018-10-11 17:53:40 +01:00
Christian Baer
f59a3dee78 Fixed some more inconsistencies in german language file. (#855)
* Fixed some typos and inconsistencies in the german language file and added missing translations.

* Fixed some more inconsistencies in german language file.
2018-10-11 17:21:12 +01:00
Timothy Cyrus
3ba3037242 Update README.md (#874) 2018-10-11 17:20:42 +01:00
Helmut K. C. Tessarek
dbb269fef6 add support for webp images (#858)
fixes #848
2018-10-11 17:18:33 +01:00
Laurent Cozic
e209189faa All: Added resource test units 2018-10-11 17:18:24 +01:00
Laurent Cozic
2d7065cde2 Android release v1.0.143 2018-10-10 20:36:42 +01:00
Laurent Cozic
59f5972c93 Electron release v1.0.113 2018-10-10 20:32:45 +01:00
Laurent Cozic
8bac5275c3 All: Fixed fetch logic - mark resource as fetched by default, unless it comes from sync 2018-10-10 18:53:09 +01:00
Helmut K. C. Tessarek
58d748e235 fix permissions for shell scripts (add executable flag) (#866) 2018-10-09 22:58:18 +01:00
44 changed files with 610 additions and 231 deletions

View File

@@ -15,6 +15,8 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.1.1\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
msgid "To delete a tag, untag the associated notes."
msgstr ""
@@ -197,8 +199,8 @@ msgid ""
"complete database including notebooks, notes, tags and resources."
msgstr ""
"Exportiert Joplin-Dateien in den angegebenen Pfad. Standardmäßig wird die "
"komplette Datenbank inklusive Notizbüchern, Notizen, Tags und Anhängen "
"exportiert."
"komplette Datenbank inklusive Notizbüchern, Notizen, Schlagwörtern und "
"Anhängen exportiert."
#, javascript-format
msgid "Destination format: %s"
@@ -305,7 +307,7 @@ msgstr "Anhänge: %d."
#, javascript-format
msgid "Tagged: %d."
msgstr "Getagged: %d."
msgstr "Verschlagwortet: %d."
msgid "Importing notes..."
msgstr "Importiere Notizen..."
@@ -918,7 +920,7 @@ msgid "Notebook title:"
msgstr "Notizbuch-Titel:"
msgid "Add or remove tags:"
msgstr "Füge hinzu oder entferne Schlagwörter:"
msgstr "Schlagwörter hinzufügen oder entfernen:"
msgid "Separate each tag by a comma."
msgstr "Trenne jedes Schlagwort mit einem Komma."

View File

@@ -1,6 +1,6 @@
{
"name": "joplin",
"version": "1.0.116",
"version": "1.0.117",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -19,7 +19,7 @@
],
"owner": "Laurent Cozic"
},
"version": "1.0.116",
"version": "1.0.117",
"bin": {
"joplin": "./main.js"
},

View File

@@ -0,0 +1,31 @@
require('app-module-path').addPath(__dirname);
const { time } = require('lib/time-utils.js');
const { asyncTest, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('test-utils.js');
const Folder = require('lib/models/Folder.js');
const Note = require('lib/models/Note.js');
const Resource = require('lib/models/Resource.js');
const BaseModel = require('lib/BaseModel.js');
const { shim } = require('lib/shim');
process.on('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
});
describe('models_Resource', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should have a "done" fetch_status when created locally', asyncTest(async () => {
let folder1 = await Folder.save({ title: "folder1" });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, __dirname + '/../tests/support/photo.jpg');
let resource1 = (await Resource.all())[0];
console.info(resource1);
}));
});

0
CliClientDemo/publish.sh Normal file → Executable file
View File

View File

@@ -1,20 +1,20 @@
function randomClipperPort(state, env) {
const startPorts = {
prod: 41184,
dev: 27583,
};
const startPorts = {
prod: 41184,
dev: 27583,
};
const startPort = env === 'prod' ? startPorts.prod : startPorts.dev;
const startPort = env === 'prod' ? startPorts.prod : startPorts.dev;
if (!state) {
state = { offset: 0 };
} else {
state.offset++;
}
if (!state) {
state = { offset: 0 };
} else {
state.offset++;
}
state.port = startPort + state.offset;
state.port = startPort + state.offset;
return state;
return state;
}
module.exports = randomClipperPort;

View File

@@ -49,7 +49,6 @@ class Application extends BaseApplication {
constructor() {
super();
this.lastMenuScreen_ = null;
this.powerSaveBlockerId_ = null;
}
hasGui() {
@@ -221,17 +220,6 @@ class Application extends BaseApplication {
Setting.setValue('sidebarVisibility', newState.sidebarVisibility);
}
if (action.type === 'SYNC_STARTED') {
if (!this.powerSaveBlockerId_) this.powerSaveBlockerId_ = bridge().powerSaveBlockerStart('prevent-app-suspension');
}
if (action.type === 'SYNC_COMPLETED') {
if (this.powerSaveBlockerId_) {
bridge().powerSaveBlockerStop(this.powerSaveBlockerId_);
this.powerSaveBlockerId_ = null;
}
}
return result;
}
@@ -741,8 +729,6 @@ class Application extends BaseApplication {
ids: Setting.value('collapsedFolderIds'),
});
if (shim.isLinux()) bridge().setAllowPowerSaveBlockerToggle(true);
// Note: Auto-update currently doesn't work in Linux: it downloads the update
// but then doesn't install it on exit.
if (shim.isWindows() || shim.isMac()) {

View File

@@ -1,7 +1,6 @@
const { _, setLocale } = require('lib/locale.js');
const { dirname } = require('lib/path-utils.js');
const { Logger } = require('lib/logger.js');
const { powerSaveBlocker } = require('electron');
class Bridge {
@@ -9,7 +8,6 @@ class Bridge {
this.electronWrapper_ = electronWrapper;
this.autoUpdateLogger_ = null;
this.lastSelectedPath_ = null;
this.allowPowerSaveBlockerToggle_ = false;
}
electronApp() {
@@ -24,10 +22,6 @@ class Bridge {
return this.electronWrapper_.window();
}
setAllowPowerSaveBlockerToggle(v) {
this.allowPowerSaveBlockerToggle_ = v;
}
windowContentSize() {
if (!this.window()) return { width: 0, height: 0 };
const s = this.window().getContentSize();
@@ -126,19 +120,7 @@ class Bridge {
const { checkForUpdates } = require('./checkForUpdates.js');
checkForUpdates(inBackground, window, logFilePath);
}
powerSaveBlockerStart(type) {
if (!this.allowPowerSaveBlockerToggle_) return null;
console.info('Enable powerSaveBlockerStart: ' + type);
return powerSaveBlocker.start(type);
}
powerSaveBlockerStop(id) {
if (!this.allowPowerSaveBlockerToggle_) return null;
console.info('Disable powerSaveBlocker: ' + id);
return powerSaveBlocker.stop(id);
}
}
let bridge_ = null;

View File

@@ -595,6 +595,8 @@ class NoteTextComponent extends React.Component {
} else {
require('electron').shell.openExternal(msg);
}
} else if (msg.indexOf('#') === 0) {
// This is an internal anchor, which is handled by the WebView so skip this case
} else {
bridge().showErrorMessageBox(_('Unsupported link or message: %s', msg));
}

View File

@@ -12,6 +12,7 @@ const { bridge } = require("electron").remote.require("./bridge");
const Menu = bridge().Menu;
const MenuItem = bridge().MenuItem;
const InteropServiceHelper = require("../InteropServiceHelper.js");
const { shim } = require('lib/shim');
class SideBarComponent extends React.Component {
@@ -178,6 +179,35 @@ class SideBarComponent extends React.Component {
return style;
}
clearForceUpdateDuringSync() {
if (this.forceUpdateDuringSyncIID_) {
clearInterval(this.forceUpdateDuringSyncIID_);
this.forceUpdateDuringSyncIID_ = null;
}
}
componentDidUpdate(prevProps) {
if (shim.isLinux()) {
// For some reason, the UI seems to sleep in some Linux distro during
// sync. Cannot find the reason for it and cannot replicate, so here
// as a test force the update at regular intervals.
// https://github.com/laurent22/joplin/issues/312#issuecomment-429472193
if (!prevProps.syncStarted && this.props.syncStarted) {
this.clearForceUpdateDuringSync();
this.forceUpdateDuringSyncIID_ = setInterval(() => {
this.forceUpdate();
}, 2000);
}
if (prevProps.syncStarted && !this.props.syncStarted) this.clearForceUpdateDuringSync();
}
}
componentWillUnmount() {
this.clearForceUpdateDuringSync();
}
itemContextMenu(event) {
const itemId = event.target.getAttribute("data-id");
if (itemId === Folder.conflictFolderId()) return;

View File

@@ -276,12 +276,24 @@
}
});
// Prevent URLs added via <a> tags from being opened within the application itself
document.addEventListener('click', function(event) {
const t = event.target;
// Prevent URLs added via <a> tags from being opened within the application itself
if (t && t.nodeName === 'A' && !t.hasAttribute('data-from-md')) {
event.preventDefault();
ipcProxySendToHost(t.getAttribute('href'));
return;
}
// IF this is an internal link, jump to the anchor directly
if (t && t.nodeName === 'A' && t.hasAttribute('data-from-md')) {
const href = t.getAttribute('href');
if (href.indexOf('#') === 0) {
event.preventDefault();
location.hash = href;
return;
}
}
});

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.0.112",
"version": "1.0.114",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.0.112",
"version": "1.0.114",
"description": "Joplin for Desktop",
"main": "main.js",
"scripts": {

0
ElectronClient/run-prod.sh Normal file → Executable file
View File

View File

@@ -1,52 +1,70 @@
#!/bin/bash
set -e
# Title
echo " _ _ _ _ _ _ _ "
echo " | | | |(_) (_) | | | | | "
echo " | | ___ _ __ | | _ _ __ _ _ __ ___| |_ __ _| | | ___ _ __ "
echo " _ | |/ _ \| _ \| || | _ \ | | _ \ / __| __ | | |/ _ \ __| "
echo " | |__| | (_) | |_) | || | | | | | | | | \__ \ || (_| | | | __/ | "
echo " \____/ \___/| .__/|_||_|_| |_| |_|_| |_|___/\__\__,_|_|_|\___|_| "
echo " | | "
echo " |_| "
echo " _ _ _ _ _ _ "
echo " | | (_) (_) | | | | | "
echo " | | ___ _ __ _ _ __ _ _ __ ___| |_ __ _| | | ___ _ __ "
echo " _ | |/ _ \\\| '_ \| | '_ \\ | | '_ \\\/ __| __/ _\` | | |/ _ \ '__|"
echo " | |__| | (_) | |_) | | | | | | | | | \__ \ || (_| | | | __/ | "
echo " \____/ \___/| .__/|_|_| |_| |_|_| |_|___/\__\__,_|_|_|\___|_| "
echo " | | "
echo " |_| "
echo ""
#-----------------------------------------------------
# Download Joplin
#-----------------------------------------------------
# Get the latest version to download
version=$(curl --silent "https://api.github.com/repos/laurent22/joplin/releases/latest" | grep -Po '"tag_name": "v\K.*?(?=")')
# Delete previous version
rm -f ~/.joplin/*.AppImage ~/.local/share/applications/*joplin.desktop
# Check if it's in the latest version
touch VERSION
if [[ $(< ~/.joplin/VERSION) != "$version" ]]; then
# Creates the folder where the binary will be stored
mkdir -p ~/.joplin/
# Delete previous version
rm -f ~/.joplin/*.AppImage ~/.local/share/applications/joplin.desktop ~/.joplin/VERSION
# Creates the folder where the binary will be stored
mkdir -p ~/.joplin/
# Download the latest version
wget -O ~/.joplin/Joplin.AppImage https://github.com/laurent22/joplin/releases/download/v$version/Joplin-$version-x86_64.AppImage
# Gives execution privileges
chmod +x ~/.joplin/Joplin.AppImage
#-----------------------------------------------------
# Icon
#-----------------------------------------------------
# Download icon
wget -O ~/.joplin/Icon512.png https://joplin.cozic.net/images/Icon512.png
# Detect desktop environment
if [ "$XDG_CURRENT_DESKTOP" = "" ]
then
desktop=$(echo "$XDG_DATA_DIRS" | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
else
desktop=$XDG_CURRENT_DESKTOP
fi
desktop=${desktop,,} # convert to lower case
# Download the latest version
wget -O ~/.joplin/Joplin-$version-x86_64.AppImage https://github.com/laurent22/joplin/releases/download/v$version/Joplin-$version-x86_64.AppImage
# Gives execution privileges
chmod +x ~/.joplin/Joplin-$version-x86_64.AppImage
# Download icon
wget -O ~/.joplin/Icon512.png https://joplin.cozic.net/images/Icon512.png
# Detect desktop environment
if [ "$XDG_CURRENT_DESKTOP" = "" ]
then
desktop=$(echo "$XDG_DATA_DIRS" | sed 's/.*\(xfce\|kde\|gnome\).*/\1/')
# Create icon for Gnome
if [[ $desktop =~ .*gnome.* ]]
then
echo -e "[Desktop Entry]\nEncoding=UTF-8\nName=Joplin\nExec=/home/$USER/.joplin/Joplin-$version-x86_64.AppImage\nIcon=/home/$USER/.joplin/Icon512.png\nType=Application\nCategories=Application;" >> ~/.local/share/applications/joplin.desktop
fi
#-----------------------------------------------------
# Finish
#-----------------------------------------------------
# Informs the user that it has been installed and cleans variables
echo 'Joplin installed in the version' $version
# Add version
echo $version > ~/.joplin/VERSION
else
desktop=$XDG_CURRENT_DESKTOP
echo 'You are now in the latest version.'
fi
desktop=${desktop,,} # convert to lower case
# Create icon for Gnome
if [[ $desktop =~ .*gnome.* ]]
then
echo -e "[Desktop Entry]\nEncoding=UTF-8\nName=Joplin\nExec=/home/$USER/.joplin/Joplin-$version-x86_64.AppImage\nIcon=/home/$USER/.joplin/Icon512.png\nType=Application\nCategories=Application;" >> ~/.local/share/applications/joplin.desktop
fi
# Informs the user that it has been installed and cleans variables
echo 'Joplin installed in the version' $version
# start Joplin:
~/.joplin/Joplin-$version-x86_64.AppImage
unset version

View File

@@ -34,9 +34,9 @@ Three types of applications are available: for the **desktop** (Windows, macOS a
Operating System | Download | Alternative
-----------------|--------|-------------------
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/Joplin-Setup-1.0.111.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a> | or Get the <a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/JoplinPortable.exe'>Portable version</a><br>(to run from a USB key, etc.)
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/Joplin-1.0.111.dmg'><img alt='Get it on macOS' height="40px" src='https://joplin.cozic.net/images/BadgeMacOS.png'/></a> |
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/Joplin-1.0.111-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a> | An Arch Linux package<br>[is also available](#terminal-application).
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/Joplin-Setup-1.0.114.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a> | or Get the <a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/JoplinPortable.exe'>Portable version</a><br>(to run from a USB key, etc.)
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/Joplin-1.0.114.dmg'><img alt='Get it on macOS' height="40px" src='https://joplin.cozic.net/images/BadgeMacOS.png'/></a> |
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/Joplin-1.0.114-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a> | An Arch Linux package<br>[is also available](#terminal-application).
The [portable application](https://en.wikipedia.org/wiki/Portable_application) allows installing the software on a portable device such as a USB key. Simply copy the file JoplinPortable.exe in any directory on that USB key ; the application will then create a directory called "JoplinProfile" next to the executable file.
@@ -50,7 +50,7 @@ wget -O - https://raw.githubusercontent.com/laurent22/joplin/master/Joplin_insta
Operating System | Download | Alt. Download
-----------------|----------|----------------
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplin.cozic.net/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.142/joplin-v1.0.142.apk)
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplin.cozic.net/images/BadgeAndroid.png'/></a> | or [Download APK File](https://github.com/laurent22/joplin-android/releases/download/android-v1.0.175/joplin-v1.0.175.apk)
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://joplin.cozic.net/images/BadgeIOS.png'/></a> | -
## Terminal application
@@ -173,7 +173,7 @@ If synchronisation does not work, please consult the logs in the app profile dir
## Dropbox synchronisation
When syncing with Dropbox, Joplin creates a sub-directory in Dropbox, in /Apps/Joplin and read/write the notes and notebooks from it. The application does not have access to anything outside this directory.
When syncing with Dropbox, Joplin creates a sub-directory in Dropbox, in `/Apps/Joplin` and read/write the notes and notebooks from it. The application does not have access to anything outside this directory.
On the **desktop application** or **mobile application**, select "Dropbox" as the synchronisation target in the config screen (it is selected by default). Then, to initiate the synchronisation process, click on the "Synchronise" button in the sidebar and follow the instructions.
@@ -192,6 +192,7 @@ WebDAV-compatible services that are known to work with Joplin:
- [Fastmail](https://www.fastmail.com/)
- [HiDrive](https://www.strato.fr/stockage-en-ligne/) from Strato. [Setup help](https://github.com/laurent22/joplin/issues/309)
- [Nginx WebDAV Module](https://nginx.org/en/docs/http/ngx_http_dav_module.html)
- [NextCloud](https://nextcloud.com/)
- [OwnCloud](https://owncloud.org/)
- [Seafile](https://www.seafile.com/)
- [Stack](https://www.transip.nl/stack/)
@@ -259,7 +260,7 @@ Since getting the ID of a note is not straightforward, each app provides a way t
## Math notation
Math expressions can be added using the [Katex notation](https://khan.github.io/KaTeX/). To add an inline equation, wrap the expression in `$EXPRESSION$`, eg. `$\sqrt{3x-1}+(1+x)^2$`. To create an expression block, wrap it as follow:
Math expressions can be added using the [KaTeX notation](https://khan.github.io/KaTeX/). To add an inline equation, wrap the expression in `$EXPRESSION$`, eg. `$\sqrt{3x-1}+(1+x)^2$`. To create an expression block, wrap it as follow:
$$
EXPRESSION

View File

@@ -90,8 +90,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097320
versionName "1.0.142"
versionCode 2097411
versionName "1.0.175"
ndk {
abiFilters "armeabi-v7a", "x86"
}
@@ -137,6 +137,7 @@ android {
}
dependencies {
compile project(':react-native-camera')
compile project(':react-native-file-viewer')
compile project(':react-native-securerandom')
compile project(':react-native-push-notification')
@@ -153,6 +154,24 @@ dependencies {
compile project(':react-native-image-resizer')
compile project(':react-native-share-extension')
compile "com.facebook.react:react-native:+"
// To fix the error below, which happened after adding react-native-camera.
// Doesn't make any sense since rn-camera neither defines v26 nor 27 but
// v25.0.2 in build.gradle, but anyway now it works ¯\_(ツ)_/¯
// --------------------------------------------------------------------------------------
// Fatal error
// { Error: Command failed: ./gradlew assembleRelease -PbuildDir=build --console plain
//
// FAILURE: Build failed with an exception.
//
// * What went wrong:
// Execution failed for task ':app:preReleaseBuild'.
// > Android dependency 'com.android.support:support-v4' has different version for the compile (26.1.0) and runtime (27.1.1) classpath. You should manually set the same version via DependencyResolution
// --------------------------------------------------------------------------------------
// https://github.com/react-native-community/react-native-camera/issues/1532#issuecomment-386434771
compile ("com.android.support:support-v4:26.0.1") {
force = true //<-- force dependency resolution to 26.0.1 in my case
}
}
// Run this once to be able to run the application with BUCK

View File

@@ -3,6 +3,7 @@ package net.cozic.joplin;
import android.app.Application;
import com.facebook.react.ReactApplication;
import org.reactnative.camera.RNCameraPackage;
import com.vinzscam.reactnativefileviewer.RNFileViewerPackage;
import net.rhogan.rnsecurerandom.RNSecureRandomPackage;
import com.dieam.reactnativepushnotification.ReactNativePushNotificationPackage;
@@ -37,6 +38,7 @@ public class MainApplication extends Application implements ReactApplication {
return Arrays.<ReactPackage>asList(
new ImageResizerPackage(),
new MainReactPackage(),
new RNCameraPackage(),
new RNFileViewerPackage(),
new RNSecureRandomPackage(),
new ReactNativePushNotificationPackage(),

View File

@@ -1,4 +1,6 @@
rootProject.name = 'Joplin'
include ':react-native-camera'
project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android')
include ':react-native-file-viewer'
project(':react-native-file-viewer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-file-viewer/android')
include ':react-native-securerandom'

0
ReactNativeClient/debug_log.sh Normal file → Executable file
View File

View File

@@ -13,6 +13,7 @@
00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; };
00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; };
0DAD2E67F6A14BDC8250B927 /* libRNDocumentPicker.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 82214D3345D846709A314868 /* libRNDocumentPicker.a */; };
12AE298E1C0E445682922DAB /* libRNCamera.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E132B594F4FB4C96A2E2B0FF /* libRNCamera.a */; };
133E29F31AD74F7200F7D852 /* libRCTLinking.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 78C398B91ACF4ADC00677621 /* libRCTLinking.a */; };
139105C61AF99C1200B5F7CC /* libRCTSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139105C11AF99BAD00B5F7CC /* libRCTSettings.a */; };
139FDEF61B0652A700C62182 /* libRCTWebSocket.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 139FDEF41B06529B00C62182 /* libRCTWebSocket.a */; };
@@ -342,6 +343,13 @@
remoteGlobalIDString = 134814201AA4EA6300B7C361;
remoteInfo = RNFileViewer;
};
4D8C5643217161BF00E93280 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = FC908F114F494130A324B402 /* RNCamera.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 4107012F1ACB723B00C6AA39;
remoteInfo = RNCamera;
};
4DA7F80C1FC1DA9C00353191 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A4716DB8654B431D894F89E1 /* RNImagePicker.xcodeproj */;
@@ -441,9 +449,11 @@
CCDC2774CD86466F897D88E2 /* libRNFileViewer.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFileViewer.a; sourceTree = "<group>"; };
CCDE9E9AF09B45F391B1C2AF /* SQLite.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = SQLite.xcodeproj; path = "../node_modules/react-native-sqlite-storage/src/ios/SQLite.xcodeproj"; sourceTree = "<group>"; };
DF1C50EBC11E46A3AF87F80A /* RCTImageResizer.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RCTImageResizer.xcodeproj; path = "../node_modules/react-native-image-resizer/ios/RCTImageResizer.xcodeproj"; sourceTree = "<group>"; };
E132B594F4FB4C96A2E2B0FF /* libRNCamera.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNCamera.a; sourceTree = "<group>"; };
E2638D52624B477FABB52B8F /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = "<group>"; };
F098E1ACCB594C828C851A57 /* libRNFS.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFS.a; sourceTree = "<group>"; };
F5E37D05726A4A08B2EE323A /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFetchBlob.a; sourceTree = "<group>"; };
FC908F114F494130A324B402 /* RNCamera.xcodeproj */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "wrapper.pb-project"; name = RNCamera.xcodeproj; path = "../node_modules/react-native-camera/ios/RNCamera.xcodeproj"; sourceTree = "<group>"; };
FD370E24D76E461D960DD85D /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Feather.ttf"; sourceTree = "<group>"; };
FF411B45E68B4A8CBCC35777 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -477,6 +487,7 @@
AF99EEC6C55042F7BFC87583 /* libRNImagePicker.a in Frameworks */,
F3D0BB525E6C490294D73075 /* libRNSecureRandom.a in Frameworks */,
82C61D3DAE0A4666883001E9 /* libRNFileViewer.a in Frameworks */,
12AE298E1C0E445682922DAB /* libRNCamera.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -611,6 +622,7 @@
44A39642217548C8ADA91CBA /* libRNImagePicker.a */,
22647ACF9A4C45918C44C599 /* libRNSecureRandom.a */,
CCDC2774CD86466F897D88E2 /* libRNFileViewer.a */,
E132B594F4FB4C96A2E2B0FF /* libRNCamera.a */,
);
name = "Recovered References";
sourceTree = "<group>";
@@ -672,6 +684,14 @@
name = Products;
sourceTree = "<group>";
};
4D8C5640217161BF00E93280 /* Products */ = {
isa = PBXGroup;
children = (
4D8C5644217161BF00E93280 /* libRNCamera.a */,
);
name = Products;
sourceTree = "<group>";
};
4DA7F8091FC1DA9C00353191 /* Products */ = {
isa = PBXGroup;
children = (
@@ -750,6 +770,7 @@
A4716DB8654B431D894F89E1 /* RNImagePicker.xcodeproj */,
252BD7B86BF7435B960DA901 /* RNSecureRandom.xcodeproj */,
59F5448FAF7345F8B568BD00 /* RNFileViewer.xcodeproj */,
FC908F114F494130A324B402 /* RNCamera.xcodeproj */,
);
name = Libraries;
sourceTree = "<group>";
@@ -907,6 +928,10 @@
ProductGroup = 146834001AC3E56700842450 /* Products */;
ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */;
},
{
ProductGroup = 4D8C5640217161BF00E93280 /* Products */;
ProjectRef = FC908F114F494130A324B402 /* RNCamera.xcodeproj */;
},
{
ProductGroup = 4D2A85AD1FBCE3AC0028537D /* Products */;
ProjectRef = 02C42EA98156482DB00BF86D /* RNDocumentPicker.xcodeproj */;
@@ -1242,6 +1267,13 @@
remoteRef = 4D8B719B2163E8C500136BBC /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4D8C5644217161BF00E93280 /* libRNCamera.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libRNCamera.a;
remoteRef = 4D8C5643217161BF00E93280 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
4DA7F80D1FC1DA9C00353191 /* libRNImagePicker.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
@@ -1379,6 +1411,7 @@
"$(SRCROOT)..\node_modules\neact-native-image-pickerios",
"$(SRCROOT)..\node_modules\neact-native-securerandomios",
"$(SRCROOT)..\node_modules\neact-native-file-viewerios",
"$(SRCROOT)/../node_modules/react-native-camera/ios/**",
);
INFOPLIST_FILE = Joplin/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -1386,6 +1419,7 @@
"$(inherited)",
"\"$(SRCROOT)/Joplin\"",
"\"$(SRCROOT)/Joplin\"",
"\"$(SRCROOT)/Joplin\"",
);
OTHER_LDFLAGS = (
"$(inherited)",
@@ -1421,6 +1455,7 @@
"$(SRCROOT)..\node_modules\neact-native-image-pickerios",
"$(SRCROOT)..\node_modules\neact-native-securerandomios",
"$(SRCROOT)..\node_modules\neact-native-file-viewerios",
"$(SRCROOT)/../node_modules/react-native-camera/ios/**",
);
INFOPLIST_FILE = Joplin/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
@@ -1428,6 +1463,7 @@
"$(inherited)",
"\"$(SRCROOT)/Joplin\"",
"\"$(SRCROOT)/Joplin\"",
"\"$(SRCROOT)/Joplin\"",
);
OTHER_LDFLAGS = (
"$(inherited)",

View File

@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>10.0.24</string>
<string>10.0.26</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>24</string>
<string>26</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>

View File

@@ -89,13 +89,14 @@ class MdToHtml {
if (!resource) {
// Can happen for example if an image is attached to a note, but the resource hasn't
// been downloaded from the sync target yet.
console.warn('Cannot load resource: ' + id);
console.info('Cannot load resource: ' + id);
delete this.loadedResources_[id];
return;
}
if (resource.fetch_status !== Resource.FETCH_STATUS_DONE) {
delete this.loadedResources_[id];
console.warn('Resource not yet fetched: ' + id);
console.info('Resource not yet fetched: ' + id);
return;
}

View File

@@ -0,0 +1,83 @@
const React = require('react'); const Component = React.Component;
const { View, Button, StyleSheet, TouchableOpacity } = require('react-native');
const { globalStyle, themeStyle } = require('lib/components/global-style.js');
import { RNCamera } from 'react-native-camera';
const Icon = require('react-native-vector-icons/Ionicons').default;
const { _ } = require('lib/locale.js');
class CameraView extends Component {
constructor() {
super();
this.state = {
snapping: false,
};
this.back_onPress = this.back_onPress.bind(this);
this.photo_onPress = this.photo_onPress.bind(this);
}
back_onPress() {
if (this.props.onCancel) this.props.onCancel();
}
async photo_onPress() {
if (!this.camera || !this.props.onPhoto) return;
this.setState({ snapping: true });
const result = await this.camera.takePictureAsync({
quality: 0.8,
exif: true,
fixOrientation: true
});
if (this.props.onPhoto) this.props.onPhoto(result);
this.setState({ snapping: false });
}
render() {
const theme = themeStyle(this.props.theme);
const photoIcon = this.state.snapping ? 'md-checkmark' : 'md-camera';
return (
<View style={this.props.style}>
<RNCamera
style={{flex:1}}
ref={ref => { this.camera = ref; }}
type={RNCamera.Constants.Type.back}
permissionDialogTitle={_('Permission to use camera')}
permissionDialogMessage={_('Your permission to use your camera is required.')}
>
<View style={{flex:1, justifyContent:'space-between', flexDirection:'column'}}>
<View style={{flex:1, justifyContent:'flex-start'}}>
<TouchableOpacity onPress={this.back_onPress}>
<View style={{ marginLeft:5, marginTop:5, borderRadius:90, width:50,height:50, display:'flex', backgroundColor:'#ffffff55', justifyContent:'center', alignItems:'center'}}>
<Icon name={'md-arrow-back'} style={{
fontSize: 40,
color: 'black',
}} />
</View>
</TouchableOpacity>
</View>
<View style={{flex:1, justifyContent:'center', alignItems:'flex-end', flexDirection:'row'}}>
<TouchableOpacity onPress={this.photo_onPress}>
<View style={{marginBottom:20, borderRadius:90, width:90,height:90,backgroundColor:'#ffffffaa', display:'flex', justifyContent:'center', alignItems:'center'}}>
<Icon name={photoIcon} style={{
fontSize: 60,
color: 'black',
}} />
</View>
</TouchableOpacity>
</View>
</View>
</RNCamera>
</View>
);
}
}
module.exports = CameraView;

View File

@@ -64,6 +64,11 @@ class NoteBodyViewer extends Component {
return (safeGetNoteProp(this.props, 'body') + '').length !== (safeGetNoteProp(nextProps, 'body') + '').length;
}
rebuildMd() {
this.mdToHtml_.clearCache();
this.forceUpdate();
}
render() {
const note = this.props.note;
const style = this.props.style;

View File

@@ -22,6 +22,7 @@ const { Checkbox } = require('lib/components/checkbox.js');
const { _ } = require('lib/locale.js');
const { reg } = require('lib/registry.js');
const { shim } = require('lib/shim.js');
const ResourceFetcher = require('lib/services/ResourceFetcher');
const { BaseScreenComponent } = require('lib/components/base-screen.js');
const { globalStyle, themeStyle } = require('lib/components/global-style.js');
const { dialogs } = require('lib/dialogs.js');
@@ -35,6 +36,7 @@ const ImagePicker = require('react-native-image-picker');
const AlarmService = require('lib/services/AlarmService.js');
const { SelectDateTimeDialog } = require('lib/components/select-date-time-dialog.js');
const ShareExtension = require('react-native-share-extension').default;
const CameraView = require('lib/components/CameraView');
import FileViewer from 'react-native-file-viewer';
@@ -59,6 +61,7 @@ class NoteScreenComponent extends BaseScreenComponent {
heightBumpView:0,
noteTagDialogShown: false,
fromShare: false,
showCamera: false,
};
// iOS doesn't support multiline text fields properly so disable it
@@ -136,6 +139,7 @@ class NoteScreenComponent extends BaseScreenComponent {
});
}, 5);
} else if (item.type_ === BaseModel.TYPE_RESOURCE) {
if (!Resource.isReady(item)) throw new Error(_('This attachment is not downloaded or not decrypted yet.'));
const resourcePath = Resource.fullPath(item);
await FileViewer.open(resourcePath);
} else {
@@ -148,6 +152,18 @@ class NoteScreenComponent extends BaseScreenComponent {
dialogs.error(this, error.message);
}
}
this.resourceFetcher_downloadComplete = async (resource) => {
if (!this.state.note || !this.state.note.body) return;
const resourceIds = await Note.linkedResourceIds(this.state.note.body);
if (resourceIds.indexOf(resource.id) >= 0) {
this.refs.noteBodyViewer.rebuildMd();
}
}
this.attachPhoto_onPress = this.attachPhoto_onPress.bind(this);
this.cameraView_onPhoto = this.cameraView_onPhoto.bind(this);
this.cameraView_onCancel = this.cameraView_onCancel.bind(this);
}
styles() {
@@ -205,6 +221,8 @@ class NoteScreenComponent extends BaseScreenComponent {
BackButtonService.addHandler(this.backHandler);
NavService.addHandler(this.navHandler);
ResourceFetcher.instance().on('downloadComplete', this.resourceFetcher_downloadComplete);
await shared.initState(this);
this.refreshNoteMetadata();
@@ -218,6 +236,8 @@ class NoteScreenComponent extends BaseScreenComponent {
BackButtonService.removeHandler(this.backHandler);
NavService.removeHandler(this.navHandler);
ResourceFetcher.instance().off('downloadComplete', this.resourceFetcher_downloadComplete);
if (Platform.OS !== 'ios' && this.state.fromShare) {
ShareExtension.close();
}
@@ -321,7 +341,7 @@ class NoteScreenComponent extends BaseScreenComponent {
}
}
async attachFile(pickerResponse, fileType) {
async attachFile(pickerResponse, fileType) {
if (!pickerResponse) {
reg.logger().warn('Got no response from picker');
return;
@@ -340,7 +360,6 @@ class NoteScreenComponent extends BaseScreenComponent {
const localFilePath = pickerResponse.uri;
let mimeType = pickerResponse.type;
if (!mimeType) {
const ext = fileExtension(localFilePath);
mimeType = mimeUtils.fromFileExtension(ext);
@@ -362,7 +381,7 @@ class NoteScreenComponent extends BaseScreenComponent {
resource.id = uuid.create();
resource.mime = mimeType;
resource.title = pickerResponse.fileName ? pickerResponse.fileName : _('Untitled');
resource.file_extension = safeFileExtension(fileExtension(pickerResponse.fileName));
resource.file_extension = safeFileExtension(fileExtension(pickerResponse.fileName ? pickerResponse.fileName : localFilePath));
if (!resource.mime) resource.mime = 'application/octet-stream';
@@ -408,6 +427,25 @@ class NoteScreenComponent extends BaseScreenComponent {
await this.attachFile(response, 'image');
}
attachPhoto_onPress() {
this.setState({ showCamera: true });
}
cameraView_onPhoto(data) {
this.attachFile({
uri: data.uri,
didCancel: false,
error: null,
type: 'image/jpg',
}, 'image');
this.setState({ showCamera: false });
}
cameraView_onCancel() {
this.setState({ showCamera: false });
}
async attachFile_onPress() {
const response = await this.pickDocument();
await this.attachFile(response, 'all');
@@ -463,6 +501,17 @@ class NoteScreenComponent extends BaseScreenComponent {
}
}
async showSource_onPress() {
if (!this.state.note.id) return;
let note = await Note.load(this.state.note.id);
try {
Linking.openURL(note.source_url);
} catch (error) {
await dialogs.error(this, error.message);
}
}
copyMarkdownLink_onPress() {
const note = this.state.note;
Clipboard.setString(Note.markdownTag(note));
@@ -472,6 +521,7 @@ class NoteScreenComponent extends BaseScreenComponent {
const note = this.state.note;
const isTodo = note && !!note.is_todo;
const isSaved = note && note.id;
const hasSource = note && note.source_url;
let output = [];
@@ -480,7 +530,7 @@ class NoteScreenComponent extends BaseScreenComponent {
let canAttachPicture = true;
if (Platform.OS === 'android' && Platform.Version < 21) canAttachPicture = false;
if (canAttachPicture) {
output.push({ title: _('Attach photo'), onPress: () => { this.attachImage_onPress(); } });
output.push({ title: _('Attach photo'), onPress: () => { this.attachPhoto_onPress(); } });
output.push({ title: _('Attach any file'), onPress: () => { this.attachFile_onPress(); } });
output.push({ isDivider: true });
}
@@ -496,6 +546,7 @@ class NoteScreenComponent extends BaseScreenComponent {
output.push({ isDivider: true });
if (this.props.showAdvancedOptions) output.push({ title: this.state.showNoteMetadata ? _('Hide metadata') : _('Show metadata'), onPress: () => { this.showMetadata_onPress(); } });
output.push({ title: _('View on map'), onPress: () => { this.showOnMap_onPress(); } });
if (hasSource) output.push({ title: _('Go to source URL'), onPress: () => { this.showSource_onPress(); } });
output.push({ isDivider: true });
output.push({ title: _('Delete'), onPress: () => { this.deleteNote_onPress(); } });
@@ -528,6 +579,13 @@ class NoteScreenComponent extends BaseScreenComponent {
const folder = this.state.folder;
const isNew = !note.id;
if (this.state.showCamera) {
return <CameraView theme={this.props.theme} style={{flex:1}} onPhoto={this.cameraView_onPhoto} onCancel={this.cameraView_onCancel}/>
}
let bodyComponent = null;
if (this.state.mode == 'view') {
const onCheckboxChange = (newBody) => {
@@ -536,6 +594,7 @@ class NoteScreenComponent extends BaseScreenComponent {
bodyComponent = <NoteBodyViewer
onJoplinLinkClick={this.onJoplinLinkClick_}
ref="noteBodyViewer"
style={this.styles().noteBodyViewer}
webViewStyle={theme}
note={note}

View File

@@ -397,7 +397,7 @@ class JoplinDatabase extends Database {
}
if (targetVersion == 13) {
queries.push('ALTER TABLE resources ADD COLUMN fetch_status INT NOT NULL DEFAULT "0"');
queries.push('ALTER TABLE resources ADD COLUMN fetch_status INT NOT NULL DEFAULT "2"');
queries.push('ALTER TABLE resources ADD COLUMN fetch_error TEXT NOT NULL DEFAULT ""');
queries.push({ sql: 'UPDATE resources SET fetch_status = ?', params: [Resource.FETCH_STATUS_DONE] });
}

View File

@@ -73,8 +73,12 @@ class Note extends BaseItem {
}
static defaultTitle(note) {
if (note.body && note.body.length) {
const lines = note.body.trim().split("\n");
return this.defaultTitleFromBody(note.body);
}
static defaultTitleFromBody(body) {
if (body && body.length) {
const lines = body.trim().split("\n");
let output = lines[0].trim();
// Remove the first #, *, etc.
while (output.length) {

View File

@@ -26,7 +26,7 @@ class Resource extends BaseItem {
}
static isSupportedImageMimeType(type) {
const imageMimeTypes = ["image/jpg", "image/jpeg", "image/png", "image/gif", "image/svg+xml"];
const imageMimeTypes = ["image/jpg", "image/jpeg", "image/png", "image/gif", "image/svg+xml", "image/webp"];
return imageMimeTypes.indexOf(type.toLowerCase()) >= 0;
}
@@ -94,7 +94,7 @@ class Resource extends BaseItem {
const plainTextPath = this.fullPath(decryptedItem);
const encryptedPath = this.fullPath(decryptedItem, true);
const noExtPath = pathUtils.dirname(encryptedPath) + '/' + pathUtils.filename(encryptedPath);
// When the resource blob is downloaded by the synchroniser, it's initially a file with no
// extension (since it's encrypted, so we don't know its extension). So here rename it
// to a file with a ".crypted" extension so that it's better identified, and then decrypt it.

View File

@@ -90,7 +90,7 @@ class Setting extends BaseModel {
// Might be fixed in Electron 18.x but no non-beta release yet. So for now
// by default we disable it on Linux.
'showTrayIcon': { value: platform !== 'linux', type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Show tray icon'), description: () => {
return platform === 'linux' ? _('Note: Does not work in all desktop environments.') : null;
return platform === 'linux' ? _('Note: Does not work in all desktop environments.') : _('This will allow Joplin to run in the background. It is recommended to enable this setting so that your notes are constantly being synchronised, thus reducing the number of conflicts.');
}},
'startMinimized': { value: false, type: Setting.TYPE_BOOL, public: true, appTypes: ['desktop'], label: () => _('Start application minimised in the tray icon') },

View File

@@ -7,6 +7,10 @@ shim.isNode = () => {
};
shim.isReactNative = () => {
if (typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('ReactNativeDebugger') >= 0) {
return true;
}
return !shim.isNode();
};
@@ -14,6 +18,10 @@ shim.isLinux = () => {
return process && process.platform === 'linux';
}
shim.isFreeBSD = () => {
return process && process.platform === 'freebsd';
}
shim.isWindows = () => {
return process && process.platform === 'win32';
}
@@ -27,6 +35,7 @@ shim.platformName = function() {
if (shim.isMac()) return 'darwin';
if (shim.isWindows()) return 'win32';
if (shim.isLinux()) return 'linux';
if (shim.isFreeBSD()) return 'freebsd';
throw new Error('Cannot determine platform');
}
@@ -141,4 +150,4 @@ shim.Buffer = null;
shim.openUrl = () => { throw new Error('Not implemented'); }
shim.waitForFrame = () => { throw new Error('Not implemented'); }
module.exports = { shim };
module.exports = { shim };

View File

@@ -555,6 +555,8 @@ class Synchronizer {
if (action == "createLocal") options.isNew = true;
if (action == "updateLocal") options.oldItem = local;
const creatingNewResource = content.type_ == BaseModel.TYPE_RESOURCE && action == "createLocal";
// if (content.type_ == BaseModel.TYPE_RESOURCE && action == "createLocal") {
// let localResourceContentPath = Resource.fullPath(content);
// let remoteResourceContentPath = this.resourceDirName_ + "/" + content.id;
@@ -571,11 +573,11 @@ class Synchronizer {
// }
// }
if (creatingNewResource) content.fetch_status = Resource.FETCH_STATUS_IDLE;
await ItemClass.save(content, options);
if (content.type_ == BaseModel.TYPE_RESOURCE && action == "createLocal") {
this.dispatch({ type: "SYNC_CREATED_RESOURCE", id: content.id });
}
if (creatingNewResource) this.dispatch({ type: "SYNC_CREATED_RESOURCE", id: content.id });
if (!hasAutoEnabledEncryption && content.type_ === BaseModel.TYPE_MASTER_KEY && !masterKeysBefore) {
hasAutoEnabledEncryption = true;

View File

@@ -14,6 +14,8 @@
// require("ReactFeatureFlags").warnAboutDeprecatedLifecycles = false;
// console.disableYellowBox = true
const { AppRegistry } = require('react-native');
const { Root } = require('./root.js');

View File

@@ -6539,6 +6539,31 @@
"prop-types": "^15.5.10"
}
},
"react-native-camera": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-native-camera/-/react-native-camera-1.3.0.tgz",
"integrity": "sha512-f4Nev0dvJmWQPbXLYu4BF17agLWS6iQ+vanPlWkEaa4MAjbClD/YrQaR8w9vY+C472crSp3kRGHJXIQzSwgMpw==",
"requires": {
"lodash": "^4.17.10",
"prop-types": "^15.6.2"
},
"dependencies": {
"lodash": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
},
"prop-types": {
"version": "15.6.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz",
"integrity": "sha512-3pboPvLiWD7dkI3qf3KbUe6hKFKa52w+AE0VCqECtf+QHAKgOL37tTaNCnuX1nAAQ4ZhyP+kYVKf8rLmJ/feDQ==",
"requires": {
"loose-envify": "^1.3.1",
"object-assign": "^4.1.1"
}
}
}
},
"react-native-datepicker": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/react-native-datepicker/-/react-native-datepicker-1.6.0.tgz",

View File

@@ -26,6 +26,7 @@
"react": "^16.5.0",
"react-native": "^0.57.1",
"react-native-action-button": "^2.6.9",
"react-native-camera": "^1.3.0",
"react-native-datepicker": "^1.6.0",
"react-native-dialogbox": "^0.6.6",
"react-native-document-picker": "^2.1.0",

View File

@@ -542,16 +542,32 @@ class AppComponent extends React.Component {
try {
const { type, value } = await ShareExtension.data();
if (type != "" && this.props.selectedFolderId) {
// reg.logger().info('Got share data:', type, value);
this.props.dispatch({
type: 'NAV_GO',
routeName: 'Note',
noteId: null,
sharedData: {type: type, value: value},
folderId: this.props.selectedFolderId,
itemType: 'note',
if (type != "" && this.props.selectedFolderId) {
const newNote = await Note.save({
title: Note.defaultTitleFromBody(value),
body: value,
parent_id: this.props.selectedFolderId
});
// This is a bit hacky, but the surest way to go to
// the needed note. We go back one screen in case there's
// already a note open - if we don't do this, the dispatch
// below will do nothing (because routeName wouldn't change)
// Then we wait a bit for the state to be set correctly, and
// finally we go to the new note.
this.props.dispatch({
type: 'NAV_BACK',
});
setTimeout(() => {
this.props.dispatch({
type: 'NAV_GO',
routeName: 'Note',
noteId: newNote.id,
});
}, 5);
}
} catch(e) {

0
ReactNativeClient/start_server.sh Normal file → Executable file
View File

View File

@@ -1,5 +1,5 @@
const fs = require('fs-extra');
const { execCommand, githubRelease, githubOauthToken } = require('./tool-utils.js');
const { execCommand, githubRelease, githubOauthToken, isWindows, fileExists } = require('./tool-utils.js');
const path = require('path');
const fetch = require('node-fetch');
const uriTemplate = require('uri-template');
@@ -60,9 +60,23 @@ async function main() {
console.info('Running from: ' + process.cwd());
console.info('Building APK file...');
const output = await execCommand('/mnt/c/Windows/System32/cmd.exe /c "cd ReactNativeClient\\android && gradlew.bat assembleRelease -PbuildDir=build --console plain"');
let restoreDir = null;
let apkBuildCmd = 'assembleRelease -PbuildDir=build --console plain';
if (await fileExists('/mnt/c/Windows/System32/cmd.exe')) {
apkBuildCmd = '/mnt/c/Windows/System32/cmd.exe /c "cd ReactNativeClient\\android && gradlew.bat ' + apkBuildCmd + '"';
} else {
process.chdir(rnDir + '/android');
apkBuildCmd = './gradlew ' + apkBuildCmd;
restoreDir = rootDir;
}
// const output = await execCommand('/mnt/c/Windows/System32/cmd.exe /c "cd ReactNativeClient\\android && gradlew.bat assembleRelease -PbuildDir=build --console plain"');
const output = await execCommand(apkBuildCmd);
console.info(output);
if (restoreDir) process.chdir(restoreDir);
await fs.mkdirp(releaseDir);
console.info('Copying APK to ' + apkFilePath);

View File

@@ -68,6 +68,8 @@ toolUtils.unlinkForce = async function(filePath) {
}
toolUtils.fileExists = async function(filePath) {
const fs = require('fs-extra');
return new Promise((resolve, reject) => {
fs.stat(filePath, function(err, stat) {
if (err == null) {
@@ -115,4 +117,16 @@ toolUtils.githubRelease = async function(project, tagName, isDraft) {
return responseJson;
}
toolUtils.isLinux = () => {
return process && process.platform === 'linux';
}
toolUtils.isWindows = () => {
return process && process.platform === 'win32';
}
toolUtils.isMac = () => {
return process && process.platform === 'darwin';
}
module.exports = toolUtils;

View File

@@ -251,6 +251,22 @@
</ul>
</div>
<h1 id="joplin-changelog">Joplin changelog</h1>
<h2 id="-v1-0-114-https-github-com-laurent22-joplin-releases-tag-v1-0-114-2018-10-24t20-14-10z"><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.114">v1.0.114</a> - 2018-10-24T20:14:10Z</h2>
<ul>
<li>Fixes <a href="https://github.com/laurent22/joplin/issues/832">#832</a>: Enex import: Don&#39;t add extra line breaks at the beginning of list item when it contains a block element</li>
<li>Fixes <a href="https://github.com/laurent22/joplin/issues/798">#798</a>: Enable Select All shortcut in macOS</li>
<li>API: Fixed handling of PUT method and log errors to file</li>
<li>Api: Fixes <a href="https://github.com/laurent22/joplin/issues/843">#843</a>: Fixed regression that was preventing resource metadata from being downloaded</li>
<li>Fixes <a href="https://github.com/laurent22/joplin/issues/847">#847</a>: Prevent view from scrolling to top when clicking checkbox and editor not visible</li>
<li>Resolves <a href="https://github.com/laurent22/joplin/issues/751">#751</a>: Allow switching between todo and note when multiple notes are selected</li>
<li>Fixed potential crash that can happen if editor is not ready</li>
<li>Prevent URLs added via A tag from being opened inside app</li>
<li>Fixes <a href="https://github.com/laurent22/joplin/issues/853">#853</a>: Replace characters to equivalent US-ASCII ones when exporting files</li>
<li>Improved the way resources are loaded to prepare to allow making downloading resources optional, and to make sync faster</li>
<li>Fixes <a href="https://github.com/laurent22/joplin/issues/312">#312</a> (maybe): Removed power saving feature, which wasn\&#39;t doing anything and added a possible fix to the UI freezing issue on Linux</li>
<li>Improved: Handle internal anchors</li>
<li>Improved Linux install script</li>
</ul>
<h2 id="-v1-0-111-https-github-com-laurent22-joplin-releases-tag-v1-0-111-2018-09-30t20-15-09z"><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.111">v1.0.111</a> - 2018-09-30T20:15:09Z</h2>
<p>This is mainly a release to fix a bug related to the new IMG tag support.</p>
<ul>
@@ -496,12 +512,6 @@
<li>Fixed: <a href="https://github.com/laurent22/joplin/issues/241">#241</a>: Ignore response for certain WebDAV calls to improve compatibility with some services.</li>
<li>Updated: French and Español translation</li>
</ul>
<h2 id="-v1-0-66-https-github-com-laurent22-joplin-releases-tag-v1-0-66-2018-02-18t23-09-09z"><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.66">v1.0.66</a> - 2018-02-18T23:09:09Z</h2>
<ul>
<li>Fixed: Local items were no longer being deleted via sync.</li>
<li>Improved: More debug information when WebDAV sync target does not work.</li>
<li>Improved: Compatibility with some WebDAV services (Seafile in particular)</li>
</ul>
<script>
function stickyHeader() {

View File

@@ -279,17 +279,17 @@
<tbody>
<tr>
<td>Windows (32 and 64-bit)</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/Joplin-Setup-1.0.111.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a></td>
<td>or Get the <a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/JoplinPortable.exe'>Portable version</a><br>(to run from a USB key, etc.)</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/Joplin-Setup-1.0.114.exe'><img alt='Get it on Windows' height="40px" src='https://joplin.cozic.net/images/BadgeWindows.png'/></a></td>
<td>or Get the <a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/JoplinPortable.exe'>Portable version</a><br>(to run from a USB key, etc.)</td>
</tr>
<tr>
<td>macOS</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/Joplin-1.0.111.dmg'><img alt='Get it on macOS' height="40px" src='https://joplin.cozic.net/images/BadgeMacOS.png'/></a></td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/Joplin-1.0.114.dmg'><img alt='Get it on macOS' height="40px" src='https://joplin.cozic.net/images/BadgeMacOS.png'/></a></td>
<td></td>
</tr>
<tr>
<td>Linux</td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.111/Joplin-1.0.111-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a></td>
<td><a href='https://github.com/laurent22/joplin/releases/download/v1.0.114/Joplin-1.0.114-x86_64.AppImage'><img alt='Get it on Linux' height="40px" src='https://joplin.cozic.net/images/BadgeLinux.png'/></a></td>
<td>An Arch Linux package<br><a href="#terminal-application">is also available</a>.</td>
</tr>
</tbody>
@@ -311,7 +311,7 @@
<tr>
<td>Android</td>
<td><a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://joplin.cozic.net/images/BadgeAndroid.png'/></a></td>
<td>or <a href="https://github.com/laurent22/joplin-android/releases/download/android-v1.0.142/joplin-v1.0.142.apk">Download APK File</a></td>
<td>or <a href="https://github.com/laurent22/joplin-android/releases/download/android-v1.0.175/joplin-v1.0.175.apk">Download APK File</a></td>
</tr>
<tr>
<td>iOS</td>
@@ -404,7 +404,7 @@
:config sync.target 5
</code></pre><p>If synchronisation does not work, please consult the logs in the app profile directory - it is often due to a misconfigured URL or password. The log should indicate what the exact issue is.</p>
<h2 id="dropbox-synchronisation">Dropbox synchronisation</h2>
<p>When syncing with Dropbox, Joplin creates a sub-directory in Dropbox, in /Apps/Joplin and read/write the notes and notebooks from it. The application does not have access to anything outside this directory.</p>
<p>When syncing with Dropbox, Joplin creates a sub-directory in Dropbox, in <code>/Apps/Joplin</code> and read/write the notes and notebooks from it. The application does not have access to anything outside this directory.</p>
<p>On the <strong>desktop application</strong> or <strong>mobile application</strong>, select &quot;Dropbox&quot; as the synchronisation target in the config screen (it is selected by default). Then, to initiate the synchronisation process, click on the &quot;Synchronise&quot; button in the sidebar and follow the instructions.</p>
<p>On the <strong>terminal application</strong>, to initiate the synchronisation process, type <code>:sync</code>. You will be asked to follow a link to authorise the application. It is possible to also synchronise outside of the user interface by typing <code>joplin sync</code> from the terminal. This can be used to setup a cron script to synchronise at regular interval. For example, this would do it every 30 minutes:</p>
<pre><code>*/30 * * * * /path/to/joplin sync
@@ -417,6 +417,7 @@
<li><a href="https://www.fastmail.com/">Fastmail</a></li>
<li><a href="https://www.strato.fr/stockage-en-ligne/">HiDrive</a> from Strato. <a href="https://github.com/laurent22/joplin/issues/309">Setup help</a></li>
<li><a href="https://nginx.org/en/docs/http/ngx_http_dav_module.html">Nginx WebDAV Module</a></li>
<li><a href="https://nextcloud.com/">NextCloud</a></li>
<li><a href="https://owncloud.org/">OwnCloud</a></li>
<li><a href="https://www.seafile.com/">Seafile</a></li>
<li><a href="https://www.transip.nl/stack/">Stack</a></li>
@@ -459,7 +460,7 @@
<pre><code>[Link to my note](:/0b0d62d15e60409dac34f354b6e9e839)
</code></pre><p>Since getting the ID of a note is not straightforward, each app provides a way to create such link. In the <strong>desktop app</strong>, right click on a note an select &quot;Copy Markdown link&quot;. In the <strong>mobile app</strong>, open a note and, in the top right menu, select &quot;Copy Markdown link&quot;. You can then paste this link anywhere in another note.</p>
<h2 id="math-notation">Math notation</h2>
<p>Math expressions can be added using the <a href="https://khan.github.io/KaTeX/">Katex notation</a>. To add an inline equation, wrap the expression in <code>$EXPRESSION$</code>, eg. <code>$\sqrt{3x-1}+(1+x)^2$</code>. To create an expression block, wrap it as follow:</p>
<p>Math expressions can be added using the <a href="https://khan.github.io/KaTeX/">KaTeX notation</a>. To add an inline equation, wrap the expression in <code>$EXPRESSION$</code>, eg. <code>$\sqrt{3x-1}+(1+x)^2$</code>. To create an expression block, wrap it as follow:</p>
<pre><code>$$
EXPRESSION
$$

View File

@@ -261,23 +261,23 @@
<tbody>
<tr>
<td>Total Windows downloads</td>
<td>60940</td>
<td>72838</td>
</tr>
<tr>
<td>Total macOs downloads</td>
<td>24311</td>
<td>27452</td>
</tr>
<tr>
<td>Total Linux downloads</td>
<td>21700</td>
<td>25291</td>
</tr>
<tr>
<td>Windows %</td>
<td>57%</td>
<td>58%</td>
</tr>
<tr>
<td>macOS %</td>
<td>23%</td>
<td>22%</td>
</tr>
<tr>
<td>Linux %</td>
@@ -298,28 +298,36 @@
</thead>
<tbody>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.114">v1.0.114</a></td>
<td>2018-10-24T20:14:10Z</td>
<td></td>
<td>2</td>
<td></td>
<td>2 </td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.111">v1.0.111</a></td>
<td>2018-09-30T20:15:09Z</td>
<td>1</td>
<td></td>
<td></td>
<td>1 </td>
<td>11714</td>
<td>3080</td>
<td>3627</td>
<td>18421</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.110">v1.0.110</a></td>
<td>2018-09-29T12:29:21Z</td>
<td>782</td>
<td>243</td>
<td>95</td>
<td>1120</td>
<td>919</td>
<td>368</td>
<td>99</td>
<td>1386</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.109">v1.0.109</a></td>
<td>2018-09-27T18:01:41Z</td>
<td>1939</td>
<td>653</td>
<td>304</td>
<td>2896</td>
<td>2063</td>
<td>672</td>
<td>307</td>
<td>3042</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.108">v1.0.108</a></td>
@@ -332,58 +340,58 @@
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.107">v1.0.107</a></td>
<td>2018-09-16T19:51:07Z</td>
<td>6888</td>
<td>2103</td>
<td>1688</td>
<td>10679</td>
<td>7098</td>
<td>2108</td>
<td>1694</td>
<td>10900</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.106">v1.0.106</a></td>
<td>2018-09-08T15:23:40Z</td>
<td>4499</td>
<td>4501</td>
<td>1435</td>
<td>285</td>
<td>6219</td>
<td>288</td>
<td>6224</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.105">v1.0.105</a></td>
<td>2018-09-05T11:29:36Z</td>
<td>4552</td>
<td>1544</td>
<td>1426</td>
<td>7522</td>
<td>4555</td>
<td>1549</td>
<td>1427</td>
<td>7531</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.104">v1.0.104</a></td>
<td>2018-06-28T20:25:36Z</td>
<td>14943</td>
<td>14947</td>
<td>4649</td>
<td>6882</td>
<td>26474</td>
<td>6893</td>
<td>26489</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.103">v1.0.103</a></td>
<td>2018-06-21T19:38:13Z</td>
<td>2001</td>
<td>852</td>
<td>854</td>
<td>664</td>
<td>3517</td>
<td>3519</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.101">v1.0.101</a></td>
<td>2018-06-17T18:35:11Z</td>
<td>1283</td>
<td>1284</td>
<td>577</td>
<td>397</td>
<td>2257</td>
<td>2258</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.100">v1.0.100</a></td>
<td>2018-06-14T17:41:43Z</td>
<td>848</td>
<td>405</td>
<td>849</td>
<td>406</td>
<td>226</td>
<td>1479</td>
<td>1481</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.99">v1.0.99</a></td>
@@ -396,18 +404,18 @@
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.97">v1.0.97</a></td>
<td>2018-06-09T19:23:34Z</td>
<td>290</td>
<td>291</td>
<td>131</td>
<td>51</td>
<td>472</td>
<td>473</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.96">v1.0.96</a></td>
<td>2018-05-26T16:36:39Z</td>
<td>2671</td>
<td>1194</td>
<td>1152</td>
<td>5017</td>
<td>1159</td>
<td>5024</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.95">v1.0.95</a></td>
@@ -429,9 +437,9 @@
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.93">v1.0.93</a></td>
<td>2018-05-14T11:36:01Z</td>
<td>1766</td>
<td>847</td>
<td>853</td>
<td>738</td>
<td>3351</td>
<td>3357</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.91">v1.0.91</a></td>
@@ -460,18 +468,18 @@
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.83">v1.0.83</a></td>
<td>2018-04-04T19:43:58Z</td>
<td>4442</td>
<td>2378</td>
<td>4454</td>
<td>2381</td>
<td>2627</td>
<td>9447</td>
<td>9462</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.82">v1.0.82</a></td>
<td>2018-03-31T19:16:31Z</td>
<td>684</td>
<td>383</td>
<td>92</td>
<td>1159</td>
<td>93</td>
<td>1160</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.81">v1.0.81</a></td>
@@ -524,18 +532,10 @@
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.67">v1.0.67</a></td>
<td>2018-02-19T22:51:08Z</td>
<td>1802</td>
<td>1805</td>
<td>579</td>
<td></td>
<td>2381</td>
</tr>
<tr>
<td><a href="https://github.com/laurent22/joplin/releases/tag/v1.0.66">v1.0.66</a></td>
<td>2018-02-18T23:09:09Z</td>
<td>313</td>
<td>107</td>
<td>72</td>
<td>492</td>
<td>2384</td>
</tr>
</tbody>
</table>

View File

@@ -1,5 +1,21 @@
# Joplin changelog
## [v1.0.114](https://github.com/laurent22/joplin/releases/tag/v1.0.114) - 2018-10-24T20:14:10Z
- Fixes [#832](https://github.com/laurent22/joplin/issues/832): Enex import: Don't add extra line breaks at the beginning of list item when it contains a block element
- Fixes [#798](https://github.com/laurent22/joplin/issues/798): Enable Select All shortcut in macOS
- API: Fixed handling of PUT method and log errors to file
- Api: Fixes [#843](https://github.com/laurent22/joplin/issues/843): Fixed regression that was preventing resource metadata from being downloaded
- Fixes [#847](https://github.com/laurent22/joplin/issues/847): Prevent view from scrolling to top when clicking checkbox and editor not visible
- Resolves [#751](https://github.com/laurent22/joplin/issues/751): Allow switching between todo and note when multiple notes are selected
- Fixed potential crash that can happen if editor is not ready
- Prevent URLs added via A tag from being opened inside app
- Fixes [#853](https://github.com/laurent22/joplin/issues/853): Replace characters to equivalent US-ASCII ones when exporting files
- Improved the way resources are loaded to prepare to allow making downloading resources optional, and to make sync faster
- Fixes [#312](https://github.com/laurent22/joplin/issues/312) (maybe): Removed power saving feature, which wasn\'t doing anything and added a possible fix to the UI freezing issue on Linux
- Improved: Handle internal anchors
- Improved Linux install script
## [v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) - 2018-09-30T20:15:09Z
This is mainly a release to fix a bug related to the new IMG tag support.
@@ -257,10 +273,4 @@ Note: This fixes an invalid database upgrade in the previous version.
- Fixed: [#217](https://github.com/laurent22/joplin/issues/217): Display a message when the note has no content and only the note viewer is visible
- Fixed: [#240](https://github.com/laurent22/joplin/issues/240): Tags should be handled in a case-insensitive way
- Fixed: [#241](https://github.com/laurent22/joplin/issues/241): Ignore response for certain WebDAV calls to improve compatibility with some services.
- Updated: French and Español translation
## [v1.0.66](https://github.com/laurent22/joplin/releases/tag/v1.0.66) - 2018-02-18T23:09:09Z
- Fixed: Local items were no longer being deleted via sync.
- Improved: More debug information when WebDAV sync target does not work.
- Improved: Compatibility with some WebDAV services (Seafile in particular)
- Updated: French and Español translation

View File

@@ -2,42 +2,42 @@
Name | Value
--- | ---
Total Windows downloads | 60940
Total macOs downloads | 24311
Total Linux downloads | 21700
Windows % | 57%
macOS % | 23%
Total Windows downloads | 72838
Total macOs downloads | 27452
Total Linux downloads | 25291
Windows % | 58%
macOS % | 22%
Linux % | 20%
Version | Date | Windows | macOS | Linux | Total
--- | --- | --- | --- | --- | ---
[v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) | 2018-09-30T20:15:09Z | 1 | | | 1
[v1.0.110](https://github.com/laurent22/joplin/releases/tag/v1.0.110) | 2018-09-29T12:29:21Z | 782 | 243 | 95 | 1120
[v1.0.109](https://github.com/laurent22/joplin/releases/tag/v1.0.109) | 2018-09-27T18:01:41Z | 1939 | 653 | 304 | 2896
[v1.0.114](https://github.com/laurent22/joplin/releases/tag/v1.0.114) | 2018-10-24T20:14:10Z | | 2 | | 2
[v1.0.111](https://github.com/laurent22/joplin/releases/tag/v1.0.111) | 2018-09-30T20:15:09Z | 11714 | 3080 | 3627 | 18421
[v1.0.110](https://github.com/laurent22/joplin/releases/tag/v1.0.110) | 2018-09-29T12:29:21Z | 919 | 368 | 99 | 1386
[v1.0.109](https://github.com/laurent22/joplin/releases/tag/v1.0.109) | 2018-09-27T18:01:41Z | 2063 | 672 | 307 | 3042
[v1.0.108](https://github.com/laurent22/joplin/releases/tag/v1.0.108) | 2018-09-29T18:49:29Z | 4 | | | 4
[v1.0.107](https://github.com/laurent22/joplin/releases/tag/v1.0.107) | 2018-09-16T19:51:07Z | 6888 | 2103 | 1688 | 10679
[v1.0.106](https://github.com/laurent22/joplin/releases/tag/v1.0.106) | 2018-09-08T15:23:40Z | 4499 | 1435 | 285 | 6219
[v1.0.105](https://github.com/laurent22/joplin/releases/tag/v1.0.105) | 2018-09-05T11:29:36Z | 4552 | 1544 | 1426 | 7522
[v1.0.104](https://github.com/laurent22/joplin/releases/tag/v1.0.104) | 2018-06-28T20:25:36Z | 14943 | 4649 | 6882 | 26474
[v1.0.103](https://github.com/laurent22/joplin/releases/tag/v1.0.103) | 2018-06-21T19:38:13Z | 2001 | 852 | 664 | 3517
[v1.0.101](https://github.com/laurent22/joplin/releases/tag/v1.0.101) | 2018-06-17T18:35:11Z | 1283 | 577 | 397 | 2257
[v1.0.100](https://github.com/laurent22/joplin/releases/tag/v1.0.100) | 2018-06-14T17:41:43Z | 848 | 405 | 226 | 1479
[v1.0.107](https://github.com/laurent22/joplin/releases/tag/v1.0.107) | 2018-09-16T19:51:07Z | 7098 | 2108 | 1694 | 10900
[v1.0.106](https://github.com/laurent22/joplin/releases/tag/v1.0.106) | 2018-09-08T15:23:40Z | 4501 | 1435 | 288 | 6224
[v1.0.105](https://github.com/laurent22/joplin/releases/tag/v1.0.105) | 2018-09-05T11:29:36Z | 4555 | 1549 | 1427 | 7531
[v1.0.104](https://github.com/laurent22/joplin/releases/tag/v1.0.104) | 2018-06-28T20:25:36Z | 14947 | 4649 | 6893 | 26489
[v1.0.103](https://github.com/laurent22/joplin/releases/tag/v1.0.103) | 2018-06-21T19:38:13Z | 2001 | 854 | 664 | 3519
[v1.0.101](https://github.com/laurent22/joplin/releases/tag/v1.0.101) | 2018-06-17T18:35:11Z | 1284 | 577 | 397 | 2258
[v1.0.100](https://github.com/laurent22/joplin/releases/tag/v1.0.100) | 2018-06-14T17:41:43Z | 849 | 406 | 226 | 1481
[v1.0.99](https://github.com/laurent22/joplin/releases/tag/v1.0.99) | 2018-06-10T13:18:23Z | 1228 | 575 | 370 | 2173
[v1.0.97](https://github.com/laurent22/joplin/releases/tag/v1.0.97) | 2018-06-09T19:23:34Z | 290 | 131 | 51 | 472
[v1.0.96](https://github.com/laurent22/joplin/releases/tag/v1.0.96) | 2018-05-26T16:36:39Z | 2671 | 1194 | 1152 | 5017
[v1.0.97](https://github.com/laurent22/joplin/releases/tag/v1.0.97) | 2018-06-09T19:23:34Z | 291 | 131 | 51 | 473
[v1.0.96](https://github.com/laurent22/joplin/releases/tag/v1.0.96) | 2018-05-26T16:36:39Z | 2671 | 1194 | 1159 | 5024
[v1.0.95](https://github.com/laurent22/joplin/releases/tag/v1.0.95) | 2018-05-25T13:04:30Z | 381 | 186 | 81 | 648
[v1.0.94](https://github.com/laurent22/joplin/releases/tag/v1.0.94) | 2018-05-21T20:52:59Z | 1094 | 553 | 354 | 2001
[v1.0.93](https://github.com/laurent22/joplin/releases/tag/v1.0.93) | 2018-05-14T11:36:01Z | 1766 | 847 | 738 | 3351
[v1.0.93](https://github.com/laurent22/joplin/releases/tag/v1.0.93) | 2018-05-14T11:36:01Z | 1766 | 853 | 738 | 3357
[v1.0.91](https://github.com/laurent22/joplin/releases/tag/v1.0.91) | 2018-05-10T14:48:04Z | 812 | 531 | 286 | 1629
[v1.0.89](https://github.com/laurent22/joplin/releases/tag/v1.0.89) | 2018-05-09T13:05:05Z | 469 | 206 | 90 | 765
[v1.0.85](https://github.com/laurent22/joplin/releases/tag/v1.0.85) | 2018-05-01T21:08:24Z | 1638 | 929 | 607 | 3174
[v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 4442 | 2378 | 2627 | 9447
[v1.0.82](https://github.com/laurent22/joplin/releases/tag/v1.0.82) | 2018-03-31T19:16:31Z | 684 | 383 | 92 | 1159
[v1.0.83](https://github.com/laurent22/joplin/releases/tag/v1.0.83) | 2018-04-04T19:43:58Z | 4454 | 2381 | 2627 | 9462
[v1.0.82](https://github.com/laurent22/joplin/releases/tag/v1.0.82) | 2018-03-31T19:16:31Z | 684 | 383 | 93 | 1160
[v1.0.81](https://github.com/laurent22/joplin/releases/tag/v1.0.81) | 2018-03-28T08:13:58Z | 984 | 565 | 742 | 2291
[v1.0.79](https://github.com/laurent22/joplin/releases/tag/v1.0.79) | 2018-03-23T18:00:11Z | 919 | 509 | 353 | 1781
[v1.0.78](https://github.com/laurent22/joplin/releases/tag/v1.0.78) | 2018-03-17T15:27:18Z | 1302 | 836 | 841 | 2979
[v1.0.77](https://github.com/laurent22/joplin/releases/tag/v1.0.77) | 2018-03-16T15:12:35Z | 165 | 87 | 25 | 277
[v1.0.72](https://github.com/laurent22/joplin/releases/tag/v1.0.72) | 2018-03-14T09:44:35Z | 396 | 232 | 32 | 660
[v1.0.70](https://github.com/laurent22/joplin/releases/tag/v1.0.70) | 2018-02-28T20:04:30Z | 1844 | 1022 | 1220 | 4086
[v1.0.67](https://github.com/laurent22/joplin/releases/tag/v1.0.67) | 2018-02-19T22:51:08Z | 1802 | 579 | | 2381
[v1.0.66](https://github.com/laurent22/joplin/releases/tag/v1.0.66) | 2018-02-18T23:09:09Z | 313 | 107 | 72 | 492
[v1.0.67](https://github.com/laurent22/joplin/releases/tag/v1.0.67) | 2018-02-19T22:51:08Z | 1805 | 579 | | 2384