You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-30 20:39:46 +02:00
Compare commits
4 Commits
android-v2
...
webpack_el
Author | SHA1 | Date | |
---|---|---|---|
|
4f5e52c363 | ||
|
4e7087b350 | ||
|
59e7c4933d | ||
|
621f83d3ce |
@@ -75,7 +75,6 @@ packages/pdf-viewer/dist
|
||||
plugin_types/
|
||||
readme/
|
||||
packages/react-native-vosk/lib/
|
||||
packages/lib/countable/Countable.js
|
||||
|
||||
# AUTO-GENERATED - EXCLUDED TYPESCRIPT BUILD
|
||||
packages/app-cli/app/LinkSelector.js
|
||||
@@ -260,6 +259,7 @@ packages/app-desktop/gui/NoteEditor/utils/useWindowCommandHandler.js
|
||||
packages/app-desktop/gui/NoteList/NoteList.js
|
||||
packages/app-desktop/gui/NoteList/commands/focusElementNoteList.js
|
||||
packages/app-desktop/gui/NoteList/commands/index.js
|
||||
packages/app-desktop/gui/NoteList/itemAnchorRef.js
|
||||
packages/app-desktop/gui/NoteList/types.js
|
||||
packages/app-desktop/gui/NoteListControls/NoteListControls.js
|
||||
packages/app-desktop/gui/NoteListControls/commands/focusSearch.js
|
||||
@@ -312,6 +312,7 @@ packages/app-desktop/gui/TagItem.js
|
||||
packages/app-desktop/gui/TagList.js
|
||||
packages/app-desktop/gui/ToggleEditorsButton/ToggleEditorsButton.js
|
||||
packages/app-desktop/gui/ToggleEditorsButton/styles/index.js
|
||||
packages/app-desktop/gui/ToggleEditorsButton/types.js
|
||||
packages/app-desktop/gui/ToolbarBase.js
|
||||
packages/app-desktop/gui/ToolbarButton/ToolbarButton.js
|
||||
packages/app-desktop/gui/ToolbarButton/styles/index.js
|
||||
@@ -364,7 +365,6 @@ packages/app-mobile/components/CameraView.js
|
||||
packages/app-mobile/components/CustomButton.js
|
||||
packages/app-mobile/components/Dropdown.js
|
||||
packages/app-mobile/components/ExtendedWebView.js
|
||||
packages/app-mobile/components/FolderPicker.js
|
||||
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useOnMessage.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
|
||||
@@ -427,8 +427,8 @@ packages/app-mobile/services/AlarmServiceDriver.android.js
|
||||
packages/app-mobile/services/AlarmServiceDriver.ios.js
|
||||
packages/app-mobile/services/e2ee/RSA.react-native.js
|
||||
packages/app-mobile/services/profiles/index.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.android.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.ios.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.dummy.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.js
|
||||
packages/app-mobile/setupQuickActions.js
|
||||
packages/app-mobile/tools/buildInjectedJs.js
|
||||
packages/app-mobile/utils/ShareExtension.js
|
||||
@@ -485,7 +485,6 @@ packages/lib/SyncTargetOneDrive.js
|
||||
packages/lib/SyncTargetRegistry.js
|
||||
packages/lib/Synchronizer.js
|
||||
packages/lib/TaskQueue.js
|
||||
packages/lib/WelcomeUtils.js
|
||||
packages/lib/array.js
|
||||
packages/lib/callbackUrlUtils.js
|
||||
packages/lib/callbackUrlUtils.test.js
|
||||
@@ -521,7 +520,6 @@ packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex-md-gen.test.js
|
||||
packages/lib/import-enex.js
|
||||
packages/lib/locale.js
|
||||
packages/lib/locale.test.js
|
||||
packages/lib/markdownUtils.js
|
||||
packages/lib/markdownUtils.test.js
|
||||
packages/lib/markdownUtils2.test.js
|
||||
@@ -553,6 +551,7 @@ packages/lib/models/SmartFilter.js
|
||||
packages/lib/models/Tag.js
|
||||
packages/lib/models/dateTimeFormats.test.js
|
||||
packages/lib/models/settings/FileHandler.js
|
||||
packages/lib/models/settings/types.js
|
||||
packages/lib/models/utils/itemCanBeEncrypted.js
|
||||
packages/lib/models/utils/paginatedFeed.js
|
||||
packages/lib/models/utils/paginationToSql.js
|
||||
@@ -687,8 +686,6 @@ packages/lib/services/plugins/utils/validatePluginVersion.test.js
|
||||
packages/lib/services/profileConfig/index.js
|
||||
packages/lib/services/profileConfig/index.test.js
|
||||
packages/lib/services/profileConfig/initProfile.js
|
||||
packages/lib/services/profileConfig/mergeGlobalAndLocalSettings.js
|
||||
packages/lib/services/profileConfig/splitGlobalAndLocalSettings.js
|
||||
packages/lib/services/profileConfig/types.js
|
||||
packages/lib/services/rest/Api.js
|
||||
packages/lib/services/rest/Api.test.js
|
||||
@@ -815,6 +812,7 @@ packages/plugins/ToggleSidebars/api/index.js
|
||||
packages/plugins/ToggleSidebars/api/types.js
|
||||
packages/plugins/ToggleSidebars/src/index.js
|
||||
packages/react-native-saf-x/src/index.js
|
||||
packages/react-native-vosk/src/index.js
|
||||
packages/renderer/HtmlToHtml.js
|
||||
packages/renderer/InMemoryCache.js
|
||||
packages/renderer/MarkupToHtml.js
|
||||
@@ -848,7 +846,6 @@ packages/renderer/noteStyle.js
|
||||
packages/renderer/pathUtils.js
|
||||
packages/renderer/utils.js
|
||||
packages/tools/build-release-stats.js
|
||||
packages/tools/build-welcome.js
|
||||
packages/tools/buildServerDocker.js
|
||||
packages/tools/buildServerDocker.test.js
|
||||
packages/tools/bundleDefaultPlugins.js
|
||||
|
@@ -141,7 +141,6 @@ module.exports = {
|
||||
'spaced-comment': ['error', 'always'],
|
||||
'keyword-spacing': ['error', { 'before': true, 'after': true }],
|
||||
'no-multi-spaces': ['error'],
|
||||
'prefer-object-spread': ['error'],
|
||||
|
||||
// Regarding the keyword blacklist:
|
||||
// - err: We generally avoid using too many abbreviations, so it should
|
||||
|
24
.github/scripts/run_ci.sh
vendored
24
.github/scripts/run_ci.sh
vendored
@@ -183,32 +183,12 @@ if [[ $GIT_TAG_NAME = v* ]]; then
|
||||
# cd "$ROOT_DIR/packages/tools"
|
||||
# node bundleDefaultPlugins.js
|
||||
cd "$ROOT_DIR/packages/app-desktop"
|
||||
|
||||
if [ "$IS_MACOS" == "1" ]; then
|
||||
# This is to fix this error:
|
||||
#
|
||||
# Exit code: ENOENT. spawn /usr/bin/python ENOENT
|
||||
#
|
||||
# Ref: https://github.com/electron-userland/electron-builder/issues/6767#issuecomment-1096589528
|
||||
#
|
||||
# It can be removed once we upgrade to electron-builder@23, however we
|
||||
# cannot currently do this due to this error:
|
||||
# https://github.com/laurent22/joplin/issues/8149
|
||||
PYTHON_PATH=$(which python) USE_HARD_LINKS=false yarn run dist
|
||||
else
|
||||
USE_HARD_LINKS=false yarn run dist
|
||||
fi
|
||||
USE_HARD_LINKS=false yarn run dist
|
||||
elif [[ $IS_LINUX = 1 ]] && [[ $GIT_TAG_NAME = $SERVER_TAG_PREFIX-* ]]; then
|
||||
echo "Step: Building Docker Image..."
|
||||
cd "$ROOT_DIR"
|
||||
yarn run buildServerDocker --tag-name $GIT_TAG_NAME --push-images --repository $SERVER_REPOSITORY
|
||||
else
|
||||
echo "Step: Building but *not* publishing desktop application..."
|
||||
|
||||
if [ "$IS_MACOS" == "1" ]; then
|
||||
# See above why we need to specify Python
|
||||
PYTHON_PATH=$(which python) USE_HARD_LINKS=false yarn run dist --publish=never
|
||||
else
|
||||
USE_HARD_LINKS=false yarn run dist --publish=never
|
||||
fi
|
||||
USE_HARD_LINKS=false yarn run dist --publish=never
|
||||
fi
|
||||
|
3
.github/workflows/build-android.yml
vendored
3
.github/workflows/build-android.yml
vendored
@@ -17,8 +17,9 @@ jobs:
|
||||
concurrent_skipping: 'same_content_newer'
|
||||
|
||||
BuildAndroidDebug:
|
||||
if: github.repository == 'laurent22/joplin'
|
||||
needs: pre_job
|
||||
if: github.repository == 'laurent22/joplin' && needs.pre_job.outputs.should_skip != 'true'
|
||||
if: needs.pre_job.outputs.should_skip != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Install Linux dependencies
|
||||
|
1
.github/workflows/github-actions-main.yml
vendored
1
.github/workflows/github-actions-main.yml
vendored
@@ -50,7 +50,6 @@ jobs:
|
||||
sudo apt-get install -y gettext
|
||||
sudo apt-get install -y libsecret-1-dev
|
||||
sudo apt-get install -y translate-toolkit
|
||||
sudo apt-get install -y rsync
|
||||
|
||||
- name: Install Docker Engine
|
||||
# if: runner.os == 'Linux' && startsWith(github.ref, 'refs/tags/server-v')
|
||||
|
14
.gitignore
vendored
14
.gitignore
vendored
@@ -245,6 +245,7 @@ packages/app-desktop/gui/NoteEditor/utils/useWindowCommandHandler.js
|
||||
packages/app-desktop/gui/NoteList/NoteList.js
|
||||
packages/app-desktop/gui/NoteList/commands/focusElementNoteList.js
|
||||
packages/app-desktop/gui/NoteList/commands/index.js
|
||||
packages/app-desktop/gui/NoteList/itemAnchorRef.js
|
||||
packages/app-desktop/gui/NoteList/types.js
|
||||
packages/app-desktop/gui/NoteListControls/NoteListControls.js
|
||||
packages/app-desktop/gui/NoteListControls/commands/focusSearch.js
|
||||
@@ -297,6 +298,7 @@ packages/app-desktop/gui/TagItem.js
|
||||
packages/app-desktop/gui/TagList.js
|
||||
packages/app-desktop/gui/ToggleEditorsButton/ToggleEditorsButton.js
|
||||
packages/app-desktop/gui/ToggleEditorsButton/styles/index.js
|
||||
packages/app-desktop/gui/ToggleEditorsButton/types.js
|
||||
packages/app-desktop/gui/ToolbarBase.js
|
||||
packages/app-desktop/gui/ToolbarButton/ToolbarButton.js
|
||||
packages/app-desktop/gui/ToolbarButton/styles/index.js
|
||||
@@ -349,7 +351,6 @@ packages/app-mobile/components/CameraView.js
|
||||
packages/app-mobile/components/CustomButton.js
|
||||
packages/app-mobile/components/Dropdown.js
|
||||
packages/app-mobile/components/ExtendedWebView.js
|
||||
packages/app-mobile/components/FolderPicker.js
|
||||
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useOnMessage.js
|
||||
packages/app-mobile/components/NoteBodyViewer/hooks/useOnResourceLongPress.js
|
||||
@@ -412,8 +413,8 @@ packages/app-mobile/services/AlarmServiceDriver.android.js
|
||||
packages/app-mobile/services/AlarmServiceDriver.ios.js
|
||||
packages/app-mobile/services/e2ee/RSA.react-native.js
|
||||
packages/app-mobile/services/profiles/index.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.android.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.ios.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.dummy.js
|
||||
packages/app-mobile/services/voiceTyping/vosk.js
|
||||
packages/app-mobile/setupQuickActions.js
|
||||
packages/app-mobile/tools/buildInjectedJs.js
|
||||
packages/app-mobile/utils/ShareExtension.js
|
||||
@@ -470,7 +471,6 @@ packages/lib/SyncTargetOneDrive.js
|
||||
packages/lib/SyncTargetRegistry.js
|
||||
packages/lib/Synchronizer.js
|
||||
packages/lib/TaskQueue.js
|
||||
packages/lib/WelcomeUtils.js
|
||||
packages/lib/array.js
|
||||
packages/lib/callbackUrlUtils.js
|
||||
packages/lib/callbackUrlUtils.test.js
|
||||
@@ -506,7 +506,6 @@ packages/lib/import-enex-md-gen.js
|
||||
packages/lib/import-enex-md-gen.test.js
|
||||
packages/lib/import-enex.js
|
||||
packages/lib/locale.js
|
||||
packages/lib/locale.test.js
|
||||
packages/lib/markdownUtils.js
|
||||
packages/lib/markdownUtils.test.js
|
||||
packages/lib/markdownUtils2.test.js
|
||||
@@ -538,6 +537,7 @@ packages/lib/models/SmartFilter.js
|
||||
packages/lib/models/Tag.js
|
||||
packages/lib/models/dateTimeFormats.test.js
|
||||
packages/lib/models/settings/FileHandler.js
|
||||
packages/lib/models/settings/types.js
|
||||
packages/lib/models/utils/itemCanBeEncrypted.js
|
||||
packages/lib/models/utils/paginatedFeed.js
|
||||
packages/lib/models/utils/paginationToSql.js
|
||||
@@ -672,8 +672,6 @@ packages/lib/services/plugins/utils/validatePluginVersion.test.js
|
||||
packages/lib/services/profileConfig/index.js
|
||||
packages/lib/services/profileConfig/index.test.js
|
||||
packages/lib/services/profileConfig/initProfile.js
|
||||
packages/lib/services/profileConfig/mergeGlobalAndLocalSettings.js
|
||||
packages/lib/services/profileConfig/splitGlobalAndLocalSettings.js
|
||||
packages/lib/services/profileConfig/types.js
|
||||
packages/lib/services/rest/Api.js
|
||||
packages/lib/services/rest/Api.test.js
|
||||
@@ -800,6 +798,7 @@ packages/plugins/ToggleSidebars/api/index.js
|
||||
packages/plugins/ToggleSidebars/api/types.js
|
||||
packages/plugins/ToggleSidebars/src/index.js
|
||||
packages/react-native-saf-x/src/index.js
|
||||
packages/react-native-vosk/src/index.js
|
||||
packages/renderer/HtmlToHtml.js
|
||||
packages/renderer/InMemoryCache.js
|
||||
packages/renderer/MarkupToHtml.js
|
||||
@@ -833,7 +832,6 @@ packages/renderer/noteStyle.js
|
||||
packages/renderer/pathUtils.js
|
||||
packages/renderer/utils.js
|
||||
packages/tools/build-release-stats.js
|
||||
packages/tools/build-welcome.js
|
||||
packages/tools/buildServerDocker.js
|
||||
packages/tools/buildServerDocker.test.js
|
||||
packages/tools/bundleDefaultPlugins.js
|
||||
|
@@ -15,6 +15,7 @@
|
||||
"@joplin/tools",
|
||||
"@joplin/react-native-saf-x",
|
||||
"@joplin/react-native-alarm-notification",
|
||||
"@joplin/react-native-vosk",
|
||||
"@joplin/utils"
|
||||
]
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ index 6afcbbf0cc8ca2d69dd78077d61e59a90b2136bb..9f8d72b4ec5b2b3d290975d6a255917c
|
||||
def kotlin_version = getExtOrDefault('kotlinVersion')
|
||||
|
||||
diff --git a/android/src/main/java/com/reactnativevosk/VoskModule.kt b/android/src/main/java/com/reactnativevosk/VoskModule.kt
|
||||
index 0e2b6595b1b2cf1ee01c6c64239c4b0ea37fce19..5a8539b9cce8951967640dba755e29a4e3ff404a 100644
|
||||
index 0e2b6595b1b2cf1ee01c6c64239c4b0ea37fce19..f3da440bc2863a59db6d2d1691c54d8d4870cb3f 100644
|
||||
--- a/android/src/main/java/com/reactnativevosk/VoskModule.kt
|
||||
+++ b/android/src/main/java/com/reactnativevosk/VoskModule.kt
|
||||
@@ -19,13 +19,25 @@ class VoskModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
||||
@@ -66,25 +66,7 @@ index 0e2b6595b1b2cf1ee01c6c64239c4b0ea37fce19..5a8539b9cce8951967640dba755e29a4
|
||||
sendEvent("onResult", text)
|
||||
}
|
||||
}
|
||||
@@ -93,12 +105,11 @@ class VoskModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
||||
@ReactMethod
|
||||
fun loadModel(path: String, promise: Promise) {
|
||||
cleanModel();
|
||||
- StorageService.unpack(context, path, "models",
|
||||
- { model: Model? ->
|
||||
- this.model = model
|
||||
- promise.resolve("Model successfully loaded")
|
||||
- }
|
||||
- ) { e: IOException ->
|
||||
+
|
||||
+ try {
|
||||
+ this.model = Model(path);
|
||||
+ promise.resolve("Model successfully loaded")
|
||||
+ } catch (e: IOException) {
|
||||
this.model = null
|
||||
promise.reject(e)
|
||||
}
|
||||
@@ -153,6 +164,25 @@ class VoskModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
||||
@@ -153,6 +165,25 @@ class VoskModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
||||
cleanRecognizer();
|
||||
}
|
||||
|
||||
@@ -123,70 +105,6 @@ index 441e41cc402cca3a60b34978ef4fea976076259c..a173acebb4b314402550442ad471e0f7
|
||||
unload: () => void;
|
||||
onResult: (onResult: (e: VoskEvent) => void) => EventSubscription;
|
||||
onFinalResult: (onFinalResult: (e: VoskEvent) => void) => EventSubscription;
|
||||
diff --git a/package.json b/package.json
|
||||
index 707eddb8d68007f93071ac659c5b087c935c5f01..90ebe20f224eeec472c377df1fef9b15f2ff8200 100644
|
||||
--- a/package.json
|
||||
+++ b/package.json
|
||||
@@ -11,12 +11,9 @@
|
||||
"src",
|
||||
"lib",
|
||||
"android",
|
||||
- "ios",
|
||||
"cpp",
|
||||
- "react-native-vosk.podspec",
|
||||
"!lib/typescript/example",
|
||||
"!android/build",
|
||||
- "!ios/build",
|
||||
"!**/__tests__",
|
||||
"!**/__fixtures__",
|
||||
"!**/__mocks__"
|
||||
diff --git a/react-native-vosk.podspec b/react-native-vosk.podspec
|
||||
deleted file mode 100644
|
||||
index e3d41b90c5eef890c7a5108aaf16ac07d34a698b..0000000000000000000000000000000000000000
|
||||
--- a/react-native-vosk.podspec
|
||||
+++ /dev/null
|
||||
@@ -1,41 +0,0 @@
|
||||
-require "json"
|
||||
-
|
||||
-package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
||||
-folly_version = '2021.06.28.00-v2'
|
||||
-folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
||||
-
|
||||
-Pod::Spec.new do |s|
|
||||
- s.name = "react-native-vosk"
|
||||
- s.version = package["version"]
|
||||
- s.summary = package["description"]
|
||||
- s.homepage = package["homepage"]
|
||||
- s.license = package["license"]
|
||||
- s.authors = package["author"]
|
||||
-
|
||||
- s.platforms = { :ios => "10.0" }
|
||||
- s.source = { :git => "https://github.com/riderodd/react-native-vosk.git", :tag => "#{s.version}" }
|
||||
-
|
||||
- s.source_files = "ios/**/*.{h,m,mm,swift}"
|
||||
- s.resource_bundles = { 'Vosk' => ['ios/Vosk/*'] }
|
||||
-
|
||||
- s.dependency "React-Core"
|
||||
- s.frameworks = "Accelerate"
|
||||
- s.library = "c++"
|
||||
- s.vendored_frameworks = "ios/libvosk.xcframework"
|
||||
- s.requires_arc = true
|
||||
-
|
||||
- # Don't install the dependencies when we run `pod install` in the old architecture.
|
||||
- if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
||||
- s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
||||
- s.pod_target_xcconfig = {
|
||||
- "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
||||
- "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
||||
- }
|
||||
-
|
||||
- s.dependency "React-Codegen"
|
||||
- s.dependency "RCT-Folly", folly_version
|
||||
- s.dependency "RCTRequired"
|
||||
- s.dependency "RCTTypeSafety"
|
||||
- s.dependency "ReactCommon/turbomodule/core"
|
||||
- end
|
||||
-end
|
||||
diff --git a/src/index.tsx b/src/index.tsx
|
||||
index d9f90c921d89b1b4d85e145443ed3376546a368a..29e4068dbd7500828a73145bd25497a52c9bf638 100644
|
||||
--- a/src/index.tsx
|
||||
|
30
.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch
Normal file
30
.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
|
||||
index a8abd71833879201e3438b2fa51d712a311c4551..ffe9c2c6dfa5c703ba76b65d94d5dd6784102c19 100644
|
||||
--- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
|
||||
+++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java
|
||||
@@ -591,7 +591,7 @@ public class RNFetchBlobReq extends BroadcastReceiver implements Runnable {
|
||||
// ignored.printStackTrace();
|
||||
}
|
||||
|
||||
- RNFetchBlobFileResp rnFetchBlobFileResp = (RNFetchBlobFileResp) responseBody;
|
||||
+ RNFetchBlobFileResp rnFetchBlobFileResp = new RNFetchBlobFileResp(responseBody);
|
||||
|
||||
if(rnFetchBlobFileResp != null && !rnFetchBlobFileResp.isDownloadComplete()){
|
||||
callback.invoke("Download interrupted.", null);
|
||||
diff --git a/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java b/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
|
||||
index 2470eef612308c15a89dfea5a1f16937469be29f..965f8becc195965907699182c764ec9e51811450 100644
|
||||
--- a/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
|
||||
+++ b/android/src/main/java/com/RNFetchBlob/Response/RNFetchBlobFileResp.java
|
||||
@@ -35,6 +35,12 @@ public class RNFetchBlobFileResp extends ResponseBody {
|
||||
FileOutputStream ofStream;
|
||||
boolean isEndMarkerReceived;
|
||||
|
||||
+ // ref: https://github.com/joltup/rn-fetch-blob/issues/490#issuecomment-990899440
|
||||
+ public RNFetchBlobFileResp(ResponseBody body) {
|
||||
+ super();
|
||||
+ this.originalBody = body;
|
||||
+ }
|
||||
+
|
||||
public RNFetchBlobFileResp(ReactApplicationContext ctx, String taskId, ResponseBody body, String path, boolean overwrite) throws IOException {
|
||||
super();
|
||||
this.rctContext = ctx;
|
@@ -42,7 +42,7 @@ export function addJoplinChecklistCommands(editor, ToggleList) {
|
||||
});
|
||||
|
||||
editor.addCommand('InsertJoplinChecklist', function (ui, detail) {
|
||||
detail = { ...detail, listType: 'joplinChecklist' };
|
||||
detail = Object.assign({}, detail, { listType: 'joplinChecklist' });
|
||||
ToggleList.toggleList(editor, 'UL', detail);
|
||||
});
|
||||
}
|
Binary file not shown.
Before Width: | Height: | Size: 6.1 KiB |
@@ -9,9 +9,7 @@ function getOs() {
|
||||
function getFilename(path) {
|
||||
if (!path) return '';
|
||||
const s = path.split('/');
|
||||
const urlWithParams = s.pop();
|
||||
const s2 = urlWithParams.split('?');
|
||||
return s2[0];
|
||||
return s.pop();
|
||||
}
|
||||
|
||||
function getMobileOs() {
|
||||
|
@@ -114,20 +114,6 @@ elif [[ $ARCHITECTURE =~ .*i386.*|.*i686.* ]] ; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#-----------------------------------------------------
|
||||
print "Checking dependencies..."
|
||||
## Check if libfuse2 is present.
|
||||
if [[ $(command -v ldconfig) ]]; then
|
||||
LIBFUSE=$(ldconfig -p | grep "libfuse.so.2" || echo '')
|
||||
else
|
||||
LIBFUSE=$(find /lib /usr/lib /lib64 /usr/lib64 /usr/local/lib -name "libfuse.so.2" 2>/dev/null | grep "libfuse.so.2" || echo '')
|
||||
fi
|
||||
if [[ $LIBFUSE == "" ]] ; then
|
||||
print "${COLOR_RED}Error: Can't get libfuse2 on system, please install libfuse2${COLOR_RESET}"
|
||||
print "See https://joplinapp.org/faq/#desktop-application-will-not-launch-on-linux and https://github.com/AppImage/AppImageKit/wiki/FUSE for more information"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#-----------------------------------------------------
|
||||
# Download Joplin
|
||||
#-----------------------------------------------------
|
||||
@@ -148,16 +134,10 @@ else
|
||||
print "The latest version is ${RELEASE_VERSION}, but you have ${CURRENT_VERSION:-no version} installed."
|
||||
fi
|
||||
|
||||
# Check if it's an update or a new install
|
||||
DOWNLOAD_TYPE="New"
|
||||
if [[ -f ~/.joplin/Joplin.AppImage ]]; then
|
||||
DOWNLOAD_TYPE="Update"
|
||||
fi
|
||||
|
||||
#-----------------------------------------------------
|
||||
print 'Downloading Joplin...'
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
wget -O "${TEMP_DIR}/Joplin.AppImage" "https://objects.joplinusercontent.com/v${RELEASE_VERSION}/Joplin-${RELEASE_VERSION}.AppImage?source=LinuxInstallScript&type=$DOWNLOAD_TYPE"
|
||||
wget -O "${TEMP_DIR}/Joplin.AppImage" "https://github.com/laurent22/joplin/releases/download/v${RELEASE_VERSION}/Joplin-${RELEASE_VERSION}.AppImage"
|
||||
wget -O "${TEMP_DIR}/joplin.png" https://joplinapp.org/images/Icon512.png
|
||||
|
||||
#-----------------------------------------------------
|
||||
|
44
README.md
44
README.md
@@ -22,23 +22,21 @@ Three types of applications are available: for **desktop** (Windows, macOS and L
|
||||
|
||||
Operating System | Download
|
||||
---|---
|
||||
Windows (32 and 64-bit) | <a href='https://objects.joplinusercontent.com/v2.10.19/Joplin-Setup-2.10.19.exe?source=JoplinWebsite&type=New'><img alt='Get it on Windows' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeWindows.png'/></a>
|
||||
macOS | <a href='https://objects.joplinusercontent.com/v2.10.19/Joplin-2.10.19.dmg?source=JoplinWebsite&type=New'><img alt='Get it on macOS' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeMacOS.png'/></a>
|
||||
Linux | <a href='https://objects.joplinusercontent.com/v2.10.19/Joplin-2.10.19.AppImage?source=JoplinWebsite&type=New'><img alt='Get it on Linux' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeLinux.png'/></a>
|
||||
Windows (32 and 64-bit) | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-Setup-2.9.17.exe'><img alt='Get it on Windows' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeWindows.png'/></a>
|
||||
macOS | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-2.9.17.dmg'><img alt='Get it on macOS' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeMacOS.png'/></a>
|
||||
Linux | <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/Joplin-2.9.17.AppImage'><img alt='Get it on Linux' width="134px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeLinux.png'/></a>
|
||||
|
||||
**On Windows**, you may also use the <a href='https://objects.joplinusercontent.com/v2.10.19/JoplinPortable.exe?source=JoplinWebsite&type=New'>Portable version</a>. The [portable application](https://en.wikipedia.org/wiki/Portable_application) allows installing the software on a portable device such as a USB key. Simply copy the file JoplinPortable.exe in any directory on that USB key ; the application will then create a directory called "JoplinProfile" next to the executable file.
|
||||
**On Windows**, you may also use the <a href='https://github.com/laurent22/joplin/releases/download/v2.9.17/JoplinPortable.exe'>Portable version</a>. The [portable application](https://en.wikipedia.org/wiki/Portable_application) allows installing the software on a portable device such as a USB key. Simply copy the file JoplinPortable.exe in any directory on that USB key ; the application will then create a directory called "JoplinProfile" next to the executable file.
|
||||
|
||||
**On Linux**, the recommended way is to use the following installation script as it will handle the desktop icon too:
|
||||
|
||||
<pre><code style="word-break: break-all">wget -O - https://raw.githubusercontent.com/laurent22/joplin/dev/Joplin_install_and_update.sh | bash</code></pre>
|
||||
|
||||
The install and update script supports the [following flags](https://github.com/laurent22/joplin/blob/dev/Joplin_install_and_update.sh#L50) (around line 50 at the time of this writing).
|
||||
|
||||
## Mobile applications
|
||||
|
||||
Operating System | Download | Alt. Download
|
||||
---|---|---
|
||||
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeAndroid.png'/></a> | or download the APK file: [64-bit](https://objects.joplinusercontent.com/android-v2.9.8/joplin-v2.9.8.apk?source=JoplinWebsite&type=New) [32-bit](https://objects.joplinusercontent.com/android-v2.9.8/joplin-v2.9.8-32bit.apk?source=JoplinWebsite&type=New)
|
||||
Android | <a href='https://play.google.com/store/apps/details?id=net.cozic.joplin&utm_source=GitHub&utm_campaign=README&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img alt='Get it on Google Play' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeAndroid.png'/></a> | or download the APK file: [64-bit](https://github.com/laurent22/joplin-android/releases/download/android-v2.9.8/joplin-v2.9.8.apk) [32-bit](https://github.com/laurent22/joplin-android/releases/download/android-v2.9.8/joplin-v2.9.8-32bit.apk)
|
||||
iOS | <a href='https://itunes.apple.com/us/app/joplin/id1315599797'><img alt='Get it on the App Store' height="40px" src='https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/BadgeIOS.png'/></a> | -
|
||||
|
||||
## Terminal application
|
||||
@@ -66,7 +64,7 @@ A community maintained list of these distributions can be found here: [Unofficia
|
||||
# Sponsors
|
||||
|
||||
<!-- SPONSORS-ORG -->
|
||||
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a> <a href="https://tranio.com/spain/"><img title="Property for sale in Spain" width="256" src="https://joplinapp.org/images/sponsors/TranioOverseasProperty.jpg"/></a>
|
||||
<a href="https://seirei.ne.jp"><img title="Serei Network" width="256" src="https://joplinapp.org/images/sponsors/SeireiNetwork.png"/></a> <a href="https://www.hosting.de/nextcloud/?mtm_campaign=managed-nextcloud&mtm_kwd=joplinapp&mtm_source=joplinapp-webseite&mtm_medium=banner"><img title="Hosting.de" width="256" src="https://joplinapp.org/images/sponsors/HostingDe.png"/></a> <a href="https://residence-greece.com/"><img title="Greece Golden Visa" width="256" src="https://joplinapp.org/images/sponsors/ResidenceGreece.jpg"/></a> <a href="https://grundstueckspreise.info/"><img title="SP Software GmbH" width="256" src="https://joplinapp.org/images/sponsors/Grundstueckspreise.png"/></a>
|
||||
<!-- SPONSORS-ORG -->
|
||||
|
||||
* * *
|
||||
@@ -536,24 +534,24 @@ Current translations:
|
||||
<img src="https://joplinapp.org/images/flags/es/basque_country.png" width="16px"/> | Basque | [eu](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/eu.po) | juan.abasolo@ehu.eus | 22%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ba.png" width="16px"/> | Bosnian (Bosna i Hercegovina) | [bs_BA](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/bs_BA.po) | [Derviš T.](mailto:dervis.t@pm.me) | 57%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/bg.png" width="16px"/> | Bulgarian (България) | [bg_BG](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/bg_BG.po) | | 45%
|
||||
<img src="https://joplinapp.org/images/flags/es/catalonia.png" width="16px"/> | Catalan | [ca](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ca.po) | [Xavi Ivars](mailto:xavi.ivars@gmail.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/hr.png" width="16px"/> | Croatian (Hrvatska) | [hr_HR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hr_HR.po) | [Milo Ivir](mailto:mail@milotype.de) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/cz.png" width="16px"/> | Czech (Česká republika) | [cs_CZ](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/cs_CZ.po) | Fejby | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/dk.png" width="16px"/> | Dansk (Danmark) | [da_DK](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/da_DK.po) | ERYpTION | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/de.png" width="16px"/> | Deutsch (Deutschland) | [de_DE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/de_DE.po) | [MrKanister](mailto:pueblos_spatulas@aleeas.com) | 98%
|
||||
<img src="https://joplinapp.org/images/flags/es/catalonia.png" width="16px"/> | Catalan | [ca](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ca.po) | [Xavi Ivars](mailto:xavi.ivars@gmail.com) | 89%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/hr.png" width="16px"/> | Croatian (Hrvatska) | [hr_HR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hr_HR.po) | [Milo Ivir](mailto:mail@milotype.de) | 89%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/cz.png" width="16px"/> | Czech (Česká republika) | [cs_CZ](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/cs_CZ.po) | Fejby | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/dk.png" width="16px"/> | Dansk (Danmark) | [da_DK](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/da_DK.po) | ERYpTION | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/de.png" width="16px"/> | Deutsch (Deutschland) | [de_DE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/de_DE.po) | [MrKanister](mailto:pueblos_spatulas@aleeas.com) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ee.png" width="16px"/> | Eesti Keel (Eesti) | [et_EE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/et_EE.po) | | 44%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/gb.png" width="16px"/> | English (United Kingdom) | [en_GB](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/en_GB.po) | | 100%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/us.png" width="16px"/> | English (United States of America) | [en_US](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/en_US.po) | | 100%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/es.png" width="16px"/> | Español (España) | [es_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/es_ES.po) | [Francisco Villaverde](mailto:teko.gr@gmail.com) | 97%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/es.png" width="16px"/> | Español (España) | [es_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/es_ES.po) | [Francisco Villaverde](mailto:teko.gr@gmail.com) | 98%
|
||||
<img src="https://joplinapp.org/images/flags/esperanto.png" width="16px"/> | Esperanto | [eo](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/eo.po) | Marton Paulo | 25%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/fi.png" width="16px"/> | Finnish (Suomi) | [fi_FI](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fi_FI.po) | mrkaato0 | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/fi.png" width="16px"/> | Finnish (Suomi) | [fi_FI](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fi_FI.po) | mrkaato0 | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/fr.png" width="16px"/> | Français (France) | [fr_FR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fr_FR.po) | Laurent Cozic | 100%
|
||||
<img src="https://joplinapp.org/images/flags/es/galicia.png" width="16px"/> | Galician (España) | [gl_ES](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/gl_ES.po) | [Marcos Lans](mailto:marcoslansgarza@gmail.com) | 29%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/id.png" width="16px"/> | Indonesian (Indonesia) | [id_ID](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/id_ID.po) | [Wisnu Adi Santoso](mailto:waditos@gmail.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/id.png" width="16px"/> | Indonesian (Indonesia) | [id_ID](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/id_ID.po) | [Wisnu Adi Santoso](mailto:waditos@gmail.com) | 89%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/it.png" width="16px"/> | Italiano (Italia) | [it_IT](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/it_IT.po) | [Manuel Tassi](mailto:mannivuwiki@gmail.com) | 80%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/hu.png" width="16px"/> | Magyar (Magyarország) | [hu_HU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/hu_HU.po) | [Magyari Balázs](mailto:balmag@gmail.com) | 77%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/be.png" width="16px"/> | Nederlands (België, Belgique, Belgien) | [nl_BE](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_BE.po) | | 78%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/nl.png" width="16px"/> | Nederlands (Nederland) | [nl_NL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_NL.po) | [MHolkamp](mailto:mholkamp@users.noreply.github.com) | 87%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/nl.png" width="16px"/> | Nederlands (Nederland) | [nl_NL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nl_NL.po) | [MHolkamp](mailto:mholkamp@users.noreply.github.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/no.png" width="16px"/> | Norwegian (Norge, Noreg) | [nb_NO](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/nb_NO.po) | [Mats Estensen](mailto:code@mxe.no) | 87%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ir.png" width="16px"/> | Persian | [fa](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/fa.po) | [Kourosh Firoozbakht](mailto:kourox@protonmail.com) | 55%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/pl.png" width="16px"/> | Polski (Polska) | [pl_PL](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/pl_PL.po) | [X3NO](mailto:X3NO@disroot.org) | 90%
|
||||
@@ -564,15 +562,15 @@ Current translations:
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/se.png" width="16px"/> | Svenska | [sv](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sv.po) | [Jonatan Nyberg](mailto:jonatan@autistici.org) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/th.png" width="16px"/> | Thai (ประเทศไทย) | [th_TH](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/th_TH.po) | | 36%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/vn.png" width="16px"/> | Tiếng Việt | [vi](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/vi.po) | | 77%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/tr.png" width="16px"/> | Türkçe (Türkiye) | [tr_TR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/tr_TR.po) | [Arda Kılıçdağı](mailto:arda@kilicdagi.com) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/tr.png" width="16px"/> | Türkçe (Türkiye) | [tr_TR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/tr_TR.po) | [Arda Kılıçdağı](mailto:arda@kilicdagi.com) | 89%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ua.png" width="16px"/> | Ukrainian (Україна) | [uk_UA](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/uk_UA.po) | [Vyacheslav Andreykiv](mailto:vandreykiv@gmail.com) | 72%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/gr.png" width="16px"/> | Ελληνικά (Ελλάδα) | [el_GR](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/el_GR.po) | [Harris Arvanitis](mailto:xaris@tuta.io) | 87%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ru.png" width="16px"/> | Русский (Россия) | [ru_RU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ru_RU.po) | [Dmitriy K](mailto:dmitry@atsip.ru) | 99%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/rs.png" width="16px"/> | српски језик (Србија) | [sr_RS](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sr_RS.po) | | 64%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/ru.png" width="16px"/> | Русский (Россия) | [ru_RU](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ru_RU.po) | [Dmitriy Q](mailto:krotesk@mail.ru) | 98%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/rs.png" width="16px"/> | српски језик (Србија) | [sr_RS](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/sr_RS.po) | | 65%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/cn.png" width="16px"/> | 中文 (简体) | [zh_CN](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_CN.po) | [wh201906](mailto:wh201906@yandex.com) | 96%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/tw.png" width="16px"/> | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_TW.po) | [Kevin Hsu](mailto:kevin.hsu.hws@gmail.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/jp.png" width="16px"/> | 日本語 (日本) | [ja_JP](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ja_JP.po) | [genneko](mailto:genneko217@gmail.com) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/kr.png" width="16px"/> | 한국어 | [ko](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ko.po) | [Ji-Hyeon Gim](mailto:potatogim@potatogim.net) | 88%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/tw.png" width="16px"/> | 中文 (繁體) | [zh_TW](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/zh_TW.po) | [Kevin Hsu](mailto:kevin.hsu.hws@gmail.com) | 89%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/jp.png" width="16px"/> | 日本語 (日本) | [ja_JP](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ja_JP.po) | [genneko](mailto:genneko217@gmail.com) | 89%
|
||||
<img src="https://joplinapp.org/images/flags/country-4x3/kr.png" width="16px"/> | 한국어 | [ko](https://github.com/laurent22/joplin/blob/dev/packages/tools/locales/ko.po) | [Ji-Hyeon Gim](mailto:potatogim@potatogim.net) | 89%
|
||||
<!-- LOCALE-TABLE-AUTO-GENERATED -->
|
||||
|
||||
# Contributors
|
||||
|
@@ -107,10 +107,7 @@
|
||||
".eslintignore": true,
|
||||
".gitignore": true,
|
||||
".vscode/*": true,
|
||||
".yarn/cache": true,
|
||||
".yarn/install-state.gz": true,
|
||||
".yarn/plugins": true,
|
||||
".yarn/releases": true,
|
||||
".yarn": true,
|
||||
"*.sublime-workspace": true,
|
||||
"**/_mydocs": true,
|
||||
"**/_mydocs/EnexSamples/*.enex": true,
|
||||
|
21
package.json
21
package.json
@@ -66,36 +66,37 @@
|
||||
"devDependencies": {
|
||||
"@joplin/utils": "~2.11",
|
||||
"@seiyab/eslint-plugin-react-hooks": "4.5.1-beta.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.59.0",
|
||||
"@typescript-eslint/parser": "5.59.0",
|
||||
"@typescript-eslint/eslint-plugin": "5.48.2",
|
||||
"@typescript-eslint/parser": "5.48.2",
|
||||
"cspell": "5.21.2",
|
||||
"eslint": "8.39.0",
|
||||
"eslint-interactive": "10.7.0",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"eslint": "8.31.0",
|
||||
"eslint-interactive": "10.3.0",
|
||||
"eslint-plugin-import": "2.27.4",
|
||||
"eslint-plugin-jest": "27.2.1",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-react": "7.32.2",
|
||||
"eslint-plugin-react": "7.32.0",
|
||||
"execa": "5.1.1",
|
||||
"fs-extra": "11.1.1",
|
||||
"glob": "8.1.0",
|
||||
"gulp": "4.0.2",
|
||||
"husky": "3.1.0",
|
||||
"lerna": "3.22.1",
|
||||
"lint-staged": "13.2.2",
|
||||
"lint-staged": "13.2.1",
|
||||
"madge": "6.0.0",
|
||||
"npm-package-json-lint": "6.4.0",
|
||||
"typedoc": "0.17.8",
|
||||
"typescript": "5.0.2"
|
||||
"typescript": "4.9.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/fs-extra": "11.0.1",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"http-server": "14.1.1",
|
||||
"node-gyp": "9.3.1",
|
||||
"nodemon": "2.0.22"
|
||||
},
|
||||
"packageManager": "yarn@3.5.0",
|
||||
"packageManager": "yarn@3.3.1",
|
||||
"resolutions": {
|
||||
"react-native-camera@4.2.1": "patch:react-native-camera@npm%3A4.2.1#./.yarn/patches/react-native-camera-npm-4.2.1-24b2600a7e.patch",
|
||||
"rn-fetch-blob@0.12.0": "patch:rn-fetch-blob@npm%3A0.12.0#./.yarn/patches/rn-fetch-blob-npm-0.12.0-cf02e3c544.patch",
|
||||
"react-native-vosk@0.1.12": "patch:react-native-vosk@npm%3A0.1.12#./.yarn/patches/react-native-vosk-npm-0.1.12-76b1caaae8.patch"
|
||||
}
|
||||
}
|
||||
|
@@ -302,7 +302,7 @@ class AppGui {
|
||||
const output = [];
|
||||
|
||||
for (let i = 0; i < keymap.length; i++) {
|
||||
const item = { ...keymap[i] };
|
||||
const item = Object.assign({}, keymap[i]);
|
||||
|
||||
if (!item.command) throw new Error(`Missing command for keymap item: ${JSON.stringify(item)}`);
|
||||
|
||||
@@ -427,7 +427,7 @@ class AppGui {
|
||||
async handleModelAction(action) {
|
||||
this.logger().info('Action:', action);
|
||||
|
||||
const state = { ...defaultState };
|
||||
const state = Object.assign({}, defaultState);
|
||||
state.notes = this.widget('noteList').items;
|
||||
|
||||
const newState = reducer(state, action);
|
||||
|
@@ -192,7 +192,7 @@ class Application extends BaseApplication {
|
||||
let output = await this.cache_.getItem('metadata');
|
||||
if (output) {
|
||||
this.commandMetadata_ = output;
|
||||
return { ...this.commandMetadata_ };
|
||||
return Object.assign({}, this.commandMetadata_);
|
||||
}
|
||||
|
||||
const commands = this.commands();
|
||||
@@ -207,7 +207,7 @@ class Application extends BaseApplication {
|
||||
await this.cache_.setItem('metadata', output, 1000 * 60 * 60 * 24);
|
||||
|
||||
this.commandMetadata_ = output;
|
||||
return { ...this.commandMetadata_ };
|
||||
return Object.assign({}, this.commandMetadata_);
|
||||
}
|
||||
|
||||
hasGui() {
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import Setting, { SettingStorage } from '@joplin/lib/models/Setting';
|
||||
import { schemaUrl } from '@joplin/lib/models/settings/types';
|
||||
import { SettingItemType } from '@joplin/lib/services/plugins/api/types';
|
||||
import shim from '@joplin/lib/shim';
|
||||
|
||||
@@ -38,7 +39,7 @@ class Command extends BaseCommand {
|
||||
public async action(args: any) {
|
||||
const schema: Record<string, any> = {
|
||||
title: 'JSON schema for Joplin setting files',
|
||||
'$id': Setting.schemaUrl,
|
||||
'$id': schemaUrl,
|
||||
'$schema': 'https://json-schema.org/draft-07/schema#',
|
||||
type: 'object',
|
||||
properties: {},
|
||||
|
@@ -57,7 +57,7 @@
|
||||
"proper-lockfile": "4.1.2",
|
||||
"read-chunk": "2.1.0",
|
||||
"server-destroy": "1.0.1",
|
||||
"sharp": "0.32.1",
|
||||
"sharp": "0.32.0",
|
||||
"sprintf-js": "1.1.2",
|
||||
"sqlite3": "5.1.6",
|
||||
"string-padding": "1.0.2",
|
||||
@@ -71,13 +71,13 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@joplin/tools": "~2.11",
|
||||
"@types/fs-extra": "11.0.1",
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/node": "18.15.13",
|
||||
"@types/fs-extra": "9.0.13",
|
||||
"@types/jest": "29.2.6",
|
||||
"@types/node": "18.11.18",
|
||||
"@types/proper-lockfile": "^4.1.2",
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.5.0",
|
||||
"jest": "29.4.3",
|
||||
"temp": "0.9.4",
|
||||
"typescript": "5.0.2"
|
||||
"typescript": "4.9.4"
|
||||
}
|
||||
}
|
||||
|
@@ -1,19 +0,0 @@
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align:left">Left</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left">Left</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left">Left</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
@@ -1,5 +0,0 @@
|
||||
| | | |
|
||||
| :--- | :---: | ---: |
|
||||
| Left | Centered | Right |
|
||||
| Left | Centered | Right |
|
||||
| Left | Centered | Right |
|
@@ -1,26 +0,0 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:left">Left-aligned Column</th>
|
||||
<th style="text-align:center">Center-aligned Column</th>
|
||||
<th style="text-align:right">Right-aligned Column</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align:left">Left</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left">Left</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:left">Left</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
@@ -1,5 +0,0 @@
|
||||
| Left-aligned Column | Center-aligned Column | Right-aligned Column |
|
||||
| :--- | :---: | ---: |
|
||||
| Left | Centered | Right |
|
||||
| Left | Centered | Right |
|
||||
| Left | Centered | Right |
|
@@ -1,14 +0,0 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="center">abc</th>
|
||||
<th align="right">defghi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td align="center">bar</td>
|
||||
<td align="right">baz</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
@@ -1,3 +0,0 @@
|
||||
| abc | defghi |
|
||||
| :---: | ---: |
|
||||
| bar | baz |
|
@@ -1,29 +0,0 @@
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align:left">Left-aligned Column</th>
|
||||
<th>This header cell's text is unaligned, but a majority of the text in this column is center-aligned so the
|
||||
column will be center-aligned</th>
|
||||
<th style="text-align:right">Right-aligned Column</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="text-align:left">Left</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:right">This is the only right-aligned cell in this column. This is possible if a user
|
||||
edits a cell's alignment using the cell properties dialog.</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="text-align:center">This is the only center-aligned cell in this column. This is possible if a
|
||||
user edits a cell's alignment using the cell properties dialog.</td>
|
||||
<td style="text-align:center">Centered</td>
|
||||
<td style="text-align:right">Right</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
@@ -1,5 +0,0 @@
|
||||
| Left-aligned Column | This header cell's text is unaligned, but a majority of the text in this column is center-aligned so the column will be center-aligned | Right-aligned Column |
|
||||
| :--- | :---: | ---: |
|
||||
| Left | Centered | Right |
|
||||
| This is the only right-aligned cell in this column. This is possible if a user edits a cell's alignment using the cell properties dialog. | Centered | Right |
|
||||
| This is the only center-aligned cell in this column. This is possible if a user edits a cell's alignment using the cell properties dialog. | Centered | Right |
|
@@ -1 +0,0 @@
|
||||
<div class="jop-noMdConv">
|
@@ -1 +0,0 @@
|
||||
<div><svg><style></svg><iframe srcdoc="<script>top.require('child_process').execSync('calc')</script>"></iframe></div>
|
@@ -1 +0,0 @@
|
||||
<a href="#" class="jop-noMdConv">XSS</a>
|
@@ -1 +0,0 @@
|
||||
<a data-from-md="" href="javascript:top.require('child_process').execSync('open -a Calculator')">XSS</a>
|
@@ -1 +0,0 @@
|
||||
<use href="#" class="jop-noMdConv">
|
@@ -1 +0,0 @@
|
||||
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg'><image href='asdf' onerror='top.require(`child_process`).execSync(`calc.exe`)' /></svg>#x" />
|
Before Width: | Height: | Size: 193 B |
@@ -1 +0,0 @@
|
||||
<map name="test" class="jop-noMdConv"><area coords="0,0,1000,1000" href="#" class="jop-noMdConv"/></map><img usemap="#test" src="https://github.com/Ry0taK.png" class="jop-noMdConv"/>
|
@@ -1 +0,0 @@
|
||||
<map name="test"><area coords="0,0,1000,1000" href="javascript:top.require(`child_process`).execSync(`calc.exe`)"></map><img usemap="#test" src="https://github.com/Ry0taK.png">
|
@@ -1 +0,0 @@
|
||||
<a href="#top" class="jop-noMdConv">⬆️</a>
|
@@ -1 +0,0 @@
|
||||
<a href="#top">⬆️</a>
|
@@ -94,12 +94,12 @@ browser_.runtime.onMessage.addListener(async (command) => {
|
||||
const imageSize = await getImageSize(imageDataUrl);
|
||||
const imagePixelRatio = imageSize.width / command.content.windowInnerWidth;
|
||||
|
||||
const content = { ...command.content };
|
||||
const content = Object.assign({}, command.content);
|
||||
content.image_data_url = imageDataUrl;
|
||||
if ('url' in content) content.source_url = content.url;
|
||||
|
||||
const ratio = browserZoom * imagePixelRatio;
|
||||
const newArea = { ...command.content.crop_rect };
|
||||
const newArea = Object.assign({}, command.content.crop_rect);
|
||||
newArea.x *= ratio;
|
||||
newArea.y *= ratio;
|
||||
newArea.width *= ratio;
|
||||
|
@@ -378,7 +378,7 @@
|
||||
tags: command.tags || '',
|
||||
image_sizes: imageSizes,
|
||||
anchor_names: anchorNames,
|
||||
source_command: { ...command },
|
||||
source_command: Object.assign({}, command),
|
||||
convert_to: convertToMarkup,
|
||||
stylesheets: stylesheets,
|
||||
};
|
||||
@@ -392,7 +392,7 @@
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
console.warn('Sending full page HTML instead');
|
||||
const newCommand = { ...command, name: 'completePageHtml' };
|
||||
const newCommand = Object.assign({}, command, { name: 'completePageHtml' });
|
||||
const response = await prepareCommandResponse(newCommand);
|
||||
response.warning = 'Could not retrieve simplified version of page - full page has been saved instead.';
|
||||
return response;
|
||||
|
@@ -67,7 +67,7 @@ class AppComponent extends Component {
|
||||
});
|
||||
|
||||
this.confirm_click = async () => {
|
||||
const content = { ...this.props.clippedContent };
|
||||
const content = Object.assign({}, this.props.clippedContent);
|
||||
content.tags = this.state.selectedTags.join(',');
|
||||
content.parent_id = this.props.selectedFolderId;
|
||||
const response = await bridge().sendContentToJoplin(content);
|
||||
|
@@ -410,7 +410,7 @@ class Bridge {
|
||||
|
||||
if (body) fetchOptions.body = typeof body === 'string' ? body : JSON.stringify(body);
|
||||
|
||||
query = { ...query, token: this.token_ };
|
||||
query = Object.assign(query || {}, { token: this.token_ });
|
||||
|
||||
let queryString = '';
|
||||
if (query) {
|
||||
|
@@ -40,34 +40,34 @@ function reducer(state = defaultState, action) {
|
||||
|
||||
if (action.type === 'WARNING_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.warning = action.text;
|
||||
|
||||
} else if (action.type === 'IS_PROBABLY_READERABLE') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.isProbablyReaderable = action.value;
|
||||
|
||||
} else if (action.type === 'CLIPPED_CONTENT_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.clippedContent = action.content;
|
||||
|
||||
} else if (action.type === 'CLIPPED_CONTENT_TITLE_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
const newContent = newState.clippedContent ? { ...newState.clippedContent } : {};
|
||||
newState = Object.assign({}, state);
|
||||
const newContent = newState.clippedContent ? Object.assign({}, newState.clippedContent) : {};
|
||||
newContent.title = action.text;
|
||||
newState.clippedContent = newContent;
|
||||
|
||||
} else if (action.type === 'CONTENT_UPLOAD') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.contentUploadOperation = action.operation;
|
||||
|
||||
} else if (action.type === 'FOLDERS_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.folders = action.folders;
|
||||
|
||||
if (!newState.selectedFolderId && action.folders.length) {
|
||||
@@ -76,30 +76,30 @@ function reducer(state = defaultState, action) {
|
||||
|
||||
} else if (action.type === 'TAGS_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.tags = action.tags;
|
||||
|
||||
} else if (action.type === 'SELECTED_FOLDER_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.selectedFolderId = action.id;
|
||||
|
||||
} else if (action.type === 'CLIPPER_SERVER_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
const clipperServer = { ...newState.clipperServer };
|
||||
newState = Object.assign({}, state);
|
||||
const clipperServer = Object.assign({}, newState.clipperServer);
|
||||
if ('foundState' in action) clipperServer.foundState = action.foundState;
|
||||
if ('port' in action) clipperServer.port = action.port;
|
||||
newState.clipperServer = clipperServer;
|
||||
|
||||
} else if (action.type === 'ENV_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.env = action.env;
|
||||
|
||||
} else if (action.type === 'AUTH_STATE_SET') {
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.authStatus = action.value;
|
||||
|
||||
}
|
||||
|
2
packages/app-desktop/.gitignore
vendored
2
packages/app-desktop/.gitignore
vendored
@@ -14,3 +14,5 @@ style.min.css
|
||||
build/lib/
|
||||
vendor/*
|
||||
!vendor/loadEmojiLib.js
|
||||
main-html.bundle.js
|
||||
main.js
|
@@ -29,11 +29,13 @@ export default class InteropServiceHelper {
|
||||
private static async exportNoteToHtmlFile(noteId: string, exportOptions: ExportNoteOptions) {
|
||||
const tempFile = `${Setting.value('tempDir')}/${md5(Date.now() + Math.random())}.html`;
|
||||
|
||||
const fullExportOptions: ExportOptions = { path: tempFile,
|
||||
const fullExportOptions: ExportOptions = Object.assign({}, {
|
||||
path: tempFile,
|
||||
format: 'html',
|
||||
target: FileSystemItem.File,
|
||||
sourceNoteIds: [noteId],
|
||||
customCss: '', ...exportOptions };
|
||||
customCss: '',
|
||||
}, exportOptions);
|
||||
|
||||
const service = InteropService.instance();
|
||||
|
||||
|
@@ -4,9 +4,6 @@ import { defaultState, State } from '@joplin/lib/reducer';
|
||||
import iterateItems from './gui/ResizableLayout/utils/iterateItems';
|
||||
import { LayoutItem } from './gui/ResizableLayout/utils/types';
|
||||
import validateLayout from './gui/ResizableLayout/utils/validateLayout';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
|
||||
const logger = Logger.create('app.reducer');
|
||||
|
||||
export interface AppStateRoute {
|
||||
type: string;
|
||||
@@ -85,7 +82,7 @@ export default function(state: AppState, action: any) {
|
||||
|
||||
const currentRoute = state.route;
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
const newNavHistory = state.navHistory.slice();
|
||||
|
||||
if (goingBack) {
|
||||
@@ -122,7 +119,7 @@ export default function(state: AppState, action: any) {
|
||||
|
||||
case 'WINDOW_CONTENT_SIZE_SET':
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.windowContentSize = action.size;
|
||||
break;
|
||||
|
||||
@@ -150,7 +147,7 @@ export default function(state: AppState, action: any) {
|
||||
return nextLayout === 'both' ? ['editor', 'viewer'] : [nextLayout];
|
||||
};
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
|
||||
const panes = state.noteVisiblePanes.slice();
|
||||
newState.noteVisiblePanes = getNextLayout(panes);
|
||||
@@ -159,7 +156,7 @@ export default function(state: AppState, action: any) {
|
||||
|
||||
case 'NOTE_VISIBLE_PANES_SET':
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.noteVisiblePanes = action.panes;
|
||||
break;
|
||||
|
||||
@@ -174,31 +171,22 @@ export default function(state: AppState, action: any) {
|
||||
case 'MAIN_LAYOUT_SET_ITEM_PROP':
|
||||
|
||||
{
|
||||
if (!state.mainLayout) {
|
||||
logger.warn('MAIN_LAYOUT_SET_ITEM_PROP: Trying to set an item prop on the layout, but layout is empty: ', JSON.stringify(action));
|
||||
} else {
|
||||
let newLayout = produce(state.mainLayout, (draftLayout: LayoutItem) => {
|
||||
iterateItems(draftLayout, (_itemIndex: number, item: LayoutItem, _parent: LayoutItem) => {
|
||||
if (!item) {
|
||||
logger.warn('MAIN_LAYOUT_SET_ITEM_PROP: Found an empty item in layout: ', JSON.stringify(state.mainLayout));
|
||||
} else {
|
||||
if (item.key === action.itemKey) {
|
||||
(item as any)[action.propName] = action.propValue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
let newLayout = produce(state.mainLayout, (draftLayout: LayoutItem) => {
|
||||
iterateItems(draftLayout, (_itemIndex: number, item: LayoutItem, _parent: LayoutItem) => {
|
||||
if (item.key === action.itemKey) {
|
||||
(item as any)[action.propName] = action.propValue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
});
|
||||
|
||||
if (newLayout !== state.mainLayout) newLayout = validateLayout(newLayout);
|
||||
if (newLayout !== state.mainLayout) newLayout = validateLayout(newLayout);
|
||||
|
||||
newState = {
|
||||
...state,
|
||||
mainLayout: newLayout,
|
||||
};
|
||||
}
|
||||
newState = {
|
||||
...state,
|
||||
mainLayout: newLayout,
|
||||
};
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -206,7 +194,7 @@ export default function(state: AppState, action: any) {
|
||||
case 'NOTE_FILE_WATCHER_ADD':
|
||||
|
||||
if (newState.watchedNoteFiles.indexOf(action.id) < 0) {
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
const watchedNoteFiles = newState.watchedNoteFiles.slice();
|
||||
watchedNoteFiles.push(action.id);
|
||||
newState.watchedNoteFiles = watchedNoteFiles;
|
||||
@@ -216,7 +204,7 @@ export default function(state: AppState, action: any) {
|
||||
case 'NOTE_FILE_WATCHER_REMOVE':
|
||||
|
||||
{
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
const idx = newState.watchedNoteFiles.indexOf(action.id);
|
||||
if (idx >= 0) {
|
||||
const watchedNoteFiles = newState.watchedNoteFiles.slice();
|
||||
@@ -229,7 +217,7 @@ export default function(state: AppState, action: any) {
|
||||
case 'NOTE_FILE_WATCHER_CLEAR':
|
||||
|
||||
if (state.watchedNoteFiles.length) {
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.watchedNoteFiles = [];
|
||||
}
|
||||
break;
|
||||
@@ -237,38 +225,38 @@ export default function(state: AppState, action: any) {
|
||||
case 'EDITOR_SCROLL_PERCENT_SET':
|
||||
|
||||
{
|
||||
newState = { ...state };
|
||||
const newPercents = { ...newState.lastEditorScrollPercents };
|
||||
newState = Object.assign({}, state);
|
||||
const newPercents = Object.assign({}, newState.lastEditorScrollPercents);
|
||||
newPercents[action.noteId] = action.percent;
|
||||
newState.lastEditorScrollPercents = newPercents;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'NOTE_DEVTOOLS_TOGGLE':
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.devToolsVisible = !newState.devToolsVisible;
|
||||
break;
|
||||
|
||||
case 'NOTE_DEVTOOLS_SET':
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.devToolsVisible = action.value;
|
||||
break;
|
||||
|
||||
case 'VISIBLE_DIALOGS_ADD':
|
||||
newState = { ...state };
|
||||
newState.visibleDialogs = { ...newState.visibleDialogs };
|
||||
newState = Object.assign({}, state);
|
||||
newState.visibleDialogs = Object.assign({}, newState.visibleDialogs);
|
||||
newState.visibleDialogs[action.name] = true;
|
||||
break;
|
||||
|
||||
case 'VISIBLE_DIALOGS_REMOVE':
|
||||
newState = { ...state };
|
||||
newState.visibleDialogs = { ...newState.visibleDialogs };
|
||||
newState = Object.assign({}, state);
|
||||
newState.visibleDialogs = Object.assign({}, newState.visibleDialogs);
|
||||
delete newState.visibleDialogs[action.name];
|
||||
break;
|
||||
|
||||
case 'FOCUS_SET':
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.focusedField = action.field;
|
||||
break;
|
||||
|
||||
@@ -276,7 +264,7 @@ export default function(state: AppState, action: any) {
|
||||
|
||||
// A field can only clear its own state
|
||||
if (action.field === state.focusedField) {
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
newState.focusedField = null;
|
||||
}
|
||||
break;
|
||||
@@ -293,7 +281,7 @@ export default function(state: AppState, action: any) {
|
||||
isOpen = action.isOpen !== false;
|
||||
}
|
||||
|
||||
newState = { ...state };
|
||||
newState = Object.assign({}, state);
|
||||
|
||||
if (isOpen) {
|
||||
const newDialogs = newState.dialogs.slice();
|
||||
|
@@ -80,7 +80,6 @@ const appDefaultState = createAppDefaultState(
|
||||
class Application extends BaseApplication {
|
||||
|
||||
private checkAllPluginStartedIID_: any = null;
|
||||
private initPluginServiceDone_: boolean = false;
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
@@ -259,9 +258,6 @@ class Application extends BaseApplication {
|
||||
}
|
||||
|
||||
private async initPluginService() {
|
||||
if (this.initPluginServiceDone_) return;
|
||||
this.initPluginServiceDone_ = true;
|
||||
|
||||
const service = PluginService.instance();
|
||||
|
||||
const pluginRunner = new PluginRunner();
|
||||
|
@@ -68,10 +68,6 @@ export class Bridge {
|
||||
return process.argv;
|
||||
}
|
||||
|
||||
public getLocale = () => {
|
||||
return this.electronApp().electronApp().getLocale();
|
||||
};
|
||||
|
||||
// Applies to electron-context-menu@3:
|
||||
//
|
||||
// For now we have to disable spell checking in non-editor text
|
||||
@@ -88,35 +84,35 @@ export class Bridge {
|
||||
// Perhaps the easiest would be to patch electron-context-menu to
|
||||
// support the renderer process again. Or possibly revert to an old
|
||||
// version of electron-context-menu.
|
||||
public setupContextMenu(_spellCheckerMenuItemsHandler: Function) {
|
||||
require('electron-context-menu')({
|
||||
allWindows: [this.window()],
|
||||
// public setupContextMenu(_spellCheckerMenuItemsHandler: Function) {
|
||||
// require('electron-context-menu')({
|
||||
// allWindows: [this.window()],
|
||||
|
||||
electronApp: this.electronApp(),
|
||||
// electronApp: this.electronApp(),
|
||||
|
||||
shouldShowMenu: (_event: any, params: any) => {
|
||||
// params.inputFieldType === 'none' when right-clicking the text
|
||||
// editor. This is a bit of a hack to detect it because in this
|
||||
// case we don't want to use the built-in context menu but a
|
||||
// custom one.
|
||||
return params.isEditable && params.inputFieldType !== 'none';
|
||||
},
|
||||
// shouldShowMenu: (_event: any, params: any) => {
|
||||
// // params.inputFieldType === 'none' when right-clicking the text
|
||||
// // editor. This is a bit of a hack to detect it because in this
|
||||
// // case we don't want to use the built-in context menu but a
|
||||
// // custom one.
|
||||
// return params.isEditable && params.inputFieldType !== 'none';
|
||||
// },
|
||||
|
||||
// menu: (actions: any, props: any) => {
|
||||
// const items = spellCheckerMenuItemsHandler(props.misspelledWord, props.dictionarySuggestions);
|
||||
// const spellCheckerMenuItems = items.map((item: any) => new MenuItem(item)); //SpellCheckerService.instance().contextMenuItems(props.misspelledWord, props.dictionarySuggestions).map((item: any) => new MenuItem(item));
|
||||
// // menu: (actions: any, props: any) => {
|
||||
// // const items = spellCheckerMenuItemsHandler(props.misspelledWord, props.dictionarySuggestions);
|
||||
// // const spellCheckerMenuItems = items.map((item: any) => new MenuItem(item)); //SpellCheckerService.instance().contextMenuItems(props.misspelledWord, props.dictionarySuggestions).map((item: any) => new MenuItem(item));
|
||||
|
||||
// const output = [
|
||||
// actions.cut(),
|
||||
// actions.copy(),
|
||||
// actions.paste(),
|
||||
// ...spellCheckerMenuItems,
|
||||
// ];
|
||||
// // const output = [
|
||||
// // actions.cut(),
|
||||
// // actions.copy(),
|
||||
// // actions.paste(),
|
||||
// // ...spellCheckerMenuItems,
|
||||
// // ];
|
||||
|
||||
// return output;
|
||||
// },
|
||||
});
|
||||
}
|
||||
// // return output;
|
||||
// // },
|
||||
// });
|
||||
// }
|
||||
|
||||
public window() {
|
||||
return this.electronWrapper_.window();
|
||||
@@ -201,10 +197,12 @@ export class Bridge {
|
||||
...options,
|
||||
};
|
||||
|
||||
const result = this.showMessageBox_(this.window(), { type: 'question',
|
||||
const result = this.showMessageBox_(this.window(), Object.assign({}, {
|
||||
type: 'question',
|
||||
message: message,
|
||||
cancelId: 1,
|
||||
buttons: options.buttons, ...options });
|
||||
buttons: options.buttons,
|
||||
}, options));
|
||||
|
||||
return result === 0;
|
||||
}
|
||||
@@ -213,17 +211,21 @@ export class Bridge {
|
||||
public showMessageBox(message: string, options: any = null) {
|
||||
if (options === null) options = {};
|
||||
|
||||
const result = this.showMessageBox_(this.window(), { type: 'question',
|
||||
const result = this.showMessageBox_(this.window(), Object.assign({}, {
|
||||
type: 'question',
|
||||
message: message,
|
||||
buttons: [_('OK'), _('Cancel')], ...options });
|
||||
buttons: [_('OK'), _('Cancel')],
|
||||
}, options));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public showInfoMessageBox(message: string, options: any = {}) {
|
||||
const result = this.showMessageBox_(this.window(), { type: 'info',
|
||||
const result = this.showMessageBox_(this.window(), Object.assign({}, {
|
||||
type: 'info',
|
||||
message: message,
|
||||
buttons: [_('OK')], ...options });
|
||||
buttons: [_('OK')],
|
||||
}, options));
|
||||
return result === 0;
|
||||
}
|
||||
|
||||
|
@@ -34,7 +34,7 @@ function getMajorMinorTagName(tagName: string) {
|
||||
}
|
||||
|
||||
async function fetchLatestRelease(options: CheckForUpdateOptions) {
|
||||
options = { includePreReleases: false, ...options };
|
||||
options = Object.assign({}, { includePreReleases: false }, options);
|
||||
|
||||
const response = await shim.fetch('https://api.github.com/repos/laurent22/joplin/releases');
|
||||
|
||||
@@ -97,8 +97,7 @@ async function fetchLatestRelease(options: CheckForUpdateOptions) {
|
||||
}
|
||||
|
||||
if (found) {
|
||||
downloadUrl = asset.browser_download_url.replace('github.com/laurent22/joplin/releases/download', 'objects.joplinusercontent.com');
|
||||
downloadUrl.concat('?source=DesktopApp&type=Update');
|
||||
downloadUrl = asset.browser_download_url;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@ export const runtime = (): CommandRuntime => {
|
||||
};
|
||||
|
||||
await saveProfileConfig(`${Setting.value('rootProfileDir')}/profiles.json`, newConfig);
|
||||
await restart();
|
||||
await restart(false);
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@@ -46,11 +46,13 @@ class ClipperConfigScreenComponent extends React.Component {
|
||||
public render() {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const containerStyle = { ...theme.containerStyle, overflowY: 'scroll',
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, {
|
||||
overflowY: 'scroll',
|
||||
// padding: theme.configScreenPadding,
|
||||
backgroundColor: theme.backgroundColor3 };
|
||||
backgroundColor: theme.backgroundColor3,
|
||||
});
|
||||
|
||||
const buttonStyle = { ...theme.buttonStyle, marginRight: 10 };
|
||||
const buttonStyle = Object.assign({}, theme.buttonStyle, { marginRight: 10 });
|
||||
|
||||
const stepBoxStyle = {
|
||||
border: '1px solid',
|
||||
@@ -104,16 +106,18 @@ class ClipperConfigScreenComponent extends React.Component {
|
||||
);
|
||||
}
|
||||
|
||||
const apiTokenStyle = { ...theme.textStyle, color: theme.colorFaded,
|
||||
const apiTokenStyle = Object.assign({}, theme.textStyle, {
|
||||
color: theme.colorFaded,
|
||||
wordBreak: 'break-all',
|
||||
paddingTop: 10,
|
||||
paddingBottom: 10 };
|
||||
paddingBottom: 10,
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div style={containerStyle}>
|
||||
<div>
|
||||
<p style={{ ...theme.textStyle, marginTop: 0 }}>{_('Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.')}</p>
|
||||
<p style={Object.assign({}, theme.textStyle, { marginTop: 0 })}>{_('Joplin Web Clipper allows saving web pages and screenshots from your browser to Joplin.')}</p>
|
||||
<p style={theme.textStyle}>{_('In order to use the web clipper, you need to do the following:')}</p>
|
||||
|
||||
<div style={stepBoxStyle}>
|
||||
|
@@ -135,7 +135,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
return (
|
||||
<div style={{ ...theme.textStyle, marginBottom: 15 }}>
|
||||
<div style={Object.assign({}, theme.textStyle, { marginBottom: 15 })}>
|
||||
{description}
|
||||
</div>
|
||||
);
|
||||
@@ -177,7 +177,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
|
||||
if (section.name === 'sync') {
|
||||
const syncTargetMd = SyncTargetRegistry.idToMetadata(settings['sync.target']);
|
||||
const statusStyle = { ...theme.textStyle, marginTop: 10 };
|
||||
const statusStyle = Object.assign({}, theme.textStyle, { marginTop: 10 });
|
||||
|
||||
if (syncTargetMd.supportsConfigCheck) {
|
||||
const messages = shared.checkSyncConfigMessages(this);
|
||||
@@ -207,7 +207,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
|
||||
if (advancedSettingComps.length) {
|
||||
const iconName = this.state.showAdvancedSettings ? 'fa fa-angle-down' : 'fa fa-angle-right';
|
||||
// const advancedSettingsButtonStyle = { ...theme.buttonStyle, marginBottom: 10 };
|
||||
// const advancedSettingsButtonStyle = Object.assign({}, theme.buttonStyle, { marginBottom: 10 });
|
||||
advancedSettingsButton = (
|
||||
<div style={{ marginBottom: 10 }}>
|
||||
<Button
|
||||
@@ -233,19 +233,23 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
|
||||
private labelStyle(themeId: number) {
|
||||
const theme = themeStyle(themeId);
|
||||
return { ...theme.textStyle, display: 'block',
|
||||
return Object.assign({}, theme.textStyle, {
|
||||
display: 'block',
|
||||
color: theme.color,
|
||||
fontSize: theme.fontSize * 1.083333,
|
||||
fontWeight: 500,
|
||||
marginBottom: theme.mainPadding / 2 };
|
||||
marginBottom: theme.mainPadding / 2,
|
||||
});
|
||||
}
|
||||
|
||||
private descriptionStyle(themeId: number) {
|
||||
const theme = themeStyle(themeId);
|
||||
return { ...theme.textStyle, color: theme.colorFaded,
|
||||
return Object.assign({}, theme.textStyle, {
|
||||
color: theme.colorFaded,
|
||||
fontStyle: 'italic',
|
||||
maxWidth: '70em',
|
||||
marginTop: 5 };
|
||||
marginTop: 5,
|
||||
});
|
||||
}
|
||||
|
||||
private renderLabel(themeId: number, label: string) {
|
||||
@@ -260,12 +264,14 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
private renderHeader(themeId: number, label: string, style: any = null) {
|
||||
const theme = themeStyle(themeId);
|
||||
|
||||
const labelStyle = { ...theme.textStyle, display: 'block',
|
||||
const labelStyle = Object.assign({}, theme.textStyle, {
|
||||
display: 'block',
|
||||
color: theme.color,
|
||||
fontSize: theme.fontSize * 1.25,
|
||||
fontWeight: 500,
|
||||
marginBottom: theme.mainPadding,
|
||||
...style };
|
||||
...style,
|
||||
});
|
||||
|
||||
return (
|
||||
<div style={labelStyle}>
|
||||
@@ -289,13 +295,17 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
|
||||
const labelStyle = this.labelStyle(this.props.themeId);
|
||||
|
||||
const subLabel = { ...labelStyle, display: 'block',
|
||||
const subLabel = Object.assign({}, labelStyle, {
|
||||
display: 'block',
|
||||
opacity: 0.7,
|
||||
marginBottom: labelStyle.marginBottom };
|
||||
marginBottom: labelStyle.marginBottom,
|
||||
});
|
||||
|
||||
const checkboxLabelStyle = { ...labelStyle, marginLeft: 8,
|
||||
const checkboxLabelStyle = Object.assign({}, labelStyle, {
|
||||
marginLeft: 8,
|
||||
display: 'inline',
|
||||
backgroundColor: 'transparent' };
|
||||
backgroundColor: 'transparent',
|
||||
});
|
||||
|
||||
const controlStyle = {
|
||||
display: 'inline-block',
|
||||
@@ -304,7 +314,8 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
backgroundColor: theme.backgroundColor,
|
||||
};
|
||||
|
||||
const textInputBaseStyle = { ...controlStyle, fontFamily: theme.fontFamily,
|
||||
const textInputBaseStyle = Object.assign({}, controlStyle, {
|
||||
fontFamily: theme.fontFamily,
|
||||
border: '1px solid',
|
||||
padding: '4px 6px',
|
||||
boxSizing: 'border-box',
|
||||
@@ -313,7 +324,8 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
paddingLeft: 6,
|
||||
paddingRight: 6,
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4 };
|
||||
paddingBottom: 4,
|
||||
});
|
||||
|
||||
const updateSettingValue = (key: string, value: any) => {
|
||||
const md = Setting.settingMetadata(key);
|
||||
@@ -369,12 +381,14 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
);
|
||||
}
|
||||
|
||||
const selectStyle = { ...controlStyle, paddingLeft: 6,
|
||||
const selectStyle = Object.assign({}, controlStyle, {
|
||||
paddingLeft: 6,
|
||||
paddingRight: 6,
|
||||
paddingTop: 4,
|
||||
paddingBottom: 4,
|
||||
borderColor: theme.borderColor4,
|
||||
borderRadius: 3 };
|
||||
borderRadius: 3,
|
||||
});
|
||||
|
||||
return (
|
||||
<div key={key} style={rowStyle}>
|
||||
@@ -429,8 +443,10 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
</div>
|
||||
);
|
||||
} else if (md.type === Setting.TYPE_STRING) {
|
||||
const inputStyle: any = { ...textInputBaseStyle, width: '50%',
|
||||
minWidth: '20em' };
|
||||
const inputStyle: any = Object.assign({}, textInputBaseStyle, {
|
||||
width: '50%',
|
||||
minWidth: '20em',
|
||||
});
|
||||
const inputType = md.secure === true ? 'password' : 'text';
|
||||
|
||||
if (md.subType === 'file_path_and_args' || md.subType === 'file_path' || md.subType === 'directory_path') {
|
||||
@@ -526,7 +542,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: inputStyle.marginBottom }}>
|
||||
<input
|
||||
type={inputType}
|
||||
style={{ ...inputStyle, marginBottom: 0, marginRight: 5 }}
|
||||
style={Object.assign({}, inputStyle, { marginBottom: 0, marginRight: 5 })}
|
||||
onChange={(event: any) => {
|
||||
onPathChange(event);
|
||||
}}
|
||||
@@ -579,7 +595,7 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
const label = [md.label()];
|
||||
if (md.unitLabel) label.push(`(${md.unitLabel()})`);
|
||||
|
||||
const inputStyle: any = { ...textInputBaseStyle };
|
||||
const inputStyle: any = Object.assign({}, textInputBaseStyle);
|
||||
|
||||
return (
|
||||
<div key={key} style={rowStyle}>
|
||||
@@ -663,13 +679,15 @@ class ConfigScreenComponent extends React.Component<any, any> {
|
||||
public render() {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const style = {
|
||||
...this.props.style,
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: theme.backgroundColor3,
|
||||
};
|
||||
const style = Object.assign({},
|
||||
this.props.style,
|
||||
{
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
backgroundColor: theme.backgroundColor3,
|
||||
}
|
||||
);
|
||||
|
||||
const settings = this.state.settings;
|
||||
|
||||
|
@@ -74,7 +74,7 @@ export default function DialogButtonRow(props: Props) {
|
||||
|
||||
if (props.cancelButtonShow !== false) {
|
||||
buttonComps.push(
|
||||
<button disabled={props.cancelButtonDisabled} key="cancel" style={{ ...buttonStyle }} onClick={onCancelButtonClick}>
|
||||
<button disabled={props.cancelButtonDisabled} key="cancel" style={Object.assign({}, buttonStyle)} onClick={onCancelButtonClick}>
|
||||
{props.cancelButtonLabel ? props.cancelButtonLabel : _('Cancel')}
|
||||
</button>
|
||||
);
|
||||
|
@@ -29,13 +29,15 @@ class DropboxLoginScreenComponent extends React.Component<any, any> {
|
||||
const style = this.props.style;
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const containerStyle = { ...theme.containerStyle, padding: theme.configScreenPadding,
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, {
|
||||
padding: theme.configScreenPadding,
|
||||
height: style.height - theme.margin * 2,
|
||||
flex: 1 };
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
const inputStyle = { ...theme.inputStyle, width: 500 };
|
||||
const inputStyle = Object.assign({}, theme.inputStyle, { width: 500 });
|
||||
|
||||
const buttonStyle = { ...theme.buttonStyle, marginRight: 10 };
|
||||
const buttonStyle = Object.assign({}, theme.buttonStyle, { marginRight: 10 });
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
|
||||
|
@@ -82,7 +82,7 @@ function ExtensionBadge(props: Props) {
|
||||
void bridge().openExternal(props.url);
|
||||
};
|
||||
|
||||
const rootStyle = props.style ? { ...style.root, ...props.style } : style.root;
|
||||
const rootStyle = props.style ? Object.assign({}, style.root, props.style) : style.root;
|
||||
|
||||
return (
|
||||
<a style={rootStyle} onClick={onClick} href="#">
|
||||
|
@@ -23,7 +23,7 @@ class HelpButtonComponent extends React.Component<Props> {
|
||||
|
||||
public render() {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
const style = { ...this.props.style, color: theme.color, textDecoration: 'none' };
|
||||
const style = Object.assign({}, this.props.style, { color: theme.color, textDecoration: 'none' });
|
||||
const helpIconStyle = { flex: 0, width: 16, height: 16, marginLeft: 10 };
|
||||
const extraProps: any = {};
|
||||
if (this.props.tip) extraProps['data-tip'] = this.props.tip;
|
||||
|
@@ -18,19 +18,21 @@ class IconButton extends React.Component<Props> {
|
||||
};
|
||||
const icon = <i style={iconStyle} className={`fas ${this.props.iconName}`}></i>;
|
||||
|
||||
const rootStyle = {
|
||||
display: 'flex',
|
||||
textDecoration: 'none',
|
||||
padding: 10,
|
||||
width: theme.buttonMinHeight,
|
||||
height: theme.buttonMinHeight,
|
||||
boxSizing: 'border-box',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: theme.backgroundColor,
|
||||
cursor: 'default',
|
||||
...style,
|
||||
};
|
||||
const rootStyle = Object.assign(
|
||||
{
|
||||
display: 'flex',
|
||||
textDecoration: 'none',
|
||||
padding: 10,
|
||||
width: theme.buttonMinHeight,
|
||||
height: theme.buttonMinHeight,
|
||||
boxSizing: 'border-box',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundColor: theme.backgroundColor,
|
||||
cursor: 'default',
|
||||
},
|
||||
style
|
||||
);
|
||||
|
||||
return (
|
||||
<a
|
||||
|
@@ -1,4 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import Logger from '@joplin/lib/Logger';
|
||||
|
||||
const logger = Logger.create('ItemList');
|
||||
|
||||
interface Props {
|
||||
style: any;
|
||||
@@ -47,6 +50,15 @@ class ItemList extends React.Component<Props, State> {
|
||||
let bottomItemIndex = topItemIndex + (visibleItemCount - 1);
|
||||
if (bottomItemIndex >= props.items.length) bottomItemIndex = props.items.length - 1;
|
||||
|
||||
// EDGE CASE:
|
||||
// ref: https://github.com/laurent22/joplin/issues/4124
|
||||
// when the note list is hidden, visibleItemCount is negative, and scroll top is positive when a note is selected
|
||||
if (visibleItemCount < 0 && this.scrollTop_ > 0) {
|
||||
logger.warn('Resetting scrollTop to 0. visibleItemCount is negative, scrollTop is positive.');
|
||||
// we will reset the scroll top so that there is no blank space at the top of note list
|
||||
this.scrollTop_ = 0;
|
||||
}
|
||||
|
||||
this.setState({
|
||||
topItemIndex: topItemIndex,
|
||||
bottomItemIndex: bottomItemIndex,
|
||||
@@ -69,6 +81,21 @@ class ItemList extends React.Component<Props, State> {
|
||||
this.updateStateItemIndexes(newProps);
|
||||
}
|
||||
|
||||
public componentDidUpdate(): void {
|
||||
// EDGE CASE
|
||||
// scroll top is not updated when item list visibility is toggled
|
||||
// if the user was at the bottom of the item list before hiding, blank spaces are added at the bottom of the item list
|
||||
if (this.offsetScroll() !== this.listRef.current?.scrollTop) {
|
||||
logger.warn(`scrollTop mismatch. Updating scrollTop with current listRef scrollTop(${this.listRef.current.scrollTop})`);
|
||||
// update scroll postion once if there is a mismatch in scroll position after showing item list
|
||||
this.onScroll({
|
||||
target: {
|
||||
scrollTop: this.listRef.current.scrollTop,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public onScroll(event: any) {
|
||||
this.scrollTop_ = event.target.scrollTop;
|
||||
this.updateStateItemIndexes();
|
||||
@@ -121,8 +148,10 @@ class ItemList extends React.Component<Props, State> {
|
||||
|
||||
public render() {
|
||||
const items = this.props.items;
|
||||
const style = { ...this.props.style, overflowX: 'hidden',
|
||||
overflowY: 'auto' };
|
||||
const style = Object.assign({}, this.props.style, {
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'auto',
|
||||
});
|
||||
|
||||
// if (this.props.disabled) style.opacity = 0.5;
|
||||
|
||||
|
@@ -501,14 +501,16 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
height: height,
|
||||
};
|
||||
|
||||
this.styles_.modalLayer = { ...theme.textStyle, zIndex: 10000,
|
||||
this.styles_.modalLayer = Object.assign({}, theme.textStyle, {
|
||||
zIndex: 10000,
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
left: 0,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
width: width - 20,
|
||||
height: height - 20,
|
||||
padding: 10 };
|
||||
padding: 10,
|
||||
});
|
||||
|
||||
return this.styles_;
|
||||
}
|
||||
@@ -801,11 +803,13 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
|
||||
public render() {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
const style = {
|
||||
color: theme.color,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
...this.props.style,
|
||||
};
|
||||
const style = Object.assign(
|
||||
{
|
||||
color: theme.color,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
},
|
||||
this.props.style
|
||||
);
|
||||
const promptOptions = this.state.promptOptions;
|
||||
const styles = this.styles(this.props.themeId, style.width, style.height, this.messageBoxVisible());
|
||||
|
||||
@@ -820,7 +824,7 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
const dialogInfo = PluginManager.instance().pluginDialogToShow(this.props.pluginsLegacy);
|
||||
const pluginDialog = !dialogInfo ? null : <dialogInfo.Dialog {...dialogInfo.props} />;
|
||||
|
||||
const modalLayerStyle = { ...styles.modalLayer, display: this.state.modalLayer.visible ? 'block' : 'none' };
|
||||
const modalLayerStyle = Object.assign({}, styles.modalLayer, { display: this.state.modalLayer.visible ? 'block' : 'none' });
|
||||
|
||||
const notePropertiesDialogOptions = this.state.notePropertiesDialogOptions;
|
||||
const noteContentPropertiesDialogOptions = this.state.noteContentPropertiesDialogOptions;
|
||||
@@ -862,7 +866,6 @@ class MainScreenComponent extends React.Component<Props, State> {
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
const syncInfo = localSyncInfoFromState(state);
|
||||
const showNeedUpgradingEnabledMasterKeyMessage = !!EncryptionService.instance().masterKeysThatNeedUpgrading(syncInfo.masterKeys.filter((k) => !!k.enabled)).length;
|
||||
|
||||
return {
|
||||
themeId: state.settings.theme,
|
||||
@@ -870,7 +873,7 @@ const mapStateToProps = (state: AppState) => {
|
||||
hasDisabledSyncItems: state.hasDisabledSyncItems,
|
||||
hasDisabledEncryptionItems: state.hasDisabledEncryptionItems,
|
||||
showMissingMasterKeyMessage: showMissingMasterKeyMessage(syncInfo, state.notLoadedMasterKeys),
|
||||
showNeedUpgradingMasterKeyMessage: showNeedUpgradingEnabledMasterKeyMessage,
|
||||
showNeedUpgradingMasterKeyMessage: !!EncryptionService.instance().masterKeysThatNeedUpgrading(syncInfo.masterKeys).length,
|
||||
showShouldReencryptMessage: state.settings['encryption.shouldReencrypt'] >= Setting.SHOULD_REENCRYPT_YES,
|
||||
shouldUpgradeSyncTarget: state.settings['sync.upgradeState'] === Setting.SYNC_UPGRADE_STATE_SHOULD_DO,
|
||||
pluginsLegacy: state.pluginsLegacy,
|
||||
|
@@ -22,7 +22,7 @@ export const runtime = (comp: any): CommandRuntime => {
|
||||
const { newConfig, newProfile } = createNewProfile(context.state.profileConfig, answer);
|
||||
newConfig.currentProfileId = newProfile.id;
|
||||
await saveProfileConfig(`${Setting.value('rootProfileDir')}/profiles.json`, newConfig);
|
||||
await restart();
|
||||
await restart(false);
|
||||
}
|
||||
|
||||
comp.setState({ promptOptions: null });
|
||||
|
@@ -17,9 +17,11 @@ export const runtime = (): CommandRuntime => {
|
||||
|
||||
const defaultValues = Note.previewFieldsWithDefaultValues({ includeTimestamps: false });
|
||||
|
||||
let newNote = { ...defaultValues, parent_id: folderId,
|
||||
let newNote = Object.assign({}, defaultValues, {
|
||||
parent_id: folderId,
|
||||
is_todo: isTodo ? 1 : 0,
|
||||
body: body };
|
||||
body: body,
|
||||
});
|
||||
|
||||
newNote = await Note.save(newNote, { provisional: true });
|
||||
|
||||
|
@@ -3,7 +3,7 @@ import { useState, useEffect } from 'react';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import DialogButtonRow from './DialogButtonRow';
|
||||
const { themeStyle } = require('@joplin/lib/theme');
|
||||
const Countable = require('@joplin/lib/countable/Countable');
|
||||
const Countable = require('countable');
|
||||
import markupLanguageUtils from '../utils/markupLanguageUtils';
|
||||
|
||||
interface NoteContentPropertiesDialogProps {
|
||||
|
@@ -32,52 +32,84 @@ import Setting from '@joplin/lib/models/Setting';
|
||||
|
||||
// import eventManager from '@joplin/lib/eventManager';
|
||||
|
||||
import { reg } from '@joplin/lib/registry';
|
||||
// import { reg } from '@joplin/lib/registry';
|
||||
|
||||
// Based on http://pypl.github.io/PYPL.html
|
||||
const topLanguages = [
|
||||
'python',
|
||||
'clike',
|
||||
'javascript',
|
||||
'jsx',
|
||||
'php',
|
||||
'r',
|
||||
'swift',
|
||||
'go',
|
||||
'vb',
|
||||
'vbscript',
|
||||
'ruby',
|
||||
'rust',
|
||||
'dart',
|
||||
'lua',
|
||||
'groovy',
|
||||
'perl',
|
||||
'cobol',
|
||||
'julia',
|
||||
'haskell',
|
||||
'pascal',
|
||||
'css',
|
||||
require('codemirror/mode/python/python');
|
||||
require('codemirror/mode/clike/clike');
|
||||
require('codemirror/mode/javascript/javascript');
|
||||
require('codemirror/mode/jsx/jsx');
|
||||
require('codemirror/mode/php/php');
|
||||
require('codemirror/mode/r/r');
|
||||
require('codemirror/mode/swift/swift');
|
||||
require('codemirror/mode/go/go');
|
||||
require('codemirror/mode/vb/vb');
|
||||
require('codemirror/mode/vbscript/vbscript');
|
||||
require('codemirror/mode/ruby/ruby');
|
||||
require('codemirror/mode/rust/rust');
|
||||
require('codemirror/mode/dart/dart');
|
||||
require('codemirror/mode/lua/lua');
|
||||
require('codemirror/mode/groovy/groovy');
|
||||
require('codemirror/mode/perl/perl');
|
||||
require('codemirror/mode/cobol/cobol');
|
||||
require('codemirror/mode/julia/julia');
|
||||
require('codemirror/mode/haskell/haskell');
|
||||
require('codemirror/mode/pascal/pascal');
|
||||
require('codemirror/mode/css/css');
|
||||
|
||||
// Additional languages, not in the PYPL list
|
||||
'xml', // For HTML too
|
||||
'markdown',
|
||||
'yaml',
|
||||
'shell',
|
||||
'dockerfile',
|
||||
'diff',
|
||||
'erlang',
|
||||
'sql',
|
||||
];
|
||||
// Load Top Modes
|
||||
for (let i = 0; i < topLanguages.length; i++) {
|
||||
const mode = topLanguages[i];
|
||||
// Additional languages, not in the PYPL list
|
||||
require('codemirror/mode/xml/xml'); // For HTML too
|
||||
require('codemirror/mode/markdown/markdown');
|
||||
require('codemirror/mode/yaml/yaml');
|
||||
require('codemirror/mode/shell/shell');
|
||||
require('codemirror/mode/dockerfile/dockerfile');
|
||||
require('codemirror/mode/diff/diff');
|
||||
require('codemirror/mode/erlang/erlang');
|
||||
require('codemirror/mode/sql/sql');
|
||||
|
||||
if (CodeMirror.modeInfo.find((m: any) => m.mode === mode)) {
|
||||
require(`codemirror/mode/${mode}/${mode}`);
|
||||
} else {
|
||||
reg.logger().error('Cannot find CodeMirror mode: ', mode);
|
||||
}
|
||||
}
|
||||
// // Based on http://pypl.github.io/PYPL.html
|
||||
// const topLanguages = [
|
||||
// 'python',
|
||||
// 'clike',
|
||||
// 'javascript',
|
||||
// 'jsx',
|
||||
// 'php',
|
||||
// 'r',
|
||||
// 'swift',
|
||||
// 'go',
|
||||
// 'vb',
|
||||
// 'vbscript',
|
||||
// 'ruby',
|
||||
// 'rust',
|
||||
// 'dart',
|
||||
// 'lua',
|
||||
// 'groovy',
|
||||
// 'perl',
|
||||
// 'cobol',
|
||||
// 'julia',
|
||||
// 'haskell',
|
||||
// 'pascal',
|
||||
// 'css',
|
||||
|
||||
// // Additional languages, not in the PYPL list
|
||||
// 'xml', // For HTML too
|
||||
// 'markdown',
|
||||
// 'yaml',
|
||||
// 'shell',
|
||||
// 'dockerfile',
|
||||
// 'diff',
|
||||
// 'erlang',
|
||||
// 'sql',
|
||||
// ];
|
||||
// // Load Top Modes
|
||||
// for (let i = 0; i < topLanguages.length; i++) {
|
||||
// const mode = topLanguages[i];
|
||||
|
||||
// if (CodeMirror.modeInfo.find((m: any) => m.mode === mode)) {
|
||||
// require(`codemirror/mode/${mode}/${mode}`);
|
||||
// } else {
|
||||
// reg.logger().error('Cannot find CodeMirror mode: ', mode);
|
||||
// }
|
||||
// }
|
||||
|
||||
export interface EditorProps {
|
||||
value: string;
|
||||
|
@@ -31,7 +31,7 @@ export default function useExternalPlugins(CodeMirror: any, plugins: PluginState
|
||||
}
|
||||
|
||||
if (mod.codeMirrorOptions) {
|
||||
newOptions = { ...newOptions, ...mod.codeMirrorOptions };
|
||||
newOptions = Object.assign({}, newOptions, mod.codeMirrorOptions);
|
||||
}
|
||||
|
||||
if (mod.assets) {
|
||||
|
@@ -6,7 +6,8 @@ import useScroll from './utils/useScroll';
|
||||
import styles_ from './styles';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import { ToolbarButtonInfo } from '@joplin/lib/services/commands/ToolbarButtonUtils';
|
||||
import ToggleEditorsButton, { Value as ToggleEditorsButtonValue } from '../../../ToggleEditorsButton/ToggleEditorsButton';
|
||||
import ToggleEditorsButton from '../../../ToggleEditorsButton/ToggleEditorsButton';
|
||||
import { Value as ToggleEditorsButtonValue } from '../../../ToggleEditorsButton/types';
|
||||
import ToolbarButton from '../../../../gui/ToolbarButton/ToolbarButton';
|
||||
import usePluginServiceRegistration from '../../utils/usePluginServiceRegistration';
|
||||
import { utils as pluginUtils } from '@joplin/lib/services/plugins/reducer';
|
||||
|
@@ -1544,7 +1544,7 @@
|
||||
}
|
||||
});
|
||||
editor.addCommand('InsertJoplinChecklist', function (ui, detail) {
|
||||
detail = { ...detail, listType: 'joplinChecklist' };
|
||||
detail = Object.assign({}, detail, { listType: 'joplinChecklist' });
|
||||
ToggleList.toggleList(editor, 'UL', detail);
|
||||
});
|
||||
}
|
||||
|
@@ -364,11 +364,13 @@ function NoteEditor(props: NoteEditorProps) {
|
||||
}, [props.dispatch, formNote]);
|
||||
|
||||
function renderNoNotes(rootStyle: any) {
|
||||
const emptyDivStyle = {
|
||||
backgroundColor: 'black',
|
||||
opacity: 0.1,
|
||||
...rootStyle,
|
||||
};
|
||||
const emptyDivStyle = Object.assign(
|
||||
{
|
||||
backgroundColor: 'black',
|
||||
opacity: 0.1,
|
||||
},
|
||||
rootStyle
|
||||
);
|
||||
return <div style={emptyDivStyle}></div>;
|
||||
}
|
||||
|
||||
|
@@ -59,12 +59,14 @@ export default function useMarkupToHtml(deps: HookDependencies) {
|
||||
|
||||
delete options.replaceResourceInternalToExternalLinks;
|
||||
|
||||
const result = await markupToHtml.render(markupLanguage, md, theme, { codeTheme: theme.codeThemeCss,
|
||||
const result = await markupToHtml.render(markupLanguage, md, theme, Object.assign({}, {
|
||||
codeTheme: theme.codeThemeCss,
|
||||
resources: resources,
|
||||
postMessageSyntax: 'ipcProxySendToHost',
|
||||
splitted: true,
|
||||
externalAssetsOnly: true,
|
||||
codeHighlightCacheKey: 'useMarkupToHtml', ...options });
|
||||
codeHighlightCacheKey: 'useMarkupToHtml',
|
||||
}, options));
|
||||
|
||||
return result;
|
||||
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
|
||||
|
@@ -62,7 +62,7 @@ export default function useNoteSearchBar({ noteSearchBarRef }: UseNoteSearchBarP
|
||||
|
||||
const noteSearchBarNextPrevious = useCallback((inc: number) => {
|
||||
setLocalSearch((prev: LocalSearch) => {
|
||||
const ls = { ...prev };
|
||||
const ls = Object.assign({}, prev);
|
||||
ls.selectedIndex += inc;
|
||||
ls.timestamp = Date.now();
|
||||
if (ls.selectedIndex < 0) ls.selectedIndex = ls.resultCount - 1;
|
||||
|
@@ -19,6 +19,7 @@ import Note from '@joplin/lib/models/Note';
|
||||
import Folder from '@joplin/lib/models/Folder';
|
||||
import { Props } from './types';
|
||||
import usePrevious from '../hooks/usePrevious';
|
||||
import itemAnchorRef, { itemAnchorRefs_ } from './itemAnchorRef';
|
||||
|
||||
const commands = [
|
||||
require('./commands/focusElementNoteList'),
|
||||
@@ -31,15 +32,6 @@ const StyledRoot = styled.div`
|
||||
border-right: 1px solid ${(props: any) => props.theme.dividerColor};
|
||||
`;
|
||||
|
||||
const itemAnchorRefs_: any = {
|
||||
current: {},
|
||||
};
|
||||
|
||||
export const itemAnchorRef = (itemId: string) => {
|
||||
if (itemAnchorRefs_.current[itemId] && itemAnchorRefs_.current[itemId].current) return itemAnchorRefs_.current[itemId].current;
|
||||
return null;
|
||||
};
|
||||
|
||||
const NoteListComponent = (props: Props) => {
|
||||
const [dragOverTargetNoteIndex, setDragOverTargetNoteIndex] = useState(null);
|
||||
const [width, setWidth] = useState(0);
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { CommandRuntime, CommandDeclaration, CommandContext } from '@joplin/lib/services/CommandService';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { stateUtils } from '@joplin/lib/reducer';
|
||||
import { itemAnchorRef } from '../NoteList';
|
||||
import itemAnchorRef from '../itemAnchorRef';
|
||||
|
||||
export const declaration: CommandDeclaration = {
|
||||
name: 'focusElementNoteList',
|
||||
|
8
packages/app-desktop/gui/NoteList/itemAnchorRef.ts
Normal file
8
packages/app-desktop/gui/NoteList/itemAnchorRef.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export const itemAnchorRefs_: any = {
|
||||
current: {},
|
||||
};
|
||||
|
||||
export default (itemId: string) => {
|
||||
if (itemAnchorRefs_.current[itemId] && itemAnchorRefs_.current[itemId].current) return itemAnchorRefs_.current[itemId].current;
|
||||
return null;
|
||||
};
|
@@ -181,7 +181,7 @@ function NoteListControls(props: Props) {
|
||||
useEffect(() => {
|
||||
if (breakpoint === dynamicBreakpoints.Xl) {
|
||||
noteControlsRef.current.style.flexDirection = 'row';
|
||||
searchAndSortRef.current.style.flex = '2 1 50%';
|
||||
searchAndSortRef.current.style.flex = '2 1 auto';
|
||||
props.onContentHeightChange(true);
|
||||
} else {
|
||||
noteControlsRef.current.style.flexDirection = 'column';
|
||||
|
@@ -108,10 +108,10 @@ function NoteListItem(props: NoteListItemProps, ref: any) {
|
||||
);
|
||||
}
|
||||
|
||||
let listItemTitleStyle = { ...props.style.listItemTitle };
|
||||
let listItemTitleStyle = Object.assign({}, props.style.listItemTitle);
|
||||
listItemTitleStyle.paddingLeft = !item.is_todo ? hPadding : 4;
|
||||
if (item.is_shared) listItemTitleStyle.color = theme.colorWarn3;
|
||||
if (item.is_todo && !!item.todo_completed) listItemTitleStyle = { ...listItemTitleStyle, ...props.style.listItemTitleCompleted };
|
||||
if (item.is_todo && !!item.todo_completed) listItemTitleStyle = Object.assign(listItemTitleStyle, props.style.listItemTitleCompleted);
|
||||
|
||||
const displayTitle = Note.displayTitle(item);
|
||||
let titleComp = null;
|
||||
|
@@ -114,7 +114,7 @@ class NotePropertiesDialog extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
public formNoteToNote(formNote: any) {
|
||||
const note = { id: formNote.id, ...this.latLongFromLocation(formNote.location) };
|
||||
const note = Object.assign({ id: formNote.id }, this.latLongFromLocation(formNote.location));
|
||||
note.user_created_time = time.formatLocalToMs(formNote.user_created_time);
|
||||
note.user_updated_time = time.formatLocalToMs(formNote.user_updated_time);
|
||||
|
||||
@@ -211,7 +211,7 @@ class NotePropertiesDialog extends React.Component<Props, State> {
|
||||
if (!this.state.editedKey) return;
|
||||
|
||||
return new Promise((resolve: Function) => {
|
||||
const newFormNote = { ...this.state.formNote };
|
||||
const newFormNote = Object.assign({}, this.state.formNote);
|
||||
|
||||
if (this.state.editedKey.indexOf('_time') >= 0) {
|
||||
const dt = time.anythingToDateTime(this.state.editedValue, new Date());
|
||||
@@ -248,7 +248,7 @@ class NotePropertiesDialog extends React.Component<Props, State> {
|
||||
public createNoteField(key: string, value: any) {
|
||||
const styles = this.styles(this.props.themeId);
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
const labelComp = <label style={{ ...theme.textStyle, ...theme.controlBoxLabel }}>{this.formatLabel(key)}</label>;
|
||||
const labelComp = <label style={Object.assign({}, theme.textStyle, theme.controlBoxLabel)}>{this.formatLabel(key)}</label>;
|
||||
let controlComp = null;
|
||||
let editComp = null;
|
||||
let editCompHandler = null;
|
||||
@@ -317,7 +317,7 @@ class NotePropertiesDialog extends React.Component<Props, State> {
|
||||
const ll = this.latLongFromLocation(value);
|
||||
url = Note.geoLocationUrlFromLatLong(ll.latitude, ll.longitude);
|
||||
}
|
||||
const urlStyle = { ...theme.urlStyle, maxWidth: '180px', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' };
|
||||
const urlStyle = Object.assign({}, theme.urlStyle, { maxWidth: '180px', overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' });
|
||||
controlComp = (
|
||||
<a href="#" onClick={() => bridge().openExternal(url)} style={urlStyle}>
|
||||
{displayedValue}
|
||||
@@ -330,7 +330,7 @@ class NotePropertiesDialog extends React.Component<Props, State> {
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
controlComp = <div style={{ ...theme.textStyle, ...theme.controlBoxValue }}>{displayedValue}</div>;
|
||||
controlComp = <div style={Object.assign({}, theme.textStyle, theme.controlBoxValue)}>{displayedValue}</div>;
|
||||
}
|
||||
|
||||
if (['id', 'revisionsLink', 'markup_language'].indexOf(key) < 0) {
|
||||
|
@@ -67,8 +67,8 @@ class NoteRevisionViewerComponent extends React.PureComponent<Props, State> {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
titleInput: { ...theme.inputStyle, flex: 1 },
|
||||
revisionList: { ...theme.dropdownList, marginLeft: 10, flex: 0.5 },
|
||||
titleInput: Object.assign({}, theme.inputStyle, { flex: 1 }),
|
||||
revisionList: Object.assign({}, theme.dropdownList, { marginLeft: 10, flex: 0.5 }),
|
||||
};
|
||||
|
||||
return style;
|
||||
@@ -205,14 +205,14 @@ class NoteRevisionViewerComponent extends React.PureComponent<Props, State> {
|
||||
|
||||
const titleInput = (
|
||||
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center', marginBottom: 10, borderWidth: 1, borderBottomStyle: 'solid', borderColor: theme.dividerColor, paddingBottom: 10 }}>
|
||||
<button onClick={this.backButton_click} style={{ ...theme.buttonStyle, marginRight: 10, height: theme.inputStyle.height }}>
|
||||
<button onClick={this.backButton_click} style={Object.assign({}, theme.buttonStyle, { marginRight: 10, height: theme.inputStyle.height })}>
|
||||
<i style={theme.buttonIconStyle} className={'fa fa-chevron-left'}></i>{_('Back')}
|
||||
</button>
|
||||
<input readOnly type="text" style={style.titleInput} value={this.state.note ? this.state.note.title : ''} />
|
||||
<select disabled={!this.state.revisions.length} value={this.state.currentRevId} style={style.revisionList} onChange={this.revisionList_onChange}>
|
||||
{revisionListItems}
|
||||
</select>
|
||||
<button disabled={!this.state.revisions.length || this.state.restoring} onClick={this.importButton_onClick} style={{ ...theme.buttonStyle, marginLeft: 10, height: theme.inputStyle.height }}>
|
||||
<button disabled={!this.state.revisions.length || this.state.restoring} onClick={this.importButton_onClick} style={Object.assign({}, theme.buttonStyle, { marginLeft: 10, height: theme.inputStyle.height })}>
|
||||
{restoreButtonTitle}
|
||||
</button>
|
||||
<HelpButton tip={helpMessage} id="noteRevisionHelpButton" onClick={this.helpButton_onClick} />
|
||||
|
@@ -37,8 +37,10 @@ class NoteSearchBar extends React.Component<Props> {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const style = {
|
||||
root: { ...theme.textStyle, backgroundColor: theme.backgroundColor,
|
||||
color: theme.colorFaded },
|
||||
root: Object.assign({}, theme.textStyle, {
|
||||
backgroundColor: theme.backgroundColor,
|
||||
color: theme.colorFaded,
|
||||
}),
|
||||
};
|
||||
|
||||
return style;
|
||||
@@ -148,10 +150,12 @@ class NoteSearchBar extends React.Component<Props> {
|
||||
const previousButton = this.buttonIconComponent('fa-chevron-up', this.previousButton_click, buttonEnabled);
|
||||
const nextButton = this.buttonIconComponent('fa-chevron-down', this.nextButton_click, buttonEnabled);
|
||||
|
||||
const textStyle = { fontSize: theme.fontSize,
|
||||
const textStyle = Object.assign({
|
||||
fontSize: theme.fontSize,
|
||||
fontFamily: theme.fontFamily,
|
||||
color: theme.colorFaded,
|
||||
backgroundColor: theme.backgroundColor };
|
||||
backgroundColor: theme.backgroundColor,
|
||||
});
|
||||
|
||||
const matchesFoundString = (query.length > 0) ? (
|
||||
<div style={textStyle}>
|
||||
|
@@ -15,8 +15,10 @@ class NoteStatusBarComponent extends React.Component<Props> {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const style = {
|
||||
root: { ...theme.textStyle, backgroundColor: theme.backgroundColor,
|
||||
color: theme.colorFaded },
|
||||
root: Object.assign({}, theme.textStyle, {
|
||||
backgroundColor: theme.backgroundColor,
|
||||
color: theme.colorFaded,
|
||||
}),
|
||||
};
|
||||
|
||||
return style;
|
||||
|
@@ -173,7 +173,7 @@ export default class NoteTextViewerComponent extends React.Component<Props, any>
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
public render() {
|
||||
const viewerStyle = { border: 'none', ...this.props.viewerStyle };
|
||||
const viewerStyle = Object.assign({}, { border: 'none' }, this.props.viewerStyle);
|
||||
return <iframe className="noteTextViewer" ref={this.webviewRef_} style={viewerStyle} src="gui/note-viewer/index.html"></iframe>;
|
||||
}
|
||||
}
|
||||
|
@@ -26,15 +26,11 @@ export default class PromptDialog extends React.Component<Props, any> {
|
||||
private focusInput_: boolean;
|
||||
private styles_: any;
|
||||
private styleKey_: string;
|
||||
private menuIsOpened_: boolean = false;
|
||||
|
||||
public constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.answerInput_ = React.createRef();
|
||||
|
||||
this.select_menuOpen = this.select_menuOpen.bind(this);
|
||||
this.select_menuClose = this.select_menuClose.bind(this);
|
||||
}
|
||||
|
||||
public UNSAFE_componentWillMount() {
|
||||
@@ -43,7 +39,6 @@ export default class PromptDialog extends React.Component<Props, any> {
|
||||
answer: this.props.defaultValue ? this.props.defaultValue : '',
|
||||
});
|
||||
this.focusInput_ = true;
|
||||
this.menuIsOpened_ = false;
|
||||
}
|
||||
|
||||
public UNSAFE_componentWillReceiveProps(newProps: Props) {
|
||||
@@ -57,14 +52,6 @@ export default class PromptDialog extends React.Component<Props, any> {
|
||||
}
|
||||
}
|
||||
|
||||
private select_menuOpen() {
|
||||
this.menuIsOpened_ = true;
|
||||
}
|
||||
|
||||
private select_menuClose() {
|
||||
this.menuIsOpened_ = false;
|
||||
}
|
||||
|
||||
public componentDidUpdate() {
|
||||
if (this.focusInput_ && this.answerInput_.current) this.answerInput_.current.focus();
|
||||
this.focusInput_ = false;
|
||||
@@ -132,49 +119,43 @@ export default class PromptDialog extends React.Component<Props, any> {
|
||||
};
|
||||
|
||||
this.styles_.select = {
|
||||
control: (provided: any) => {
|
||||
return { ...provided,
|
||||
control: (provided: any) =>
|
||||
Object.assign(provided, {
|
||||
minWidth: width * 0.2,
|
||||
maxWidth: width * 0.5,
|
||||
fontFamily: theme.fontFamily,
|
||||
};
|
||||
},
|
||||
input: (provided: any) => {
|
||||
return { ...provided,
|
||||
}),
|
||||
input: (provided: any) =>
|
||||
Object.assign(provided, {
|
||||
minWidth: '20px',
|
||||
color: theme.color,
|
||||
};
|
||||
},
|
||||
menu: (provided: any) => {
|
||||
return { ...provided,
|
||||
}),
|
||||
menu: (provided: any) =>
|
||||
Object.assign(provided, {
|
||||
color: theme.color,
|
||||
fontFamily: theme.fontFamily,
|
||||
backgroundColor: theme.backgroundColor,
|
||||
};
|
||||
},
|
||||
option: (provided: any, state: any) => {
|
||||
return { ...provided,
|
||||
}),
|
||||
option: (provided: any, state: any) =>
|
||||
Object.assign(provided, {
|
||||
color: theme.color,
|
||||
fontFamily: theme.fontFamily,
|
||||
paddingLeft: `${10 + (state.data.indentDepth || 0) * 20}px`,
|
||||
};
|
||||
},
|
||||
multiValueLabel: (provided: any) => {
|
||||
return { ...provided,
|
||||
}),
|
||||
multiValueLabel: (provided: any) =>
|
||||
Object.assign(provided, {
|
||||
fontFamily: theme.fontFamily,
|
||||
};
|
||||
},
|
||||
multiValueRemove: (provided: any) => {
|
||||
return { ...provided,
|
||||
}),
|
||||
multiValueRemove: (provided: any) =>
|
||||
Object.assign(provided, {
|
||||
color: theme.color,
|
||||
};
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
this.styles_.selectTheme = (tagTheme: any) => {
|
||||
return { ...tagTheme,
|
||||
this.styles_.selectTheme = (tagTheme: any) =>
|
||||
Object.assign(tagTheme, {
|
||||
borderRadius: 2,
|
||||
colors: { ...tagTheme.colors,
|
||||
colors: Object.assign(tagTheme.colors, {
|
||||
primary: theme.raisedBackgroundColor,
|
||||
primary25: theme.raisedBackgroundColor,
|
||||
neutral0: theme.backgroundColor,
|
||||
@@ -190,11 +171,12 @@ export default class PromptDialog extends React.Component<Props, any> {
|
||||
neutral90: theme.color,
|
||||
danger: theme.backgroundColor,
|
||||
dangerLight: theme.colorError2,
|
||||
},
|
||||
};
|
||||
};
|
||||
}),
|
||||
});
|
||||
|
||||
this.styles_.desc = { ...theme.textStyle, marginTop: 10 };
|
||||
this.styles_.desc = Object.assign({}, theme.textStyle, {
|
||||
marginTop: 10,
|
||||
});
|
||||
|
||||
return this.styles_;
|
||||
}
|
||||
@@ -242,14 +224,16 @@ export default class PromptDialog extends React.Component<Props, any> {
|
||||
|
||||
const onKeyDown = (event: any) => {
|
||||
if (event.key === 'Enter') {
|
||||
// If the dropdown is open, we don't close the dialog - instead
|
||||
// the currently item will be selcted. If it is closed however
|
||||
// we confirm the dialog.
|
||||
if ((this.props.inputType === 'tags' || this.props.inputType === 'dropdown') && this.menuIsOpened_) {
|
||||
if (this.props.inputType === 'tags' || this.props.inputType === 'dropdown') {
|
||||
// Do nothing
|
||||
} else {
|
||||
onClose(true);
|
||||
}
|
||||
|
||||
// } else if (this.answerInput_.current && !this.answerInput_.current.state.menuIsOpen) {
|
||||
// // The menu will be open if the user is selecting a new item
|
||||
// onClose(true);
|
||||
// }
|
||||
} else if (event.key === 'Escape') {
|
||||
onClose(false);
|
||||
}
|
||||
@@ -262,9 +246,9 @@ export default class PromptDialog extends React.Component<Props, any> {
|
||||
if (this.props.inputType === 'datetime') {
|
||||
inputComp = <Datetime className="datetime-picker" value={this.state.answer} inputProps={{ style: styles.input }} dateFormat={time.dateFormat()} timeFormat={time.timeFormat()} onChange={(momentObject: any) => onDateTimeChange(momentObject)} />;
|
||||
} else if (this.props.inputType === 'tags') {
|
||||
inputComp = <CreatableSelect className="tag-selector" onMenuOpen={this.select_menuOpen} onMenuClose={this.select_menuClose} styles={styles.select} theme={styles.selectTheme} ref={this.answerInput_} value={this.state.answer} placeholder="" components={makeAnimated()} isMulti={true} isClearable={false} backspaceRemovesValue={true} options={this.props.autocomplete} onChange={onSelectChange} onKeyDown={(event: any) => onKeyDown(event)} />;
|
||||
inputComp = <CreatableSelect className="tag-selector" styles={styles.select} theme={styles.selectTheme} ref={this.answerInput_} value={this.state.answer} placeholder="" components={makeAnimated()} isMulti={true} isClearable={false} backspaceRemovesValue={true} options={this.props.autocomplete} onChange={onSelectChange} onKeyDown={(event: any) => onKeyDown(event)} />;
|
||||
} else if (this.props.inputType === 'dropdown') {
|
||||
inputComp = <Select className="item-selector" onMenuOpen={this.select_menuOpen} onMenuClose={this.select_menuClose} styles={styles.select} theme={styles.selectTheme} ref={this.answerInput_} components={makeAnimated()} value={this.props.answer} defaultValue={this.props.defaultValue} isClearable={false} options={this.props.autocomplete} onChange={onSelectChange} onKeyDown={(event: any) => onKeyDown(event)} />;
|
||||
inputComp = <Select className="item-selector" styles={styles.select} theme={styles.selectTheme} ref={this.answerInput_} components={makeAnimated()} value={this.props.answer} defaultValue={this.props.defaultValue} isClearable={false} options={this.props.autocomplete} onChange={onSelectChange} onKeyDown={(event: any) => onKeyDown(event)} />;
|
||||
} else {
|
||||
inputComp = <input style={styles.input} ref={this.answerInput_} value={this.state.answer} type="text" onChange={event => onChange(event)} onKeyDown={event => onKeyDown(event)} />;
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ import StyleSheetContainer from './StyleSheets/StyleSheetContainer';
|
||||
import ImportScreen from './ImportScreen';
|
||||
const { ResourceScreen } = require('./ResourceScreen.js');
|
||||
import Navigator from './Navigator';
|
||||
import WelcomeUtils from '@joplin/lib/WelcomeUtils';
|
||||
const WelcomeUtils = require('@joplin/lib/WelcomeUtils');
|
||||
const { ThemeProvider, StyleSheetManager, createGlobalStyle } = require('styled-components');
|
||||
const bridge = require('@electron/remote').require('./bridge').default;
|
||||
|
||||
@@ -141,7 +141,7 @@ class RootComponent extends React.Component<Props, any> {
|
||||
});
|
||||
}
|
||||
|
||||
await WelcomeUtils.install(Setting.value('locale'), this.props.dispatch);
|
||||
await WelcomeUtils.install(this.props.dispatch);
|
||||
}
|
||||
|
||||
private renderModalMessage(props: ModalDialogProps) {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { useEffect, useRef, useCallback, useMemo } from 'react';
|
||||
import styled, { css } from 'styled-components';
|
||||
import styled from 'styled-components';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import { StyledRoot, StyledAddButton, StyledShareIcon, StyledHeader, StyledHeaderIcon, StyledAllNotesIcon, StyledHeaderLabel, StyledListItem, StyledListItemAnchor, StyledExpandLink, StyledNoteCount, StyledSyncReportText, StyledSyncReport, StyledSynchronizeButton } from './styles';
|
||||
import { ButtonLevel } from '../Button/Button';
|
||||
@@ -40,14 +40,23 @@ const { clipboard } = require('electron');
|
||||
|
||||
const logger = Logger.create('Sidebar');
|
||||
|
||||
// Workaround sidebar rendering bug on Linux Intel GPU.
|
||||
// https://github.com/laurent22/joplin/issues/7506
|
||||
const StyledSpanFix = styled.span`
|
||||
${shim.isLinux() && css`
|
||||
position: relative;
|
||||
`}
|
||||
const StyledFoldersHolder = styled.div`
|
||||
// linux bug: https://github.com/laurent22/joplin/issues/7506#issuecomment-1447101057
|
||||
& a.list-item {
|
||||
${shim.isLinux() && {
|
||||
opacity: 1,
|
||||
}}
|
||||
}
|
||||
`;
|
||||
const TagsHolder = styled.div`
|
||||
// linux bug: https://github.com/laurent22/joplin/issues/8000
|
||||
// solution ref: https://github.com/laurent22/joplin/issues/7506#issuecomment-1447101057
|
||||
& a.list-item {
|
||||
${shim.isLinux() && {
|
||||
opacity: 1,
|
||||
}}
|
||||
}
|
||||
`;
|
||||
|
||||
|
||||
interface Props {
|
||||
themeId: number;
|
||||
@@ -129,7 +138,7 @@ function FolderItem(props: any) {
|
||||
}}
|
||||
onDoubleClick={onFolderToggleClick_}
|
||||
>
|
||||
{showFolderIcon ? renderFolderIcon(folderIcon) : null}<StyledSpanFix className="title" style={{ lineHeight: 0 }}>{folderTitle}</StyledSpanFix>
|
||||
{showFolderIcon ? renderFolderIcon(folderIcon) : null}<span className="title" style={{ lineHeight: 0 }}>{folderTitle}</span>
|
||||
{shareIcon} {noteCountComp}
|
||||
</StyledListItemAnchor>
|
||||
</StyledListItem>
|
||||
@@ -564,7 +573,7 @@ const SidebarComponent = (props: Props) => {
|
||||
tagItem_click(tag);
|
||||
}}
|
||||
>
|
||||
<StyledSpanFix className="tag-label">{Tag.displayTitle(tag)}</StyledSpanFix>
|
||||
<span className="tag-label">{Tag.displayTitle(tag)}</span>
|
||||
{noteCount}
|
||||
</StyledListItemAnchor>
|
||||
</StyledListItem>
|
||||
@@ -716,13 +725,13 @@ const SidebarComponent = (props: Props) => {
|
||||
const folderItems = [renderAllNotesItem(theme, allNotesSelected)].concat(result.items);
|
||||
folderItemsOrder_.current = result.order;
|
||||
items.push(
|
||||
<div
|
||||
<StyledFoldersHolder
|
||||
className={`folders ${props.folderHeaderIsExpanded ? 'expanded' : ''}`}
|
||||
key="folder_items"
|
||||
style={foldersStyle}
|
||||
>
|
||||
{folderItems}
|
||||
</div>
|
||||
</StyledFoldersHolder>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -738,9 +747,9 @@ const SidebarComponent = (props: Props) => {
|
||||
tagItemsOrder_.current = result.order;
|
||||
|
||||
items.push(
|
||||
<div className="tags" key="tag_items" style={{ display: props.tagHeaderIsExpanded ? 'block' : 'none' }}>
|
||||
<TagsHolder className="tags" key="tag_items" style={{ display: props.tagHeaderIsExpanded ? 'block' : 'none' }}>
|
||||
{tagItems}
|
||||
</div>
|
||||
</TagsHolder>
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -56,13 +56,15 @@ function StatusScreen(props: Props) {
|
||||
flexDirection: 'column',
|
||||
};
|
||||
|
||||
const retryStyle = { ...theme.urlStyle, marginLeft: 5 };
|
||||
const retryAllStyle = { ...theme.urlStyle, marginTop: 5, display: 'inline-block' };
|
||||
const retryStyle = Object.assign({}, theme.urlStyle, { marginLeft: 5 });
|
||||
const retryAllStyle = Object.assign({}, theme.urlStyle, { marginTop: 5, display: 'inline-block' });
|
||||
|
||||
const containerPadding = theme.configScreenPadding;
|
||||
|
||||
const containerStyle = { ...theme.containerStyle, padding: containerPadding,
|
||||
flex: 1 };
|
||||
const containerStyle = Object.assign({}, theme.containerStyle, {
|
||||
padding: containerPadding,
|
||||
flex: 1,
|
||||
});
|
||||
|
||||
function renderSectionTitleHtml(key: string, title: string) {
|
||||
return (
|
||||
|
@@ -37,5 +37,5 @@ export default function(props: Props): any {
|
||||
};
|
||||
}, [styleSheetContent]);
|
||||
|
||||
return <div style={{ display: 'none' }}></div>;
|
||||
return null; // <div style={{ display: 'none' }}></div>;
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import { AppState } from '../app.reducer';
|
||||
class TagItemComponent extends React.Component {
|
||||
public render() {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
const style = { ...theme.tagStyle };
|
||||
const style = Object.assign({}, theme.tagStyle);
|
||||
const { title, id } = this.props;
|
||||
|
||||
return <button style={style} onClick={() => CommandService.instance().execute('openTag', id)}>{title}</button>;
|
||||
|
@@ -1,17 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import styles_ from './styles';
|
||||
import { ToolbarButtonInfo } from '@joplin/lib/services/commands/ToolbarButtonUtils';
|
||||
|
||||
export enum Value {
|
||||
Markdown = 'markdown',
|
||||
RichText = 'richText',
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
themeId: number;
|
||||
value: Value;
|
||||
toolbarButtonInfo: ToolbarButtonInfo;
|
||||
}
|
||||
import { Props } from './types';
|
||||
|
||||
export default function ToggleEditorsButton(props: Props) {
|
||||
const style = styles_(props);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { Props, Value } from '../ToggleEditorsButton';
|
||||
import { Props, Value } from '../types';
|
||||
const { buildStyle } = require('@joplin/lib/theme');
|
||||
|
||||
export default function styles(props: Props) {
|
||||
|
12
packages/app-desktop/gui/ToggleEditorsButton/types.ts
Normal file
12
packages/app-desktop/gui/ToggleEditorsButton/types.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ToolbarButtonInfo } from '@joplin/lib/services/commands/ToolbarButtonUtils';
|
||||
|
||||
export enum Value {
|
||||
Markdown = 'markdown',
|
||||
RichText = 'richText',
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
themeId: number;
|
||||
value: Value;
|
||||
toolbarButtonInfo: ToolbarButtonInfo;
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import ToolbarButton from './ToolbarButton/ToolbarButton';
|
||||
import ToggleEditorsButton, { Value } from './ToggleEditorsButton/ToggleEditorsButton';
|
||||
import ToggleEditorsButton from './ToggleEditorsButton/ToggleEditorsButton';
|
||||
import { Value } from './ToggleEditorsButton/types';
|
||||
import ToolbarSpace from './ToolbarSpace';
|
||||
const { connect } = require('react-redux');
|
||||
const { themeStyle } = require('@joplin/lib/theme');
|
||||
@@ -16,12 +17,14 @@ class ToolbarBaseComponent extends React.Component<Props, any> {
|
||||
public render() {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
|
||||
const style: any = { display: 'flex',
|
||||
const style: any = Object.assign({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
boxSizing: 'border-box',
|
||||
backgroundColor: theme.backgroundColor3,
|
||||
padding: theme.toolbarPadding,
|
||||
paddingRight: theme.mainPadding, ...this.props.style };
|
||||
paddingRight: theme.mainPadding,
|
||||
}, this.props.style);
|
||||
|
||||
const groupStyle: any = {
|
||||
display: 'flex',
|
||||
@@ -43,11 +46,13 @@ class ToolbarBaseComponent extends React.Component<Props, any> {
|
||||
|
||||
if (!key) key = `${o.type}_${i}`;
|
||||
|
||||
const props = {
|
||||
key: key,
|
||||
themeId: this.props.themeId,
|
||||
...o,
|
||||
};
|
||||
const props = Object.assign(
|
||||
{
|
||||
key: key,
|
||||
themeId: this.props.themeId,
|
||||
},
|
||||
o
|
||||
);
|
||||
|
||||
if (o.name === 'toggleEditors') {
|
||||
rightItemComps.push(<ToggleEditorsButton
|
||||
@@ -73,7 +78,7 @@ class ToolbarBaseComponent extends React.Component<Props, any> {
|
||||
<div style={groupStyle}>
|
||||
{centerItemComps}
|
||||
</div>
|
||||
<div style={{ ...groupStyle, flex: 1, justifyContent: 'flex-end' }}>
|
||||
<div style={Object.assign({}, groupStyle, { flex: 1, justifyContent: 'flex-end' })}>
|
||||
{rightItemComps}
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -8,7 +8,7 @@ interface Props {
|
||||
class ToolbarSpace extends React.Component<Props> {
|
||||
public render() {
|
||||
const theme = themeStyle(this.props.themeId);
|
||||
const style = { ...theme.toolbarStyle };
|
||||
const style = Object.assign({}, theme.toolbarStyle);
|
||||
style.minWidth = style.height / 2;
|
||||
|
||||
return <span style={style}></span>;
|
||||
|
@@ -96,23 +96,25 @@ markJsUtils.markKeyword = (mark, keyword, stringUtils, extraOptions = null) => {
|
||||
|
||||
mark.mark(
|
||||
[value],
|
||||
{
|
||||
|
||||
accuracy: accuracy,
|
||||
filter: (node, _term, _totalCounter, _counter) => {
|
||||
// We exclude SVG because it creates a "<mark>" tag inside
|
||||
// the document, which is not a valid SVG tag. As a result
|
||||
// the content within that tag disappears.
|
||||
//
|
||||
// mark.js has an "exclude" parameter, but it doesn't work
|
||||
// so we use "filter" instead.
|
||||
//
|
||||
// https://github.com/joplin/plugin-abc-sheet-music
|
||||
if (isInsideContainer(node, 'SVG')) return false;
|
||||
return true;
|
||||
Object.assign(
|
||||
{},
|
||||
{
|
||||
accuracy: accuracy,
|
||||
filter: (node, _term, _totalCounter, _counter) => {
|
||||
// We exclude SVG because it creates a "<mark>" tag inside
|
||||
// the document, which is not a valid SVG tag. As a result
|
||||
// the content within that tag disappears.
|
||||
//
|
||||
// mark.js has an "exclude" parameter, but it doesn't work
|
||||
// so we use "filter" instead.
|
||||
//
|
||||
// https://github.com/joplin/plugin-abc-sheet-music
|
||||
if (isInsideContainer(node, 'SVG')) return false;
|
||||
return true;
|
||||
},
|
||||
},
|
||||
...extraOptions,
|
||||
}
|
||||
extraOptions
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -41,9 +41,13 @@ const style = createSelector(
|
||||
},
|
||||
};
|
||||
|
||||
output.buttonIconSelected = { ...output.buttonIcon, color: theme.highlightedColor };
|
||||
output.buttonIconSelected = Object.assign({}, output.buttonIcon, {
|
||||
color: theme.highlightedColor,
|
||||
});
|
||||
|
||||
output.buttonLabelSelected = { ...output.buttonLabel, color: theme.color };
|
||||
output.buttonLabelSelected = Object.assign({}, output.buttonLabel, {
|
||||
color: theme.color,
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@@ -42,7 +42,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="react-root"></div>
|
||||
<script src="main-html.js"></script>
|
||||
<script src="main-html.bundle.js"></script>
|
||||
<style>
|
||||
/* Disable dragging of links (which are often buttons) */
|
||||
a:not([draggable=true]), img:not([draggable=true]) {
|
||||
|
@@ -3,12 +3,15 @@
|
||||
// Disable React message in console "Download the React DevTools for a better development experience"
|
||||
// https://stackoverflow.com/questions/42196819/disable-hide-download-the-react-devtools#42196820
|
||||
// eslint-disable-next-line no-undef
|
||||
__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
|
||||
supportsFiber: true,
|
||||
inject: function() {},
|
||||
onCommitFiberRoot: function() {},
|
||||
onCommitFiberUnmount: function() {},
|
||||
};
|
||||
if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined') {
|
||||
// eslint-disable-next-line no-undef
|
||||
__REACT_DEVTOOLS_GLOBAL_HOOK__ = {
|
||||
supportsFiber: true,
|
||||
inject: function() {},
|
||||
onCommitFiberRoot: function() {},
|
||||
onCommitFiberUnmount: function() {},
|
||||
};
|
||||
}
|
||||
|
||||
const app = require('./app').default;
|
||||
const Folder = require('@joplin/lib/models/Folder').default;
|
||||
|
@@ -1,18 +1,20 @@
|
||||
{
|
||||
"name": "@joplin/app-desktop",
|
||||
"version": "2.11.9",
|
||||
"version": "2.11.1",
|
||||
"description": "Joplin for Desktop",
|
||||
"main": "main.js",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dist": "yarn run electronRebuild && npx electron-builder",
|
||||
"pack-html": "rollup --config rollup-main-html.config.js",
|
||||
"pack-main": "rollup --config rollup-main.config.js",
|
||||
"build": "gulp build",
|
||||
"postinstall": "yarn run build",
|
||||
"electronBuilder": "gulp electronBuilder",
|
||||
"electronRebuild": "gulp electronRebuild",
|
||||
"tsc": "tsc --project tsconfig.json",
|
||||
"watch": "tsc --watch --preserveWatchOutput --project tsconfig.json",
|
||||
"start": "gulp build && electron . --env dev --log-level debug --open-dev-tools",
|
||||
"start": "gulp build && electron . --env dev --log-level debug --no-welcome --open-dev-tools",
|
||||
"test": "jest",
|
||||
"test-ci": "yarn test"
|
||||
},
|
||||
@@ -27,7 +29,7 @@
|
||||
},
|
||||
"build": {
|
||||
"appId": "net.cozic.joplin-desktop",
|
||||
"compression": "normal",
|
||||
"compression": "maximum",
|
||||
"productName": "Joplin",
|
||||
"npmRebuild": false,
|
||||
"afterSign": "./tools/notarizeMacApp.js",
|
||||
@@ -36,6 +38,9 @@
|
||||
"build/images/**",
|
||||
"build/defaultPlugins/**"
|
||||
],
|
||||
"files": [
|
||||
"!node_modules/**/*"
|
||||
],
|
||||
"afterAllArtifactBuild": "./generateSha512.js",
|
||||
"asar": true,
|
||||
"asarUnpack": "./node_modules/node-notifier/vendor/**",
|
||||
@@ -109,24 +114,28 @@
|
||||
"homepage": "https://github.com/laurent22/joplin#readme",
|
||||
"devDependencies": {
|
||||
"@joplin/tools": "~2.11",
|
||||
"@rollup/plugin-commonjs": "24.1.0",
|
||||
"@rollup/plugin-json": "6.0.0",
|
||||
"@rollup/plugin-node-resolve": "15.0.2",
|
||||
"@testing-library/react-hooks": "8.0.1",
|
||||
"@types/jest": "29.5.1",
|
||||
"@types/node": "18.15.13",
|
||||
"@types/react": "16.14.41",
|
||||
"@types/jest": "29.2.6",
|
||||
"@types/node": "18.11.18",
|
||||
"@types/react": "16.14.35",
|
||||
"@types/react-redux": "7.1.25",
|
||||
"@types/styled-components": "5.1.26",
|
||||
"electron": "19.1.4",
|
||||
"electron-builder": "22.11.7",
|
||||
"electron-builder": "23.6.0",
|
||||
"electron-notarize": "1.2.2",
|
||||
"electron-rebuild": "3.2.9",
|
||||
"glob": "8.1.0",
|
||||
"gulp": "4.0.2",
|
||||
"jest": "29.5.0",
|
||||
"jest-environment-jsdom": "29.5.0",
|
||||
"jest": "29.4.3",
|
||||
"jest-environment-jsdom": "29.4.3",
|
||||
"js-sha512": "0.8.0",
|
||||
"nan": "2.17.0",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "5.0.2"
|
||||
"rollup": "3.21.0",
|
||||
"typescript": "4.9.4"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"7zip-bin-linux": "^1.0.1",
|
||||
@@ -163,7 +172,7 @@
|
||||
"react-datetime": "3.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-redux": "8.0.5",
|
||||
"react-select": "5.7.3",
|
||||
"react-select": "5.7.2",
|
||||
"react-toggle-button": "2.2.0",
|
||||
"react-tooltip": "4.5.1",
|
||||
"redux": "4.2.1",
|
||||
@@ -171,7 +180,7 @@
|
||||
"roboto-fontface": "0.10.0",
|
||||
"smalltalk": "2.5.1",
|
||||
"sqlite3": "5.1.6",
|
||||
"styled-components": "5.3.10",
|
||||
"styled-components": "5.3.9",
|
||||
"styled-system": "5.1.5",
|
||||
"taboverride": "4.0.3",
|
||||
"tinymce": "5.10.6"
|
||||
|
@@ -133,8 +133,8 @@ class Dialog extends React.PureComponent<Props, State> {
|
||||
}
|
||||
|
||||
this.styles_[styleKey] = {
|
||||
dialogBox: { ...theme.dialogBox, minWidth: '50%', maxWidth: '50%' },
|
||||
input: { ...theme.inputStyle, flex: 1 },
|
||||
dialogBox: Object.assign({}, theme.dialogBox, { minWidth: '50%', maxWidth: '50%' }),
|
||||
input: Object.assign({}, theme.inputStyle, { flex: 1 }),
|
||||
row: {
|
||||
overflow: 'hidden',
|
||||
height: itemHeight,
|
||||
@@ -148,7 +148,7 @@ class Dialog extends React.PureComponent<Props, State> {
|
||||
borderBottomColor: theme.dividerColor,
|
||||
boxSizing: 'border-box',
|
||||
},
|
||||
help: { ...theme.textStyle, marginBottom: 10 },
|
||||
help: Object.assign({}, theme.textStyle, { marginBottom: 10 }),
|
||||
inputHelpWrapper: { display: 'flex', flexDirection: 'row', alignItems: 'center' },
|
||||
};
|
||||
|
||||
@@ -163,15 +163,19 @@ class Dialog extends React.PureComponent<Props, State> {
|
||||
userSelect: 'none',
|
||||
};
|
||||
|
||||
const rowTitleStyle = { ...rowTextStyle, fontSize: rowTextStyle.fontSize * 1.4,
|
||||
const rowTitleStyle = Object.assign({}, rowTextStyle, {
|
||||
fontSize: rowTextStyle.fontSize * 1.4,
|
||||
marginBottom: this.state.resultsInBody ? 6 : 4,
|
||||
color: theme.colorFaded };
|
||||
color: theme.colorFaded,
|
||||
});
|
||||
|
||||
const rowFragmentsStyle = { ...rowTextStyle, fontSize: rowTextStyle.fontSize * 1.2,
|
||||
const rowFragmentsStyle = Object.assign({}, rowTextStyle, {
|
||||
fontSize: rowTextStyle.fontSize * 1.2,
|
||||
marginBottom: this.state.resultsInBody ? 8 : 6,
|
||||
color: theme.colorFaded };
|
||||
color: theme.colorFaded,
|
||||
});
|
||||
|
||||
this.styles_[styleKey].rowSelected = { ...this.styles_[styleKey].row, backgroundColor: theme.selectedColor };
|
||||
this.styles_[styleKey].rowSelected = Object.assign({}, this.styles_[styleKey].row, { backgroundColor: theme.selectedColor });
|
||||
this.styles_[styleKey].rowPath = rowTextStyle;
|
||||
this.styles_[styleKey].rowTitle = rowTitleStyle;
|
||||
this.styles_[styleKey].rowFragments = rowFragmentsStyle;
|
||||
@@ -300,7 +304,7 @@ class Dialog extends React.PureComponent<Props, State> {
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
const row = results[i];
|
||||
const path = Folder.folderPathString(this.props.folders, row.parent_id);
|
||||
results[i] = { ...row, path: path ? path : '/' };
|
||||
results[i] = Object.assign({}, row, { path: path ? path : '/' });
|
||||
}
|
||||
} else { // Note TITLE or BODY
|
||||
listType = BaseModel.TYPE_NOTE;
|
||||
@@ -313,7 +317,7 @@ class Dialog extends React.PureComponent<Props, State> {
|
||||
for (let i = 0; i < results.length; i++) {
|
||||
const row = results[i];
|
||||
const path = Folder.folderPathString(this.props.folders, row.parent_id);
|
||||
results[i] = { ...row, path: path };
|
||||
results[i] = Object.assign({}, row, { path: path });
|
||||
}
|
||||
} else {
|
||||
const limit = 20;
|
||||
@@ -361,9 +365,9 @@ class Dialog extends React.PureComponent<Props, State> {
|
||||
|
||||
}
|
||||
|
||||
results[i] = { ...row, path, fragments };
|
||||
results[i] = Object.assign({}, row, { path, fragments });
|
||||
} else {
|
||||
results[i] = { ...row, path: path, fragments: '' };
|
||||
results[i] = Object.assign({}, row, { path: path, fragments: '' });
|
||||
}
|
||||
}
|
||||
|
||||
|
24
packages/app-desktop/rollup-main-html.config.js
Normal file
24
packages/app-desktop/rollup-main-html.config.js
Normal file
@@ -0,0 +1,24 @@
|
||||
const commonjs = require('@rollup/plugin-commonjs');
|
||||
const nodeResolve = require('@rollup/plugin-node-resolve');
|
||||
const pluginJson = require('@rollup/plugin-json');
|
||||
|
||||
module.exports = {
|
||||
input: 'main-html.js',
|
||||
output: {
|
||||
file: 'main-html.bundle.js',
|
||||
format: 'cjs',
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
pluginJson(),
|
||||
commonjs({
|
||||
dynamicRequireTargets: [
|
||||
'codemirror/mode/python/python',
|
||||
],
|
||||
}),
|
||||
],
|
||||
external: [
|
||||
'keytar',
|
||||
'fsevents',
|
||||
],
|
||||
};
|
16
packages/app-desktop/rollup-main.config.js
Normal file
16
packages/app-desktop/rollup-main.config.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const commonjs = require('@rollup/plugin-commonjs');
|
||||
const nodeResolve = require('@rollup/plugin-node-resolve');
|
||||
const pluginJson = require('@rollup/plugin-json');
|
||||
|
||||
module.exports = {
|
||||
input: 'main.source.js',
|
||||
output: {
|
||||
file: 'main.js',
|
||||
format: 'cjs',
|
||||
},
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
pluginJson(),
|
||||
commonjs(),
|
||||
],
|
||||
};
|
@@ -79,13 +79,9 @@ import org.apache.tools.ant.taskdefs.condition.Os
|
||||
*/
|
||||
|
||||
project.ext.react = [
|
||||
// 2023-05-09: This seems to be optional, but it's not. Without it, the app
|
||||
// will crash on certain devices with this error:
|
||||
//
|
||||
// > java.lang.UnsatisfiedLinkError: couldn't find DSO to load: libhermes.so"
|
||||
//
|
||||
// https://github.com/laurent22/joplin/issues/8144#issuecomment-1539629812
|
||||
enableHermes: true, // clean and rebuild if changing
|
||||
// 2023/05/07: Leave that to `false` for now because Hermes is rubbish at
|
||||
// reporting errors, which it makes it impossible to investigate crashes.
|
||||
enableHermes: false, // clean and rebuild if changing
|
||||
]
|
||||
|
||||
apply from: "../../node_modules/react-native/react.gradle"
|
||||
@@ -156,8 +152,8 @@ android {
|
||||
applicationId "net.cozic.joplin"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 2097715
|
||||
versionName "2.11.30"
|
||||
versionCode 2097695
|
||||
versionName "2.11.10"
|
||||
// ndk {
|
||||
// abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64"
|
||||
// }
|
||||
@@ -304,11 +300,8 @@ dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
|
||||
//noinspection GradleDynamicVersion
|
||||
// implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
implementation ("com.facebook.react:react-native") version {
|
||||
strictly "0.70.6" // pass in your react-native version
|
||||
}
|
||||
|
||||
implementation "com.facebook.react:react-native:+" // From node_modules
|
||||
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
|
||||
|
||||
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user