1
0
mirror of https://github.com/laurent22/joplin.git synced 2026-01-14 00:29:38 +02:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Laurent Cozic
07ddeab667 Fix mobile build 2021-07-16 14:30:19 +01:00
Laurent Cozic
ca4602f47b Tweaks 2021-07-16 11:29:11 +01:00
Laurent Cozic
40886892c9 Merge branch 'dev' into codemirror_theme_update 2021-07-16 11:14:13 +01:00
Laurent Cozic
58c4f9eded Merge branch 'dev' of github.com:laurent22/joplin into dev 2021-07-16 11:13:50 +01:00
Xavi Ivars
2c525c2163 All: Translation: Update ca.po (#5193) 2021-07-15 13:29:02 -04:00
stephan11H
68f119efbd All: Translation: Update de_DE.po (#5186)
* update german translation file

* update German translation file

* changed translation for *full changelog*

Co-authored-by: Stephan Hildebrand <stephan.hildebrand@rwth-aachen.de>
2021-07-15 12:51:33 -04:00
Elaborendum
e88753c609 All: Translation: Update es_ES.po (#5190) 2021-07-15 12:49:27 -04:00
Laurent Cozic
8395d5daa9 Mobile: Added new beta editor based on CodeMirror 6 2021-07-13 19:13:13 +01:00
Laurent Cozic
56c85b0713 fixed bold 2021-07-10 17:14:01 +01:00
Laurent Cozic
8387b446b6 fix 2021-07-10 17:05:57 +01:00
Laurent Cozic
82a90bef91 also increase default font size for the editor 2021-07-10 17:01:07 +01:00
Laurent Cozic
6b2f33c45f udpate theme 2021-07-10 16:56:18 +01:00
23 changed files with 2534 additions and 889 deletions

View File

@@ -53,6 +53,7 @@ packages/app-mobile/locales
packages/app-mobile/node_modules
packages/app-mobile/pluginAssets/
packages/app-mobile/lib/rnInjectedJs/
packages/app-mobile/components/NoteEditor/CodeMirror.bundle.js
packages/lib/assets/
packages/lib/rnInjectedJs/
packages/lib/vendor/
@@ -701,6 +702,12 @@ packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js.ma
packages/app-mobile/components/NoteBodyViewer/hooks/useSource.d.ts
packages/app-mobile/components/NoteBodyViewer/hooks/useSource.js
packages/app-mobile/components/NoteBodyViewer/hooks/useSource.js.map
packages/app-mobile/components/NoteEditor/CodeMirror.d.ts
packages/app-mobile/components/NoteEditor/CodeMirror.js
packages/app-mobile/components/NoteEditor/CodeMirror.js.map
packages/app-mobile/components/NoteEditor/NoteEditor.d.ts
packages/app-mobile/components/NoteEditor/NoteEditor.js
packages/app-mobile/components/NoteEditor/NoteEditor.js.map
packages/app-mobile/components/SelectDateTimeDialog.d.ts
packages/app-mobile/components/SelectDateTimeDialog.js
packages/app-mobile/components/SelectDateTimeDialog.js.map

6
.gitignore vendored
View File

@@ -687,6 +687,12 @@ packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js.ma
packages/app-mobile/components/NoteBodyViewer/hooks/useSource.d.ts
packages/app-mobile/components/NoteBodyViewer/hooks/useSource.js
packages/app-mobile/components/NoteBodyViewer/hooks/useSource.js.map
packages/app-mobile/components/NoteEditor/CodeMirror.d.ts
packages/app-mobile/components/NoteEditor/CodeMirror.js
packages/app-mobile/components/NoteEditor/CodeMirror.js.map
packages/app-mobile/components/NoteEditor/NoteEditor.d.ts
packages/app-mobile/components/NoteEditor/NoteEditor.js
packages/app-mobile/components/NoteEditor/NoteEditor.js.map
packages/app-mobile/components/SelectDateTimeDialog.d.ts
packages/app-mobile/components/SelectDateTimeDialog.js
packages/app-mobile/components/SelectDateTimeDialog.js.map

View File

@@ -396,7 +396,9 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
color: inherit !important;
background-color: inherit !important;
position: absolute !important;
-webkit-box-shadow: none !important; // Some themes add a box shadow for some reason
/* Some themes add a box shadow for some reason */
-webkit-box-shadow: none !important;
line-height: ${theme.lineHeight} !important;
}
.CodeMirror-lines {
@@ -422,20 +424,54 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
font-family: ${monospaceFonts.join(', ')} !important;
}
.cm-header-1 {
.CodeMirror .cm-header-1 {
font-size: 1.5em;
color: ${theme.color};
}
.cm-header-2 {
.CodeMirror .cm-header-2 {
font-size: 1.3em;
color: ${theme.color};
}
.cm-header-3 {
.CodeMirror .cm-header-3 {
font-size: 1.1em;
color: ${theme.color};
}
.cm-header-4, .cm-header-5, .cm-header-6 {
.CodeMirror .cm-header-4, .CodeMirror .cm-header-5, .CodeMirror .cm-header-6 {
font-size: 1em;
color: ${theme.color};
}
.CodeMirror .cm-quote {
color: ${theme.color};
opacity: ${theme.blockQuoteOpacity};
}
div.CodeMirror span.cm-link-text {
color: ${theme.urlColor};
}
div.CodeMirror span.cm-url {
color: ${theme.urlColor};
opacity: 0.5;
}
.CodeMirror .cm-variable-2, .CodeMirror .cm-variable-3, .CodeMirror .cm-keyword {
color: ${theme.color};
}
div.CodeMirror span.cm-comment {
color: ${theme.codeColor};
}
div.CodeMirror span.cm-strong {
color: ${theme.colorBright};
}
div.CodeMirror span.cm-hr {
color: ${theme.dividerColor};
}
.cm-header-1, .cm-header-2, .cm-header-3, .cm-header-4, .cm-header-5, .cm-header-6 {
@@ -467,6 +503,8 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
}
/* The default dark theme colors don't have enough contrast with the background */
/*
.cm-s-nord span.cm-comment {
color: #9aa4b6 !important;
}
@@ -486,6 +524,7 @@ function CodeMirror(props: NoteBodyEditorProps, ref: any) {
.cm-s-solarized.cm-s-dark span.cm-comment {
color: #8ba1a7 !important;
}
*/
${selectionColorCss}
`));

View File

@@ -61,4 +61,6 @@ buck-out/
# Custom
lib/csstojs/
lib/rnInjectedJs/
dist/
dist/
components/NoteEditor/CodeMirror.bundle.js
components/NoteEditor/CodeMirror.bundle.min.js

View File

@@ -141,8 +141,8 @@ android {
applicationId "net.cozic.joplin"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 2097639
versionName "2.2.0"
versionCode 2097640
versionName "2.2.1"
ndk {
abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
}

View File

@@ -0,0 +1,160 @@
/* eslint-disable import/prefer-default-export */
// This contains the CodeMirror instance, which needs to be built into a bundle
// using `npm run buildInjectedJs`. This bundle is then loaded from
// NoteEditor.tsx into the webview.
//
// In general, since this file is harder to debug due to the intermediate built
// step, it's better to keep it as light as possible - it shoud just be a light
// wrapper to access CodeMirror functionalities. Anything else should be done
// from NoteEditor.tsx.
import { EditorState, Extension } from '@codemirror/state';
import { EditorView, drawSelection, highlightSpecialChars, ViewUpdate } from '@codemirror/view';
import { markdown } from '@codemirror/lang-markdown';
import { defaultHighlightStyle, HighlightStyle, tags } from '@codemirror/highlight';
import { undo, redo, history, undoDepth, redoDepth } from '@codemirror/history';
interface CodeMirrorResult {
editor: EditorView;
undo: Function;
redo: Function;
}
function postMessage(name: string, data: any) {
(window as any).ReactNativeWebView.postMessage(JSON.stringify({
data,
name,
}));
}
function logMessage(...msg: any[]) {
postMessage('onLog', { value: msg });
}
const createTheme = (theme: any): Extension => {
const baseTheme = EditorView.baseTheme({
'&': {
color: theme.color,
backgroundColor: theme.backgroundColor,
fontFamily: theme.fontFamily,
fontSize: `${theme.fontSize}px`,
},
});
const appearanceTheme = EditorView.theme({}, { dark: theme.appearance === 'dark' });
const baseHeadingStyle = {
fontWeight: 'bold',
fontFamily: theme.fontFamily,
};
const syntaxHighlighting = HighlightStyle.define([
{
tag: tags.strong,
fontWeight: 'bold',
},
{
tag: tags.emphasis,
fontStyle: 'italic',
},
{
...baseHeadingStyle,
tag: tags.heading1,
fontSize: '1.6em',
borderBottom: `1px solid ${theme.dividerColor}`,
},
{
...baseHeadingStyle,
tag: tags.heading2,
fontSize: '1.4em',
},
{
...baseHeadingStyle,
tag: tags.heading3,
fontSize: '1.3em',
},
{
...baseHeadingStyle,
tag: tags.heading4,
fontSize: '1.2em',
},
{
...baseHeadingStyle,
tag: tags.heading5,
fontSize: '1.1em',
},
{
...baseHeadingStyle,
tag: tags.heading6,
fontSize: '1.0em',
},
{
tag: tags.list,
fontFamily: theme.fontFamily,
},
]);
return [
baseTheme,
appearanceTheme,
syntaxHighlighting,
];
};
export function initCodeMirror(parentElement: any, initialText: string, theme: any): CodeMirrorResult {
logMessage('Initializing CodeMirror...');
let schedulePostUndoRedoDepthChangeId_: any = 0;
function schedulePostUndoRedoDepthChange(editor: EditorView, doItNow: boolean = false) {
if (schedulePostUndoRedoDepthChangeId_) {
if (doItNow) {
clearTimeout(schedulePostUndoRedoDepthChangeId_);
} else {
return;
}
}
schedulePostUndoRedoDepthChangeId_ = setTimeout(() => {
schedulePostUndoRedoDepthChangeId_ = null;
postMessage('onUndoRedoDepthChange', {
undoDepth: undoDepth(editor.state),
redoDepth: redoDepth(editor.state),
});
}, doItNow ? 0 : 1000);
}
const editor = new EditorView({
state: EditorState.create({
extensions: [
markdown(),
createTheme(theme),
history(),
drawSelection(),
highlightSpecialChars(),
EditorView.lineWrapping,
defaultHighlightStyle.fallback,
EditorView.updateListener.of((viewUpdate: ViewUpdate) => {
if (viewUpdate.docChanged) {
postMessage('onChange', { value: editor.state.doc.toString() });
schedulePostUndoRedoDepthChange(editor);
}
}),
],
doc: initialText,
}),
parent: parentElement,
});
return {
editor,
undo: () => {
undo(editor);
schedulePostUndoRedoDepthChange(editor, true);
},
redo: () => {
redo(editor);
schedulePostUndoRedoDepthChange(editor, true);
},
};
}

View File

@@ -0,0 +1,333 @@
import Setting from '@joplin/lib/models/Setting';
import shim from '@joplin/lib/shim';
import { themeStyle } from '@joplin/lib/theme';
const React = require('react');
const { forwardRef, useImperativeHandle, useEffect, useState, useCallback, useRef } = require('react');
const { WebView } = require('react-native-webview');
const { editorFont } = require('../global-style');
export interface ChangeEvent {
value: string;
}
export interface UndoRedoDepthChangeEvent {
undoDepth: number;
redoDepth: number;
}
type ChangeEventHandler = (event: ChangeEvent)=> void;
type UndoRedoDepthChangeHandler = (event: UndoRedoDepthChangeEvent)=> void;
interface Props {
themeId: number;
initialText: string;
style: any;
onChange: ChangeEventHandler;
onUndoRedoDepthChange: UndoRedoDepthChangeHandler;
}
function fontFamilyFromSettings() {
const f = editorFont(Setting.value('style.editor.fontFamily'));
return [f, 'sans-serif'].join(', ');
}
// function useCss(themeId:number):string {
// const [css, setCss] = useState('');
// // useEffect(() => {
// // const theme = themeStyle(themeId);
// // // Selection in dark mode is hard to see so make it brighter.
// // // https://discourse.joplinapp.org/t/dragging-in-dark-theme/12433/4?u=laurent
// // const selectionColorCss = theme.appearance === ThemeAppearance.Dark ?
// // `.CodeMirror-selected {
// // background: #6b6b6b !important;
// // }` : '';
// // const monospaceFonts = [];
// // // if (Setting.value('style.editor.monospaceFontFamily')) monospaceFonts.push(`"${Setting.value('style.editor.monospaceFontFamily')}"`);
// // monospaceFonts.push('monospace');
// // const fontSize = 15;
// // const fontFamily = fontFamilyFromSettings();
// // // BUG: caret-color seems to be ignored for some reason
// // const caretColor = theme.appearance === ThemeAppearance.Dark ? "white" : 'black';
// // setCss(`
// // /* These must be important to prevent the codemirror defaults from taking over*/
// // .CodeMirror {
// // font-family: ${fontFamily};
// // font-size: ${fontSize}px;
// // height: 100% !important;
// // width: 100% !important;
// // color: ${theme.color};
// // background-color: ${theme.backgroundColor};
// // position: absolute !important;
// // -webkit-box-shadow: none !important; // Some themes add a box shadow for some reason
// // }
// // .CodeMirror-lines {
// // /* This is used to enable the scroll-past end behaviour. The same height should */
// // /* be applied to the viewer. */
// // padding-bottom: 400px !important;
// // }
// // /* Left padding is applied at the editor component level, so we should remove it from the lines */
// // .CodeMirror pre.CodeMirror-line,
// // .CodeMirror pre.CodeMirror-line-like {
// // padding-left: 0;
// // }
// // .CodeMirror-sizer {
// // /* Add a fixed right padding to account for the appearance (and disappearance) */
// // /* of the sidebar */
// // padding-right: 10px !important;
// // }
// // /* This enforces monospace for certain elements (code, tables, etc.) */
// // .cm-jn-monospace {
// // font-family: ${monospaceFonts.join(', ')} !important;
// // }
// // .cm-header-1 {
// // font-size: 1.5em;
// // }
// // .cm-header-2 {
// // font-size: 1.3em;
// // }
// // .cm-header-3 {
// // font-size: 1.1em;
// // }
// // .cm-header-4, .cm-header-5, .cm-header-6 {
// // font-size: 1em;
// // }
// // .cm-header-1, .cm-header-2, .cm-header-3, .cm-header-4, .cm-header-5, .cm-header-6 {
// // line-height: 1.5em;
// // }
// // .cm-search-marker {
// // background: ${theme.searchMarkerBackgroundColor};
// // color: ${theme.searchMarkerColor} !important;
// // }
// // .cm-search-marker-selected {
// // background: ${theme.selectedColor2};
// // color: ${theme.color2} !important;
// // }
// // .cm-search-marker-scrollbar {
// // background: ${theme.searchMarkerBackgroundColor};
// // -moz-box-sizing: border-box;
// // box-sizing: border-box;
// // opacity: .5;
// // }
// // /* We need to use important to override theme specific values */
// // .cm-error {
// // color: inherit !important;
// // background-color: inherit !important;
// // border-bottom: 1px dotted #dc322f;
// // }
// // /* The default dark theme colors don't have enough contrast with the background */
// // .cm-s-nord span.cm-comment {
// // color: #9aa4b6 !important;
// // }
// // .cm-s-dracula span.cm-comment {
// // color: #a1abc9 !important;
// // }
// // .cm-s-monokai span.cm-comment {
// // color: #908b74 !important;
// // }
// // .cm-s-material-darker span.cm-comment {
// // color: #878787 !important;
// // }
// // .cm-s-solarized.cm-s-dark span.cm-comment {
// // color: #8ba1a7 !important;
// // }
// // /* MOBILE SPECIFIC */
// // .CodeMirror .cm-scroller,
// // .CodeMirror .cm-line {
// // font-family: ${fontFamily};
// // caret-color: ${caretColor};
// // }
// // ${selectionColorCss}
// // `);
// // }, [themeId]);
// return css;
// }
function useHtml(css: string): string {
const [html, setHtml] = useState('');
useEffect(() => {
setHtml(
`
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<style>
.cm-editor {
height: 100%;
}
${css}
</style>
</head>
<body style="margin:0; height:100vh; width:100vh; width:100vw; min-width:100vw;">
<div class="CodeMirror" style="height:100%;"></div>
</body>
</html>
`
);
}, [css]);
return html;
}
function editorTheme(themeId: number) {
return {
...themeStyle(themeId),
fontSize: 15,
fontFamily: fontFamilyFromSettings(),
};
}
function NoteEditor(props: Props, ref: any) {
const [source, setSource] = useState(undefined);
const webviewRef = useRef(null);
const injectedJavaScript = `
function postMessage(name, data) {
window.ReactNativeWebView.postMessage(JSON.stringify({
data,
name,
}));
}
function logMessage(...msg) {
postMessage('onLog', { value: msg });
}
// This variable is not used within this script
// but is called using "injectJavaScript" from
// the wrapper component.
let cm = null;
try {
${shim.injectedJs('codeMirrorBundle')};
const parentElement = document.getElementsByClassName('CodeMirror')[0];
const theme = ${JSON.stringify(editorTheme(props.themeId))};
const initialText = ${JSON.stringify(props.initialText)};
cm = codeMirrorBundle.initCodeMirror(parentElement, initialText, theme);
} catch (e) {
window.ReactNativeWebView.postMessage("error:" + e.message + ": " + JSON.stringify(e))
} finally {
true;
}
`;
// const css = useCss(props.themeId);
const html = useHtml('');
useImperativeHandle(ref, () => {
return {
undo: function() {
webviewRef.current.injectJavaScript('cm.undo(); true;');
},
redo: function() {
webviewRef.current.injectJavaScript('cm.redo(); true;');
},
};
});
useEffect(() => {
let cancelled = false;
async function createHtmlFile() {
const tempFile = `${Setting.value('resourceDir')}/NoteEditor.html`;
await shim.fsDriver().writeFile(tempFile, html, 'utf8');
if (cancelled) return;
setSource({
uri: `file://${tempFile}?r=${Math.round(Math.random() * 100000000)}`,
baseUrl: `file://${Setting.value('resourceDir')}/`,
});
}
void createHtmlFile();
return () => {
cancelled = true;
};
}, [html]);
const onMessage = useCallback((event: any) => {
const data = event.nativeEvent.data;
if (data.indexOf('error:') === 0) {
console.error('CodeMirror:', data);
return;
}
const msg = JSON.parse(data);
const handlers: Record<string, Function> = {
onLog: (event: any) => {
console.info('CodeMirror:', ...event.value);
},
onChange: (event: ChangeEvent) => {
props.onChange(event);
},
onUndoRedoDepthChange: (event: UndoRedoDepthChangeEvent) => {
console.info('onUndoRedoDepthChange', event);
props.onUndoRedoDepthChange(event);
},
};
if (handlers[msg.name]) {
handlers[msg.name](msg.data);
} else {
console.info('Unsupported CodeMirror message:', msg);
}
}, [props.onChange]);
const onError = useCallback(() => {
console.error('NoteEditor: webview error');
});
// - `setSupportMultipleWindows` must be `true` for security reasons:
// https://github.com/react-native-webview/react-native-webview/releases/tag/v11.0.0
return <WebView
style={props.style}
ref={webviewRef}
useWebKit={true}
source={source}
setSupportMultipleWindows={true}
allowingReadAccessToURL={`file://${Setting.value('resourceDir')}`}
originWhitelist={['file://*', './*', 'http://*', 'https://*']}
allowFileAccess={true}
injectedJavaScript={injectedJavaScript}
onMessage={onMessage}
onError={onError}
/>;
}
export default forwardRef(NoteEditor);

View File

@@ -1,10 +1,11 @@
import AsyncActionQueue from '@joplin/lib/AsyncActionQueue';
import UndoRedoService from '@joplin/lib/services/UndoRedoService';
import uuid from '@joplin/lib/uuid';
import Setting from '@joplin/lib/models/Setting';
import shim from '@joplin/lib/shim';
import UndoRedoService from '@joplin/lib/services/UndoRedoService';
import NoteBodyViewer from '../NoteBodyViewer/NoteBodyViewer';
import checkPermissions from '../../utils/checkPermissions';
import NoteEditor, { ChangeEvent, UndoRedoDepthChangeEvent } from '../NoteEditor/NoteEditor';
const FileViewer = require('react-native-file-viewer').default;
const React = require('react');
@@ -42,6 +43,7 @@ const ImagePicker = require('react-native-image-picker').default;
import SelectDateTimeDialog from '../SelectDateTimeDialog';
import ShareExtension from '../../utils/ShareExtension.js';
import CameraView from '../CameraView';
import { NoteEntity } from '@joplin/lib/services/database/types';
const urlUtils = require('@joplin/lib/urlUtils');
const emptyArray: any[] = [];
@@ -95,6 +97,8 @@ class NoteScreenComponent extends BaseScreenComponent {
this.styles_ = {};
this.editorRef = React.createRef();
const saveDialog = async () => {
if (this.isModified()) {
const buttonId = await dialogs.pop(this, _('This note has been modified:'), [{ text: _('Save changes'), id: 'save' }, { text: _('Discard changes'), id: 'discard' }, { text: _('Cancel'), id: 'cancel' }]);
@@ -230,16 +234,38 @@ class NoteScreenComponent extends BaseScreenComponent {
this.body_selectionChange = this.body_selectionChange.bind(this);
this.onBodyViewerLoadEnd = this.onBodyViewerLoadEnd.bind(this);
this.onBodyViewerCheckboxChange = this.onBodyViewerCheckboxChange.bind(this);
this.onBodyChange = this.onBodyChange.bind(this);
this.onUndoRedoDepthChange = this.onUndoRedoDepthChange.bind(this);
}
undoRedoService_stackChange() {
this.setState({ undoRedoButtonState: {
canUndo: this.undoRedoService_.canUndo,
canRedo: this.undoRedoService_.canRedo,
} });
private useEditorBeta(): boolean {
return this.props.useEditorBeta;
}
async undoRedo(type: string) {
private onBodyChange(event: ChangeEvent) {
shared.noteComponent_change(this, 'body', event.value);
this.scheduleSave();
}
private onUndoRedoDepthChange(event: UndoRedoDepthChangeEvent) {
if (this.useEditorBeta()) {
this.setState({ undoRedoButtonState: {
canUndo: !!event.undoDepth,
canRedo: !!event.redoDepth,
} });
}
}
private undoRedoService_stackChange() {
if (!this.useEditorBeta()) {
this.setState({ undoRedoButtonState: {
canUndo: this.undoRedoService_.canUndo,
canRedo: this.undoRedoService_.canRedo,
} });
}
}
private async undoRedo(type: string) {
const undoState = await this.undoRedoService_[type](this.undoState());
if (!undoState) return;
@@ -253,11 +279,25 @@ class NoteScreenComponent extends BaseScreenComponent {
}
screenHeader_undoButtonPress() {
void this.undoRedo('undo');
if (this.useEditorBeta()) {
this.editorRef.current.undo();
} else {
void this.undoRedo('undo');
}
}
screenHeader_redoButtonPress() {
void this.undoRedo('redo');
if (this.useEditorBeta()) {
this.editorRef.current.redo();
} else {
void this.undoRedo('redo');
}
}
undoState(noteBody: string = null) {
return {
body: noteBody === null ? this.state.note.body : noteBody,
};
}
styles() {
@@ -355,12 +395,6 @@ class NoteScreenComponent extends BaseScreenComponent {
return shared.isModified(this);
}
undoState(noteBody: string = null) {
return {
body: noteBody === null ? this.state.note.body : noteBody,
};
}
async requestGeoLocationPermissions() {
if (!Setting.value('trackLocation')) return;
@@ -448,6 +482,7 @@ class NoteScreenComponent extends BaseScreenComponent {
} else {
this.undoRedoService_.schedulePush(this.undoState());
}
shared.noteComponent_change(this, 'body', text);
this.scheduleSave();
}
@@ -844,6 +879,11 @@ class NoteScreenComponent extends BaseScreenComponent {
output.push({
title: _('Attach...'),
onPress: async () => {
if (this.state.mode === 'edit' && this.useEditorBeta()) {
alert('Attaching files from the beta editor is not yet supported. You may do so from the viewer mode instead.');
return;
}
const buttons = [];
// On iOS, it will show "local files", which means certain files saved from the browser
@@ -1017,7 +1057,7 @@ class NoteScreenComponent extends BaseScreenComponent {
}
const theme = themeStyle(this.props.themeId);
const note = this.state.note;
const note: NoteEntity = this.state.note;
const isTodo = !!Number(note.is_todo);
if (this.state.showCamera) {
@@ -1066,25 +1106,37 @@ class NoteScreenComponent extends BaseScreenComponent {
// abcd|
// abcde|
// abcde|f
bodyComponent = (
<TextInput
autoCapitalize="sentences"
if (!this.useEditorBeta()) {
bodyComponent = (
<TextInput
autoCapitalize="sentences"
style={this.styles().bodyTextInput}
ref="noteBodyTextField"
multiline={true}
value={note.body}
onChangeText={(text: string) => this.body_changeText(text)}
onSelectionChange={this.body_selectionChange}
blurOnSubmit={false}
selectionColor={theme.textSelectionColor}
keyboardAppearance={theme.keyboardAppearance}
placeholder={_('Add body')}
placeholderTextColor={theme.colorFaded}
// need some extra padding for iOS so that the keyboard won't cover last line of the note
// see https://github.com/laurent22/joplin/issues/3607
paddingBottom={ Platform.OS === 'ios' ? 40 : 0}
/>
);
} else {
bodyComponent = <NoteEditor
ref={this.editorRef}
themeId={this.props.themeId}
initialText={note.body}
onChange={this.onBodyChange}
onUndoRedoDepthChange={this.onUndoRedoDepthChange}
style={this.styles().bodyTextInput}
ref="noteBodyTextField"
multiline={true}
value={note.body}
onChangeText={(text: string) => this.body_changeText(text)}
onSelectionChange={this.body_selectionChange}
blurOnSubmit={false}
selectionColor={theme.textSelectionColor}
keyboardAppearance={theme.keyboardAppearance}
placeholder={_('Add body')}
placeholderTextColor={theme.colorFaded}
// need some extra padding for iOS so that the keyboard won't cover last line of the note
// see https://github.com/laurent22/joplin/issues/3607
paddingBottom={ Platform.OS === 'ios' ? 40 : 0}
/>
);
/>;
}
}
const renderActionButton = () => {
@@ -1187,6 +1239,7 @@ const NoteScreen = connect((state: any) => {
showSideMenu: state.showSideMenu,
provisionalNoteIds: state.provisionalNoteIds,
highlightedWords: state.highlightedWords,
useEditorBeta: state.settings['editor.beta'],
};
})(NoteScreenComponent);

View File

@@ -5,8 +5,8 @@ const tasks = {
encodeAssets: {
fn: require('./tools/encodeAssets'),
},
buildReactNativeInjectedJs: {
fn: require('./tools/buildReactNativeInjectedJs'),
buildInjectedJs: {
fn: require('./tools/buildInjectedJs'),
},
podInstall: {
fn: require('./tools/podInstall'),
@@ -16,7 +16,7 @@ const tasks = {
utils.registerGulpTasks(gulp, tasks);
gulp.task('build', gulp.series(
'buildReactNativeInjectedJs',
'buildInjectedJs',
'encodeAssets',
'podInstall'
));

File diff suppressed because it is too large Load Diff

View File

@@ -10,11 +10,13 @@
"tsc": "node node_modules/typescript/bin/tsc --project tsconfig.json",
"watch": "node node_modules/typescript/bin/tsc --watch --project tsconfig.json",
"clean": "node tools/clean.js",
"buildInjectedJs": "gulp buildInjectedJs",
"watchInjectedJs": "nodemon --verbose --watch components/NoteEditor/CodeMirror.ts --exec \"npm run buildInjectedJs\"",
"postinstall": "jetify && npm run build"
},
"dependencies": {
"@joplin/lib": "^1.0.9",
"@joplin/renderer": "^1.0.17",
"@joplin/lib": "^2.2.0",
"@joplin/renderer": "^2.2.0",
"@react-native-community/clipboard": "^1.5.0",
"@react-native-community/datetimepicker": "^3.0.3",
"@react-native-community/geolocation": "^2.0.2",
@@ -62,7 +64,14 @@
"devDependencies": {
"@babel/core": "^7.11.6",
"@babel/runtime": "^7.11.2",
"@codemirror/highlight": "^0.18.4",
"@codemirror/history": "^0.18.1",
"@codemirror/lang-markdown": "^0.18.4",
"@codemirror/state": "^0.18.7",
"@codemirror/view": "^0.18.19",
"@joplin/tools": "^1.0.9",
"@rollup/plugin-node-resolve": "^13.0.0",
"@rollup/plugin-typescript": "^8.2.1",
"@types/node": "^14.14.6",
"@types/react": "^16.9.55",
"@types/react-native": "^0.64.4",
@@ -71,6 +80,9 @@
"gulp": "^4.0.2",
"jetifier": "^1.6.5",
"metro-react-native-babel-preset": "^0.63.0",
"typescript": "^4.0.5"
"nodemon": "^2.0.12",
"rollup": "^2.53.1",
"typescript": "^4.0.5",
"uglify-js": "^3.13.10"
}
}

View File

@@ -0,0 +1,37 @@
// React Native WebView cannot load external JS files, however it can load
// arbitrary JS via the injectedJavaScript property. So we use this to load external
// files: First here we convert the JS file to a plain string, and that string
// is then loaded by eg. the Mermaid plugin, and finally injected in the WebView.
const fs = require('fs-extra');
const exec = require('child_process').exec;
const path = require('path');
const rootDir = path.dirname(path.dirname(path.dirname(__dirname)));
const mobileDir = `${rootDir}/packages/app-mobile`;
const outputDir = `${mobileDir}/lib/rnInjectedJs`;
const codeMirrorBundleFile = `${mobileDir}/components/NoteEditor/CodeMirror.bundle.min.js`;
async function copyJs(name, filePath) {
const js = await fs.readFile(filePath, 'utf-8');
const json = `module.exports = ${JSON.stringify(js)};`;
const outputPath = `${outputDir}/${name}.js`;
console.info(`Creating: ${outputPath}`);
await fs.writeFile(outputPath, json);
}
async function buildCodeMirrorBundle() {
const sourceFile = `${mobileDir}/components/NoteEditor/CodeMirror.ts`;
const fullBundleFile = `${mobileDir}/components/NoteEditor/CodeMirror.bundle.js`;
await exec(`./node_modules/rollup/dist/bin/rollup "${sourceFile}" --name codeMirrorBundle -f iife -o "${fullBundleFile}" -p @rollup/plugin-node-resolve -p @rollup/plugin-typescript`, { stdio: 'pipe' });
await exec(`./node_modules/uglify-js/bin/uglifyjs --compress -o "${codeMirrorBundleFile}" -- "${fullBundleFile}"`, { stdio: 'pipe' });
}
async function main() {
await fs.mkdirp(outputDir);
await buildCodeMirrorBundle();
await copyJs('webviewLib', `${mobileDir}/node_modules/@joplin/lib/renderers/webviewLib.js`);
await copyJs('CodeMirror.bundle', `${mobileDir}/components/NoteEditor/CodeMirror.bundle.min.js`);
}
module.exports = main;

View File

@@ -1,23 +0,0 @@
// React Native WebView cannot load external JS files, however it can load
// arbitrary JS via the injectedJavaScript property. So we use this to load external
// files: First here we convert the JS file to a plain string, and that string
// is then loaded by eg. the Mermaid plugin, and finally injected in the WebView.
const fs = require('fs-extra');
const rnDir = `${__dirname}/..`;
const outputDir = `${rnDir}/lib/rnInjectedJs`;
async function copyJs(name, filePath) {
const js = await fs.readFile(filePath, 'utf-8');
const json = `module.exports = ${JSON.stringify(js)};`;
const outputPath = `${outputDir}/${name}.js`;
await fs.writeFile(outputPath, json);
}
async function main() {
await fs.mkdirp(outputDir);
await copyJs('webviewLib', `${rnDir}/node_modules/@joplin/lib/renderers/webviewLib.js`);
}
module.exports = main;

View File

@@ -14,6 +14,7 @@ const Resource = require('@joplin/lib/models/Resource').default;
const injectedJs = {
webviewLib: require('@joplin/lib/rnInjectedJs/webviewLib'),
codeMirrorBundle: require('../lib/rnInjectedJs/CodeMirror.bundle'),
};
function shimInit() {

View File

@@ -785,10 +785,10 @@ class Setting extends BaseModel {
value: false,
type: SettingItemType.Bool,
section: 'note',
public: false, // mobilePlatform === 'ios',
public: true,
appTypes: [AppType.Mobile],
label: () => 'Opt-in to the editor beta',
description: () => 'This beta adds list continuation, Markdown preview, and Markdown shortcuts. If you find bugs, please report them in the Discourse forum.',
description: () => 'This beta adds list continuation and syntax highlighting. If you find bugs, please report them in the Discourse forum.',
},
newTodoFocus: {
@@ -915,7 +915,7 @@ class Setting extends BaseModel {
// Deprecated in favour of windowContentZoomFactor
'style.zoom': { value: 100, type: SettingItemType.Int, public: false, storage: SettingStorage.File, appTypes: [AppType.Desktop], section: 'appearance', label: () => '', minimum: 50, maximum: 500, step: 10 },
'style.editor.fontSize': { value: 13, type: SettingItemType.Int, public: true, storage: SettingStorage.File, appTypes: [AppType.Desktop], section: 'appearance', label: () => _('Editor font size'), minimum: 4, maximum: 50, step: 1 },
'style.editor.fontSize': { value: 15, type: SettingItemType.Int, public: true, storage: SettingStorage.File, appTypes: [AppType.Desktop], section: 'appearance', label: () => _('Editor font size'), minimum: 4, maximum: 50, step: 1 },
'style.editor.fontFamily':
(mobilePlatform) ?
({

View File

@@ -1,7 +1,10 @@
import { Theme, ThemeAppearance } from './type';
import lightTheme from './light';
// This is the default dark theme in Joplin
const theme: Theme = {
...lightTheme,
appearance: ThemeAppearance.Dark,
// Color scheme "1" is the basic one, like used to display the note

View File

@@ -50,6 +50,8 @@ const theme: Theme = {
codeBorderColor: 'rgb(220, 220, 220)',
codeColor: 'rgb(0,0,0)',
blockQuoteOpacity: 0.7,
codeMirrorTheme: 'default',
codeThemeCss: 'atom-one-light.css',
};

View File

@@ -52,6 +52,8 @@ export interface Theme {
codeBorderColor: string;
codeColor: string;
blockQuoteOpacity: number;
codeMirrorTheme: string;
codeThemeCss: string;

View File

@@ -205,7 +205,7 @@ export default function(theme: any) {
border-left: 4px solid ${theme.codeBorderColor};
padding-left: 1.2em;
margin-left: 0;
opacity: .7;
opacity: ${theme.blockQuoteOpacity};
}
.jop-tinymce table,

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,10 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 2.3\n"
"X-Generator: Poedit 3.0\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
#: packages/app-desktop/bridge.js:106 packages/app-desktop/bridge.js:110
#: packages/app-desktop/bridge.js:126 packages/app-desktop/bridge.js:134
@@ -124,11 +126,11 @@ msgstr "Herunterladen"
#: packages/app-desktop/checkForUpdates.js:189
msgid "Skip this version"
msgstr ""
msgstr "Überspringe diese Version"
#: packages/app-desktop/checkForUpdates.js:189
msgid "Full changelog"
msgstr ""
msgstr "Komplettes Änderungsprotokoll"
#: packages/app-desktop/gui/NoteRevisionViewer.min.js:100
msgid "This note has no history"
@@ -270,14 +272,12 @@ msgid "Retry"
msgstr "Erneut versuchen"
#: packages/app-desktop/gui/StatusScreen/StatusScreen.js:137
#, fuzzy
msgid "Advanced tools"
msgstr "Erweiterte Optionen"
#: packages/app-desktop/gui/StatusScreen/StatusScreen.js:139
#, fuzzy
msgid "Export debug report"
msgstr "Fehlerbericht exportieren"
msgstr "Ereignisprotokoll exportieren"
#: packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/CodeMirror.js:183
msgid "strong text"
@@ -521,9 +521,8 @@ msgid "Delete line"
msgstr "Zeile löschen"
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:92
#, fuzzy
msgid "Duplicate line"
msgstr "Duplizieren"
msgstr "Dupliziere Zeile"
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:96
msgid "Undo"
@@ -718,10 +717,12 @@ msgid ""
"Safe mode is currently active. Note rendering and all plugins are "
"temporarily disabled."
msgstr ""
"Sicherer Modus aktiv. Notizdarstellung und alle Plugins werden vorübergehend "
"deaktiviert."
#: packages/app-desktop/gui/MainScreen/MainScreen.js:447
msgid "Disable safe mode and restart"
msgstr ""
msgstr "Sicheren Modus beenden und neu starten"
#: packages/app-desktop/gui/MainScreen/MainScreen.js:451
msgid ""
@@ -767,15 +768,15 @@ msgstr "Weitere Information"
#: packages/app-desktop/gui/MainScreen/MainScreen.js:477
#, javascript-format
msgid "%s (%s) would like to share a notebook with you."
msgstr ""
msgstr "%s (%s) möchte ein Notizbuch mit dir teilen."
#: packages/app-desktop/gui/MainScreen/MainScreen.js:479
msgid "Accept"
msgstr ""
msgstr "Akzeptieren"
#: packages/app-desktop/gui/MainScreen/MainScreen.js:481
msgid "Reject"
msgstr ""
msgstr "Ablehnen"
#: packages/app-desktop/gui/MainScreen/MainScreen.js:485
msgid "Some items cannot be synchronised."
@@ -861,9 +862,8 @@ msgid "Toggle editors"
msgstr "Editoren umschalten"
#: packages/app-desktop/gui/MainScreen/commands/showShareFolderDialog.js:16
#, fuzzy
msgid "Share notebook..."
msgstr "Notiz teilen ..."
msgstr "Notizbuch teilen ..."
#: packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js:16
msgid "Change application layout"
@@ -1122,7 +1122,6 @@ msgid "&Go"
msgstr "&Gehe zu"
#: packages/app-desktop/gui/MenuBar.js:631
#, fuzzy
msgid "Note&book"
msgstr "Notizbücher"
@@ -1531,13 +1530,12 @@ msgid "You do not have any installed plugin."
msgstr "Es sind keine Erweiterungen installiert."
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js:232
#, fuzzy
msgid "Could not connect to plugin repository"
msgstr "Erweiterung konnte nicht installiert werden: %s"
msgstr "Konnte keine Verbindung zum Plugin-Repository herstellen"
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js:234
msgid "Try again"
msgstr ""
msgstr "Versuche es erneut"
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js:242
msgid "Plugin tools"
@@ -1565,7 +1563,6 @@ msgid "Install"
msgstr "Installieren"
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js:132
#, fuzzy
msgid "Installing..."
msgstr "Wird installiert ..."
@@ -1574,12 +1571,10 @@ msgid "Installed"
msgstr "Installiert"
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js:140
#, fuzzy
msgid "Update"
msgstr "Aktualisieren"
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginBox.js:142
#, fuzzy
msgid "Updating..."
msgstr "Wird aktualisiert ..."
@@ -1732,9 +1727,8 @@ msgstr ""
"(Obergrenze: %s)."
#: packages/app-desktop/gui/ShareNoteDialog.js:141
#, fuzzy
msgid "Unshare note"
msgstr "Teilen"
msgstr "Notiz nicht mehr teilen"
#: packages/app-desktop/gui/ShareNoteDialog.js:168
msgid "Synchronising..."
@@ -1770,19 +1764,20 @@ msgstr[0] "Teilbaren Link kopieren"
msgstr[1] "Teilbare Links kopieren"
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:138
#, fuzzy
msgid "Unshare"
msgstr "Teilen"
msgstr "Nicht mehr teilen"
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:180
msgid ""
"Delete this invitation? The recipient will no longer have access to this "
"shared notebook."
msgstr ""
"Einladung löschen? Der Empfänger hat dann keinen Zugriff mehr auf dieses "
"freigegebene Notizbuch."
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:194
msgid "Add recipient:"
msgstr ""
msgstr "Füge Empfänger hinzu:"
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:197
#: packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js:28
@@ -1792,45 +1787,43 @@ msgstr "Teilen"
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:206
msgid "Recipient has not yet accepted the invitation"
msgstr ""
msgstr "Empfänger hat die Einladung noch nicht akzeptiert"
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:207
msgid "Recipient has rejected the invitation"
msgstr ""
msgstr "Empfänger hat die Einladung abgewiesen"
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:208
msgid "Recipient has accepted the invitation"
msgstr ""
msgstr "Empfänger hat die Einladung akzeptiert"
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:218
msgid "Recipients:"
msgstr ""
msgstr "Empfänger:"
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:230
#, fuzzy
msgid "Synchronizing..."
msgstr "Wird synchronisiert ..."
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:231
#, fuzzy
msgid "Sharing notebook..."
msgstr "Notiz teilen ..."
msgstr "Notizbuch wird geteilt ..."
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:241
msgid ""
"Unshare this notebook? The recipients will no longer have access to its "
"content."
msgstr ""
"Teilen des Notizbuch beenden? Der Empfänger wird keinen Zugriff mehr auf den "
"Inhalt haben."
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:251
#, fuzzy
msgid "Share Notebook"
msgstr "Notizen teilen"
msgstr "Notizbuch teilen"
#: packages/app-desktop/commands/toggleSafeMode.js:18
#, fuzzy
msgid "Toggle safe mode"
msgstr "Seitenleiste ein-/ausschalten"
msgstr "Sicheren Modus ein-/ausschalten"
#: packages/app-desktop/commands/toggleExternalEditing.js:18
msgid "Toggle external editing"
@@ -2055,7 +2048,7 @@ msgstr ""
#: packages/app-mobile/components/screens/ConfigScreen.js:406
msgid "Feature flags"
msgstr ""
msgstr "Feature Flags"
#: packages/app-mobile/components/screens/ConfigScreen.js:408
msgid "More information"
@@ -2089,7 +2082,7 @@ msgstr ""
#: packages/app-mobile/components/screens/ConfigScreen.js:428
msgid "Joplin website"
msgstr "Joplin-Webseite"
msgstr "Joplin Webseite"
#: packages/app-mobile/components/screens/ConfigScreen.js:433
msgid "Privacy Policy"
@@ -2288,15 +2281,15 @@ msgstr ""
"[Jetzt ändern](%s)"
#: packages/server/dist/models/UserModel.js:175
#, fuzzy
msgid "attachment"
msgstr "Anhänge"
msgstr "Anhang"
#: packages/server/dist/models/UserModel.js:175
#, javascript-format
msgid ""
"Cannot save %s \"%s\" because it is larger than than the allowed limit (%s)"
msgstr ""
"Kann %s \"%s\" nicht speichern, da es größer ist als das erlaubte Limit (%s)"
#: packages/lib/onedrive-api-node-utils.js:46
#, javascript-format
@@ -2339,7 +2332,7 @@ msgstr "Dropbox"
#: packages/lib/SyncTargetJoplinServer.js:57
msgid "Joplin Server"
msgstr "Joplin-Server"
msgstr "Joplin Server"
#: packages/lib/shim-init-node.js:212
#, javascript-format
@@ -2484,26 +2477,23 @@ msgstr "AWS-Geheimnis"
#: packages/lib/models/Setting.js:315
msgid "Joplin Server URL"
msgstr "Joplin-Server-URL"
msgstr "Joplin Server-URL"
#: packages/lib/models/Setting.js:333
#, fuzzy
msgid "Joplin Server email"
msgstr "Joplin-Server"
msgstr "Joplin Server E-Mail"
#: packages/lib/models/Setting.js:344
msgid "Joplin Server password"
msgstr "Joplin-Server-Passwort"
msgstr "Joplin Server-Passwort"
#: packages/lib/models/Setting.js:371
#, fuzzy
msgid "Joplin Cloud email"
msgstr "Joplin-Server"
msgstr "Joplin Cloud E-Mail"
#: packages/lib/models/Setting.js:382
#, fuzzy
msgid "Joplin Cloud password"
msgstr "Joplin-Server-Passwort"
msgstr "Joplin Server Passwort"
#: packages/lib/models/Setting.js:394
msgid "Attachment download behaviour"
@@ -2756,6 +2746,9 @@ msgid ""
"Used for most text in the markdown editor. If not found, a generic "
"proportional (variable width) font is used."
msgstr ""
"Hauptsächlich für Text im Markdown-Editor verwendet. Falls nicht vorhanden "
"wird eine generische Proportional-Schriftart (mit variabler Breite) "
"verwendet."
#: packages/lib/models/Setting.js:764
msgid "Editor monospace font family"
@@ -2767,6 +2760,9 @@ msgid ""
"tables, checkboxes, code). If not found, a generic monospace (fixed width) "
"font is used."
msgstr ""
"Verwendete Schriftart mit fester Breite, um Text lesbar zu machen (z.B. in "
"Tabellen, Kontrollkästchen, Code). Falls nicht vorhanden wird eine Monotype-"
"Scrhiftart (mit fester Breite) verwendet."
#: packages/lib/models/Setting.js:786
msgid "Custom stylesheet for rendered Markdown"
@@ -2778,11 +2774,11 @@ msgstr "Benutzerdefinierte Formatvorlagen für Joplin-weite Anwendungsstile"
#: packages/lib/models/Setting.js:812
msgid "Re-upload local data to sync target"
msgstr ""
msgstr "Lade lokale Daten erneut auf das Synchronisierungsziel hoch"
#: packages/lib/models/Setting.js:822
msgid "Delete local data and re-download from sync target"
msgstr ""
msgstr "Lösche lokale Daten und lade Daten erneut vom Synchronisierungsziel"
#: packages/lib/models/Setting.js:827
msgid "Automatically update the application"
@@ -3108,9 +3104,8 @@ msgid "Encrypted items cannot be modified"
msgstr "Verschlüsselte Elemente können nicht verändert werden"
#: packages/lib/SyncTargetJoplinCloud.js:28
#, fuzzy
msgid "Joplin Cloud"
msgstr "Joplin Forum"
msgstr "Joplin Cloud"
#: packages/lib/BaseApplication.js:152 packages/lib/BaseApplication.js:164
#: packages/lib/BaseApplication.js:196
@@ -3243,9 +3238,9 @@ msgid "Cancelling..."
msgstr "Wird abgebrochen ..."
#: packages/lib/Synchronizer.js:156
#, fuzzy, javascript-format
#, javascript-format
msgid "Completed: %s (%s)"
msgstr "Abgeschlossen: %s"
msgstr "Abgeschlossen: %s (%s)"
#: packages/lib/Synchronizer.js:158
#, javascript-format
@@ -3967,6 +3962,7 @@ msgid ""
"Runs the commands contained in the text file. There should be one command "
"per line."
msgstr ""
"Führe Befehle aus Textdatei aus. Jede Zeile darf nur einen Befehl enthalten."
#: packages/app-cli/app/command-version.js:11
msgid "Displays version information"

View File

@@ -20,9 +20,11 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 3.0\n"
"X-Generator: Poedit 2.4.3\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: UTF-8\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: \n"
#: packages/app-desktop/bridge.js:106 packages/app-desktop/bridge.js:110
#: packages/app-desktop/bridge.js:126 packages/app-desktop/bridge.js:134
@@ -337,7 +339,7 @@ msgstr "Casillas"
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js:17
msgid "Highlight"
msgstr "Destacar"
msgstr "Resaltado"
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/utils/setupToolbarButtons.js:22
msgid "Strikethrough"
@@ -377,7 +379,7 @@ msgstr "Código Integrado"
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js:654
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:83
msgid "Insert Date Time"
msgstr "Introducir fecha"
msgstr "Insertar Fecha y Hora"
#: packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js:1103
msgid "Drop notes or files here"
@@ -520,7 +522,7 @@ msgstr "Borrar línea"
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:92
msgid "Duplicate line"
msgstr "Duplicar linea"
msgstr "Duplicar línea"
#: packages/app-desktop/gui/NoteEditor/commands/editorCommandDeclarations.js:96
msgid "Undo"
@@ -713,8 +715,8 @@ msgid ""
"Safe mode is currently active. Note rendering and all plugins are "
"temporarily disabled."
msgstr ""
"El modo seguro está activo actualmente. La representación de notas y todos "
"los complementos están temporalmente deshabilitados."
"El modo seguro está actualmente activo. El renderizado de notas y todos los "
"plugins están temporalmente deshabilitados."
#: packages/app-desktop/gui/MainScreen/MainScreen.js:447
msgid "Disable safe mode and restart"
@@ -764,7 +766,7 @@ msgstr "Más información"
#: packages/app-desktop/gui/MainScreen/MainScreen.js:477
#, javascript-format
msgid "%s (%s) would like to share a notebook with you."
msgstr "%s (%s) le gustaría compartir una libreta contigo."
msgstr "A %s (%s) le gustaría compartir una libreta contigo."
#: packages/app-desktop/gui/MainScreen/MainScreen.js:479
msgid "Accept"
@@ -1516,11 +1518,11 @@ msgstr "No tiene ningún plugin instalado."
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js:232
msgid "Could not connect to plugin repository"
msgstr "No se pudo conectar con el repositorio del plugin: %s"
msgstr "No se pudo conectar con el repositorio de plugins"
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js:234
msgid "Try again"
msgstr "Intenta nuevamente"
msgstr "Vuelva a intentarlo"
#: packages/app-desktop/gui/ConfigScreen/controls/plugins/PluginsStates.js:242
msgid "Plugin tools"
@@ -1787,7 +1789,7 @@ msgstr "Sincronizando..."
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:231
msgid "Sharing notebook..."
msgstr "Compartir libreta..."
msgstr "Compartiendo libreta..."
#: packages/app-desktop/gui/ShareFolderDialog/ShareFolderDialog.js:241
msgid ""
@@ -1896,7 +1898,7 @@ msgstr "Configuración"
#: packages/app-mobile/components/side-menu-content.js:351
msgid "Mobile data - auto-sync disabled"
msgstr "Datos móviles: sincronización automática deshabilitada"
msgstr "Datos móviles - sincronización automática deshabilitada"
#: packages/app-mobile/components/note-list.js:97
msgid "You currently have no notebooks."
@@ -2026,7 +2028,7 @@ msgstr ""
#: packages/app-mobile/components/screens/ConfigScreen.js:406
msgid "Feature flags"
msgstr ""
msgstr "Feature flags"
#: packages/app-mobile/components/screens/ConfigScreen.js:408
msgid "More information"
@@ -2460,7 +2462,7 @@ msgstr "URL del Servidor de Joplin"
#: packages/lib/models/Setting.js:333
msgid "Joplin Server email"
msgstr "Email del servidor Joplin"
msgstr "Email del Servidor de Joplin"
#: packages/lib/models/Setting.js:344
msgid "Joplin Server password"
@@ -2468,11 +2470,11 @@ msgstr "Contraseña del Servidor de Joplin"
#: packages/lib/models/Setting.js:371
msgid "Joplin Cloud email"
msgstr "Email del servidor Joplin"
msgstr "Email de Joplin Cloud"
#: packages/lib/models/Setting.js:382
msgid "Joplin Cloud password"
msgstr "Contraseña del servidor Joplin"
msgstr "Contraseña de Joplin Cloud"
#: packages/lib/models/Setting.js:394
msgid "Attachment download behaviour"
@@ -2727,7 +2729,7 @@ msgid ""
"tables, checkboxes, code). If not found, a generic monospace (fixed width) "
"font is used."
msgstr ""
"Se utiliza cuando se necesita una fuente de ancho fijo para presentar el "
"Se utiliza donde se necesita una fuente de ancho fijo para presentar el "
"texto de manera legible (por ejemplo, tablas, casillas de verificación, "
"código). Si no se encuentra, se utiliza una fuente genérica monoespaciada "
"(ancho fijo)."
@@ -2742,12 +2744,12 @@ msgstr "Hoja de estilos para personalizar todo Joplin"
#: packages/lib/models/Setting.js:812
msgid "Re-upload local data to sync target"
msgstr "Vuelva a cargar datos locales para sincronizar el destino"
msgstr "Volver a cargar datos locales al objetivo de sincronización"
#: packages/lib/models/Setting.js:822
msgid "Delete local data and re-download from sync target"
msgstr ""
"Elimine los datos locales y vuelva a descargarlos desde el destino de "
"Eliminar datos locales y volver a descargarlos desde el objetivo de "
"sincronización"
#: packages/lib/models/Setting.js:827
@@ -3072,7 +3074,7 @@ msgstr "Los elementos cifrados no pueden ser modificados"
#: packages/lib/SyncTargetJoplinCloud.js:28
msgid "Joplin Cloud"
msgstr "Nube de Joplin"
msgstr "Joplin Cloud"
#: packages/lib/BaseApplication.js:152 packages/lib/BaseApplication.js:164
#: packages/lib/BaseApplication.js:196
@@ -3205,9 +3207,9 @@ msgid "Cancelling..."
msgstr "Cancelando..."
#: packages/lib/Synchronizer.js:156
#, fuzzy, javascript-format
#, javascript-format
msgid "Completed: %s (%s)"
msgstr "Completado: %s"
msgstr "Completado: %s (%s)"
#: packages/lib/Synchronizer.js:158
#, javascript-format

View File

@@ -1,5 +1,12 @@
# Joplin Android app changelog
## [android-v2.2.1](https://github.com/laurent22/joplin/releases/tag/android-v2.2.1) (Pre-release) - 2021-07-13T17:37:38Z
- New: Added improved editor (beta)
- Improved: Disable backup to Google Drive (#5114 by Roman Musin)
- Improved: Interpret only valid search filters (#5103) (#3871 by [@JackGruber](https://github.com/JackGruber))
- Improved: Removed old editor code (e01a175)
## [android-v2.1.4](https://github.com/laurent22/joplin/releases/tag/android-v2.1.4) - 2021-07-03T08:31:36Z
- Fixed: Fixes #5133: Items keep being uploaded to Joplin Server after a note has been shared.