1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-27 20:29:45 +02:00

Compare commits

..

24 Commits

Author SHA1 Message Date
Laurent Cozic
35aebc9f52 Android release v1.3.3 2020-10-16 17:05:22 +01:00
Laurent Cozic
cb3e1cf1e9 Mobile: Upgraded React Native to v0.63
commit 2fb6cee901
Merge: 4e303be85f db509955f6
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 16:24:07 2020 +0100

    Merge branch 'dev' into rn_63

commit 4e303be85f
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 16:14:39 2020 +0100

    Clean up

commit e3a37ec2d6
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 15:57:55 2020 +0100

    Use different script for pre-commit and manual start

commit bd236648fc
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 15:56:45 2020 +0100

    Removed RN eslint config

commit e7feda41c9
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 15:27:08 2020 +0100

    Revert "Disable git hook for now"

    This reverts commit 89263ac742.

commit cfd63fe46f
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 13:02:32 2020 +0100

    Ask permission to use geo-location

commit 66059939a3
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 12:26:20 2020 +0100

    Fixed WebView race condition

commit 1e0d2b7b86
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 11:56:21 2020 +0100

    Fixed webview issues

commit f537d22d7f
Author: Laurent Cozic <laurent@cozic.net>
Date:   Fri Oct 16 11:08:29 2020 +0100

    Improve resource file watching

commit eec32cf70a
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 18:40:13 2020 +0100

    Removed cache package dependency and implemented one more suitable for React Native

commit efa346fea4
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 14:57:21 2020 +0100

    iOS: Added fonts to Info.plist although it was working without it

commit 572b647bc0
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 14:56:49 2020 +0100

    Specify content-type header for OneDrive to prevent network error

commit bcedf6c7f0
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 12:45:01 2020 +0100

    iOS: Disable long press menu since it is already built-in

commit 7359dd61d1
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 12:37:40 2020 +0100

    Removed unused react-native-device-info

commit 2d63ab36d3
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 12:35:54 2020 +0100

    iOS: Fixed taking a picture

commit 8e2875a91c
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 12:11:13 2020 +0100

    iOS: Restored camera roll functionality

commit 75f5edf2ad
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 11:40:13 2020 +0100

    iOS: Fixed build settings

commit b220c98419
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 11:40:03 2020 +0100

    iOS: Got images to work with WebKit

commit c34b43e841
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 10:24:52 2020 +0100

    iOS: Restore more settings

commit 32997611e6
Author: Laurent Cozic <laurent@cozic.net>
Date:   Thu Oct 15 10:15:14 2020 +0100

    iOS: Added back icons and other properties

commit b5811d7f7c
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 14 23:53:14 2020 +0100

    Got iOS build to work

commit dc6d7c00e0
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 14 18:40:06 2020 +0100

    Imported old settings in gradle build

commit dff59f5603
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 14 18:20:00 2020 +0100

    Restored sharing

commit 0bdb449e72
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 14 17:25:40 2020 +0100

    Updated NoteBodyViewer

commit 0c0d228815
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 14 16:54:42 2020 +0100

    Fixed networking

commit 6ff45ce485
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 14 13:11:00 2020 +0100

    Fixed document picker

commit cc889182b6
Author: Laurent Cozic <laurent@cozic.net>
Date:   Wed Oct 14 12:56:27 2020 +0100

    Added back support for alarms

commit 040261abfa
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 13 22:04:49 2020 +0100

    Fixed Clipboard and remove image-picker package

commit 1077ad8f16
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 13 21:54:52 2020 +0100

    Fixed Select Alarm dialog and PoorManIntervals class

commit 8296676fd5
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 13 21:32:52 2020 +0100

    Fixed icons and warnings

commit 3b0e3f6f43
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 13 17:02:59 2020 +0100

    Got app to build again

commit 89263ac742
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 13 15:41:17 2020 +0100

    Disable git hook for now

commit d6da162f67
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 13 15:39:12 2020 +0100

    Restored back all RN packages

commit 7f8ce3732c
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 13 15:13:12 2020 +0100

    Restored base packages

commit ea59726eb3
Author: Laurent Cozic <laurent@cozic.net>
Date:   Tue Oct 13 15:05:17 2020 +0100

    Started over from scratch
2020-10-16 16:26:19 +01:00
Andros Fenollosa
db509955f6 Cli: Updated installation script with BSD support (#3930) 2020-10-16 15:18:57 +01:00
Caleb John
fb39899f8e Desktop, Cli: Regression: Fix export of pluginAssets when exporting to html/pdf (#3927) 2020-10-16 15:18:19 +01:00
Laurent Cozic
f5d4bedc07 Doc: Fixed plugin API 2020-10-15 16:08:01 +01:00
Laurent Cozic
e710709c15 Fixed special space 2020-10-15 15:54:31 +01:00
Laurent Cozic
d74d6d9539 Update website 2020-10-15 15:35:43 +01:00
Laurent Cozic
435e8dfc3b Trying deployment again 2020-10-15 15:17:18 +01:00
Laurent Cozic
6c68459b34 Update website 2020-10-15 15:07:26 +01:00
Laurent Cozic
2e75a63b26 Updatee website 2020-10-13 13:02:35 +01:00
Laurent Cozic
c328996568 Desktop: Fixed toggleNoteList and toggleSidebar commands 2020-10-13 13:01:02 +01:00
Laurent Cozic
c648f19693 Desktop: Added support for Menu API for plugins 2020-10-13 12:57:03 +01:00
Laurent Cozic
2caaf8e8c1 Desktop: Added support for plugins packaged as JS bundles 2020-10-13 11:16:36 +01:00
Laurent Cozic
ceb7a7303d Desktop: Plugin API - added support for settings.globalValue method 2020-10-13 09:59:53 +01:00
Laurent Cozic
c01f533342 Desktop: Regression: Remove Hide Joplin menu item on Linux too 2020-10-13 09:45:40 +01:00
Laurent Cozic
ff50361e19 Merge branch 'dev' into release-1.3 2020-10-13 09:42:26 +01:00
Laurent Cozic
3539a452a3 Desktop: Remove Hide Joplin menu item on Linux and Windows 2020-10-12 10:45:00 +01:00
Laurent Cozic
9dfe084a02 Destkop: Create template directory on startup 2020-10-12 09:52:36 +01:00
Laurent Cozic
66204401c9 Desktop: Fixes #3899: Regression - Layout Button Sequence menu items were disabled 2020-10-11 22:22:04 +01:00
Laurent Cozic
0644e2897d Security: Updated packages to fix security vulnerabilities 2020-10-11 22:16:53 +01:00
Laurent Cozic
5761451def Merge branch 'dev' into release-1.3 2020-10-11 22:13:06 +01:00
Laurent Cozic
12db3d20ee Electron release v1.3.2 2020-10-11 19:37:57 +01:00
Laurent Cozic
80a70a6649 Desktop: Regression: Context menu in sidebar could point to wrong item 2020-10-11 19:37:12 +01:00
Laurent Cozic
02ed297529 tab 2020-10-11 19:27:33 +01:00
280 changed files with 15668 additions and 7449 deletions

View File

@@ -64,11 +64,13 @@ CliClient/build/
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
CliClient/app/LinkSelector.js
CliClient/app/services/plugins/PluginRunner.js
CliClient/tests/InMemoryCache.js
CliClient/tests/models_Setting.js
CliClient/tests/services_CommandService.js
CliClient/tests/services_InteropService.js
CliClient/tests/services_PluginService.js
CliClient/tests/services_rest_Api.js
CliClient/tests/services/plugins/api/JoplinSetting.js
CliClient/tests/services/plugins/sandboxProxy.js
CliClient/tests/synchronizer_LockHandler.js
CliClient/tests/synchronizer_MigrationHandler.js
@@ -200,13 +202,21 @@ ReactNativeClient/lib/commands/historyBackward.js
ReactNativeClient/lib/commands/historyForward.js
ReactNativeClient/lib/commands/synchronize.js
ReactNativeClient/lib/components/BackButtonDialogBox.js
ReactNativeClient/lib/components/CameraView.js
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnMessage.js
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useSource.js
ReactNativeClient/lib/components/NoteBodyViewer/NoteBodyViewer.js
ReactNativeClient/lib/components/screens/Note.js
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
ReactNativeClient/lib/components/SelectDateTimeDialog.js
ReactNativeClient/lib/errorUtils.js
ReactNativeClient/lib/eventManager.js
ReactNativeClient/lib/hooks/useEffectDebugger.js
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
ReactNativeClient/lib/hooks/usePrevious.js
ReactNativeClient/lib/hooks/usePropsDebugger.js
ReactNativeClient/lib/InMemoryCache.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
@@ -218,6 +228,7 @@ ReactNativeClient/lib/markdownUtils.js
ReactNativeClient/lib/models/Alarm.js
ReactNativeClient/lib/models/Setting.js
ReactNativeClient/lib/ntpDate.js
ReactNativeClient/lib/PoorManIntervals.js
ReactNativeClient/lib/reducer.js
ReactNativeClient/lib/services/AlarmService.js
ReactNativeClient/lib/services/AlarmServiceDriver.android.js
@@ -263,11 +274,13 @@ ReactNativeClient/lib/services/plugins/api/JoplinSettings.js
ReactNativeClient/lib/services/plugins/api/JoplinViews.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsDialogs.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenuItems.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenus.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsPanels.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsToolbarButtons.js
ReactNativeClient/lib/services/plugins/api/JoplinWorkspace.js
ReactNativeClient/lib/services/plugins/api/types.js
ReactNativeClient/lib/services/plugins/BasePluginRunner.js
ReactNativeClient/lib/services/plugins/MenuController.js
ReactNativeClient/lib/services/plugins/MenuItemController.js
ReactNativeClient/lib/services/plugins/Plugin.js
ReactNativeClient/lib/services/plugins/PluginService.js

13
.gitignore vendored
View File

@@ -58,11 +58,13 @@ plugin_types/
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
CliClient/app/LinkSelector.js
CliClient/app/services/plugins/PluginRunner.js
CliClient/tests/InMemoryCache.js
CliClient/tests/models_Setting.js
CliClient/tests/services_CommandService.js
CliClient/tests/services_InteropService.js
CliClient/tests/services_PluginService.js
CliClient/tests/services_rest_Api.js
CliClient/tests/services/plugins/api/JoplinSetting.js
CliClient/tests/services/plugins/sandboxProxy.js
CliClient/tests/synchronizer_LockHandler.js
CliClient/tests/synchronizer_MigrationHandler.js
@@ -194,13 +196,21 @@ ReactNativeClient/lib/commands/historyBackward.js
ReactNativeClient/lib/commands/historyForward.js
ReactNativeClient/lib/commands/synchronize.js
ReactNativeClient/lib/components/BackButtonDialogBox.js
ReactNativeClient/lib/components/CameraView.js
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnMessage.js
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
ReactNativeClient/lib/components/NoteBodyViewer/hooks/useSource.js
ReactNativeClient/lib/components/NoteBodyViewer/NoteBodyViewer.js
ReactNativeClient/lib/components/screens/Note.js
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
ReactNativeClient/lib/components/SelectDateTimeDialog.js
ReactNativeClient/lib/errorUtils.js
ReactNativeClient/lib/eventManager.js
ReactNativeClient/lib/hooks/useEffectDebugger.js
ReactNativeClient/lib/hooks/useImperativeHandlerDebugger.js
ReactNativeClient/lib/hooks/usePrevious.js
ReactNativeClient/lib/hooks/usePropsDebugger.js
ReactNativeClient/lib/InMemoryCache.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/checkbox.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/fence.js
ReactNativeClient/lib/joplin-renderer/MdToHtml/rules/mermaid.js
@@ -212,6 +222,7 @@ ReactNativeClient/lib/markdownUtils.js
ReactNativeClient/lib/models/Alarm.js
ReactNativeClient/lib/models/Setting.js
ReactNativeClient/lib/ntpDate.js
ReactNativeClient/lib/PoorManIntervals.js
ReactNativeClient/lib/reducer.js
ReactNativeClient/lib/services/AlarmService.js
ReactNativeClient/lib/services/AlarmServiceDriver.android.js
@@ -257,11 +268,13 @@ ReactNativeClient/lib/services/plugins/api/JoplinSettings.js
ReactNativeClient/lib/services/plugins/api/JoplinViews.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsDialogs.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenuItems.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsMenus.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsPanels.js
ReactNativeClient/lib/services/plugins/api/JoplinViewsToolbarButtons.js
ReactNativeClient/lib/services/plugins/api/JoplinWorkspace.js
ReactNativeClient/lib/services/plugins/api/types.js
ReactNativeClient/lib/services/plugins/BasePluginRunner.js
ReactNativeClient/lib/services/plugins/MenuController.js
ReactNativeClient/lib/services/plugins/MenuItemController.js
ReactNativeClient/lib/services/plugins/Plugin.js
ReactNativeClient/lib/services/plugins/PluginService.js

View File

@@ -4199,11 +4199,6 @@
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4="
},
"memory-cache": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
"integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo="
},
"micromatch": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",

View File

@@ -6,7 +6,7 @@
"scripts": {
"test": "gulp buildTests -L && node node_modules/jasmine/bin/jasmine.js --fail-fast=true --config=tests/support/jasmine.json",
"test-ci": "gulp buildTests -L && node node_modules/jasmine/bin/jasmine.js --config=tests/support/jasmine.json",
"postinstall": "npm run build && patch-package --patch-dir ../patches",
"postinstall": "npm run build && patch-package --patch-dir ../patches/shared && patch-package --patch-dir ../patches/node",
"build": "gulp build",
"start": "gulp build -L && node 'build/main.js' --stack-trace-enabled --log-level debug --env dev"
},
@@ -80,7 +80,6 @@
"markdown-it-toc-done-right": "^4.1.0",
"md5": "^2.2.1",
"md5-file": "^4.0.0",
"memory-cache": "^0.2.0",
"mime": "^2.0.3",
"moment": "^2.24.0",
"multiparty": "^4.2.1",

View File

@@ -0,0 +1,59 @@
import InMemoryCache from 'lib/InMemoryCache';
const { time } = require('lib/time-utils.js');
describe('InMemoryCache', function() {
it('should get and set values', () => {
const cache = new InMemoryCache();
expect(cache.value('test')).toBe(undefined);
expect(cache.value('test', 'default')).toBe('default');
cache.setValue('test', 'something');
expect(cache.value('test')).toBe('something');
// Check we get the exact same object back (cache should not copy)
const someObj = { abcd: '123' };
cache.setValue('someObj', someObj);
expect(cache.value('someObj')).toBe(someObj);
});
it('should expire values', async () => {
const cache = new InMemoryCache();
// Check that the value is udefined once the cache has expired
cache.setValue('test', 'something', 500);
expect(cache.value('test')).toBe('something');
await time.msleep(510);
expect(cache.value('test')).toBe(undefined);
// Check that the TTL is reset every time setValue is called
cache.setValue('test', 'something', 300);
await time.msleep(100);
cache.setValue('test', 'something', 300);
await time.msleep(100);
cache.setValue('test', 'something', 300);
await time.msleep(100);
cache.setValue('test', 'something', 300);
await time.msleep(100);
expect(cache.value('test')).toBe('something');
});
it('should delete old records', async () => {
const cache = new InMemoryCache(5);
cache.setValue('1', '1');
cache.setValue('2', '2');
cache.setValue('3', '3');
cache.setValue('4', '4');
cache.setValue('5', '5');
expect(cache.value('1')).toBe('1');
cache.setValue('6', '6');
expect(cache.value('1')).toBe(undefined);
});
});

View File

@@ -0,0 +1,16 @@
// import Setting from 'lib/models/Setting';
// const { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('../test-utils.js');
// describe('plugin_api_JoplinSetting', function() {
// beforeEach(async (done) => {
// await setupDatabaseAndSynchronizer(1);
// await switchClient(1);
// done();
// });
// it('should get and set plugin-specific values', asyncTest(async () => {
// await
// }));
// });

View File

@@ -2,7 +2,7 @@ import PluginRunner from '../app/services/plugins/PluginRunner';
import PluginService from 'lib/services/plugins/PluginService';
require('app-module-path').addPath(__dirname);
const { asyncTest, setupDatabaseAndSynchronizer, switchClient } = require('test-utils.js');
const { asyncTest, setupDatabaseAndSynchronizer, switchClient, expectThrow } = require('test-utils.js');
const Note = require('lib/models/Note');
const Folder = require('lib/models/Folder');
@@ -40,8 +40,7 @@ describe('services_PluginService', function() {
it('should load and run a simple plugin', asyncTest(async () => {
const service = newPluginService();
const plugin = await service.loadPlugin(`${testPluginDir}/simple`);
await service.runPlugin(plugin);
await service.loadAndRunPlugins([`${testPluginDir}/simple`]);
const allFolders = await Folder.all();
expect(allFolders.length).toBe(1);
@@ -55,9 +54,9 @@ describe('services_PluginService', function() {
it('should load and run a plugin that uses external packages', asyncTest(async () => {
const service = newPluginService();
const plugin = await service.loadPlugin(`${testPluginDir}/withExternalModules`);
await service.loadAndRunPlugins([`${testPluginDir}/withExternalModules`]);
const plugin = service.pluginById('withexternalmodules');
expect(plugin.id).toBe('withexternalmodules');
await service.runPlugin(plugin);
const allFolders = await Folder.all();
expect(allFolders.length).toBe(1);
@@ -78,4 +77,75 @@ describe('services_PluginService', function() {
expect(allFolders.map((f:any) => f.title).sort().join(', ')).toBe('multi - simple1, multi - simple2');
}));
it('should load plugins from JS bundles', asyncTest(async () => {
const service = newPluginService();
const plugin = await service.loadPluginFromString('example', '/tmp', `
/* joplin-manifest:
{
"manifest_version": 1,
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "Laurent Cozic",
"homepage_url": "https://joplinapp.org"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.data.post(['folders'], null, { title: "my plugin folder" });
},
});
`);
await service.runPlugin(plugin);
expect(plugin.manifest.manifest_version).toBe(1);
expect(plugin.manifest.name).toBe('JS Bundle test');
const allFolders = await Folder.all();
expect(allFolders.length).toBe(1);
}));
it('should load plugins from JS bundle files', asyncTest(async () => {
const service = newPluginService();
await service.loadAndRunPlugins(`${testPluginDir}/jsbundles`);
expect(!!service.pluginById('example')).toBe(true);
expect((await Folder.all()).length).toBe(1);
}));
it('should validate JS bundles', asyncTest(async () => {
const invalidJsBundles = [
`
/* joplin-manifest:
{
"not_a_valid_manifest_at_all": 1
}
*/
joplin.plugins.register({
onStart: async function() {},
});
`, `
/* joplin-manifest:
*/
joplin.plugins.register({
onStart: async function() {},
});
`, `
joplin.plugins.register({
onStart: async function() {},
});
`, '',
];
const service = newPluginService();
for (const jsBundle of invalidJsBundles) {
await expectThrow(async () => await service.loadPluginFromString('example', '/tmp', jsBundle));
}
}));
});

View File

@@ -146,7 +146,7 @@ describe('services_rest_Api', function() {
}));
const noteId = response.id;
{
const note = await Note.load(noteId);
expect(note.latitude).toBe('48.73207100');
@@ -154,7 +154,7 @@ describe('services_rest_Api', function() {
expect(note.altitude).toBe('21.0000');
}
await api.route('PUT', 'notes/' + noteId, null, JSON.stringify({
await api.route('PUT', `notes/${noteId}`, null, JSON.stringify({
latitude: '49',
longitude: '-3',
altitude: '22',

View File

@@ -3,6 +3,7 @@
"spec_files": [
"*.js",
"services/plugins/*.js",
"services/plugins/api/*.js",
"!test-utils.js"
],
"stopSpecOnExpectationFailure": false,

View File

@@ -0,0 +1,16 @@
/* joplin-manifest:
{
"manifest_version": 1,
"name": "JS Bundle test",
"description": "JS Bundle Test plugin",
"version": "1.0.0",
"author": "Laurent Cozic",
"homepage_url": "https://joplinapp.org"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.data.post(['folders'], null, { title: "my plugin folder" });
},
});

View File

@@ -0,0 +1,2 @@
dist/*
node_modules/

View File

@@ -0,0 +1,14 @@
# Joplin Plugin
This is a template to create a new Joplin plugin.
The main two files you will want to look at are:
- `/src/index.ts`, which contains the entry point for the plugin source code.
- `/src/manifest.json`, which is the plugin manifest. It contains information such as the plugin a name, version, etc.
The plugin is built using webpack, which create the compiled code in `/dist`. The project is setup to use TypeScript, although you can change the configuration to use plain JavaScript.
## Building the plugin
To build the plugin, simply run `npm run dist`.

View File

@@ -0,0 +1,15 @@
import Plugin from '../Plugin';
import Joplin from './Joplin';
import Logger from 'lib/Logger';
/**
* @ignore
*/
export default class Global {
private joplin_;
private requireWhiteList_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get joplin(): Joplin;
private requireWhiteList;
require(filePath: string): any;
get process(): any;
}

View File

@@ -0,0 +1,38 @@
import Plugin from '../Plugin';
import JoplinData from './JoplinData';
import JoplinPlugins from './JoplinPlugins';
import JoplinWorkspace from './JoplinWorkspace';
import JoplinFilters from './JoplinFilters';
import JoplinCommands from './JoplinCommands';
import JoplinViews from './JoplinViews';
import JoplinInterop from './JoplinInterop';
import JoplinSettings from './JoplinSettings';
import Logger from 'lib/Logger';
/**
* This is the main entry point to the Joplin API. You can access various services using the provided accessors.
*/
export default class Joplin {
private data_;
private plugins_;
private workspace_;
private filters_;
private commands_;
private views_;
private interop_;
private settings_;
constructor(logger: Logger, implementation: any, plugin: Plugin, store: any);
get data(): JoplinData;
get plugins(): JoplinPlugins;
get workspace(): JoplinWorkspace;
/**
* @ignore
*
* Not sure if it's the best way to hook into the app
* so for now disable filters.
*/
get filters(): JoplinFilters;
get commands(): JoplinCommands;
get views(): JoplinViews;
get interop(): JoplinInterop;
get settings(): JoplinSettings;
}

View File

@@ -0,0 +1,51 @@
import { Command } from './types';
/**
* This class allows executing or registering new Joplin commands. Commands can be executed or associated with
* {@link JoplinViewsToolbarButtons | toolbar buttons} or {@link JoplinViewsMenuItems | menu items}.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/register_command)
*
* ## Executing Joplin's internal commands
*
* It is also possible to execute internal Joplin's commands which, as of now, are not well documented.
* You can find the list directly on GitHub though at the following locations:
*
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/gui/MainScreen/commands
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/commands
* https://github.com/laurent22/joplin/tree/dev/ElectronClient/gui/NoteEditor/commands/editorCommandDeclarations.ts
*
* To view what arguments are supported, you can open any of these files and look at the `execute()` command.
*/
export default class JoplinCommands {
/**
* <span class="platform-desktop">desktop</span> Executes the given command.
* The `props` are the arguments passed to the command, and they vary based on the command
*
* ```typescript
* // Create a new note in the current notebook:
* await joplin.commands.execute('newNote');
*
* // Create a new sub-notebook under the provided notebook
* // Note: internally, notebooks are called "folders".
* await joplin.commands.execute('newFolder', { parent_id: "SOME_FOLDER_ID" });
* ```
*/
execute(commandName: string, props?: any): Promise<any>;
/**
* <span class="platform-desktop">desktop</span> Registers a new command.
*
* ```typescript
* // Register a new commmand called "testCommand1"
*
* await joplin.commands.register({
* name: 'testCommand1',
* label: 'My Test Command 1',
* iconName: 'fas fa-music',
* execute: () => {
* alert('Testing plugin command 1');
* },
* });
* ```
*/
register(command: Command): Promise<void>;
}

View File

@@ -0,0 +1,47 @@
import { Path } from './types';
/**
* This module provides access to the Joplin data API: https://joplinapp.org/api/references/rest_api/
* This is the main way to retrieve data, such as notes, notebooks, tags, etc.
* or to update them or delete them.
*
* This is also what you would use to search notes, via the `search` endpoint.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/simple)
*
* In general you would use the methods in this class as if you were using a REST API. There are four methods that map to GET, POST, PUT and DELETE calls.
* And each method takes these parameters:
*
* * `path`: This is an array that represents the path to the resource in the form `["resouceName", "resourceId", "resourceLink"]` (eg. ["tags", ":id", "notes"]). The "resources" segment is the name of the resources you want to access (eg. "notes", "folders", etc.). If not followed by anything, it will refer to all the resources in that collection. The optional "resourceId" points to a particular resources within the collection. Finally, an optional "link" can be present, which links the resource to a collection of resources. This can be used in the API for example to retrieve all the notes associated with a tag.
* * `query`: (Optional) The query parameters. In a URL, this is the part after the question mark "?". In this case, it should be an object with key/value pairs.
* * `data`: (Optional) Applies to PUT and POST calls only. The request body contains the data you want to create or modify, for example the content of a note or folder.
* * `files`: (Optional) Used to create new resources and associate them with files.
*
* Please refer to the [Joplin API documentation](https://joplinapp.org/api/references/rest_api/) for complete details about each call. As the plugin runs within the Joplin application **you do not need an authorisation token** to use this API.
*
* For example:
*
* ```typescript
* // Get a note ID, title and body
* const noteId = 'some_note_id';
* const note = await joplin.data.get(['notes', noteId], { fields: ['id', 'title', 'body'] });
*
* // Get all folders
* const folders = await joplin.data.get(['folders']);
*
* // Set the note body
* await joplin.data.put(['notes', noteId], null, { body: "New note body" });
*
* // Create a new note under one of the folders
* await joplin.data.post(['notes'], null, { body: "my new note", title: "some title", parent_id: folders[0].id });
* ```
*/
export default class JoplinData {
private api_;
private pathSegmentRegex_;
private serializeApiBody;
private pathToString;
get(path: Path, query?: any): Promise<any>;
post(path: Path, query?: any, body?: any, files?: any[]): Promise<any>;
put(path: Path, query?: any, body?: any, files?: any[]): Promise<any>;
delete(path: Path, query?: any): Promise<any>;
}

View File

@@ -0,0 +1,10 @@
/**
* @ignore
*
* Not sure if it's the best way to hook into the app
* so for now disable filters.
*/
export default class JoplinFilters {
on(name: string, callback: Function): Promise<void>;
off(name: string, callback: Function): Promise<void>;
}

View File

@@ -0,0 +1,17 @@
import { ExportModule, ImportModule } from './types';
/**
* Provides a way to create modules to import external data into Joplin or to export notes into any arbitrary format.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/json_export)
*
* To implement an import or export module, you would simply define an object with various event handlers that are called
* by the application during the import/export process.
*
* See the documentation of the [[ExportModule]] and [[ImportModule]] for more information.
*
* You may also want to refer to the Joplin API documentation to see the list of properties for each item (note, notebook, etc.) - https://joplinapp.org/api/references/rest_api/
*/
export default class JoplinInterop {
registerExportModule(module: ExportModule): Promise<void>;
registerImportModule(module: ImportModule): Promise<void>;
}

View File

@@ -0,0 +1,24 @@
import Plugin from '../Plugin';
import Logger from 'lib/Logger';
import { Script } from './types';
/**
* This class provides access to plugin-related features.
*/
export default class JoplinPlugins {
private logger;
private plugin;
constructor(logger: Logger, plugin: Plugin);
/**
* Registers a new plugin. This is the entry point when creating a plugin. You should pass a simple object with an `onStart` method to it.
* That `onStart` method will be executed as soon as the plugin is loaded.
*
* ```typescript
* joplin.plugins.register({
* onStart: async function() {
* // Run your plugin code here
* }
* });
* ```
*/
register(script: Script): Promise<void>;
}

View File

@@ -0,0 +1,43 @@
import Plugin from '../Plugin';
import { SettingItem, SettingSection } from './types';
/**
* This API allows registering new settings and setting sections, as well as getting and setting settings. Once a setting has been registered it will appear in the config screen and be editable by the user.
*
* Settings are essentially key/value pairs.
*
* Note: Currently this API does **not** provide access to Joplin's built-in settings. This is by design as plugins that modify user settings could give unexpected results
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/settings)
*/
export default class JoplinSettings {
private plugin_;
constructor(plugin: Plugin);
private namespacedKey;
/**
* Registers a new setting. Note that registering a setting item is dynamic and will be gone next time Joplin starts.
* What it means is that you need to register the setting every time the plugin starts (for example in the onStart event).
* The setting value however will be preserved from one launch to the next so there is no risk that it will be lost even if for some
* reason the plugin fails to start at some point.
*/
registerSetting(key: string, settingItem: SettingItem): Promise<void>;
/**
* Registers a new setting section. Like for registerSetting, it is dynamic and needs to be done every time the plugin starts.
*/
registerSection(name: string, section: SettingSection): Promise<void>;
/**
* Gets a setting value (only applies to setting you registered from your plugin)
*/
value(key: string): Promise<any>;
/**
* Sets a setting value (only applies to setting you registered from your plugin)
*/
setValue(key: string, value: any): Promise<void>;
/**
* Gets a global setting value, including app-specific settings and those set by other plugins.
*
* The list of available settings is not documented yet, but can be found by looking at the source code:
*
* https://github.com/laurent22/joplin/blob/3539a452a359162c461d2849829d2d42973eab50/ReactNativeClient/lib/models/Setting.ts#L142
*/
globalValue(key: string): Promise<any>;
}

View File

@@ -0,0 +1,28 @@
import Plugin from '../Plugin';
import JoplinViewsDialogs from './JoplinViewsDialogs';
import JoplinViewsMenuItems from './JoplinViewsMenuItems';
import JoplinViewsMenus from './JoplinViewsMenus';
import JoplinViewsToolbarButtons from './JoplinViewsToolbarButtons';
import JoplinViewsPanels from './JoplinViewsPanels';
/**
* This namespace provides access to view-related services.
*
* All view services provide a `create()` method which you would use to create the view object, whether it's a dialog, a toolbar button or a menu item.
* In some cases, the `create()` method will return a [[ViewHandle]], which you would use to act on the view, for example to set certain properties or call some methods.
*/
export default class JoplinViews {
private store;
private plugin;
private dialogs_;
private panels_;
private menuItems_;
private menus_;
private toolbarButtons_;
private implementation_;
constructor(implementation: any, plugin: Plugin, store: any);
get dialogs(): JoplinViewsDialogs;
get panels(): JoplinViewsPanels;
get menuItems(): JoplinViewsMenuItems;
get menus(): JoplinViewsMenus;
get toolbarButtons(): JoplinViewsToolbarButtons;
}

View File

@@ -0,0 +1,36 @@
import Plugin from '../Plugin';
import { ButtonSpec, ViewHandle, ButtonId } from './types';
/**
* Allows creating and managing dialogs. A dialog is modal window that contains a webview and a row of buttons. You can update the update the webview using the `setHtml` method.
* Dialogs are hidden by default and you need to call `open()` to open them. Once the user clicks on a button, the `open` call will return and provide the button ID that was
* clicked on. There is currently no "close" method since the dialog should be thought as a modal one and thus can only be closed by clicking on one of the buttons.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/dialog)
*/
export default class JoplinViewsDialogs {
private store;
private plugin;
private implementation_;
constructor(implementation: any, plugin: Plugin, store: any);
private controller;
/**
* Creates a new dialog
*/
create(): Promise<ViewHandle>;
/**
* Displays a message box with OK/Cancel buttons. Returns the button index that was clicked - "0" for OK and "1" for "Cancel"
*/
showMessageBox(message: string): Promise<number>;
/**
* Sets the dialog HTML content
*/
setHtml(handle: ViewHandle, html: string): Promise<string>;
/**
* Sets the dialog buttons.
*/
setButtons(handle: ViewHandle, buttons: ButtonSpec[]): Promise<ButtonSpec[]>;
/**
* Opens the dialog
*/
open(handle: ViewHandle): Promise<ButtonId>;
}

View File

@@ -0,0 +1,16 @@
import { CreateMenuItemOptions, MenuItemLocation } from './types';
import Plugin from '../Plugin';
/**
* Allows creating and managing menu items.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/register_command)
*/
export default class JoplinViewsMenuItems {
private store;
private plugin;
constructor(plugin: Plugin, store: any);
/**
* Creates a new menu item and associate it with the given command. You can specify under which menu the item should appear using the `location` parameter.
*/
create(commandName: string, location?: MenuItemLocation, options?: CreateMenuItemOptions): Promise<void>;
}

View File

@@ -0,0 +1,18 @@
import { MenuItem, MenuItemLocation } from './types';
import Plugin from '../Plugin';
/**
* Allows creating menus.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/menu)
*/
export default class JoplinViewsMenus {
private store;
private plugin;
constructor(plugin: Plugin, store: any);
private registerCommandAccelerators;
/**
* Creates a new menu from the provided menu items and place it at the given location. As of now, it is only possible to place the
* menu as a sub-menu of the application build-in menus.
*/
create(label: string, menuItems: MenuItem[], location?: MenuItemLocation): Promise<void>;
}

View File

@@ -0,0 +1,30 @@
import Plugin from '../Plugin';
import { ViewHandle } from './types';
/**
* Allows creating and managing view panels. View panels currently are displayed at the right of the sidebar and allows displaying any HTML content (within a webview) and update it in real-time. For example
* it could be used to display a table of content for the active note, or display various metadata or graph.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/toc)
*/
export default class JoplinViewsPanels {
private store;
private plugin;
constructor(plugin: Plugin, store: any);
private controller;
/**
* Creates a new panel
*/
create(): Promise<ViewHandle>;
/**
* Sets the panel webview HTML
*/
setHtml(handle: ViewHandle, html: string): Promise<string>;
/**
* Adds and loads a new JS or CSS files into the panel.
*/
addScript(handle: ViewHandle, scriptPath: string): Promise<void>;
/**
* Called when a message is sent from the webview (using postMessage).
*/
onMessage(handle: ViewHandle, callback: Function): Promise<void>;
}

View File

@@ -0,0 +1,16 @@
import { ToolbarButtonLocation } from './types';
import Plugin from '../Plugin';
/**
* Allows creating and managing toolbar buttons.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/register_command)
*/
export default class JoplinViewsToolbarButtons {
private store;
private plugin;
constructor(plugin: Plugin, store: any);
/**
* Creates a new toolbar button and associate it with the given command.
*/
create(commandName: string, location: ToolbarButtonLocation): Promise<void>;
}

View File

@@ -0,0 +1,34 @@
/**
* The workspace service provides access to all the parts of Joplin that are being worked on - i.e. the currently selected notes or notebooks as well
* as various related events, such as when a new note is selected, or when the note content changes.
*
* [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins)
*/
export default class JoplinWorkspace {
private store;
constructor(_implementation: any, store: any);
/**
* Called when a new note or notes are selected.
*/
onNoteSelectionChange(callback: Function): Promise<void>;
/**
* Called when the content of a note changes.
*/
onNoteContentChange(callback: Function): Promise<void>;
/**
* Called when an alarm associated with a to-do is triggered.
*/
onNoteAlarmTrigger(callback: Function): Promise<void>;
/**
* Called when the synchronisation process has finished.
*/
onSyncComplete(callback: Function): Promise<void>;
/**
* Gets the currently selected note
*/
selectedNote(): Promise<any>;
/**
* Gets the IDs of the selected notes (can be zero, one, or many). Use the data API to retrieve information about these notes.
*/
selectedNoteIds(): Promise<string[]>;
}

View File

@@ -0,0 +1,5 @@
import type Joplin from './Joplin';
declare const joplin:Joplin;
export default joplin;

View File

@@ -0,0 +1,263 @@
// =================================================================
// Command API types
// =================================================================
export interface Command {
name: string
label: string
iconName?: string,
execute(props:any):Promise<any>
isEnabled?(props:any):boolean
mapStateToProps?(state:any):any
}
// =================================================================
// Interop API types
// =================================================================
export enum FileSystemItem {
File = 'file',
Directory = 'directory',
}
export enum ImportModuleOutputFormat {
Markdown = 'md',
Html = 'html',
}
/**
* Used to implement a module to export data from Joplin. [View the demo plugin](https://github.com/laurent22/joplin/tree/dev/CliClient/tests/support/plugins/json_export) for an example.
*
* In general, all the event handlers you'll need to implement take a `context` object as a first argument. This object will contain the export or import path as well as various optional properties, such as which notes or notebooks need to be exported.
*
* To get a better sense of what it will contain it can be useful to print it using `console.info(context)`.
*/
export interface ExportModule {
/**
* The format to be exported, eg "enex", "jex", "json", etc.
*/
format: string,
/**
* The description that will appear in the UI, for example in the menu item.
*/
description: string,
/**
* Whether the module will export a single file or multiple files in a directory. It affects the open dialog that will be presented to the user when using your exporter.
*/
target: FileSystemItem,
/**
* Only applies to single file exporters or importers
* It tells whether the format can package multiple notes into one file.
* For example JEX or ENEX can, but HTML cannot.
*/
isNoteArchive: boolean,
/**
* The extensions of the files exported by your module. For example, it is `["htm", "html"]` for the HTML module, and just `["jex"]` for the JEX module.
*/
fileExtensions?: string[],
/**
* Called when the export process starts.
*/
onInit(context:ExportContext): Promise<void>;
/**
* Called when an item needs to be processed. An "item" can be any Joplin object, such as a note, a folder, a notebook, etc.
*/
onProcessItem(context:ExportContext, itemType:number, item:any):Promise<void>;
/**
* Called when a resource file needs to be exported.
*/
onProcessResource(context:ExportContext, resource:any, filePath:string):Promise<void>;
/**
* Called when the export process is done.
*/
onClose(context:ExportContext):Promise<void>;
}
export interface ImportModule {
/**
* The format to be exported, eg "enex", "jex", "json", etc.
*/
format: string,
/**
* The description that will appear in the UI, for example in the menu item.
*/
description: string,
/**
* Only applies to single file exporters or importers
* It tells whether the format can package multiple notes into one file.
* For example JEX or ENEX can, but HTML cannot.
*/
isNoteArchive: boolean,
/**
* The type of sources that are supported by the module. Tells whether the module can import files or directories or both.
*/
sources: FileSystemItem[],
/**
* Tells the file extensions of the exported files.
*/
fileExtensions?: string[],
/**
* Tells the type of notes that will be generated, either HTML or Markdown (default).
*/
outputFormat?: ImportModuleOutputFormat,
/**
* Called when the import process starts. There is only one event handler within which you should import the complete data.
*/
onExec(context:ImportContext): Promise<void>;
}
export interface ExportOptions {
format?: string,
path?:string,
sourceFolderIds?: string[],
sourceNoteIds?: string[],
modulePath?:string,
target?:FileSystemItem,
}
export interface ExportContext {
destPath: string,
options: ExportOptions,
/**
* You can attach your own custom data using this propery - it will then be passed to each event handler, allowing you to keep state from one event to the next.
*/
userData?: any,
}
export interface ImportContext {
sourcePath: string,
options: any,
warnings: string[],
}
// =================================================================
// Misc types
// =================================================================
export interface Script {
onStart?(event:any):Promise<void>,
}
// =================================================================
// Menu types
// =================================================================
export interface CreateMenuItemOptions {
accelerator: string,
}
export enum MenuItemLocation {
File = 'file',
Edit = 'edit',
View = 'view',
Note = 'note',
Tools = 'tools',
Help = 'help',
Context = 'context',
}
export interface MenuItem {
commandName?: string,
accelerator?: string,
submenu?: MenuItem[],
label?: string,
}
// =================================================================
// View API types
// =================================================================
export interface ButtonSpec {
id: ButtonId,
title?: string,
onClick?():void,
}
export type ButtonId = string;
export enum ToolbarButtonLocation {
/**
* This toolbar in the top right corner of the application. It applies to the note as a whole, including its metadata.
*/
NoteToolbar = 'noteToolbar',
/**
* This toolbar is right above the text editor. It applies to the note body only.
*/
EditorToolbar = 'editorToolbar',
}
export type ViewHandle = string;
export interface EditorCommand {
name: string;
value?: any;
}
// =================================================================
// Settings types
// =================================================================
export enum SettingItemType {
Int = 1,
String = 2,
Bool = 3,
Array = 4,
Object = 5,
Button = 6,
}
// Redefine a simplified interface to mask internal details
// and to remove function calls as they would have to be async.
export interface SettingItem {
value: any,
type: SettingItemType,
public: boolean,
label:string,
description?:string,
isEnum?: boolean,
section?: string,
options?:any,
appTypes?:string[],
secure?: boolean,
advanced?: boolean,
minimum?: number,
maximum?: number,
step?: number,
}
export interface SettingSection {
label: string,
iconName?: string,
description?: string,
name?: string,
}
// =================================================================
// Data API types
// =================================================================
/**
* An array of at least one element and at most three elements.
*
* [0]: Resource name (eg. "notes", "folders", "tags", etc.)
* [1]: (Optional) Resource ID.
* [2]: (Optional) Resource link.
*/
export type Path = string[];

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,20 @@
{
"name": "joplin_plugin",
"version": "1.0.0",
"description": "",
"scripts": {
"dist": "webpack",
"postinstall": "npm run dist"
},
"keywords": [],
"author": "",
"license": "MIT",
"devDependencies": {
"@types/node": "^14.0.14",
"copy-webpack-plugin": "^6.1.0",
"ts-loader": "^7.0.5",
"typescript": "^3.9.3",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11"
}
}

View File

@@ -0,0 +1,25 @@
import joplin from 'api';
joplin.plugins.register({
onStart: async function() {
await joplin.views.menus.create('My Menu', [
{
commandName: "newNote",
},
{
commandName: "newFolder",
},
{
label: 'My sub-menu',
submenu: [
{
commandName: 'print',
},
{
commandName: 'setTags',
},
],
},
]);
},
});

View File

@@ -0,0 +1,8 @@
{
"manifest_version": 1,
"name": "Menu Test",
"description": "",
"version": "1.0.0",
"author": "",
"homepage_url": ""
}

View File

@@ -0,0 +1,10 @@
{
"compilerOptions": {
"outDir": "./dist/",
"module": "commonjs",
"target": "es2015",
"jsx": "react",
"allowJs": true,
"baseUrl": "."
}
}

View File

@@ -0,0 +1,44 @@
const path = require('path');
const CopyPlugin = require('copy-webpack-plugin');
module.exports = {
mode: 'production',
entry: './src/index.ts',
target: 'node',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
alias: {
api: path.resolve(__dirname, 'api')
},
extensions: [ '.tsx', '.ts', '.js' ],
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CopyPlugin({
patterns: [
{
from: "**/*",
context: path.resolve(__dirname, 'src'),
to: path.resolve(__dirname, 'dist'),
globOptions: {
ignore: [
'**/*.ts',
'**/*.tsx',
],
},
},
],
}),
],
};

View File

@@ -466,14 +466,14 @@ class Application extends BaseApplication {
async start(argv:string[]):Promise<any> {
const electronIsDev = require('electron-is-dev');
await fs.mkdirp(Setting.value('templateDir'), 0o755);
// If running inside a package, the command line, instead of being "node.exe <path> <flags>" is "joplin.exe <flags>" so
// insert an extra argument so that they can be processed in a consistent way everywhere.
if (!electronIsDev) argv.splice(1, 0, '.');
argv = await super.start(argv);
await fs.mkdirp(Setting.value('templateDir'), 0o755);
await this.applySettingsSideEffects();
if (Setting.value('sync.upgradeState') === Setting.SYNC_UPGRADE_STATE_MUST_DO) {

View File

@@ -4,7 +4,7 @@ import { _ } from 'lib/locale';
export const declaration:CommandDeclaration = {
name: 'toggleNoteList',
label: () => _('Toggle note list'),
iconName: 'fa-align-justify',
iconName: 'fas fa-align-justify',
};
export const runtime = (comp:any):CommandRuntime => {
@@ -14,8 +14,5 @@ export const runtime = (comp:any):CommandRuntime => {
type: 'NOTELIST_VISIBILITY_TOGGLE',
});
},
title: () => {
return _('Toggle note list');
},
};
};

View File

@@ -4,7 +4,7 @@ import { _ } from 'lib/locale';
export const declaration:CommandDeclaration = {
name: 'toggleSidebar',
label: () => _('Toggle sidebar'),
iconName: 'fa-bars',
iconName: 'fas fa-bars',
};
export const runtime = (comp:any):CommandRuntime => {
@@ -14,8 +14,5 @@ export const runtime = (comp:any):CommandRuntime => {
type: 'SIDEBAR_VISIBILITY_TOGGLE',
});
},
title: () => {
return _('Toggle sidebar');
},
};
};

View File

@@ -5,14 +5,14 @@ import { stateUtils } from 'lib/reducer';
import CommandService from 'lib/services/CommandService';
import MenuUtils from 'lib/services/commands/MenuUtils';
import KeymapService from 'lib/services/KeymapService';
import { utils as pluginUtils, ViewInfo } from 'lib/services/plugins/reducer';
import { PluginStates, utils as pluginUtils } from 'lib/services/plugins/reducer';
import shim from 'lib/shim';
import Setting from 'lib/models/Setting';
import versionInfo from 'lib/versionInfo';
import { Module } from 'lib/services/interop/types';
import InteropServiceHelper from '../InteropServiceHelper';
import { _ } from 'lib/locale';
import { MenuItemLocation } from 'lib/services/plugins/api/types';
import { MenuItem, MenuItemLocation } from 'lib/services/plugins/api/types';
const { connect } = require('react-redux');
const { reg } = require('lib/registry.js');
@@ -23,6 +23,51 @@ const Menu = bridge().Menu;
const PluginManager = require('lib/services/PluginManager');
const TemplateUtils = require('lib/TemplateUtils');
const menuUtils = new MenuUtils(CommandService.instance());
function pluginMenuItemsCommandNames(menuItems:MenuItem[]):string[] {
let output:string[] = [];
for (const menuItem of menuItems) {
if (menuItem.submenu) {
output = output.concat(pluginMenuItemsCommandNames(menuItem.submenu));
} else {
if (menuItem.commandName) output.push(menuItem.commandName);
}
}
return output;
}
function pluginCommandNames(plugins:PluginStates):string[] {
let output:string[] = [];
for (const view of pluginUtils.viewsByType(plugins, 'menu')) {
output = output.concat(pluginMenuItemsCommandNames(view.menuItems));
}
for (const view of pluginUtils.viewsByType(plugins, 'menuItem')) {
if (view.commandName) output.push(view.commandName);
}
return output;
}
function createPluginMenuTree(label:string, menuItems:MenuItem[], onMenuItemClick:Function) {
const output:any = {
label: label,
submenu: [],
};
for (const menuItem of menuItems) {
if (menuItem.submenu) {
output.submenu.push(createPluginMenuTree(menuItem.label, menuItem.submenu, onMenuItemClick));
} else {
output.submenu.push(menuUtils.commandToMenuItem(menuItem.commandName, onMenuItemClick));
}
}
return output;
}
interface Props {
dispatch: Function,
menuItemProps: any,
@@ -36,7 +81,8 @@ interface Props {
showNoteCounts: boolean,
uncompletedTodosOnTop: boolean,
showCompletedTodos: boolean,
pluginMenuItemInfos: ViewInfo[],
pluginMenuItems: any[],
pluginMenus: any[],
}
const commandNames:string[] = [
@@ -85,8 +131,6 @@ function menuItemSetEnabled(id:string, enabled:boolean) {
menuItem.enabled = enabled;
}
const menuUtils = new MenuUtils(CommandService.instance());
function useMenu(props:Props) {
const [menu, setMenu] = useState(null);
const [keymapLastChangeTime, setKeymapLastChangeTime] = useState(Date.now());
@@ -143,7 +187,7 @@ function useMenu(props:Props) {
useEffect(() => {
const keymapService = KeymapService.instance();
const pluginCommandNames = props.pluginMenuItemInfos.map((viewInfo:ViewInfo) => viewInfo.view.commandName);
const pluginCommandNames = props.pluginMenuItems.map((view:any) => view.commandName);
const menuItemDic = menuUtils.commandsToMenuItems(commandNames.concat(pluginCommandNames), (commandName:string) => onMenuItemClickRef.current(commandName));
const quitMenuItem = {
@@ -397,12 +441,16 @@ function useMenu(props:Props) {
}, shim.isMac() ? noItem : printItem, {
type: 'separator',
platforms: ['darwin'],
}, {
},
shim.isMac() ? {
label: _('Hide %s', 'Joplin'),
platforms: ['darwin'],
accelerator: shim.isMac() && keymapService.getAccelerator('hideApp'),
click: () => { bridge().electronApp().hide(); },
}, {
} : noItem,
{
type: 'separator',
},
quitMenuItem],
@@ -641,26 +689,36 @@ function useMenu(props:Props) {
rootMenus[key].submenu = cleanUpSeparators(rootMenus[key].submenu);
}
const pluginMenuItems = PluginManager.instance().menuItems();
for (const item of pluginMenuItems) {
const itemParent = rootMenus[item.parent] ? rootMenus[item.parent] : 'tools';
itemParent.submenu.push(item);
{
// This is for GotoAnything only - should be refactored since this plugin manager is not used otherwise
const pluginMenuItems = PluginManager.instance().menuItems();
for (const item of pluginMenuItems) {
const itemParent = rootMenus[item.parent] ? rootMenus[item.parent] : 'tools';
itemParent.submenu.push(item);
}
}
// TODO: test
const pluginViewInfos = props.pluginMenuItemInfos;
for (const info of pluginViewInfos) {
const location:MenuItemLocation = info.view.location;
for (const view of props.pluginMenuItems) {
const location:MenuItemLocation = view.location;
if (location === MenuItemLocation.Context) continue;
const itemParent = rootMenus[location];
if (!itemParent) {
reg.logger().error('Menu item location does not exist: ', location, info);
reg.logger().error('Menu item location does not exist: ', location, view);
} else {
itemParent.submenu.push(menuItemDic[info.view.commandName]);
itemParent.submenu.push(menuItemDic[view.commandName]);
}
}
for (const view of props.pluginMenus) {
if (view.location === MenuItemLocation.Context) continue;
const itemParent = rootMenus[view.location];
if (!itemParent) {
reg.logger().error('Menu location does not exist: ', location, view);
} else {
itemParent.submenu.push(createPluginMenuTree(view.label, view.menuItems, (commandName:string) => onMenuItemClickRef.current(commandName)));
}
}
@@ -725,7 +783,7 @@ function useMenu(props:Props) {
} else {
setMenu(Menu.buildFromTemplate(template));
}
}, [props.routeName, props.pluginMenuItemInfos, keymapLastChangeTime, modulesLastChangeTime]);
}, [props.routeName, props.pluginMenuItems, props.pluginMenus, keymapLastChangeTime, modulesLastChangeTime]);
useEffect(() => {
for (const commandName in props.menuItemProps) {
@@ -735,7 +793,7 @@ function useMenu(props:Props) {
const layoutButtonSequenceOptions = Setting.enumOptions('layoutButtonSequence');
for (const value in layoutButtonSequenceOptions) {
menuItemSetEnabled(`layoutButtonSequence_${value}`, props.layoutButtonSequence === Number(value));
menuItemSetChecked(`layoutButtonSequence_${value}`, props.layoutButtonSequence === Number(value));
}
function applySortItemCheckState(type:string) {
@@ -801,7 +859,7 @@ function MenuBar(props:Props):JSX.Element {
const mapStateToProps = (state:AppState) => {
return {
menuItemProps: menuUtils.commandsToMenuItemProps(state, commandNames),
menuItemProps: menuUtils.commandsToMenuItemProps(state, commandNames.concat(pluginCommandNames(state.pluginService.plugins))),
routeName: state.route.routeName,
selectedFolderId: state.selectedFolderId,
layoutButtonSequence: state.settings.layoutButtonSequence,
@@ -812,7 +870,8 @@ const mapStateToProps = (state:AppState) => {
showNoteCounts: state.settings.showNoteCounts,
uncompletedTodosOnTop: state.settings.uncompletedTodosOnTop,
showCompletedTodos: state.settings.showCompletedTodos,
pluginMenuItemInfos: stateUtils.selectArrayShallow({ array: pluginUtils.viewInfosByType(state.pluginService.plugins, 'menuItem') }, 'menuBar.pluginMenuItemInfos'),
pluginMenuItems: stateUtils.selectArrayShallow({ array: pluginUtils.viewsByType(state.pluginService.plugins, 'menuItem') }, 'menuBar.pluginMenuItems'),
pluginMenus: stateUtils.selectArrayShallow({ array: pluginUtils.viewsByType(state.pluginService.plugins, 'menu') }, 'menuBar.pluginMenus'),
};
};

View File

@@ -1,6 +1,6 @@
{
"name": "Joplin",
"version": "1.3.1",
"version": "1.3.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -1535,8 +1535,7 @@
},
"mkdirp": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"resolved": "",
"dev": true,
"optional": true,
"requires": {
@@ -1701,8 +1700,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"resolved": "",
"dev": true,
"optional": true
}
@@ -1817,8 +1815,7 @@
},
"tar": {
"version": "4.4.8",
"resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz",
"integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==",
"resolved": "",
"dev": true,
"optional": true,
"requires": {
@@ -5924,9 +5921,7 @@
"minimist": {
"version": "0.0.8",
"resolved": false,
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
"dev": true,
"optional": true
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"minipass": {
"version": "2.9.0",
@@ -5950,14 +5945,9 @@
}
},
"mkdirp": {
"version": "0.5.1",
"resolved": false,
"integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
"version": "0.5.5",
"dev": true,
"optional": true,
"requires": {
"minimist": "0.0.8"
}
"optional": true
},
"ms": {
"version": "2.1.2",
@@ -6127,8 +6117,7 @@
"dependencies": {
"minimist": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"resolved": "",
"dev": true,
"optional": true
}
@@ -8072,11 +8061,6 @@
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.0.4.tgz",
"integrity": "sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA=="
},
"memory-cache": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.2.0.tgz",
"integrity": "sha1-eJCwHVLADI68nVM+H46xfjA0hxo="
},
"mermaid": {
"version": "8.8.1",
"resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.8.1.tgz",

View File

@@ -1,11 +1,11 @@
{
"name": "Joplin",
"version": "1.3.1",
"version": "1.3.2",
"description": "Joplin for Desktop",
"main": "main.js",
"scripts": {
"dist": "node_modules/.bin/electron-builder",
"build": "patch-package --patch-dir ../patches && gulp build",
"build": "patch-package --patch-dir ../patches/shared && patch-package --patch-dir ../patches/node && gulp build",
"postinstall": "npm run build && gulp electronRebuild",
"start": "gulp build && electron . --env dev --log-level debug --no-welcome --open-dev-tools"
},
@@ -169,7 +169,6 @@
"markdown-it-toc-done-right": "^4.1.0",
"md5": "^2.2.1",
"md5-file": "^4.0.0",
"memory-cache": "^0.2.0",
"mermaid": "^8.8.1",
"moment": "^2.22.2",
"multiparty": "^4.2.1",

View File

@@ -1,4 +1,5 @@
#!/bin/bash
#!/usr/bin/env bash
set -e
#-----------------------------------------------------

View File

@@ -100,7 +100,7 @@ The Web Clipper is a browser extension that allows you to save web pages and scr
- [Note History spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/history.md)
- [Sync Lock spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/sync_lock.md)
- [Plugin Architecture spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/plugins.md)
- [Search Sorting spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/search_sorting.md)
- [Search Sorting spec](https://github.com/laurent22/joplin/blob/dev/readme/spec/search_sorting.md)
- Google Summer of Code 2020

View File

@@ -21,7 +21,7 @@ node_modules/warning/.*
[include]
[libs]
node_modules/react-native/Libraries/react-native/react-native-interface.js
node_modules/react-native/interface.js
node_modules/react-native/flow/
[options]
@@ -36,9 +36,8 @@ module.file_ext=.ios.js
munge_underscores=true
module.name_mapper='^react-native$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/react-native/react-native-implementation'
module.name_mapper='^react-native/\(.*\)$' -> '<PROJECT_ROOT>/node_modules/react-native/\1'
module.name_mapper='^[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'
module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '<PROJECT_ROOT>/node_modules/react-native/Libraries/Image/RelativeImageStub'
suppress_type=$FlowIssue
suppress_type=$FlowFixMe
@@ -57,7 +56,6 @@ untyped-type-import=warn
nonstrict-import=warn
deprecated-type=warn
unsafe-getters-setters=warn
inexact-spread=warn
unnecessary-invariant=warn
signature-verification-failure=warn
deprecated-utility=error
@@ -72,4 +70,4 @@ untyped-import
untyped-type-import
[version]
^0.105.0
^0.122.0

View File

@@ -20,7 +20,6 @@ DerivedData
*.hmap
*.ipa
*.xcuserstate
project.xcworkspace
# Android/IntelliJ
#
@@ -42,29 +41,19 @@ buck-out/
*.keystore
!debug.keystore
# CocoaPods
ios/Pods/
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
# screenshots whenever they are needed.
# For more information about the recommended setup visit:
# https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md
# https://docs.fastlane.tools/best-practices/source-control/
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
*/fastlane/report.xml
*/fastlane/Preview.html
*/fastlane/screenshots
# This is generated:
android/build*
android/app/build*
# Bundle artifact
*.jsbundle
android/.project
android/.settings/
android/app/.classpath
android/app/.project
android/app/.settings/
android/app/src/debug/res/
pluginAssets/
# CocoaPods
/ios/Pods/

View File

@@ -0,0 +1,6 @@
module.exports = {
bracketSpacing: false,
jsxBracketSameLine: true,
singleQuote: true,
trailingComma: 'all',
};

View File

@@ -13,7 +13,7 @@ import {
Image,
} from 'react-native';
import { renderFormatButtons } from './renderButtons';
import { NoteBodyViewer } from 'lib/components/note-body-viewer.js';
import NoteBodyViewer from 'lib/components/NoteBodyViewer/NoteBodyViewer';
const styles = StyleSheet.create({
buttonContainer: {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -15,9 +15,14 @@ import com.android.build.OutputFile
* // the name of the generated asset file containing your JS bundle
* bundleAssetName: "index.android.bundle",
*
* // the entry file for bundle generation
* // the entry file for bundle generation. If none specified and
* // "index.android.js" exists, it will be used. Otherwise "index.js" is
* // default. Can be overridden with ENTRY_FILE environment variable.
* entryFile: "index.android.js",
*
* // https://reactnative.dev/docs/performance#enable-the-ram-format
* bundleCommand: "ram-bundle",
*
* // whether to bundle JS and assets in debug mode
* bundleInDebug: false,
*
@@ -33,6 +38,13 @@ import com.android.build.OutputFile
* // bundleInPaidRelease: true,
* // bundleInBeta: true,
*
* // whether to disable dev mode in custom build variants (by default only disabled in release)
* // for example: to disable dev mode in the staging build type (if configured)
* devDisabledInStaging: true,
* // The configuration property can be in the following formats
* // 'devDisabledIn${productFlavor}${buildType}'
* // 'devDisabledIn${buildType}'
*
* // the root of your project, i.e. where "package.json" lives
* root: "../../",
*
@@ -66,7 +78,6 @@ import com.android.build.OutputFile
*/
project.ext.react = [
entryFile: "index.android.js",
enableHermes: false, // clean and rebuild if changing
]
@@ -99,6 +110,7 @@ def enableProguardInReleaseBuilds = false
* this variant is about 6MiB larger per architecture than default.
*/
def jscFlavor = 'org.webkit:android-jsc:+'
/**
* Whether to enable the Hermes VM.
*
@@ -111,37 +123,37 @@ def enableHermes = project.ext.react.get("enableHermes", false);
android {
compileSdkVersion rootProject.ext.compileSdkVersion
// To fix this error:
// > java.io.UncheckedIOException: java.io.IOException: Execution of compression failed. java.lang.OutOfMemoryError
// https://stackoverflow.com/q/57284812/561309
dexOptions { javaMaxHeapSize "4g" }
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
defaultConfig {
applicationId "net.cozic.joplin"
defaultConfig {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097583
versionName "1.3.0"
versionCode 2097591
versionName "1.3.3"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
missingDimensionStrategy 'react-native-camera', 'general'
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
signingConfigs {
debug {
// https://github.com/react-native-community/react-native-camera/issues/2138
missingDimensionStrategy 'react-native-camera', 'general'
// Needed to fix: The number of method references in a .dex file cannot exceed 64K
multiDexEnabled true
}
splits {
abi {
reset()
enable enableSeparateBuildPerCPUArchitecture
universalApk false // If true, also generate a universal APK
include "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
keyAlias 'androiddebugkey'
@@ -156,57 +168,54 @@ android {
}
}
}
buildTypes {
debug {
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.release
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
// applicationVariants are e.g. debug, release
applicationVariants.all { variant ->
variant.outputs.each { output ->
// For each separate APK per architecture, set a unique version code as described here:
// https://developer.android.com/studio/build/configure-apk-splits.html
def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
def abi = output.getFilter(OutputFile.ABI)
if (abi != null) { // null for the universal-debug, universal-release variants
output.versionCodeOverride =
versionCodes.get(abi) * 1048576 + defaultConfig.versionCode
}
}
}
}
dependencies {
implementation "org.webkit:android-jsc:r241213"
compile project(':react-native-push-notification')
// implementation (project(':react-native-camera')) {
// // This is required because com.google.firebase requires v16.0.x of com.google.android.gms
// // while react-native-camera requires v15.x, which results in broken dependencies with
// // this error message:
// //
// // The library com.google.android.gms:play-services-base is being requested by various other libraries at [[15.0.1,15.0.1]], but resolves to 16.0.1
// //
// // For the record: found solution by removing all Firebase stuff here and running "gradlew.bat :app:dependencies"
// // That shows that react-native-camera was the one requiring v15.0.1.
// exclude group: "com.google.android.gms"
// }
implementation project(':react-native-file-viewer')
implementation project(':react-native-securerandom')
implementation project(':react-native-fs')
implementation project(':react-native-image-picker')
implementation project(':react-native-vector-icons')
implementation project(':react-native-fs')
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "com.android.support:appcompat-v7:28.0.0"
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
}
debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
exclude group:'com.squareup.okhttp3', module:'okhttp'
}
debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
exclude group:'com.facebook.flipper'
}
if (enableHermes) {
def hermesPath = "../../node_modules/hermes-engine/android/";
@@ -216,44 +225,16 @@ dependencies {
implementation jscFlavor
}
implementation project(':react-native-sqlite-storage')
implementation project(':rn-fetch-blob')
implementation project(':react-native-document-picker')
implementation project(':react-native-image-resizer')
// implementation project(':react-native-share-extension')
implementation project(':react-native-version-info')
implementation project(':react-native-camera')
implementation "com.facebook.react:react-native:+"
implementation project(':react-native-quick-actions')
// implementation "com.google.android.gms:play-services-base:16.0.1" // For Firebase
// implementation 'me.leolin:ShortcutBadger:1.1.21@aar' // For Firebase - this line if you wish to use badge on Android
// 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
}
// Needed to fix: The number of method references in a .dex file cannot exceed 64K
implementation 'com.android.support:multidex:2.0.1'
}
// Run this once to be able to run the application with BUCK
// puts all compile dependencies into folder libs for BUCK to use
task copyDownloadableDepsToLibs(type: Copy) {
from configurations.compile
into 'libs'
from configurations.compile
into 'libs'
}
apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"

View File

@@ -0,0 +1,19 @@
"""Helper definitions to glob .aar and .jar targets"""
def create_aar_targets(aarfiles):
for aarfile in aarfiles:
name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
lib_deps.append(":" + name)
android_prebuilt_aar(
name = name,
aar = aarfile,
)
def create_jar_targets(jarfiles):
for jarfile in jarfiles:
name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
lib_deps.append(":" + name)
prebuilt_jar(
name = name,
binary_jar = jarfile,
)

View File

@@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<application android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning" />
</manifest>
</manifest>

View File

@@ -0,0 +1,72 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* <p>This source code is licensed under the MIT license found in the LICENSE file in the root
* directory of this source tree.
*/
package net.cozic.joplin;
import android.content.Context;
import com.facebook.flipper.android.AndroidFlipperClient;
import com.facebook.flipper.android.utils.FlipperUtils;
import com.facebook.flipper.core.FlipperClient;
import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.modules.network.NetworkingModule;
import okhttp3.OkHttpClient;
public class ReactNativeFlipper {
public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
if (FlipperUtils.shouldEnableFlipper(context)) {
final FlipperClient client = AndroidFlipperClient.getInstance(context);
client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
client.addPlugin(new ReactFlipperPlugin());
client.addPlugin(new DatabasesFlipperPlugin(context));
client.addPlugin(new SharedPreferencesFlipperPlugin(context));
client.addPlugin(CrashReporterPlugin.getInstance());
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
@Override
public void apply(OkHttpClient.Builder builder) {
builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
}
});
client.addPlugin(networkFlipperPlugin);
client.start();
// Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
// Hence we run if after all native modules have been initialized
ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
if (reactContext == null) {
reactInstanceManager.addReactInstanceEventListener(
new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext reactContext) {
reactInstanceManager.removeReactInstanceEventListener(this);
reactContext.runOnNativeModulesQueueThread(
new Runnable() {
@Override
public void run() {
client.addPlugin(new FrescoFlipperPlugin());
}
});
}
});
} else {
client.addPlugin(new FrescoFlipperPlugin());
}
}
}
}

View File

@@ -1,111 +1,89 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto"
package="net.cozic.joplin"
android:versionCode="2"
android:versionName="0.8.0">
package="net.cozic.joplin">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove"/>
<!-- ============================= -->
<!-- START RN-push-notitication -->
<!-- ============================= -->
<!-- RN-NOTIFICATION -->
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<permission android:name="${applicationId}.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="${applicationId}.permission.C2D_MESSAGE" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<!-- ============================= -->
<!-- END RN-push-notitication -->
<!-- ============================= -->
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<!-- /RN-NOTIFICATION -->
<!-- Make these features optional to enable Chromebooks -->
<!-- Make these features optional to enable Chromebooks -->
<!-- https://github.com/laurent22/joplin/issues/37 -->
<uses-feature android:name="android.hardware.camera" android:required="false" />
<uses-feature android:name="android.hardware.camera.autofocus" android:required="false" />
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="26" />
<application
android:name=".MainApplication"
android:usesCleartextTraffic="true"
android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
android:networkSecurityConfig="@xml/network_security_config"
android:hardwareAccelerated="true"
android:largeHeap="true"
>
<!-- ============================= -->
<!-- START RN-push-notitication -->
<!-- ============================= -->
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_name" android:value="@string/default_notification_channel_id"/>
<meta-data android:name="com.dieam.reactnativepushnotification.notification_channel_description" android:value="Allow displaying a notification for Joplin's alarms"/>
<meta-data android:name="com.dieam.reactnativepushnotification.notification_color" android:resource="@android:color/white"/>
android:theme="@style/AppTheme">
<!-- RN-NOTIFICATION -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<category android:name="${applicationId}" />
</intent-filter>
android:name="com.emekalites.react.alarm.notification.AlarmReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="ACTION_DISMISS" />
<action android:name="ACTION_SNOOZE" />
</intent-filter>
</receiver>
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationPublisher" />
<receiver android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationBootEventReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<service android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationRegistrationService"/>
<receiver
android:name="com.emekalites.react.alarm.notification.AlarmDismissReceiver"
android:enabled="true"
android:exported="true" />
<receiver
android:name="com.emekalites.react.alarm.notification.AlarmBootReceiver"
android:directBootAware="true"
android:enabled="false"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- /RN-NOTIFICATION -->
<service
android:name="com.dieam.reactnativepushnotification.modules.RNPushNotificationListenerServiceGcm"
android:exported="false" >
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
</intent-filter>
</service>
<!-- ============================= -->
<!-- END RN-push-notitication -->
<!-- ============================= -->
<!--
2018-12-16: Changed android:launchMode from "singleInstance" to "singleTop" for Firebase notification
Previously singleInstance was necessary to prevent multiple instance of the RN app from running at the same time, but maybe no longer needed.
2020-10-06: Changed back again to "singleInstance" and notifications still seem to work. Changing to singleInstance
to try to fix this bug: https://discourse.joplinapp.org/t/joplin-android-app-looses-nextcloud-sync-settings/10997/6
Users would lose their settings, and it's possibly due to multiple instances of the app running at the same time, perhaps
due to sharing with the app. When checking the log, it would show "saving settings", then the app startup message, and after the app
has started, it would show "setting saved". So basically the app, or one instance of it, has started while settings were being saved
2020-10-08: Changed back again to "singleTop" as it has worked so far. The multiple instance bug was "fixed" in a different way
See ReactNativeClient/root.js for more info about the bug.
2018-12-16: Changed android:launchMode from "singleInstance" to "singleTop" for Firebase notification
Previously singleInstance was necessary to prevent multiple instance of the RN app from running at the same time, but maybe no longer needed.
2020-10-06: Changed back again to "singleInstance" and notifications still seem to work. Changing to singleInstance
to try to fix this bug: https://discourse.joplinapp.org/t/joplin-android-app-looses-nextcloud-sync-settings/10997/6
Users would lose their settings, and it's possibly due to multiple instances of the app running at the same time, perhaps
due to sharing with the app. When checking the log, it would show "saving settings", then the app startup message, and after the app
has started, it would show "setting saved". So basically the app, or one instance of it, has started while settings were being saved
2020-10-08: Changed back again to "singleTop" as it has worked so far. The multiple instance bug was "fixed" in a different way
See ReactNativeClient/root.js for more info about the bug.
-->
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTop">
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
</intent-filter>
</activity>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
<!-- SHARE EXTENSION -->
<activity
android:noHistory="true"
android:name=".share.ShareActivity"
@@ -124,6 +102,8 @@
<data android:mimeType="*/*" />
</intent-filter>
</activity>
</application>
<!-- /SHARE EXTENSION -->
</application>
</manifest>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -12,4 +12,4 @@ public class MainActivity extends ReactActivity {
protected String getMainComponentName() {
return "Joplin";
}
}
}

View File

@@ -3,24 +3,28 @@ package net.cozic.joplin;
import android.app.Application;
import android.content.Context;
import android.database.CursorWindow;
import android.os.Build;
import android.webkit.WebView;
import androidx.multidex.MultiDex;
import com.facebook.react.PackageList;
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.soloader.SoLoader;
import net.cozic.joplin.share.SharePackage;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
import net.cozic.joplin.share.SharePackage;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost =
// Needed to fix: The number of method references in a .dex file cannot exceed 64K
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
private final ReactNativeHost mReactNativeHost =
new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
@@ -29,6 +33,7 @@ public class MainApplication extends Application implements ReactApplication {
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
packages.add(new SharePackage());
@@ -41,23 +46,16 @@ public class MainApplication extends Application implements ReactApplication {
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
@Override
public void onCreate() {
super.onCreate();
// Enable debugging with the WebView we use to display notes
// Changes are made as recommended by folks at `react-native-webview`
// https://github.com/react-native-community/react-native-webview/blob/master/docs/Debugging.md
if (BuildConfig.DEBUG && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
}
// To try to fix the error "Row too big to fit into CursorWindow"
// To try to fix the error "Row too big to fit into CursorWindow"
// https://github.com/andpor/react-native-sqlite-storage/issues/364#issuecomment-526423153
// https://github.com/laurent22/joplin/issues/1767#issuecomment-515617991
try {
@@ -66,25 +64,31 @@ public class MainApplication extends Application implements ReactApplication {
field.set(null, 50 * 1024 * 1024); //the 102400 is the new size added
} catch (Exception e) {
e.printStackTrace();
}
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this); // Remove this line if you don't want Flipper enabled
}
SoLoader.init(this, /* native exopackage */ false);
initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
}
/**
* Loads Flipper in React Native templates.
* Loads Flipper in React Native templates. Call this in the onCreate method with something like
* initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
*
* @param context
* @param reactInstanceManager
*/
private static void initializeFlipper(Context context) {
private static void initializeFlipper(
Context context, ReactInstanceManager reactInstanceManager) {
if (BuildConfig.DEBUG) {
try {
/*
We use reflection here to pick up the class that initializes Flipper,
since Flipper library is not available in release mode
*/
Class<?> aClass = Class.forName("com.facebook.flipper.ReactNativeFlipper");
aClass.getMethod("initializeFlipper", Context.class).invoke(null, context);
Class<?> aClass = Class.forName("net.cozic.joplin.ReactNativeFlipper");
aClass
.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
.invoke(null, context, reactInstanceManager);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
@@ -96,4 +100,4 @@ public class MainApplication extends Application implements ReactApplication {
}
}
}
}
}

View File

@@ -1,3 +0,0 @@
<resources>
<color name="white">#FFF</color>
</resources>

View File

@@ -2,18 +2,17 @@
buildscript {
ext {
buildToolsVersion = "28.0.3"
buildToolsVersion = "29.0.2"
minSdkVersion = 16
compileSdkVersion = 28
targetSdkVersion = 28
compileSdkVersion = 29
targetSdkVersion = 29
}
repositories {
jcenter()
google()
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:3.4.2")
classpath("com.android.tools.build:gradle:3.5.3")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
@@ -22,10 +21,6 @@ buildscript {
allprojects {
repositories {
mavenLocal()
maven { url "https://jitpack.io" }
maven {
url "https://maven.google.com"
}
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url("$rootDir/../node_modules/react-native/android")
@@ -34,22 +29,9 @@ allprojects {
// Android JSC is installed from npm
url("$rootDir/../node_modules/jsc-android/dist")
}
google()
jcenter()
maven { url 'https://jitpack.io' }
maven { url 'https://www.jitpack.io' }
}
}
// TODO: Maybe remove this (forgot why it was needed - probably to make some module work)
subprojects {
afterEvaluate {project ->
if (project.hasProperty("android")) {
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
}
}
}
}

View File

@@ -17,12 +17,12 @@
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# Required for react-native-webview
# https://github.com/react-native-community/react-native-webview/blob/master/docs/Getting-Started.md
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# To fix this error:
# > java.io.UncheckedIOException: java.io.IOException: Execution of compression failed. java.lang.OutOfMemoryError
# https://stackoverflow.com/q/57284812/561309
org.gradle.jvmargs=-Xmx4608m
# Version of flipper SDK to use with React Native
FLIPPER_VERSION=0.54.0

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -7,7 +7,7 @@
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
@@ -125,8 +125,8 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
@@ -154,19 +154,19 @@ if $cygwin ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@@ -175,14 +175,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View File

@@ -5,14 +5,14 @@
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"

View File

@@ -1,17 +1,3 @@
rootProject.name = 'Joplin'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
include ':app'
//include ':app', ':react-native-share-extension'
//project(':react-native-share-extension').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-share-extension/android')
include ':react-native-push-notification'
project(':react-native-push-notification').projectDir = file('../node_modules/react-native-push-notification/android')
include ':react-native-camera'
project(':react-native-camera').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-camera/android')

View File

@@ -1,29 +1,4 @@
{
"name": "Joplin",
"displayName": "Joplin",
"expo": {
"name": "Joplin",
"description": "Joplin for Android",
"slug": "Joplin",
"privacy": "public",
"sdkVersion": "18.0.0",
"version": "1.0.0",
"orientation": "portrait",
"primaryColor": "#cccccc",
"icon": "./assets/icons/app-icon.png",
"notification": {
"icon": "./assets/icons/notification-icon.png",
"color": "#000000"
},
"loading": {
"icon": "./assets/icons/loading-icon.png",
"hideExponentText": false
},
"packagerOpts": {
"assetExts": ["ttf"]
},
"ios": {
"supportsTablet": true
}
}
"displayName": "Joplin"
}

View File

@@ -0,0 +1,3 @@
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
};

View File

@@ -1,22 +0,0 @@
const gulp = require('gulp');
const utils = require('../Tools/gulp/utils');
const tasks = {
encodeAssets: {
fn: require('./tools/encodeAssets'),
},
buildReactNativeInjectedJs: {
fn: require('./tools/buildReactNativeInjectedJs'),
},
podInstall: {
fn: require('./tools/podInstall'),
},
};
utils.registerGulpTasks(gulp, tasks);
gulp.task('build', gulp.series(
'buildReactNativeInjectedJs',
'encodeAssets',
'podInstall'
));

View File

@@ -1,3 +0,0 @@
const { main } = require('./main.js');
main();

View File

@@ -1,3 +0,0 @@
const { main } = require('./main.js');
main();

View File

@@ -1,3 +1,44 @@
const { main } = require('./main.js');
// Note about the application structure:
// - The user interface and its state is managed by React/Redux.
// - Persistent storage to SQLite and Web API is handled outside of React/Redux using regular JavaScript (no middleware, no thunk, etc.).
// - Communication from React to SQLite is done by calling model methods (note.save, etc.)
// - Communication from SQLite to Redux is done via dispatcher.
main();
// So there's basically still a one way flux: React => SQLite => Redux => React
import { LogBox, AppRegistry } from 'react-native';
const { Root } = require('./root.js');
// Seems JavaScript developers love adding warnings everywhere, even when these warnings can't be fixed
// or don't really matter. Because we want important warnings to actually be fixed, we disable
// all the useless ones, that way we aren't flooded by them when the app starts, and when there's
// one we know it should be fixed (or added here).
LogBox.ignoreLogs([
// Happens for example in react-native-side-menu, but the package is discontinued
// and we should just switch to a different one (or do it without a package).
'Animated: `useNativeDriver` was not specified. This is a required option and must be explicitly set to `true` or `false`',
// What's the point of printing warnings for non-user code. Of all the things that
// are broken and unreliable in React Native, require cycles are just a minor annoyance
// which shouldn't forever print warnings.
// To make it more fun, they don't normalise paths so forward slashes and backward slashes
// need to be handled to support Windows.
'Require cycle: node_modules/react-native-',
'Require cycle: node_modules\\react-native-',
'Require cycle: node_modules/rn-fetch-blob',
'Require cycle: node_modules\\rn-fetch-blob',
'Require cycle: node_modules/aws-sdk',
'Require cycle: node_modules\\aws-sdk',
// It's being updated over time and we don't need to see these warnings all the time
'Warning: componentWillReceiveProps has been renamed',
'Warning: componentWillUpdate has been renamed',
'Warning: componentWillMount has been renamed',
// Triggered by react-native-webview. Happens on slow devices when loading the note viewer.
// Apparently it can be safely ignored:
// https://github.com/react-native-webview/react-native-webview/issues/124
'Did not receive response to shouldStartLoad in time, defaulting to YES',
]);
AppRegistry.registerComponent('Joplin', () => Root);

View File

@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -22,6 +22,19 @@
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
@@ -36,19 +49,5 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>NSLocationWhenInUseUsageDescription</key>
<string></string>
<key>NSAppTransportSecurity</key>
<!--See http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/ -->
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>localhost</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
</dict>
</plist>

View File

@@ -7,7 +7,7 @@
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>

View File

@@ -8,36 +8,37 @@
/* Begin PBXBuildFile section */
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; };
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; };
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
9E1B958F73B0E37D15AA9B24 /* libPods-Joplin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DDE6F1BE6285C68A2DA17BE9 /* libPods-Joplin.a */; };
AE6BB3A2FDA34D01864A721A /* libRNVectorIcons.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 381C047F2739439CB3E6452A /* libRNVectorIcons.a */; };
ED297163215061F000B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED297162215061F000B7C4FE /* JavaScriptCore.framework */; };
ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ED2971642150620600B7C4FE /* JavaScriptCore.framework */; };
F3D0BB525E6C490294D73075 /* libRNSecureRandom.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 22647ACF9A4C45918C44C599 /* libRNSecureRandom.a */; };
FBF57CE2F0F448FA9A8985E2 /* libsqlite3.0.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EB8BCAEA9AA41CAAE460443 /* libsqlite3.0.tbd */; };
46E31F54C547C341F605BB66 /* libPods-Joplin.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A5E1CD825FABD6C4E704EA54 /* libPods-Joplin.a */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = "<group>"; };
0EB8BCAEA9AA41CAAE460443 /* libsqlite3.0.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.0.tbd; path = usr/lib/libsqlite3.0.tbd; sourceTree = SDKROOT; };
00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
00E356F21AD99517003FC87E /* JoplinTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JoplinTests.m; sourceTree = "<group>"; };
09056573D4C040FBD5FEB93A /* Pods-Joplin-JoplinTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin-JoplinTests.debug.xcconfig"; path = "Target Support Files/Pods-Joplin-JoplinTests/Pods-Joplin-JoplinTests.debug.xcconfig"; sourceTree = "<group>"; };
13B07F961A680F5B00A75B9A /* Joplin.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Joplin.app; sourceTree = BUILT_PRODUCTS_DIR; };
13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Joplin/AppDelegate.h; sourceTree = "<group>"; };
13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Joplin/AppDelegate.m; sourceTree = "<group>"; };
13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = "<group>"; };
13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Joplin/Images.xcassets; sourceTree = "<group>"; };
13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Joplin/Info.plist; sourceTree = "<group>"; };
13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Joplin/main.m; sourceTree = "<group>"; };
22647ACF9A4C45918C44C599 /* libRNSecureRandom.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNSecureRandom.a; sourceTree = "<group>"; };
381C047F2739439CB3E6452A /* libRNVectorIcons.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNVectorIcons.a; sourceTree = "<group>"; };
4DA7F7A61FC1196F00353191 /* Joplin.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = Joplin.entitlements; path = Joplin/Joplin.entitlements; sourceTree = "<group>"; };
6CFFC13990302AAE61F81DB1 /* Pods-Joplin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin.release.xcconfig"; path = "Target Support Files/Pods-Joplin/Pods-Joplin.release.xcconfig"; sourceTree = "<group>"; };
756FF6C78FB548317DAD12C0 /* Pods-Joplin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin.debug.xcconfig"; path = "Target Support Files/Pods-Joplin/Pods-Joplin.debug.xcconfig"; sourceTree = "<group>"; };
DDE6F1BE6285C68A2DA17BE9 /* libPods-Joplin.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Joplin.a"; sourceTree = BUILT_PRODUCTS_DIR; };
14868D674CC065C7BF1C9944 /* Pods-Joplin.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin.release.xcconfig"; path = "Target Support Files/Pods-Joplin/Pods-Joplin.release.xcconfig"; sourceTree = "<group>"; };
245A6EBAE2E874DB706B16DB /* Pods-Joplin-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin-tvOS.release.xcconfig"; path = "Target Support Files/Pods-Joplin-tvOS/Pods-Joplin-tvOS.release.xcconfig"; sourceTree = "<group>"; };
258F823D616BE3D6A52BC900 /* libPods-Joplin-tvOSTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Joplin-tvOSTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
2C91CD1424C7137D07789148 /* Pods-Joplin-JoplinTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin-JoplinTests.release.xcconfig"; path = "Target Support Files/Pods-Joplin-JoplinTests/Pods-Joplin-JoplinTests.release.xcconfig"; sourceTree = "<group>"; };
2DA44D9A347489A29B995F73 /* Pods-Joplin-tvOSTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin-tvOSTests.debug.xcconfig"; path = "Target Support Files/Pods-Joplin-tvOSTests/Pods-Joplin-tvOSTests.debug.xcconfig"; sourceTree = "<group>"; };
37DBC181C4AD99CBE0D07EEB /* Pods-Joplin-tvOSTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin-tvOSTests.release.xcconfig"; path = "Target Support Files/Pods-Joplin-tvOSTests/Pods-Joplin-tvOSTests.release.xcconfig"; sourceTree = "<group>"; };
505CB61090817F4453631957 /* Pods-Joplin.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin.debug.xcconfig"; path = "Target Support Files/Pods-Joplin/Pods-Joplin.debug.xcconfig"; sourceTree = "<group>"; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = Joplin/LaunchScreen.storyboard; sourceTree = "<group>"; };
A3FEB746EE7F1B0FF28528E1 /* Pods-Joplin-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Joplin-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-Joplin-tvOS/Pods-Joplin-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
A5E1CD825FABD6C4E704EA54 /* libPods-Joplin.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Joplin.a"; sourceTree = BUILT_PRODUCTS_DIR; };
B61798F36B3BC123BF8EA4D9 /* libPods-Joplin-tvOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Joplin-tvOS.a"; sourceTree = BUILT_PRODUCTS_DIR; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
ED2971642150620600B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.0.sdk/System/Library/Frameworks/JavaScriptCore.framework; sourceTree = DEVELOPER_DIR; };
F5E37D05726A4A08B2EE323A /* libRNFetchBlob.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRNFetchBlob.a; sourceTree = "<group>"; };
F69B873C692CE22F1C4C9264 /* libPods-Joplin-JoplinTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Joplin-JoplinTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -45,68 +46,55 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
ED297163215061F000B7C4FE /* JavaScriptCore.framework in Frameworks */,
ED2971652150620600B7C4FE /* JavaScriptCore.framework in Frameworks */,
FBF57CE2F0F448FA9A8985E2 /* libsqlite3.0.tbd in Frameworks */,
AE6BB3A2FDA34D01864A721A /* libRNVectorIcons.a in Frameworks */,
F3D0BB525E6C490294D73075 /* libRNSecureRandom.a in Frameworks */,
9E1B958F73B0E37D15AA9B24 /* libPods-Joplin.a in Frameworks */,
46E31F54C547C341F605BB66 /* libPods-Joplin.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
04FA5E9085024E3A9DAF0E03 /* Frameworks */ = {
00E356EF1AD99517003FC87E /* JoplinTests */ = {
isa = PBXGroup;
children = (
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
0EB8BCAEA9AA41CAAE460443 /* libsqlite3.0.tbd */,
DDE6F1BE6285C68A2DA17BE9 /* libPods-Joplin.a */,
00E356F21AD99517003FC87E /* JoplinTests.m */,
00E356F01AD99517003FC87E /* Supporting Files */,
);
name = Frameworks;
path = JoplinTests;
sourceTree = "<group>";
};
00E356F01AD99517003FC87E /* Supporting Files */ = {
isa = PBXGroup;
children = (
00E356F11AD99517003FC87E /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
13B07FAE1A68108700A75B9A /* Joplin */ = {
isa = PBXGroup;
children = (
4DA7F7A61FC1196F00353191 /* Joplin.entitlements */,
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.m */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
13B07FB61A68108700A75B9A /* Info.plist */,
13B07FB11A68108700A75B9A /* LaunchScreen.xib */,
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
13B07FB71A68108700A75B9A /* main.m */,
);
name = Joplin;
sourceTree = "<group>";
};
4D2A85911FBCE3950028537D /* Recovered References */ = {
2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
isa = PBXGroup;
children = (
F5E37D05726A4A08B2EE323A /* libRNFetchBlob.a */,
381C047F2739439CB3E6452A /* libRNVectorIcons.a */,
22647ACF9A4C45918C44C599 /* libRNSecureRandom.a */,
ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
ED2971642150620600B7C4FE /* JavaScriptCore.framework */,
B61798F36B3BC123BF8EA4D9 /* libPods-Joplin-tvOS.a */,
258F823D616BE3D6A52BC900 /* libPods-Joplin-tvOSTests.a */,
A5E1CD825FABD6C4E704EA54 /* libPods-Joplin.a */,
F69B873C692CE22F1C4C9264 /* libPods-Joplin-JoplinTests.a */,
);
name = "Recovered References";
sourceTree = "<group>";
};
5F0B55ADB94AB5BB22C598AC /* Pods */ = {
isa = PBXGroup;
children = (
756FF6C78FB548317DAD12C0 /* Pods-Joplin.debug.xcconfig */,
6CFFC13990302AAE61F81DB1 /* Pods-Joplin.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
7FDFE2A137C24ED08645158D /* Resources */ = {
isa = PBXGroup;
children = (
);
name = Resources;
name = Frameworks;
sourceTree = "<group>";
};
832341AE1AAA6A7D00B99B32 /* Libraries */ = {
@@ -121,11 +109,10 @@
children = (
13B07FAE1A68108700A75B9A /* Joplin */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* JoplinTests */,
83CBBA001A601CBA00E9B192 /* Products */,
04FA5E9085024E3A9DAF0E03 /* Frameworks */,
7FDFE2A137C24ED08645158D /* Resources */,
4D2A85911FBCE3950028537D /* Recovered References */,
5F0B55ADB94AB5BB22C598AC /* Pods */,
2D16E6871FA4F8E400B85C8A /* Frameworks */,
9CDB1D9DB6483D893504BFCB /* Pods */,
);
indentWidth = 2;
sourceTree = "<group>";
@@ -140,6 +127,21 @@
name = Products;
sourceTree = "<group>";
};
9CDB1D9DB6483D893504BFCB /* Pods */ = {
isa = PBXGroup;
children = (
505CB61090817F4453631957 /* Pods-Joplin.debug.xcconfig */,
14868D674CC065C7BF1C9944 /* Pods-Joplin.release.xcconfig */,
09056573D4C040FBD5FEB93A /* Pods-Joplin-JoplinTests.debug.xcconfig */,
2C91CD1424C7137D07789148 /* Pods-Joplin-JoplinTests.release.xcconfig */,
A3FEB746EE7F1B0FF28528E1 /* Pods-Joplin-tvOS.debug.xcconfig */,
245A6EBAE2E874DB706B16DB /* Pods-Joplin-tvOS.release.xcconfig */,
2DA44D9A347489A29B995F73 /* Pods-Joplin-tvOSTests.debug.xcconfig */,
37DBC181C4AD99CBE0D07EEB /* Pods-Joplin-tvOSTests.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -147,19 +149,20 @@
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "Joplin" */;
buildPhases = (
071815849A41B8B427FC87DC /* [CP] Check Pods Manifest.lock */,
335ACF4DE85695BEBB18D8A3 /* [CP] Check Pods Manifest.lock */,
FD10A7F022414F080027D42C /* Start Packager */,
13B07F871A680F5B00A75B9A /* Sources */,
13B07F8C1A680F5B00A75B9A /* Frameworks */,
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
B4AFEC44AA65E5E06375BA82 /* [CP] Copy Pods Resources */,
CBC8354E4CF5CF4E15F2FCDE /* [CP] Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = Joplin;
productName = "Hello World";
productName = Joplin;
productReference = 13B07F961A680F5B00A75B9A /* Joplin.app */;
productType = "com.apple.product-type.application";
};
@@ -169,29 +172,20 @@
83CBB9F71A601CBA00E9B192 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 610;
LastUpgradeCheck = 1130;
ORGANIZATIONNAME = joplinapp.org;
TargetAttributes = {
13B07F861A680F5B00A75B9A = {
DevelopmentTeam = A9BXAFS6CT;
ProvisioningStyle = Automatic;
SystemCapabilities = {
com.apple.Push = {
enabled = 1;
};
com.apple.iCloud = {
enabled = 1;
};
};
LastSwiftMigration = 1120;
};
};
};
buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "Joplin" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
Base,
);
@@ -210,8 +204,8 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -232,7 +226,7 @@
shellPath = /bin/sh;
shellScript = "export NODE_BINARY=/usr/local/opt/node@12/bin/node\n../node_modules/react-native/scripts/react-native-xcode.sh\n";
};
071815849A41B8B427FC87DC /* [CP] Check Pods Manifest.lock */ = {
335ACF4DE85695BEBB18D8A3 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -254,7 +248,7 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
B4AFEC44AA65E5E06375BA82 /* [CP] Copy Pods Resources */ = {
CBC8354E4CF5CF4E15F2FCDE /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -277,6 +271,7 @@
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Octicons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/SimpleLineIcons.ttf",
"${PODS_ROOT}/../../node_modules/react-native-vector-icons/Fonts/Zocial.ttf",
"${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
@@ -296,12 +291,32 @@
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Octicons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/SimpleLineIcons.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/Zocial.ttf",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Joplin/Pods-Joplin-resources.sh\"\n";
showEnvVarsInLog = 0;
};
FD10A7F022414F080027D42C /* Start Packager */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "Start Packager";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -316,47 +331,19 @@
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
13B07FB21A68108700A75B9A /* Base */,
);
name = LaunchScreen.xib;
path = Joplin;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 756FF6C78FB548317DAD12C0 /* Pods-Joplin.debug.xcconfig */;
baseConfigurationReference = 505CB61090817F4453631957 /* Pods-Joplin.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 55;
DEAD_CODE_STRIPPING = NO;
DEVELOPMENT_TEAM = A9BXAFS6CT;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)..",
ode_modules,
"eact-native-image-pickerios",
"$(SRCROOT)..",
ode_modules,
"eact-native-securerandomios",
"$(SRCROOT)..",
ode_modules,
"eact-native-file-viewerios",
);
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 10.3.0;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -365,8 +352,8 @@
);
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin;
PRODUCT_NAME = Joplin;
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
@@ -374,25 +361,15 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 6CFFC13990302AAE61F81DB1 /* Pods-Joplin.release.xcconfig */;
baseConfigurationReference = 14868D674CC065C7BF1C9944 /* Pods-Joplin.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
CODE_SIGN_STYLE = Automatic;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = 55;
DEVELOPMENT_TEAM = A9BXAFS6CT;
HEADER_SEARCH_PATHS = (
"$(inherited)",
"$(SRCROOT)/../node_modules/rn-fetch-blob/ios/**",
"$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager",
"$(SRCROOT)..\node_modules\neact-native-image-pickerios",
"$(SRCROOT)..\node_modules\neact-native-securerandomios",
"$(SRCROOT)..\node_modules\neact-native-file-viewerios",
);
INFOPLIST_FILE = Joplin/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
MARKETING_VERSION = 10.3.0;
OTHER_LDFLAGS = (
"$(inherited)",
@@ -401,8 +378,7 @@
);
PRODUCT_BUNDLE_IDENTIFIER = net.cozic.joplin;
PRODUCT_NAME = Joplin;
PROVISIONING_PROFILE = "";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
};
@@ -412,24 +388,37 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
@@ -442,7 +431,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
LIBRARY_SEARCH_PATHS = (
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
"\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"",
"\"$(inherited)\"",
);
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -453,17 +448,28 @@
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
@@ -471,13 +477,20 @@
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
LIBRARY_SEARCH_PATHS = (
"\"$(TOOLCHAIN_DIR)/usr/lib/swift/$(PLATFORM_NAME)\"",
"\"$(TOOLCHAIN_DIR)/usr/lib/swift-5.0/$(PLATFORM_NAME)\"",
"\"$(inherited)\"",
);
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1130"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "Joplin-tvOS.app"
BlueprintName = "Joplin-tvOS"
ReferencedContainer = "container:Joplin.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E48F1E0B4A5D006451C7"
BuildableName = "Joplin-tvOSTests.xctest"
BlueprintName = "Joplin-tvOSTests"
ReferencedContainer = "container:Joplin.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "Joplin-tvOS.app"
BlueprintName = "Joplin-tvOS"
ReferencedContainer = "container:Joplin.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2D02E47A1E0B4A5D006451C7"
BuildableName = "Joplin-tvOS.app"
BlueprintName = "Joplin-tvOS"
ReferencedContainer = "container:Joplin.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,25 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0620"
LastUpgradeVersion = "1130"
version = "1.3">
<BuildAction
parallelizeBuildables = "NO"
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "83CBBA2D1A601D0E00E9B192"
BuildableName = "libReact.a"
BlueprintName = "React"
ReferencedContainer = "container:../node_modules/react-native/React/React.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
@@ -34,12 +20,16 @@
ReferencedContainer = "container:Joplin.xcodeproj">
</BuildableReference>
</BuildActionEntry>
<BuildActionEntry
buildForTesting = "NO"
buildForRunning = "NO"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "NO">
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "00E356ED1AD99517003FC87E"
@@ -47,34 +37,13 @@
BlueprintName = "JoplinTests"
ReferencedContainer = "container:Joplin.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "13B07F861A680F5B00A75B9A"
BuildableName = "Joplin.app"
BlueprintName = "Joplin"
ReferencedContainer = "container:Joplin.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
@@ -91,8 +60,6 @@
ReferencedContainer = "container:Joplin.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"

View File

@@ -7,4 +7,4 @@
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
</Workspace>

View File

@@ -1,16 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <React/RCTBridgeDelegate.h>
#import <UIKit/UIKit.h>
#import <UserNotifications/UNUserNotificationCenter.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate>
@interface AppDelegate : UIResponder <UIApplicationDelegate, RCTBridgeDelegate, UNUserNotificationCenterDelegate>
@property (nonatomic, strong) UIWindow *window;

View File

@@ -1,32 +1,82 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import "AppDelegate.h"
#import "RNQuickActionManager.h"
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>
#import "RNQuickActionManager.h"
#import <UserNotifications/UserNotifications.h>
#import <RNCPushNotificationIOS.h>
static void InitializeFlipper(UIApplication *application) {
FlipperClient *client = [FlipperClient sharedClient];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
[client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
[client addPlugin:[FlipperKitReactPlugin new]];
[client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
[client start];
}
#endif
@implementation AppDelegate
// ===================================================
// BEGIN react-native-quick-actions
// ===================================================
- (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL succeeded)) completionHandler {
[RNQuickActionManager onQuickActionPress:shortcutItem completionHandler:completionHandler];
}
// ===================================================
// END react-native-quick-actions
// ===================================================
// ===================================================
// BEGIN react-native-push-notification-ios
// ===================================================
// IOS 10+ Required for localNotification event
- (void)userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)(void))completionHandler
{
[RNCPushNotificationIOS didReceiveNotificationResponse:response];
completionHandler();
}
// IOS 4-10 Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RNCPushNotificationIOS didReceiveLocalNotification:notification];
}
// ===================================================
// END react-native-push-notification-ios
// ===================================================
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
InitializeFlipper(application);
#endif
RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"Joplin"
initialProperties:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
moduleName:@"Joplin"
initialProperties:nil];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
@@ -35,49 +85,15 @@
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
// BEGIN react-native-push-notification-ios
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
// END react-native-push-notification-ios
return YES;
}
// =====================================================
// For @react-native-community/push-notification-ios
// =====================================================
// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[RNCPushNotificationIOS didRegisterUserNotificationSettings:notificationSettings];
}
// Required for the register event.
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
[RNCPushNotificationIOS didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event. You must call the completion handler after handling the remote notification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
[RNCPushNotificationIOS didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
}
// Required for the registrationError event.
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
[RNCPushNotificationIOS didFailToRegisterForRemoteNotificationsWithError:error];
}
// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
[RNCPushNotificationIOS didReceiveLocalNotification:notification];
}
// =====================================================
// /For @react-native-community/push-notification-ios
// =====================================================
- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG

View File

@@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="7702" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7701"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="20" y="439" width="441" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Joplin" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
<rect key="frame" x="20" y="140" width="441" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="5cJ-9S-tgC"/>
<constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Kzo-t9-V3l"/>
<constraint firstItem="8ie-xW-0ye" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="MfP-vx-nX0"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
<constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="548" y="455"/>
</view>
</objects>
</document>

View File

@@ -47,6 +47,8 @@
<string>To add geo-location information to a note. Can be disabled in app.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>To allow attaching images to a note</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>The images will be displayed on your notes.</string>
<key>UIAppFonts</key>
<array/>
<key>UILaunchStoryboardName</key>
@@ -72,5 +74,24 @@
<string>Light</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>UIAppFonts</key>
<array>
<string>AntDesign.ttf</string>
<string>Entypo.ttf</string>
<string>EvilIcons.ttf</string>
<string>Feather.ttf</string>
<string>FontAwesome.ttf</string>
<string>FontAwesome5_Brands.ttf</string>
<string>FontAwesome5_Regular.ttf</string>
<string>FontAwesome5_Solid.ttf</string>
<string>Foundation.ttf</string>
<string>Ionicons.ttf</string>
<string>MaterialIcons.ttf</string>
<string>MaterialCommunityIcons.ttf</string>
<string>SimpleLineIcons.ttf</string>
<string>Octicons.ttf</string>
<string>Zocial.ttf</string>
<string>Fontisto.ttf</string>
</array>
</dict>
</plist>

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>development</string>
<key>com.apple.developer.icloud-container-identifiers</key>
<array>
<string>iCloud.$(CFBundleIdentifier)</string>
</array>
<key>com.apple.developer.icloud-services</key>
<array>
<string>CloudDocuments</string>
</array>
<key>com.apple.developer.ubiquity-container-identifiers</key>
<array>
<string>iCloud.$(CFBundleIdentifier)</string>
</array>
<key>com.apple.developer.ubiquity-kvstore-identifier</key>
<string>$(TeamIdentifierPrefix)$(CFBundleIdentifier)</string>
</dict>
</plist>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15702" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15704"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="obG-Y5-kRd">
<rect key="frame" x="0.0" y="647" width="375" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Joplin" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="GJd-Yh-RWb">
<rect key="frame" x="0.0" y="202" width="375" height="43"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Powered by React Native" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="MN2-I3-ftu">
<rect key="frame" x="0.0" y="626" width="375" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="obG-Y5-kRd" secondAttribute="centerX" id="5cz-MP-9tL"/>
<constraint firstItem="Bcu-3y-fUS" firstAttribute="bottom" secondItem="MN2-I3-ftu" secondAttribute="bottom" constant="20" id="OZV-Vh-mqD"/>
<constraint firstItem="Bcu-3y-fUS" firstAttribute="centerX" secondItem="GJd-Yh-RWb" secondAttribute="centerX" id="Q3B-4B-g5h"/>
<constraint firstItem="obG-Y5-kRd" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" symbolic="YES" id="SfN-ll-jLj"/>
<constraint firstAttribute="bottom" secondItem="obG-Y5-kRd" secondAttribute="bottom" constant="20" id="Y44-ml-fuU"/>
<constraint firstItem="MN2-I3-ftu" firstAttribute="centerX" secondItem="Bcu-3y-fUS" secondAttribute="centerX" id="akx-eg-2ui"/>
<constraint firstItem="MN2-I3-ftu" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" id="i1E-0Y-4RG"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="bottom" multiplier="1/3" constant="1" id="moa-c2-u7t"/>
<constraint firstItem="GJd-Yh-RWb" firstAttribute="leading" secondItem="Bcu-3y-fUS" secondAttribute="leading" symbolic="YES" id="x7j-FC-K8j"/>
</constraints>
<viewLayoutGuide key="safeArea" id="Bcu-3y-fUS"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="52.173913043478265" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -1,12 +1,3 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>

View File

@@ -0,0 +1,65 @@
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>
#import <React/RCTLog.h>
#import <React/RCTRootView.h>
#define TIMEOUT_SECONDS 600
#define TEXT_TO_LOOK_FOR @"Welcome to React"
@interface JoplinTests : XCTestCase
@end
@implementation JoplinTests
- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test
{
if (test(view)) {
return YES;
}
for (UIView *subview in [view subviews]) {
if ([self findSubviewInView:subview matching:test]) {
return YES;
}
}
return NO;
}
- (void)testRendersWelcomeScreen
{
UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
BOOL foundElement = NO;
__block NSString *redboxError = nil;
#ifdef DEBUG
RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
if (level >= RCTLogLevelError) {
redboxError = message;
}
});
#endif
while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
[[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
[[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) {
if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
return YES;
}
return NO;
}];
}
#ifdef DEBUG
RCTSetLogFunction(RCTDefaultLogFunction);
#endif
XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
}
@end

View File

@@ -1,43 +1,23 @@
platform :ios, '9.0'
require_relative '../node_modules/react-native/scripts/react_native_pods'
require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
target 'Joplin' do
# Pods for Joplin
pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector"
pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec"
pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired"
pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety"
pod 'React', :path => '../node_modules/react-native/'
pod 'React-Core', :path => '../node_modules/react-native/'
pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules'
pod 'React-Core/DevSupport', :path => '../node_modules/react-native/'
pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS'
pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation'
pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob'
pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image'
pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS'
pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network'
pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings'
pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text'
pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration'
pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/'
pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact'
pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi'
pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor'
pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector'
pod 'ReactCommon/jscallinvoker', :path => "../node_modules/react-native/ReactCommon"
pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon"
pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga'
pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'
pod 'rn-fetch-blob', :path => '../node_modules/rn-fetch-blob'
use_native_modules!
end
# target 'Joplin-tvOS' do
# # Pods for Joplin-tvOS
# target 'Joplin-tvOSTests' do
# inherit! :search_paths
# # Pods for testing
# end
# end
# Note: it was 13.4 to get @react-native-community/datetimepicker to work
# but it's probably not necessary actually. Just needed to upgrade XCode.
platform :ios, '10.0'
target 'Joplin' do
config = use_native_modules!
use_react_native!(:path => config["reactNativePath"])
pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable these next few lines.
use_flipper!
post_install do |installer|
flipper_post_install(installer)
end
end

View File

@@ -1,273 +1,380 @@
PODS:
- boost-for-react-native (1.63.0)
- CocoaAsyncSocket (7.6.4)
- CocoaLibEvent (1.0.0)
- DoubleConversion (1.1.6)
- FBLazyVector (0.61.5)
- FBReactNativeSpec (0.61.5):
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.5)
- RCTTypeSafety (= 0.61.5)
- React-Core (= 0.61.5)
- React-jsi (= 0.61.5)
- ReactCommon/turbomodule/core (= 0.61.5)
- Folly (2018.10.22.00):
- FBLazyVector (0.63.3)
- FBReactNativeSpec (0.63.3):
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.3)
- RCTTypeSafety (= 0.63.3)
- React-Core (= 0.63.3)
- React-jsi (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- Flipper (0.54.0):
- Flipper-Folly (~> 2.2)
- Flipper-RSocket (~> 1.1)
- Flipper-DoubleConversion (1.1.7)
- Flipper-Folly (2.3.0):
- boost-for-react-native
- CocoaLibEvent (~> 1.0)
- Flipper-DoubleConversion
- Flipper-Glog
- OpenSSL-Universal (= 1.0.2.20)
- Flipper-Glog (0.3.6)
- Flipper-PeerTalk (0.0.4)
- Flipper-RSocket (1.1.0):
- Flipper-Folly (~> 2.2)
- FlipperKit (0.54.0):
- FlipperKit/Core (= 0.54.0)
- FlipperKit/Core (0.54.0):
- Flipper (~> 0.54.0)
- FlipperKit/CppBridge
- FlipperKit/FBCxxFollyDynamicConvert
- FlipperKit/FBDefines
- FlipperKit/FKPortForwarding
- FlipperKit/CppBridge (0.54.0):
- Flipper (~> 0.54.0)
- FlipperKit/FBCxxFollyDynamicConvert (0.54.0):
- Flipper-Folly (~> 2.2)
- FlipperKit/FBDefines (0.54.0)
- FlipperKit/FKPortForwarding (0.54.0):
- CocoaAsyncSocket (~> 7.6)
- Flipper-PeerTalk (~> 0.0.4)
- FlipperKit/FlipperKitHighlightOverlay (0.54.0)
- FlipperKit/FlipperKitLayoutPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/FlipperKitHighlightOverlay
- FlipperKit/FlipperKitLayoutTextSearchable
- YogaKit (~> 1.18)
- FlipperKit/FlipperKitLayoutTextSearchable (0.54.0)
- FlipperKit/FlipperKitNetworkPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/FlipperKitReactPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/FlipperKitUserDefaultsPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/SKIOSNetworkPlugin (0.54.0):
- FlipperKit/Core
- FlipperKit/FlipperKitNetworkPlugin
- Folly (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- Folly/Default (= 2018.10.22.00)
- Folly/Default (= 2020.01.13.00)
- glog
- Folly/Default (2018.10.22.00):
- Folly/Default (2020.01.13.00):
- boost-for-react-native
- DoubleConversion
- glog
- glog (0.3.5)
- RCTRequired (0.61.5)
- RCTTypeSafety (0.61.5):
- FBLazyVector (= 0.61.5)
- Folly (= 2018.10.22.00)
- RCTRequired (= 0.61.5)
- React-Core (= 0.61.5)
- React (0.61.5):
- React-Core (= 0.61.5)
- React-Core/DevSupport (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-RCTActionSheet (= 0.61.5)
- React-RCTAnimation (= 0.61.5)
- React-RCTBlob (= 0.61.5)
- React-RCTImage (= 0.61.5)
- React-RCTLinking (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTSettings (= 0.61.5)
- React-RCTText (= 0.61.5)
- React-RCTVibration (= 0.61.5)
- React-Core (0.61.5):
- Folly (= 2018.10.22.00)
- OpenSSL-Universal (1.0.2.20):
- OpenSSL-Universal/Static (= 1.0.2.20)
- OpenSSL-Universal/Static (1.0.2.20)
- RCTRequired (0.63.3)
- RCTTypeSafety (0.63.3):
- FBLazyVector (= 0.63.3)
- Folly (= 2020.01.13.00)
- RCTRequired (= 0.63.3)
- React-Core (= 0.63.3)
- React (0.63.3):
- React-Core (= 0.63.3)
- React-Core/DevSupport (= 0.63.3)
- React-Core/RCTWebSocket (= 0.63.3)
- React-RCTActionSheet (= 0.63.3)
- React-RCTAnimation (= 0.63.3)
- React-RCTBlob (= 0.63.3)
- React-RCTImage (= 0.63.3)
- React-RCTLinking (= 0.63.3)
- React-RCTNetwork (= 0.63.3)
- React-RCTSettings (= 0.63.3)
- React-RCTText (= 0.63.3)
- React-RCTVibration (= 0.63.3)
- React-callinvoker (0.63.3)
- React-Core (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-Core/Default (= 0.63.3)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/CoreModulesHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/CoreModulesHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/Default (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/Default (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/DevSupport (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/DevSupport (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-jsinspector (= 0.61.5)
- React-Core/Default (= 0.63.3)
- React-Core/RCTWebSocket (= 0.63.3)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- React-jsinspector (= 0.63.3)
- Yoga
- React-Core/RCTActionSheetHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTActionSheetHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTAnimationHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTAnimationHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTBlobHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTBlobHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTImageHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTImageHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTLinkingHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTLinkingHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTNetworkHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTNetworkHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTSettingsHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTSettingsHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTTextHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTTextHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTVibrationHeaders (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTVibrationHeaders (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-Core/RCTWebSocket (0.61.5):
- Folly (= 2018.10.22.00)
- React-Core/RCTWebSocket (0.63.3):
- Folly (= 2020.01.13.00)
- glog
- React-Core/Default (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsiexecutor (= 0.61.5)
- React-Core/Default (= 0.63.3)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsiexecutor (= 0.63.3)
- Yoga
- React-CoreModules (0.61.5):
- FBReactNativeSpec (= 0.61.5)
- Folly (= 2018.10.22.00)
- RCTTypeSafety (= 0.61.5)
- React-Core/CoreModulesHeaders (= 0.61.5)
- React-RCTImage (= 0.61.5)
- ReactCommon/turbomodule/core (= 0.61.5)
- React-cxxreact (0.61.5):
- React-CoreModules (0.63.3):
- FBReactNativeSpec (= 0.63.3)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.3)
- React-Core/CoreModulesHeaders (= 0.63.3)
- React-jsi (= 0.63.3)
- React-RCTImage (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- React-cxxreact (0.63.3):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsinspector (= 0.61.5)
- React-jsi (0.61.5):
- React-callinvoker (= 0.63.3)
- React-jsinspector (= 0.63.3)
- React-jsi (0.63.3):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsi/Default (= 0.61.5)
- React-jsi/Default (0.61.5):
- React-jsi/Default (= 0.63.3)
- React-jsi/Default (0.63.3):
- boost-for-react-native (= 1.63.0)
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-jsiexecutor (0.61.5):
- React-jsiexecutor (0.63.3):
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- React-jsinspector (0.61.5)
- react-native-camera (2.10.2):
- React
- react-native-camera/RCT (= 2.10.2)
- react-native-camera/RN (= 2.10.2)
- react-native-camera/RCT (2.10.2):
- React
- react-native-camera/RN (2.10.2):
- React
- react-native-document-picker (2.3.0):
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsinspector (0.63.3)
- react-native-alarm-notification (1.7.1):
- React
- react-native-camera (3.40.0):
- React-Core
- react-native-camera/RCT (= 3.40.0)
- react-native-camera/RN (= 3.40.0)
- react-native-camera/RCT (3.40.0):
- React-Core
- react-native-camera/RN (3.40.0):
- React-Core
- react-native-document-picker (4.0.0):
- React-Core
- react-native-geolocation (2.0.2):
- React
- react-native-image-picker (0.14.3):
- react-native-image-picker (2.3.4):
- React-Core
- react-native-image-resizer (1.3.0):
- React-Core
- react-native-slider (3.0.3):
- React
- react-native-image-resizer (1.0.0):
- react-native-sqlite-storage (5.0.0):
- React
- react-native-slider (2.0.8):
- React
- react-native-sqlite-storage (4.1.0):
- React
- react-native-version-info (1.0.1):
- React
- react-native-webview (5.12.0):
- React
- React-RCTActionSheet (0.61.5):
- React-Core/RCTActionSheetHeaders (= 0.61.5)
- React-RCTAnimation (0.61.5):
- React-Core/RCTAnimationHeaders (= 0.61.5)
- React-RCTBlob (0.61.5):
- React-Core/RCTBlobHeaders (= 0.61.5)
- React-Core/RCTWebSocket (= 0.61.5)
- React-jsi (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTImage (0.61.5):
- React-Core/RCTImageHeaders (= 0.61.5)
- React-RCTNetwork (= 0.61.5)
- React-RCTLinking (0.61.5):
- React-Core/RCTLinkingHeaders (= 0.61.5)
- React-RCTNetwork (0.61.5):
- React-Core/RCTNetworkHeaders (= 0.61.5)
- React-RCTSettings (0.61.5):
- React-Core/RCTSettingsHeaders (= 0.61.5)
- React-RCTText (0.61.5):
- React-Core/RCTTextHeaders (= 0.61.5)
- React-RCTVibration (0.61.5):
- React-Core/RCTVibrationHeaders (= 0.61.5)
- ReactCommon/jscallinvoker (0.61.5):
- react-native-version-info (1.1.0):
- React-Core
- react-native-webview (10.9.2):
- React-Core
- React-RCTActionSheet (0.63.3):
- React-Core/RCTActionSheetHeaders (= 0.63.3)
- React-RCTAnimation (0.63.3):
- FBReactNativeSpec (= 0.63.3)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.3)
- React-Core/RCTAnimationHeaders (= 0.63.3)
- React-jsi (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- React-RCTBlob (0.63.3):
- FBReactNativeSpec (= 0.63.3)
- Folly (= 2020.01.13.00)
- React-Core/RCTBlobHeaders (= 0.63.3)
- React-Core/RCTWebSocket (= 0.63.3)
- React-jsi (= 0.63.3)
- React-RCTNetwork (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- React-RCTImage (0.63.3):
- FBReactNativeSpec (= 0.63.3)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.3)
- React-Core/RCTImageHeaders (= 0.63.3)
- React-jsi (= 0.63.3)
- React-RCTNetwork (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- React-RCTLinking (0.63.3):
- FBReactNativeSpec (= 0.63.3)
- React-Core/RCTLinkingHeaders (= 0.63.3)
- React-jsi (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- React-RCTNetwork (0.63.3):
- FBReactNativeSpec (= 0.63.3)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.3)
- React-Core/RCTNetworkHeaders (= 0.63.3)
- React-jsi (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- React-RCTSettings (0.63.3):
- FBReactNativeSpec (= 0.63.3)
- Folly (= 2020.01.13.00)
- RCTTypeSafety (= 0.63.3)
- React-Core/RCTSettingsHeaders (= 0.63.3)
- React-jsi (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- React-RCTText (0.63.3):
- React-Core/RCTTextHeaders (= 0.63.3)
- React-RCTVibration (0.63.3):
- FBReactNativeSpec (= 0.63.3)
- Folly (= 2020.01.13.00)
- React-Core/RCTVibrationHeaders (= 0.63.3)
- React-jsi (= 0.63.3)
- ReactCommon/turbomodule/core (= 0.63.3)
- ReactCommon/turbomodule/core (0.63.3):
- DoubleConversion
- Folly (= 2018.10.22.00)
- Folly (= 2020.01.13.00)
- glog
- React-cxxreact (= 0.61.5)
- ReactCommon/turbomodule/core (0.61.5):
- DoubleConversion
- Folly (= 2018.10.22.00)
- glog
- React-Core (= 0.61.5)
- React-cxxreact (= 0.61.5)
- React-jsi (= 0.61.5)
- ReactCommon/jscallinvoker (= 0.61.5)
- React-callinvoker (= 0.63.3)
- React-Core (= 0.63.3)
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- rn-fetch-blob (0.12.0):
- React-Core
- RNCPushNotificationIOS (1.0.5):
- React
- RNDeviceInfo (5.5.1):
- React
- RNFileViewer (1.0.1):
- React
- RNFS (2.11.17):
- RNCClipboard (1.5.0):
- React-Core
- RNCPushNotificationIOS (1.6.0):
- React-Core
- RNDateTimePicker (3.0.3):
- React-Core
- RNFileViewer (2.1.4):
- React-Core
- RNFS (2.16.6):
- React
- RNQuickAction (0.3.13):
- React
- RNSecureRandom (1.0.0-rc.0):
- React
- RNVectorIcons (6.6.0):
- RNShare (4.0.2):
- React-Core
- RNVectorIcons (7.1.0):
- React
- Yoga (1.14.0)
- YogaKit (1.18.1):
- Yoga (~> 1.14)
DEPENDENCIES:
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
- FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
- Flipper (~> 0.54.0)
- Flipper-DoubleConversion (= 1.1.7)
- Flipper-Folly (~> 2.2)
- Flipper-Glog (= 0.3.6)
- Flipper-PeerTalk (~> 0.0.4)
- Flipper-RSocket (~> 1.1)
- FlipperKit (~> 0.54.0)
- FlipperKit/Core (~> 0.54.0)
- FlipperKit/CppBridge (~> 0.54.0)
- FlipperKit/FBCxxFollyDynamicConvert (~> 0.54.0)
- FlipperKit/FBDefines (~> 0.54.0)
- FlipperKit/FKPortForwarding (~> 0.54.0)
- FlipperKit/FlipperKitHighlightOverlay (~> 0.54.0)
- FlipperKit/FlipperKitLayoutPlugin (~> 0.54.0)
- FlipperKit/FlipperKitLayoutTextSearchable (~> 0.54.0)
- FlipperKit/FlipperKitNetworkPlugin (~> 0.54.0)
- FlipperKit/FlipperKitReactPlugin (~> 0.54.0)
- FlipperKit/FlipperKitUserDefaultsPlugin (~> 0.54.0)
- FlipperKit/SKIOSNetworkPlugin (~> 0.54.0)
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
- React (from `../node_modules/react-native/`)
- React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
- React-Core (from `../node_modules/react-native/`)
- React-Core/DevSupport (from `../node_modules/react-native/`)
- React-Core/RCTWebSocket (from `../node_modules/react-native/`)
@@ -276,6 +383,7 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-alarm-notification (from `../node_modules/react-native-alarm-notification`)
- react-native-camera (from `../node_modules/react-native-camera`)
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
- "react-native-geolocation (from `../node_modules/@react-native-community/geolocation`)"
@@ -294,21 +402,33 @@ DEPENDENCIES:
- React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/jscallinvoker (from `../node_modules/react-native/ReactCommon`)
- ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
- rn-fetch-blob (from `../node_modules/rn-fetch-blob`)
- "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)"
- "RNCPushNotificationIOS (from `../node_modules/@react-native-community/push-notification-ios`)"
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- RNFileViewer (from `../node_modules/react-native-file-viewer/ios`)
- "RNDateTimePicker (from `../node_modules/@react-native-community/datetimepicker`)"
- RNFileViewer (from `../node_modules/react-native-file-viewer`)
- RNFS (from `../node_modules/react-native-fs`)
- RNQuickAction (from `../node_modules/react-native-quick-actions`)
- RNSecureRandom (from `../node_modules/react-native-securerandom`)
- RNShare (from `../node_modules/react-native-share`)
- RNVectorIcons (from `../node_modules/react-native-vector-icons`)
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
SPEC REPOS:
trunk:
- boost-for-react-native
- CocoaAsyncSocket
- CocoaLibEvent
- Flipper
- Flipper-DoubleConversion
- Flipper-Folly
- Flipper-Glog
- Flipper-PeerTalk
- Flipper-RSocket
- FlipperKit
- OpenSSL-Universal
- YogaKit
EXTERNAL SOURCES:
DoubleConversion:
@@ -327,6 +447,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/Libraries/TypeSafety"
React:
:path: "../node_modules/react-native/"
React-callinvoker:
:path: "../node_modules/react-native/ReactCommon/callinvoker"
React-Core:
:path: "../node_modules/react-native/"
React-CoreModules:
@@ -339,6 +461,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/jsiexecutor"
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
react-native-alarm-notification:
:path: "../node_modules/react-native-alarm-notification"
react-native-camera:
:path: "../node_modules/react-native-camera"
react-native-document-picker:
@@ -379,18 +503,22 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
rn-fetch-blob:
:path: "../node_modules/rn-fetch-blob"
RNCClipboard:
:path: "../node_modules/@react-native-community/clipboard"
RNCPushNotificationIOS:
:path: "../node_modules/@react-native-community/push-notification-ios"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNDateTimePicker:
:path: "../node_modules/@react-native-community/datetimepicker"
RNFileViewer:
:path: "../node_modules/react-native-file-viewer/ios"
:path: "../node_modules/react-native-file-viewer"
RNFS:
:path: "../node_modules/react-native-fs"
RNQuickAction:
:path: "../node_modules/react-native-quick-actions"
RNSecureRandom:
:path: "../node_modules/react-native-securerandom"
RNShare:
:path: "../node_modules/react-native-share"
RNVectorIcons:
:path: "../node_modules/react-native-vector-icons"
Yoga:
@@ -398,49 +526,64 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
CocoaAsyncSocket: 694058e7c0ed05a9e217d1b3c7ded962f4180845
CocoaLibEvent: 2fab71b8bd46dd33ddb959f7928ec5909f838e3f
DoubleConversion: cde416483dac037923206447da6e1454df403714
FBLazyVector: aaeaf388755e4f29cd74acbc9e3b8da6d807c37f
FBReactNativeSpec: 118d0d177724c2d67f08a59136eb29ef5943ec75
Folly: 30e7936e1c45c08d884aa59369ed951a8e68cf51
FBLazyVector: 878b59e31113e289e275165efbe4b54fa614d43d
FBReactNativeSpec: 7da9338acfb98d4ef9e5536805a0704572d33c2f
Flipper: be611d4b742d8c87fbae2ca5f44603a02539e365
Flipper-DoubleConversion: 38631e41ef4f9b12861c67d17cb5518d06badc41
Flipper-Folly: e4493b013c02d9347d5e0cb4d128680239f6c78a
Flipper-Glog: 1dfd6abf1e922806c52ceb8701a3599a79a200a6
Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9
Flipper-RSocket: 64e7431a55835eb953b0bf984ef3b90ae9fdddd7
FlipperKit: ab353d41aea8aae2ea6daaf813e67496642f3d7d
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
RCTRequired: b153add4da6e7dbc44aebf93f3cf4fcae392ddf1
RCTTypeSafety: 9aa1b91d7f9310fc6eadc3cf95126ffe818af320
React: b6a59ef847b2b40bb6e0180a97d0ca716969ac78
React-Core: 688b451f7d616cc1134ac95295b593d1b5158a04
React-CoreModules: d04f8494c1a328b69ec11db9d1137d667f916dcb
React-cxxreact: d0f7bcafa196ae410e5300736b424455e7fb7ba7
React-jsi: cb2cd74d7ccf4cffb071a46833613edc79cdf8f7
React-jsiexecutor: d5525f9ed5f782fdbacb64b9b01a43a9323d2386
React-jsinspector: fa0ecc501688c3c4c34f28834a76302233e29dc0
react-native-camera: ea85f74cf2e501d2a91a3da7092ecdac082f18df
react-native-document-picker: 8508bfda34be6c24a2cbecbe515b15108658c183
OpenSSL-Universal: ff34003318d5e1163e9529b08470708e389ffcdd
RCTRequired: 48884c74035a0b5b76dbb7a998bd93bcfc5f2047
RCTTypeSafety: edf4b618033c2f1c5b7bc3d90d8e085ed95ba2ab
React: f36e90f3ceb976546e97df3403e37d226f79d0e3
React-callinvoker: 18874f621eb96625df7a24a7dc8d6e07391affcd
React-Core: ac3d816b8e3493970153f4aaf0cff18af0bb95e6
React-CoreModules: 4016d3a4e518bcfc4f5a51252b5a05692ca6f0e1
React-cxxreact: ffc9129013b87cb36cf3f30a86695a3c397b0f99
React-jsi: df07aa95b39c5be3e41199921509bfa929ed2b9d
React-jsiexecutor: b56c03e61c0dd5f5801255f2160a815f4a53d451
React-jsinspector: 8e68ffbfe23880d3ee9bafa8be2777f60b25cbe2
react-native-alarm-notification: 8f2adb4521bf7ca867278d4c236553e154dbbbc6
react-native-camera: 5c1fbfecf63b802b8ca4a71c60d30a71550fb348
react-native-document-picker: b3e78a8f7fef98b5cb069f20fc35797d55e68e28
react-native-geolocation: cbd9d6bd06bac411eed2671810f454d4908484a8
react-native-image-picker: 3693786b3d5958c8f71deed66ec068b323565e0d
react-native-image-resizer: aa1600566fd336a044daf9273dcec5033c1d41ca
react-native-slider: b2f361499888302147205f17f6fffa921a7bda70
react-native-sqlite-storage: bb10beb2407e5fc21f3f1bcd86bacbfd6edcc818
react-native-version-info: daadd78b8fc93cf2764cb5aa52ec995961b62201
react-native-webview: 26d8993b090ca5d59eb9a9466dcb8291baa3223e
React-RCTActionSheet: 600b4d10e3aea0913b5a92256d2719c0cdd26d76
React-RCTAnimation: 791a87558389c80908ed06cc5dfc5e7920dfa360
React-RCTBlob: d89293cc0236d9cb0933d85e430b0bbe81ad1d72
React-RCTImage: 6b8e8df449eb7c814c99a92d6b52de6fe39dea4e
React-RCTLinking: 121bb231c7503cf9094f4d8461b96a130fabf4a5
React-RCTNetwork: fb353640aafcee84ca8b78957297bd395f065c9a
React-RCTSettings: 8db258ea2a5efee381fcf7a6d5044e2f8b68b640
React-RCTText: 9ccc88273e9a3aacff5094d2175a605efa854dbe
React-RCTVibration: a49a1f42bf8f5acf1c3e297097517c6b3af377ad
ReactCommon: 198c7c8d3591f975e5431bec1b0b3b581aa1c5dd
react-native-image-picker: 32d1ad2c0024ca36161ae0d5c2117e2d6c441f11
react-native-image-resizer: b53bf95ad880100e20262687e41f76fdbc9df255
react-native-slider: b733e17fdd31186707146debf1f04b5d94aa1a93
react-native-sqlite-storage: ce71689c5a73b79390a1ab213555ae80979a5dc7
react-native-version-info: 64f0f0bf3da6316298f9cd6085d50ba3a992d0c7
react-native-webview: c51f73be304c61d359ec3e7c5e4e8f2c977fd360
React-RCTActionSheet: 53ea72699698b0b47a6421cb1c8b4ab215a774aa
React-RCTAnimation: 1befece0b5183c22ae01b966f5583f42e69a83c2
React-RCTBlob: 0b284339cbe4b15705a05e2313a51c6d8b51fa40
React-RCTImage: d1756599ebd4dc2cb19d1682fe67c6b976658387
React-RCTLinking: 9af0a51c6d6a4dd1674daadafffc6d03033a6d18
React-RCTNetwork: 332c83929cc5eae0b3bbca4add1d668e1fc18bda
React-RCTSettings: d6953772cfd55f2c68ad72b7ef29efc7ec49f773
React-RCTText: 65a6de06a7389098ce24340d1d3556015c38f746
React-RCTVibration: 8e9fb25724a0805107fc1acc9075e26f814df454
ReactCommon: 4167844018c9ed375cc01a843e9ee564399e53c3
rn-fetch-blob: f065bb7ab7fb48dd002629f8bdcb0336602d3cba
RNCPushNotificationIOS: 30ed75aa2981a4ee00b8a2c46599ff18a9c7fcf6
RNDeviceInfo: 6812ed7e578d4344bf4e77102f014b5adf0b5c28
RNFileViewer: 5047ecf40477339723cc08abd55b5ebcefcef4b5
RNFS: 416676c3a9ae404454bade10e3d78147c7c33a40
RNCClipboard: 8f9f12fabf3c06e976f19f87a62c89e28dfedfca
RNCPushNotificationIOS: 20c4403b2ef8732297ea81e22f66c41bed7aaedf
RNDateTimePicker: e9fcd5ecdc0c5b018871e0d178d6040dca11973c
RNFileViewer: 83cc066ad795b1f986791d03b56fe0ee14b6a69f
RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df
RNQuickAction: 6d404a869dc872cde841ad3147416a670d13fa93
RNSecureRandom: 1f19ad1492f7ed416b8fc79e92216a1f73f13a4c
RNVectorIcons: 0bb4def82230be1333ddaeee9fcba45f0b288ed4
Yoga: f2a7cd4280bfe2cca5a7aed98ba0eb3d1310f18b
RNShare: 7a7277f3c313652422d9de072ac50714dff5e8a4
RNVectorIcons: bc69e6a278b14842063605de32bec61f0b251a59
Yoga: 7d13633d129fd179e01b8953d38d47be90db185a
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
PODFILE CHECKSUM: c8797581a23c0ae9c6a4f471c2b19dda3644a8b2
PODFILE CHECKSUM: a0d1ca4e385ef46f9103f02206ebf612107dd508
COCOAPODS: 1.9.3

View File

@@ -698,6 +698,7 @@ export default class BaseApplication {
initArgs = Object.assign(initArgs, extraFlags);
this.logger_.addTarget(TargetType.File, { path: `${profileDir}/log.txt` });
// this.logger_.addTarget(TargetType.Console, { level: Logger.LEVEL_DEBUG });
this.logger_.setLevel(initArgs.logLevel);
reg.setLogger(this.logger_);

View File

@@ -0,0 +1,84 @@
// There are plenty of packages for in-memory caching but each have their
// own gotchas and often have extra complexity which makes it work in one
// platform but not in another (for example, the use of long timeouts would
// be fine in Node but not in React Native).
//
// So this class implements a simple in-memory cache with support for TTL.
// Checking for expired keys is a bit inefficient since it doesn't rely on
// timers, so it's checking every time a value is set or retrieved. But it
// should be fine in most cases, as long as the class is not used at a massive
// scale.
interface Record {
value: any,
expiredTime: number,
}
interface Records {
[key:string]: Record;
}
interface ExpirableKeys {
[key:string]: boolean,
}
export default class Cache {
private maxRecords_:number;
private records_:Records = {};
private expirableKeys_:ExpirableKeys = {};
private recordKeyHistory_:string[] = [];
constructor(maxRecords:number = 50) {
this.maxRecords_ = maxRecords;
}
private checkExpiredRecords() {
const now = Date.now();
for (const key in this.expirableKeys_) {
if (!this.records_[key]) {
delete this.expirableKeys_[key];
} else {
if (this.records_[key].expiredTime <= now) {
delete this.records_[key];
delete this.expirableKeys_[key];
}
}
}
while (this.recordKeyHistory_.length > this.maxRecords_) {
const key = this.recordKeyHistory_[0];
delete this.records_[key];
delete this.expirableKeys_[key];
this.recordKeyHistory_.splice(0, 1);
}
}
public value(key:string, defaultValue:any = undefined):any {
this.checkExpiredRecords();
if (key in this.records_) return this.records_[key].value;
return defaultValue;
}
public setValue(key:string, value:any, ttl:number = 0) {
this.checkExpiredRecords();
this.records_[key] = {
value: value,
expiredTime: ttl ? Date.now() + ttl : 0,
};
const idx = this.recordKeyHistory_.indexOf(key);
if (idx >= 0) this.recordKeyHistory_.splice(idx, 1);
this.recordKeyHistory_.push(key);
if (ttl) {
this.expirableKeys_[key] = true;
} else {
delete this.expirableKeys_[key];
}
}
}

View File

@@ -0,0 +1,102 @@
// On mobile all the setTimeout and setInterval should go through this class
// as it will either use the native timeout/interval for short intervals or
// the custom one for long intervals.
// For custom intervals, they are triggered
// whenever the update() function is called, and in mobile it's called for
// example on the Redux action middleware or when the app gets focus.
const { time } = require('lib/time-utils.js');
type IntervalId = number;
interface Interval {
id: IntervalId,
callback: Function,
interval: number,
lastIntervalTime: number,
isTimeout: boolean,
}
interface Intervals {
[key: number]: Interval;
}
export default class PoorManIntervals {
private static maxNativeTimerDuration_ = 10 * 1000;
private static lastUpdateTime_:number = 0;
private static intervalId_:IntervalId = 0;
private static intervals_:Intervals = {};
public static setInterval(callback:Function, interval:number):IntervalId {
if (interval <= this.maxNativeTimerDuration_) return setInterval(callback, interval);
this.intervalId_++;
const id = this.intervalId_;
this.intervals_[id] = {
id: id,
callback: callback,
interval: interval,
lastIntervalTime: time.unixMs(),
isTimeout: false,
};
return id;
}
public static setTimeout(callback:Function, interval:number):IntervalId {
if (interval <= this.maxNativeTimerDuration_) return setTimeout(callback, interval);
this.intervalId_++;
const id = this.intervalId_;
this.intervals_[id] = {
id: id,
callback: callback,
interval: interval,
lastIntervalTime: time.unixMs(),
isTimeout: true,
};
return id;
}
public static clearInterval(id:IntervalId) {
const r = this.intervals_[id];
if (!r) {
clearInterval(id);
} else {
delete this.intervals_[id];
}
}
public static clearTimeout(id:IntervalId) {
const r = this.intervals_[id];
if (!r) {
clearTimeout(id);
} else {
delete this.intervals_[id];
}
}
public static update() {
// Don't update more than once a second
if (this.lastUpdateTime_ + 1000 > time.unixMs()) return;
for (const id in this.intervals_) {
const interval = this.intervals_[id];
const now = time.unixMs();
if (now - interval.lastIntervalTime >= interval.interval) {
interval.lastIntervalTime = now;
interval.callback();
if (interval.isTimeout) {
this.clearTimeout(interval.id);
}
}
}
this.lastUpdateTime_ = time.unixMs();
}
}

View File

@@ -335,8 +335,9 @@ class WebDavApi {
// </d:propfind>'
async exec(method, path = '', body = null, headers = null, options = null) {
if (headers === null) headers = {};
if (options === null) options = {};
headers = Object.assign({}, headers);
options = Object.assign({}, options);
if (!options.responseFormat) options.responseFormat = 'json';
if (!options.target) options.target = 'string';
@@ -344,6 +345,13 @@ class WebDavApi {
if (authToken) headers['Authorization'] = `Basic ${authToken}`;
// That should not be needed, but it is required for React Native 0.63+
// https://github.com/facebook/react-native/issues/30176
if (!headers['Content-Type']) {
if (method === 'PROPFIND') headers['Content-Type'] = 'text/xml';
if (method === 'PUT') headers['Content-Type'] = 'text/plain';
}
// On iOS, the network lib appends a If-None-Match header to PROPFIND calls, which is kind of correct because
// the call is idempotent and thus could be cached. According to RFC-7232 though only GET and HEAD should have
// this header for caching purposes. It makes no mention of PROPFIND.
@@ -365,7 +373,6 @@ class WebDavApi {
if (shim.httpAgent(url)) fetchOptions.agent = shim.httpAgent(url);
let response = null;
// console.info('WebDAV Call', `${method} ${url}`, headers, options);

View File

@@ -3,7 +3,7 @@ const { Platform, PermissionsAndroid } = require('react-native');
type rationale = {
title: string,
message: string,
buttonPositive: string,
buttonPositive?: string,
buttonNegative?: string
buttonNeutral?: string
}
@@ -15,5 +15,5 @@ export default async (permissions: string, rationale?: rationale) => {
if (result !== PermissionsAndroid.RESULTS.GRANTED) {
result = await PermissionsAndroid.request(permissions, rationale);
}
return result === PermissionsAndroid.RESULTS.GRANTED;
return result;
};

View File

@@ -1,4 +1,4 @@
import { RNCamera } from 'react-native-camera';
const { RNCamera } = require('react-native-camera');
const React = require('react');
const Component = React.Component;
const { connect } = require('react-redux');
@@ -31,7 +31,7 @@ class CameraView extends Component {
this.onLayout = this.onLayout.bind(this);
}
onLayout(event) {
onLayout(event:any) {
this.setState({
screenWidth: event.nativeEvent.layout.width,
screenHeight: event.nativeEvent.layout.height,
@@ -70,23 +70,26 @@ class CameraView extends Component {
fixOrientation: true,
});
this.setState({ snapping: false });
if (this.props.onPhoto) this.props.onPhoto(result);
this.setState({ snapping: false });
}
async onCameraReady() {
const ratios = await this.camera.getSupportedRatiosAsync();
this.setState({ ratios: ratios });
if (this.supportsRatios()) {
const ratios = await this.camera.getSupportedRatiosAsync();
this.setState({ ratios: ratios });
}
}
renderButton(onPress, iconName, style) {
renderButton(onPress:Function, iconNameOrIcon:any, style:any) {
let icon = null;
if (typeof iconName === 'string') {
if (typeof iconNameOrIcon === 'string') {
icon = (
<Icon
name={iconName}
name={iconNameOrIcon}
style={{
fontSize: 40,
color: 'black',
@@ -94,7 +97,7 @@ class CameraView extends Component {
/>
);
} else {
icon = iconName;
icon = iconNameOrIcon;
}
return (
@@ -106,11 +109,11 @@ class CameraView extends Component {
);
}
fitRectIntoBounds(rect, bounds) {
fitRectIntoBounds(rect:any, bounds:any) {
const rectRatio = rect.width / rect.height;
const boundsRatio = bounds.width / bounds.height;
const newDimensions = {};
const newDimensions:any = {};
// Rect is more landscape than bounds - fit to width
if (rectRatio > boundsRatio) {
@@ -124,7 +127,7 @@ class CameraView extends Component {
return newDimensions;
}
cameraRect(ratio) {
cameraRect(ratio:string) {
// To keep the calculations simpler, it's assumed that the phone is in
// portrait orientation. Then at the end we swap the values if needed.
const splitted = ratio.split(':');
@@ -146,16 +149,21 @@ class CameraView extends Component {
return output;
}
supportsRatios() {
return shim.mobilePlatform() === 'android';
}
render() {
const photoIcon = this.state.snapping ? 'md-checkmark' : 'md-camera';
const displayRatios = shim.mobilePlatform() === 'android' && this.state.ratios.length > 1;
const displayRatios = this.supportsRatios() && this.state.ratios.length > 1;
const reverseCameraButton = this.renderButton(this.reverse_onPress, 'md-reverse-camera', { flex: 1, flexDirection: 'row', justifyContent: 'flex-start', marginLeft: 20 });
const reverseCameraButton = this.renderButton(this.reverse_onPress, 'md-camera-reverse', { flex: 1, flexDirection: 'row', justifyContent: 'flex-start', marginLeft: 20 });
const ratioButton = !displayRatios ? <View style={{ flex: 1 }}/> : this.renderButton(this.ratio_onPress, <Text style={{ fontWeight: 'bold', fontSize: 20 }}>{Setting.value('camera.ratio')}</Text>, { flex: 1, flexDirection: 'row', justifyContent: 'flex-end', marginRight: 20 });
let cameraRatio = '4:3';
const cameraProps = {};
const cameraProps:any = {};
if (displayRatios) {
cameraProps.ratio = this.props.cameraRatio;
cameraRatio = this.props.cameraRatio;
@@ -170,7 +178,7 @@ class CameraView extends Component {
<View style={{ position: 'absolute', backgroundColor: '#000000', width: '100%', height: '100%' }}/>
<RNCamera
style={Object.assign({ position: 'absolute' }, cameraRect)}
ref={ref => {
ref={(ref:any) => {
this.camera = ref;
}}
type={this.props.cameraType}
@@ -223,7 +231,7 @@ class CameraView extends Component {
}
}
const mapStateToProps = state => {
const mapStateToProps = (state:any) => {
return {
cameraRatio: state.settings['camera.ratio'],
cameraType: state.settings['camera.type'],
@@ -231,4 +239,4 @@ const mapStateToProps = state => {
};
module.exports = connect(mapStateToProps)(CameraView);
export default connect(mapStateToProps)(CameraView);

View File

@@ -0,0 +1,111 @@
import { useRef, useMemo, useCallback } from 'react';
import Setting from 'lib/models/Setting';
import useSource from './hooks/useSource';
import useOnMessage from './hooks/useOnMessage';
import useOnResourceLongPress from './hooks/useOnResourceLongPress';
const React = require('react');
const { View } = require('react-native');
const { WebView } = require('react-native-webview');
const { themeStyle } = require('lib/components/global-style.js');
const BackButtonDialogBox = require('lib/components/BackButtonDialogBox').default;
const { reg } = require('lib/registry.js');
interface Props {
themeId: number,
style: any,
noteBody: string,
noteMarkupLanguage: number,
highlightedKeywords: string[],
noteResources: any,
paddingBottom: number,
noteHash: string,
onJoplinLinkClick: Function,
onCheckboxChange?: Function,
onMarkForDownload?: Function,
onLoadEnd?: Function,
}
export default function NoteBodyViewer(props:Props) {
const theme = themeStyle(props.themeId);
const webViewStyle:any = useMemo(() => {
return { backgroundColor: theme.backgroundColor };
}, [theme.backgroundColor]);
const dialogBoxRef = useRef(null);
const { source, injectedJs } = useSource(
props.noteBody,
props.noteMarkupLanguage,
props.themeId,
props.highlightedKeywords,
props.noteResources,
props.paddingBottom,
props.noteHash
);
const onResourceLongPress = useOnResourceLongPress(
props.onJoplinLinkClick,
dialogBoxRef
);
const onMessage = useOnMessage(
props.onCheckboxChange,
props.noteBody,
props.onMarkForDownload,
props.onJoplinLinkClick,
onResourceLongPress
);
const onLoadEnd = useCallback(() => {
if (props.onLoadEnd) props.onLoadEnd();
}, [props.onLoadEnd]);
function onError() {
reg.logger().error('WebView error');
}
// On iOS scalesPageToFit work like this:
//
// Find the widest image, resize it *and everything else* by x% so that
// the image fits within the viewport. The problem is that it means if there's
// a large image, everything is going to be scaled to a very small size, making
// the text unreadable.
//
// On Android:
//
// Find the widest elements and scale them (and them only) to fit within the viewport
// It means it's going to scale large images, but the text will remain at the normal
// size.
//
// That means we can use scalesPageToFix on Android but not on iOS.
// The weird thing is that on iOS, scalesPageToFix=false along with a CSS
// rule "img { max-width: 100% }", works like scalesPageToFix=true on Android.
// So we use scalesPageToFix=false on iOS along with that CSS rule.
//
// 2020-10-15: As we've now fully switched to WebKit for iOS (useWebKit=true) and
// since the WebView package went through many versions it's possible that
// the above no longer applies.
return (
<View style={props.style}>
<WebView
theme={theme}
useWebKit={true}
allowingReadAccessToURL={`file://${Setting.value('resourceDir')}`}
style={webViewStyle}
source={source}
injectedJavaScript={injectedJs.join('\n')}
originWhitelist={['file://*', './*', 'http://*', 'https://*']}
mixedContentMode="always"
allowFileAccess={true}
onLoadEnd={onLoadEnd}
onError={onError}
onMessage={onMessage}
/>
<BackButtonDialogBox ref={dialogBoxRef}/>
</View>
);
}

Some files were not shown because too many files have changed in this diff Show More