You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2026-01-05 00:12:33 +02:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea878fb614 | ||
|
|
5fd0408365 | ||
|
|
2d099b2bed | ||
|
|
3c0b9ee522 | ||
|
|
987890ba98 | ||
|
|
3358c46122 | ||
|
|
d819e6ee0c | ||
|
|
b66be79351 | ||
|
|
433fa21069 |
@@ -199,6 +199,7 @@ ReactNativeClient/lib/checkPermissions.js
|
||||
ReactNativeClient/lib/commands/historyBackward.js
|
||||
ReactNativeClient/lib/commands/historyForward.js
|
||||
ReactNativeClient/lib/commands/synchronize.js
|
||||
ReactNativeClient/lib/components/BackButtonDialogBox.js
|
||||
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
|
||||
ReactNativeClient/lib/errorUtils.js
|
||||
ReactNativeClient/lib/eventManager.js
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -193,6 +193,7 @@ ReactNativeClient/lib/checkPermissions.js
|
||||
ReactNativeClient/lib/commands/historyBackward.js
|
||||
ReactNativeClient/lib/commands/historyForward.js
|
||||
ReactNativeClient/lib/commands/synchronize.js
|
||||
ReactNativeClient/lib/components/BackButtonDialogBox.js
|
||||
ReactNativeClient/lib/components/screens/UpgradeSyncTargetScreen.js
|
||||
ReactNativeClient/lib/errorUtils.js
|
||||
ReactNativeClient/lib/eventManager.js
|
||||
|
||||
@@ -15,6 +15,8 @@ msgstr ""
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.4.1\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: \n"
|
||||
|
||||
#: ElectronClient/services/plugins/UserWebviewDialogButtonBar.js:20
|
||||
#: ElectronClient/checkForUpdates.js:139
|
||||
@@ -799,7 +801,6 @@ msgid "Toggle sidebar"
|
||||
msgstr "사이드바 표시 전환"
|
||||
|
||||
#: ElectronClient/gui/MainScreen/commands/toggleEditors.js:17
|
||||
#, fuzzy
|
||||
msgid "Toggle editors"
|
||||
msgstr "편집기 배치 형태 전환"
|
||||
|
||||
@@ -1389,9 +1390,9 @@ msgstr ""
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:62
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:142
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Error: %s"
|
||||
msgstr "오류"
|
||||
msgstr "오류: %s"
|
||||
|
||||
#: ElectronClient/gui/KeymapConfig/KeymapConfigScreen.js:125
|
||||
msgid "Command"
|
||||
@@ -1463,9 +1464,8 @@ msgid "Exit"
|
||||
msgstr "종료"
|
||||
|
||||
#: ElectronClient/commands/copyDevCommand.js:17
|
||||
#, fuzzy
|
||||
msgid "Copy dev mode command to clipboard"
|
||||
msgstr "경로를 클립보드에 복사"
|
||||
msgstr "개발자 모드 명령을 클립보드에 복사"
|
||||
|
||||
#: ElectronClient/commands/startExternalEditing.js:18
|
||||
msgid "Edit in external editor"
|
||||
@@ -1477,13 +1477,12 @@ msgid "Error opening note in editor: %s"
|
||||
msgstr "편집기에서 노트를 열 수 없는 오류가 발생하였습니다: %s"
|
||||
|
||||
#: ElectronClient/commands/toggleExternalEditing.js:16
|
||||
#, fuzzy
|
||||
msgid "Toggle external editing"
|
||||
msgstr "외부 편집을 그만 두시려면 클릭하세요"
|
||||
msgstr "외부 편집 전환"
|
||||
|
||||
#: ElectronClient/commands/toggleExternalEditing.js:42
|
||||
msgid "Stop"
|
||||
msgstr ""
|
||||
msgstr "중지"
|
||||
|
||||
#: ElectronClient/commands/stopExternalEditing.js:16
|
||||
msgid "Stop external editing"
|
||||
@@ -2203,9 +2202,9 @@ msgid "Cannot load \"%s\" module for format \"%s\" and output \"%s\""
|
||||
msgstr "\"%s\" 모듈(\"%s\" 포맷과 \"%s\" 출력을 위한)을 불러올 수 없습니다"
|
||||
|
||||
#: ReactNativeClient/lib/services/interop/InteropService.js:152
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Cannot load \"%s\" module for format \"%s\" and target \"%s\""
|
||||
msgstr "\"%s\" 모듈(\"%s\" 포맷과 \"%s\" 출력을 위한)을 불러올 수 없습니다"
|
||||
msgstr "\"%s\" 모듈(\"%s\" 포맷과 \"%s\" 대상을 위한)을 불러올 수 없습니다"
|
||||
|
||||
#: ReactNativeClient/lib/services/interop/InteropService.js:187
|
||||
#, javascript-format
|
||||
@@ -2221,25 +2220,24 @@ msgid "Restored Notes"
|
||||
msgstr "복구된 노트들"
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:236
|
||||
#, fuzzy
|
||||
msgid "command"
|
||||
msgstr "명령"
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:236
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:241
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "\"%s\" is missing the required \"%s\" property."
|
||||
msgstr "키맵 항목 %s에 필수 속성인 \"명령\"이 없습니다."
|
||||
msgstr "\"%s\"에 \"%s\" 필수 속성이 없습니다."
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:241
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:248
|
||||
msgid "accelerator"
|
||||
msgstr ""
|
||||
msgstr "단축키"
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:248
|
||||
#, fuzzy, javascript-format
|
||||
#, javascript-format
|
||||
msgid "Invalid %s: %s."
|
||||
msgstr "잘못된 답: %s"
|
||||
msgstr "유효하지 않은 %s: %s."
|
||||
|
||||
#: ReactNativeClient/lib/services/KeymapService.js:266
|
||||
#, javascript-format
|
||||
|
||||
6
CliClient/package-lock.json
generated
6
CliClient/package-lock.json
generated
@@ -5901,9 +5901,9 @@
|
||||
}
|
||||
},
|
||||
"slug": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/slug/-/slug-3.3.4.tgz",
|
||||
"integrity": "sha512-VpHbtRCEWmgaZsrZcTsVl/Dhw98lcrOYDO17DNmJCNpppI6s3qJvnNu2Q3D4L84/2bi6vkW40mjNQI9oGQsflg=="
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/slug/-/slug-3.5.0.tgz",
|
||||
"integrity": "sha512-+pZLDhMtmAc+ZcojQSMlUKDZBYmvhZiZmK8Ffx/D3Q/MIMHPDBAMbWvWN8vJb9xl2MfbDdRWxFzrdOhBiyVpow=="
|
||||
},
|
||||
"snapdragon": {
|
||||
"version": "0.8.2",
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
"sax": "^1.2.4",
|
||||
"server-destroy": "^1.0.1",
|
||||
"sharp": "^0.23.2",
|
||||
"slug": "^3.3.4",
|
||||
"slug": "^3.5.0",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"sqlite3": "^4.1.1",
|
||||
"string-padding": "^1.0.2",
|
||||
|
||||
@@ -141,7 +141,7 @@ export default function useListIdent(CodeMirror: any) {
|
||||
cm.setCursor({ line: anchor.line, ch: line.length });
|
||||
|
||||
cm.execCommand('insertListElement');
|
||||
cm.setOption('disableInput', true);
|
||||
CodeMirror.Vim.handleKey(cm, 'i', 'macro');
|
||||
};
|
||||
|
||||
CodeMirror.commands.insertListElement = function(cm: any) {
|
||||
|
||||
@@ -361,6 +361,17 @@ class SideBarComponent extends React.Component<Props, State> {
|
||||
|
||||
renderFolderItem(folder:any, selected:boolean, hasChildren:boolean, depth:number) {
|
||||
const anchorRef = this.anchorItemRef('folder', folder.id);
|
||||
const isExpanded = this.props.collapsedFolderIds.indexOf(folder.id) < 0;
|
||||
let noteCount = folder.note_count;
|
||||
|
||||
// Thunderbird count: Subtract children note_count from parent folder if it expanded.
|
||||
if (isExpanded) {
|
||||
for (let i = 0; i < this.props.folders.length; i++) {
|
||||
if (this.props.folders[i].parent_id === folder.id) {
|
||||
noteCount -= this.props.folders[i].note_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return <FolderItem
|
||||
key={folder.id}
|
||||
@@ -369,10 +380,10 @@ class SideBarComponent extends React.Component<Props, State> {
|
||||
themeId={this.props.themeId}
|
||||
depth={depth}
|
||||
selected={selected}
|
||||
isExpanded={this.props.collapsedFolderIds.indexOf(folder.id) < 0}
|
||||
isExpanded={isExpanded}
|
||||
hasChildren={hasChildren}
|
||||
anchorRef={anchorRef}
|
||||
noteCount={folder.note_count}
|
||||
noteCount={noteCount}
|
||||
onFolderDragStart_={this.onFolderDragStart_}
|
||||
onFolderDragOver_={this.onFolderDragOver_}
|
||||
onFolderDrop_={this.onFolderDrop_}
|
||||
|
||||
8
ElectronClient/package-lock.json
generated
8
ElectronClient/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.3.2",
|
||||
"version": "1.3.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@@ -10685,9 +10685,9 @@
|
||||
}
|
||||
},
|
||||
"slug": {
|
||||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/slug/-/slug-3.3.4.tgz",
|
||||
"integrity": "sha512-VpHbtRCEWmgaZsrZcTsVl/Dhw98lcrOYDO17DNmJCNpppI6s3qJvnNu2Q3D4L84/2bi6vkW40mjNQI9oGQsflg=="
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/slug/-/slug-3.5.0.tgz",
|
||||
"integrity": "sha512-+pZLDhMtmAc+ZcojQSMlUKDZBYmvhZiZmK8Ffx/D3Q/MIMHPDBAMbWvWN8vJb9xl2MfbDdRWxFzrdOhBiyVpow=="
|
||||
},
|
||||
"smalltalk": {
|
||||
"version": "2.5.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Joplin",
|
||||
"version": "1.3.2",
|
||||
"version": "1.3.1",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
@@ -196,7 +196,7 @@
|
||||
"roboto-fontface": "^0.10.0",
|
||||
"sax": "^1.2.4",
|
||||
"server-destroy": "^1.0.1",
|
||||
"slug": "^3.3.4",
|
||||
"slug": "^3.5.0",
|
||||
"smalltalk": "^2.5.1",
|
||||
"sprintf-js": "^1.1.1",
|
||||
"sqlite3": "^4.1.1",
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -337,7 +337,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 54;
|
||||
CURRENT_PROJECT_VERSION = 55;
|
||||
DEAD_CODE_STRIPPING = NO;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
@@ -380,7 +380,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = Joplin/Joplin.entitlements;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 54;
|
||||
CURRENT_PROJECT_VERSION = 55;
|
||||
DEVELOPMENT_TEAM = A9BXAFS6CT;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
|
||||
24
ReactNativeClient/lib/components/BackButtonDialogBox.ts
Normal file
24
ReactNativeClient/lib/components/BackButtonDialogBox.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
const { BackButtonService } = require('lib/services/back-button.js');
|
||||
const DialogBox = require('react-native-dialogbox').default;
|
||||
|
||||
export default class BackButtonDialogBox extends DialogBox {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.backHandler_ = () => {
|
||||
if (this.state.isVisible) {
|
||||
this.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
BackButtonService.addHandler(this.backHandler_);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
BackButtonService.removeHandler(this.backHandler_);
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,20 @@ import Async from 'react-async';
|
||||
|
||||
const React = require('react');
|
||||
const Component = React.Component;
|
||||
const { Platform, View, Text } = require('react-native');
|
||||
const { Platform, View, Text, ToastAndroid } = require('react-native');
|
||||
const { WebView } = require('react-native-webview');
|
||||
const { themeStyle } = require('lib/components/global-style.js');
|
||||
const Setting = require('lib/models/Setting').default;
|
||||
const { _ } = require('lib/locale.js');
|
||||
const { reg } = require('lib/registry.js');
|
||||
const shim = require('lib/shim').default;
|
||||
const { assetsToHeaders } = require('lib/joplin-renderer');
|
||||
const shared = require('lib/components/shared/note-screen-shared.js');
|
||||
const markupLanguageUtils = require('lib/markupLanguageUtils');
|
||||
const { dialogs } = require('lib/dialogs.js');
|
||||
const BackButtonDialogBox = require('lib/components/BackButtonDialogBox').default;
|
||||
const Resource = require('lib/models/Resource.js');
|
||||
const Share = require('react-native-share').default;
|
||||
|
||||
class NoteBodyViewer extends Component {
|
||||
constructor() {
|
||||
@@ -64,6 +69,8 @@ class NoteBodyViewer extends Component {
|
||||
resources: this.props.noteResources,
|
||||
codeTheme: theme.codeThemeCss,
|
||||
postMessageSyntax: 'window.joplinPostMessage_',
|
||||
enableLongPress: shim.isReactNative(),
|
||||
longPressDelay: 500, // TODO use system value
|
||||
};
|
||||
|
||||
const result = await this.markupToHtml_.render(
|
||||
@@ -203,6 +210,42 @@ class NoteBodyViewer extends Component {
|
||||
return this.forceUpdate_;
|
||||
}
|
||||
|
||||
async onResourceLongPress(msg) {
|
||||
try {
|
||||
const resourceId = msg.split(':')[1];
|
||||
const resource = await Resource.load(resourceId);
|
||||
const name = resource.title ? resource.title : resource.file_name;
|
||||
|
||||
const action = await dialogs.pop(this, name, [
|
||||
{ text: _('Open'), id: 'open' },
|
||||
{ text: _('Share'), id: 'share' },
|
||||
]);
|
||||
|
||||
if (action === 'open') {
|
||||
this.props.onJoplinLinkClick(`joplin://${resourceId}`);
|
||||
} else if (action === 'share') {
|
||||
const filename = resource.file_name ?
|
||||
`${resource.file_name}.${resource.file_extension}` :
|
||||
resource.title;
|
||||
const targetPath = `${Setting.value('resourceDir')}/${filename}`;
|
||||
|
||||
await shim.fsDriver().copy(Resource.fullPath(resource), targetPath);
|
||||
|
||||
await Share.open({
|
||||
type: resource.mime,
|
||||
filename: resource.title,
|
||||
url: `file://${targetPath}`,
|
||||
failOnCancel: false,
|
||||
});
|
||||
|
||||
await shim.fsDriver().remove(targetPath);
|
||||
}
|
||||
} catch (e) {
|
||||
reg.logger().error('Could not handle link long press', e);
|
||||
ToastAndroid.show('An error occurred, check log for details', ToastAndroid.SHORT);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
// Note: useWebKit={false} is needed to go around this bug:
|
||||
// https://github.com/react-native-community/react-native-webview/issues/376
|
||||
@@ -256,7 +299,9 @@ class NoteBodyViewer extends Component {
|
||||
msg = msg.split(':');
|
||||
const resourceId = msg[1];
|
||||
if (this.props.onMarkForDownload) this.props.onMarkForDownload({ resourceId: resourceId });
|
||||
} else {
|
||||
} else if (msg.startsWith('longclick:')) {
|
||||
this.onResourceLongPress(msg);
|
||||
} else if (msg.startsWith('joplin:')) {
|
||||
this.props.onJoplinLinkClick(msg);
|
||||
}
|
||||
}}
|
||||
@@ -264,6 +309,11 @@ class NoteBodyViewer extends Component {
|
||||
);
|
||||
}}
|
||||
</Async>
|
||||
<BackButtonDialogBox
|
||||
ref={dialogbox => {
|
||||
this.dialogbox = dialogbox;
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -16,8 +16,22 @@ function installRule(markdownIt, mdOptions, ruleOptions) {
|
||||
|
||||
const r = utils.imageReplacement(ruleOptions.ResourceModel, src, ruleOptions.resources, ruleOptions.resourceBaseUrl);
|
||||
if (typeof r === 'string') return r;
|
||||
if (r) return `<img data-from-md ${htmlUtils.attributesHtml(Object.assign({}, r, { title: title }))}/>`;
|
||||
if (r) {
|
||||
let js = '';
|
||||
if (ruleOptions.enableLongPress) {
|
||||
const longPressDelay = ruleOptions.longPressDelay ? ruleOptions.longPressDelay : 500;
|
||||
const id = r['data-resource-id'];
|
||||
|
||||
const longPressHandler = `${ruleOptions.postMessageSyntax}('longclick:${id}')`;
|
||||
|
||||
const touchStart = `t=setTimeout(()=>{t=null; ${longPressHandler};}, ${longPressDelay});`;
|
||||
const touchEnd = 'if (!!t) clearTimeout(t); t=null';
|
||||
|
||||
js = ` ontouchstart="${touchStart}" ontouchend="${touchEnd}"`;
|
||||
}
|
||||
|
||||
return `<img data-from-md ${htmlUtils.attributesHtml(Object.assign({}, r, { title: title }))}${js}/>`;
|
||||
}
|
||||
return defaultRender(tokens, idx, options, env, self);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,12 +64,24 @@ function installRule(markdownIt, mdOptions, ruleOptions) {
|
||||
href = href.replace(/'/g, '%27');
|
||||
|
||||
let js = `${ruleOptions.postMessageSyntax}(${JSON.stringify(href)}, { resourceId: ${JSON.stringify(resourceId)} }); return false;`;
|
||||
if (ruleOptions.enableLongPress && !!resourceId) {
|
||||
const longPressDelay = ruleOptions.longPressDelay ? ruleOptions.longPressDelay : 500;
|
||||
|
||||
const onClick = `${ruleOptions.postMessageSyntax}(${JSON.stringify(href)})`;
|
||||
const onLongClick = `${ruleOptions.postMessageSyntax}("longclick:${resourceId}")`;
|
||||
|
||||
const touchStart = `t=setTimeout(()=>{t=null; ${onLongClick};}, ${longPressDelay});`;
|
||||
const touchEnd = `if (!!t) {clearTimeout(t); t=null; ${onClick};}`;
|
||||
|
||||
js = `ontouchstart='${touchStart}' ontouchend='${touchEnd}'`;
|
||||
}
|
||||
|
||||
if (hrefAttr.indexOf('#') === 0 && href.indexOf('#') === 0) js = ''; // If it's an internal anchor, don't add any JS since the webview is going to handle navigating to the right place
|
||||
|
||||
if (ruleOptions.plainResourceRendering || pluginOptions.linkRenderingType === 2) {
|
||||
return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${htmlentities(href)}' type='${htmlentities(mime)}'>`;
|
||||
} else {
|
||||
return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${hrefAttr}' onclick='${js}' type='${htmlentities(mime)}'>${icon}`;
|
||||
return `<a data-from-md ${resourceIdAttr} title='${htmlentities(title)}' href='${hrefAttr}' ${js} type='${htmlentities(mime)}'>${icon}`;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -38,6 +38,6 @@
|
||||
"md5": "^2.2.1",
|
||||
"memory-cache": "^0.2.0",
|
||||
"mermaid": "^8.8.1",
|
||||
"slug": "^3.3.4"
|
||||
"slug": "^3.5.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ export interface CommandRuntime {
|
||||
|
||||
// Used for the (optional) toolbar button title
|
||||
title?(props:any):string,
|
||||
// props?:any
|
||||
}
|
||||
|
||||
export interface CommandDeclaration {
|
||||
|
||||
@@ -88,9 +88,10 @@ export default class MenuUtils {
|
||||
}
|
||||
|
||||
public commandToStatefulMenuItem(commandName:string, props:any = null):MenuItem {
|
||||
return this.commandToMenuItem(commandName, () => {
|
||||
const output = this.commandsToMenuItems([commandName], () => {
|
||||
return this.service.execute(commandName, props ? props : {});
|
||||
});
|
||||
return output[commandName];
|
||||
}
|
||||
|
||||
public commandsToMenuItems(commandNames:string[], onClick:Function):MenuItems {
|
||||
|
||||
12
ReactNativeClient/package-lock.json
generated
12
ReactNativeClient/package-lock.json
generated
@@ -5063,6 +5063,7 @@
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
@@ -9286,6 +9287,11 @@
|
||||
"base64-js": "*"
|
||||
}
|
||||
},
|
||||
"react-native-share": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-share/-/react-native-share-3.3.3.tgz",
|
||||
"integrity": "sha512-KFyGe7hnD7ZDJCz1kWTI5iv2MfY5weIz+aTzqyomyxxFb73rHlCRHa+NRNYvnpTntOjnqyB0/GFf1W2J9y6vJQ=="
|
||||
},
|
||||
"react-native-side-menu": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/react-native-side-menu/-/react-native-side-menu-1.1.3.tgz",
|
||||
@@ -10171,9 +10177,9 @@
|
||||
"integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc="
|
||||
},
|
||||
"slug": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/slug/-/slug-3.4.0.tgz",
|
||||
"integrity": "sha512-s234DYtuRCkzVNL8dL9BRFNmlZUF9NUGjxWG+wwBKPzUFUADrhkjKGVNhDaZs2Lc+UKh3085KItaKilwJA9I2Q=="
|
||||
"version": "3.5.0",
|
||||
"resolved": "https://registry.npmjs.org/slug/-/slug-3.5.0.tgz",
|
||||
"integrity": "sha512-+pZLDhMtmAc+ZcojQSMlUKDZBYmvhZiZmK8Ffx/D3Q/MIMHPDBAMbWvWN8vJb9xl2MfbDdRWxFzrdOhBiyVpow=="
|
||||
},
|
||||
"snapdragon": {
|
||||
"version": "0.8.2",
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
"react-native-push-notification": "git+https://github.com/laurent22/react-native-push-notification.git",
|
||||
"react-native-quick-actions": "^0.3.13",
|
||||
"react-native-securerandom": "^1.0.0-rc.0",
|
||||
"react-native-share": "^3.3.3",
|
||||
"react-native-side-menu": "^1.1.3",
|
||||
"react-native-sqlite-storage": "^4.1.0",
|
||||
"react-native-vector-icons": "^6.6.0",
|
||||
@@ -86,7 +87,7 @@
|
||||
"redux": "4.0.0",
|
||||
"reselect": "^4.0.0",
|
||||
"rn-fetch-blob": "^0.12.0",
|
||||
"slug": "^3.4.0",
|
||||
"slug": "^3.5.0",
|
||||
"stream": "0.0.2",
|
||||
"string-natural-compare": "^2.0.2",
|
||||
"string-padding": "^1.0.2",
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
diff --git a/node_modules/slug/slug.js b/node_modules/slug/slug.js
|
||||
index b40320b..2be9650 100644
|
||||
--- a/node_modules/slug/slug.js
|
||||
+++ b/node_modules/slug/slug.js
|
||||
@@ -51,13 +51,31 @@
|
||||
throw new Error('String "' + str + '" reaches code believed to be unreachable; please open an issue at https://github.com/Trott/slug/issues/new')
|
||||
}
|
||||
|
||||
- if (typeof window === 'undefined') {
|
||||
+ if (typeof window !== 'undefined' && window.btoa) {
|
||||
+ base64 = function (input) {
|
||||
+ return btoa(unescape(encodeURIComponent(input)))
|
||||
+ }
|
||||
+ } else if (typeof Buffer !== 'undefined') {
|
||||
base64 = function (input) {
|
||||
return Buffer.from(input).toString('base64')
|
||||
}
|
||||
} else {
|
||||
+ // Polyfill for environments that don't have any btoa or Buffer class (eg. React Native)
|
||||
+ // Copied from https://github.com/davidchambers/Base64.js/blob/a121f75bb10c8dd5d557886c4b1069b31258d230/base64.js#L22
|
||||
base64 = function (input) {
|
||||
- return btoa(unescape(encodeURIComponent(input)))
|
||||
+ var str = unescape(encodeURIComponent(input + ''))
|
||||
+ for (
|
||||
+ var block, charCode, idx = 0, map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=', output = '';
|
||||
+ str.charAt(idx | 0) || (map = '=', idx % 1);
|
||||
+ output += map.charAt(63 & block >> 8 - idx % 1 * 8)
|
||||
+ ) {
|
||||
+ charCode = str.charCodeAt(idx += 3 / 4)
|
||||
+ if (charCode > 0xFF) {
|
||||
+ throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.")
|
||||
+ }
|
||||
+ block = block << 8 | charCode
|
||||
+ }
|
||||
+ return output
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,5 +43,5 @@ Restart the app, and Joplin should load the plugin and execute its `onStart` han
|
||||
|
||||
# Next steps
|
||||
|
||||
- You might want to check the [plugin tutorial](https://github.com/laurent22/joplin/blob/dev/readme/api/tutorials/toc_plugin/) to get a good overview of how to create a complete plugin and how to use the plugin API.
|
||||
- You might want to check the [plugin tutorial](https://github.com/laurent22/joplin/blob/dev/readme/api/tutorials/toc_plugin.md) to get a good overview of how to create a complete plugin and how to use the plugin API.
|
||||
- For more information about the plugin API, check the [Plugin API reference](https://joplinapp.org/api/references/plugin_api/classes/joplin.html).
|
||||
|
||||
Reference in New Issue
Block a user