From c7a11f5cd267dd8703bba4edea5b4ad7f93950e3 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Fri, 13 Jan 2023 16:08:29 +0530 Subject: [PATCH 1/9] =?UTF-8?q?docs:=20release=20@excalidraw/excalidraw@0.?= =?UTF-8?q?14.0=20=20=F0=9F=8E=89=20(#6109)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/excalidraw/CHANGELOG.md | 162 ++++++++++++++++++++++++++- src/packages/excalidraw/package.json | 2 +- 2 files changed, 162 insertions(+), 2 deletions(-) diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index 85b1e114a..6bb3ea4bf 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -11,7 +11,7 @@ The change should be grouped under one of the below section and must contain PR Please add the latest change on the top under the correct section. --> -## Unreleased +## 0.14.0 (2023-01-13) ### Features @@ -36,6 +36,166 @@ Please add the latest change on the top under the correct section. - Merged `appState.currentItemStrokeSharpness` and `appState.currentItemLinearStrokeSharpness` into `appState.currentItemRoundness`. Renamed `changeSharpness` action to `changeRoundness`. Excalidraw element's `strokeSharpness` was changed to `roundness`. Check the PR for types and more details [#5553](https://github.com/excalidraw/excalidraw/pull/5553). +## Excalidraw Library + +**_This section lists the updates made to the excalidraw library and will not affect the integration._** + +### Features + +- Generic button export [#6092](https://github.com/excalidraw/excalidraw/pull/6092) + +- Scroll using PageUp and PageDown [#6038](https://github.com/excalidraw/excalidraw/pull/6038) + +- Support shrinking text containers to original height when text removed [#6025](https://github.com/excalidraw/excalidraw/pull/6025) + +- Move contextMenu into the component tree and control via appState [#6021](https://github.com/excalidraw/excalidraw/pull/6021) + +- Allow readonly actions to be used in viewMode [#5982](https://github.com/excalidraw/excalidraw/pull/5982) + +- Support labels for arrow 🔥 [#5723](https://github.com/excalidraw/excalidraw/pull/5723) + +- Don't add midpoint until dragged beyond a threshold [#5927](https://github.com/excalidraw/excalidraw/pull/5927) + +- Changed text copy/paste behaviour [#5786](https://github.com/excalidraw/excalidraw/pull/5786) + +- Reintroduce `x` shortcut for `freedraw` [#5840](https://github.com/excalidraw/excalidraw/pull/5840) + +- Tweak toolbar shortcuts & remove library shortcut [#5832](https://github.com/excalidraw/excalidraw/pull/5832) + +- Clean unused images only after 24hrs (local-only) [#5839](https://github.com/excalidraw/excalidraw/pull/5839) + +- Refetch errored/pending images on collab room init load [#5833](https://github.com/excalidraw/excalidraw/pull/5833) + +- Stop deleting whole line when no point select in line editor [#5676](https://github.com/excalidraw/excalidraw/pull/5676) + +- Editor redesign 🔥 [#5780](https://github.com/excalidraw/excalidraw/pull/5780) + +### Fixes + +- remove overflow hidden from button [#6110](https://github.com/excalidraw/excalidraw/pull/6110) + +- Mobile tools positioning [#6107](https://github.com/excalidraw/excalidraw/pull/6107) + +- Renamed folder MainMenu->main-menu and support rest props [#6103](https://github.com/excalidraw/excalidraw/pull/6103) + +- Use position absolute for mobile misc tools [#6099](https://github.com/excalidraw/excalidraw/pull/6099) + +- React.memo resolvers not accounting for all props [#6042](https://github.com/excalidraw/excalidraw/pull/6042) + +- Image horizontal flip fix + improved tests [#5799](https://github.com/excalidraw/excalidraw/pull/5799) + +- Png-exporting does not preserve angles correctly for flipped images [#6085](https://github.com/excalidraw/excalidraw/pull/6085) + +- Stale appState of MainMenu defaultItems rendered from Actions [#6074](https://github.com/excalidraw/excalidraw/pull/6074) + +- HelpDialog [#6072](https://github.com/excalidraw/excalidraw/pull/6072) + +- Show error message on collab save failure [#6063](https://github.com/excalidraw/excalidraw/pull/6063) + +- Remove ga from docker build [#6059](https://github.com/excalidraw/excalidraw/pull/6059) + +- Use displayName since name gets stripped off when uglifying/minifiyng in production [#6036](https://github.com/excalidraw/excalidraw/pull/6036) + +- Remove background from wysiwyg when editing arrow label [#6033](https://github.com/excalidraw/excalidraw/pull/6033) + +- Use canvas measureText to calculate width in measureText [#6030](https://github.com/excalidraw/excalidraw/pull/6030) + +- Restoring deleted bindings [#6029](https://github.com/excalidraw/excalidraw/pull/6029) + +- ColorPicker getColor [#5949](https://github.com/excalidraw/excalidraw/pull/5949) + +- Don't push whitespace to next line when exceeding max width during wrapping and make sure to use same width of text editor on DOM when measuring dimensions [#5996](https://github.com/excalidraw/excalidraw/pull/5996) + +- Showing `grabbing` cursor when holding `spacebar` [#6015](https://github.com/excalidraw/excalidraw/pull/6015) + +- Resize sometimes throwing on missing null-checks [#6013](https://github.com/excalidraw/excalidraw/pull/6013) + +- PWA not working after CRA@5 update [#6012](https://github.com/excalidraw/excalidraw/pull/6012) + +- Not properly restoring element stroke and bg colors [#6002](https://github.com/excalidraw/excalidraw/pull/6002) + +- Avatar outline on safari & center [#5997](https://github.com/excalidraw/excalidraw/pull/5997) + +- Chart pasting not working due to removing tab characters [#5987](https://github.com/excalidraw/excalidraw/pull/5987) + +- Apply the right type of roundness when pasting styles [#5979](https://github.com/excalidraw/excalidraw/pull/5979) + +- Remove editor onpaste handler [#5971](https://github.com/excalidraw/excalidraw/pull/5971) + +- Remove blank space [#5950](https://github.com/excalidraw/excalidraw/pull/5950) + +- Galego and Kurdî missing in languages plus two locale typos [#5954](https://github.com/excalidraw/excalidraw/pull/5954) + +- `ExcalidrawArrowElement` rather than `ExcalidrawArrowEleement` [#5955](https://github.com/excalidraw/excalidraw/pull/5955) + +- RenderFooter styling [#5962](https://github.com/excalidraw/excalidraw/pull/5962) + +- Repair element bindings on restore [#5956](https://github.com/excalidraw/excalidraw/pull/5956) + +- Don't allow whitespaces for bound text [#5939](https://github.com/excalidraw/excalidraw/pull/5939) + +- Bindings do not survive history serialization [#5942](https://github.com/excalidraw/excalidraw/pull/5942) + +- Dedupe boundElement ids when container duplicated with alt+drag [#5938](https://github.com/excalidraw/excalidraw/pull/5938) + +- Scale font correctly when using shift [#5935](https://github.com/excalidraw/excalidraw/pull/5935) + +- Always bind to container selected by user [#5880](https://github.com/excalidraw/excalidraw/pull/5880) + +- Fonts not rendered on init if `loadingdone` not fired [#5923](https://github.com/excalidraw/excalidraw/pull/5923) + +- Stop replacing `del` word with `Delete` [#5897](https://github.com/excalidraw/excalidraw/pull/5897) + +- Remove legacy React.render() from the editor [#5893](https://github.com/excalidraw/excalidraw/pull/5893) + +- Allow adding text via enter only for text containers [#5891](https://github.com/excalidraw/excalidraw/pull/5891) + +- Stop font `loadingdone` loop when rendering element SVGs [#5883](https://github.com/excalidraw/excalidraw/pull/5883) + +- Refresh text dimensions only after font load done [#5878](https://github.com/excalidraw/excalidraw/pull/5878) + +- Correctly paste contents parsed by `JSON.parse()` as text. [#5868](https://github.com/excalidraw/excalidraw/pull/5868) + +- SVG element attributes in icons.tsx [#5871](https://github.com/excalidraw/excalidraw/pull/5871) + +- Merge existing text with new when pasted [#5856](https://github.com/excalidraw/excalidraw/pull/5856) + +- Disable FAST_REFRESH to fix live reload [#5852](https://github.com/excalidraw/excalidraw/pull/5852) + +- Paste clipboard contents into unbound text elements [#5849](https://github.com/excalidraw/excalidraw/pull/5849) + +- Compute dimensions of container correctly when text pasted on container [#5845](https://github.com/excalidraw/excalidraw/pull/5845) + +- Line editor points rendering below elements [#5781](https://github.com/excalidraw/excalidraw/pull/5781) + +- Syncing 1-point lines to remote clients [#5677](https://github.com/excalidraw/excalidraw/pull/5677) + +- Incorrectly selecting linear elements on creation while tool-locked [#5785](https://github.com/excalidraw/excalidraw/pull/5785) + +- Corrected typo in toggle theme shortcut [#5813](https://github.com/excalidraw/excalidraw/pull/5813) + +- Hide canvas-modifying UI in view mode [#5815](https://github.com/excalidraw/excalidraw/pull/5815) + +- Fix vertical/horizntal centering icons [#5812](https://github.com/excalidraw/excalidraw/pull/5812) + +- Consistent use of ZOOM_STEP [#5801](https://github.com/excalidraw/excalidraw/pull/5801) + +- Multiple elements resizing regressions [#5586](https://github.com/excalidraw/excalidraw/pull/5586) + +- Changelog typo [#5795](https://github.com/excalidraw/excalidraw/pull/5795) + +### Refactor + +- Remove unnecessary code [#5933](https://github.com/excalidraw/excalidraw/pull/5933) + +### Build + +- Move release scripts to use release branch [#5958](https://github.com/excalidraw/excalidraw/pull/5958) + +- Stops ignoring .env files from docker context so env variables get set during react app build. [#5809](https://github.com/excalidraw/excalidraw/pull/5809) + +--- + ## 0.13.0 (2022-10-27) ### Excalidraw API diff --git a/src/packages/excalidraw/package.json b/src/packages/excalidraw/package.json index b830dc619..2858333df 100644 --- a/src/packages/excalidraw/package.json +++ b/src/packages/excalidraw/package.json @@ -1,6 +1,6 @@ { "name": "@excalidraw/excalidraw", - "version": "0.13.0", + "version": "0.14.0", "main": "main.js", "types": "types/packages/excalidraw/index.d.ts", "files": [ From d6a5ef19367c366ea9dc15d1f17569d829163828 Mon Sep 17 00:00:00 2001 From: Aakansha Doshi Date: Mon, 16 Jan 2023 16:08:03 +0530 Subject: [PATCH 2/9] =?UTF-8?q?docs:=20release=20@excalidraw/excalidraw@0.?= =?UTF-8?q?14.1=20=F0=9F=8E=89=20(#6112)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/excalidraw/CHANGELOG.md | 8 ++++++-- src/packages/excalidraw/package.json | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/packages/excalidraw/CHANGELOG.md b/src/packages/excalidraw/CHANGELOG.md index 6bb3ea4bf..1dd0e0be4 100644 --- a/src/packages/excalidraw/CHANGELOG.md +++ b/src/packages/excalidraw/CHANGELOG.md @@ -11,6 +11,12 @@ The change should be grouped under one of the below section and must contain PR Please add the latest change on the top under the correct section. --> +## 0.14.1 (2023-01-16) + +### Fixes + +- remove overflow hidden from button [#6110](https://github.com/excalidraw/excalidraw/pull/6110). This fixes the collaborator count css in the [LiveCollaborationTrigger](https://github.com/excalidraw/excalidraw/blob/master/src/packages/excalidraw/README.md#LiveCollaborationTrigger) component. + ## 0.14.0 (2023-01-13) ### Features @@ -72,8 +78,6 @@ Please add the latest change on the top under the correct section. ### Fixes -- remove overflow hidden from button [#6110](https://github.com/excalidraw/excalidraw/pull/6110) - - Mobile tools positioning [#6107](https://github.com/excalidraw/excalidraw/pull/6107) - Renamed folder MainMenu->main-menu and support rest props [#6103](https://github.com/excalidraw/excalidraw/pull/6103) diff --git a/src/packages/excalidraw/package.json b/src/packages/excalidraw/package.json index 2858333df..27c2e0446 100644 --- a/src/packages/excalidraw/package.json +++ b/src/packages/excalidraw/package.json @@ -1,6 +1,6 @@ { "name": "@excalidraw/excalidraw", - "version": "0.14.0", + "version": "0.14.1", "main": "main.js", "types": "types/packages/excalidraw/index.d.ts", "files": [ From d0b33d35db37f695f3962ac463c10c1c7fbe1a9c Mon Sep 17 00:00:00 2001 From: David Luzar Date: Thu, 19 Jan 2023 13:50:42 +0100 Subject: [PATCH 3/9] build: temporarily disable pre-commit (#6132) --- .husky/pre-commit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.husky/pre-commit b/.husky/pre-commit index 521508d8e..ab2a5ac5f 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,2 +1,2 @@ #!/bin/sh -yarn lint-staged +# yarn lint-staged From 0f1720be618ecfc180425ad2de98551c51b14a88 Mon Sep 17 00:00:00 2001 From: Excalidraw Bot <77840495+excalibot@users.noreply.github.com> Date: Sun, 22 Jan 2023 12:19:21 +0100 Subject: [PATCH 4/9] chore: Update translations from Crowdin (#6077) --- src/locales/ar-SA.json | 26 +++++++++++-------- src/locales/bg-BG.json | 16 ++++++++---- src/locales/bn-BD.json | 16 ++++++++---- src/locales/ca-ES.json | 16 ++++++++---- src/locales/cs-CZ.json | 16 ++++++++---- src/locales/da-DK.json | 16 ++++++++---- src/locales/de-DE.json | 28 ++++++++++++--------- src/locales/el-GR.json | 44 +++++++++++++++++++-------------- src/locales/es-ES.json | 16 ++++++++---- src/locales/eu-ES.json | 30 +++++++++++++--------- src/locales/fa-IR.json | 16 ++++++++---- src/locales/fi-FI.json | 16 ++++++++---- src/locales/fr-FR.json | 16 ++++++++---- src/locales/gl-ES.json | 20 +++++++++------ src/locales/he-IL.json | 16 ++++++++---- src/locales/hi-IN.json | 16 ++++++++---- src/locales/hu-HU.json | 16 ++++++++---- src/locales/id-ID.json | 20 +++++++++------ src/locales/it-IT.json | 20 +++++++++------ src/locales/ja-JP.json | 16 ++++++++---- src/locales/kab-KAB.json | 22 +++++++++++------ src/locales/kk-KZ.json | 16 ++++++++---- src/locales/ko-KR.json | 40 +++++++++++++++++------------- src/locales/ku-TR.json | 16 ++++++++---- src/locales/lt-LT.json | 16 ++++++++---- src/locales/lv-LV.json | 16 ++++++++---- src/locales/mr-IN.json | 16 ++++++++---- src/locales/my-MM.json | 16 ++++++++---- src/locales/nb-NO.json | 16 ++++++++---- src/locales/nl-NL.json | 18 +++++++++----- src/locales/nn-NO.json | 16 ++++++++---- src/locales/oc-FR.json | 16 ++++++++---- src/locales/pa-IN.json | 16 ++++++++---- src/locales/percentages.json | 48 ++++++++++++++++++------------------ src/locales/pl-PL.json | 16 ++++++++---- src/locales/pt-BR.json | 16 ++++++++---- src/locales/pt-PT.json | 30 +++++++++++++--------- src/locales/ro-RO.json | 16 ++++++++---- src/locales/ru-RU.json | 16 ++++++++---- src/locales/si-LK.json | 16 ++++++++---- src/locales/sk-SK.json | 20 +++++++++------ src/locales/sl-SI.json | 16 ++++++++---- src/locales/sv-SE.json | 16 ++++++++---- src/locales/ta-IN.json | 16 ++++++++---- src/locales/tr-TR.json | 26 +++++++++++-------- src/locales/uk-UA.json | 16 ++++++++---- src/locales/vi-VN.json | 16 ++++++++---- src/locales/zh-CN.json | 16 ++++++++---- src/locales/zh-HK.json | 16 ++++++++---- src/locales/zh-TW.json | 16 ++++++++---- 50 files changed, 631 insertions(+), 337 deletions(-) diff --git a/src/locales/ar-SA.json b/src/locales/ar-SA.json index 938db0977..8594200c0 100644 --- a/src/locales/ar-SA.json +++ b/src/locales/ar-SA.json @@ -1,7 +1,7 @@ { "labels": { "paste": "لصق", - "pasteAsPlaintext": "", + "pasteAsPlaintext": "اللصق كنص عادي", "pasteCharts": "لصق الرسوم البيانية", "selectAll": "تحديد الكل", "multiSelect": "إضافة عنصر للتحديد", @@ -66,13 +66,13 @@ "cartoonist": "كرتوني", "fileTitle": "إسم الملف", "colorPicker": "منتقي اللون", - "canvasColors": "", + "canvasColors": "تستخدم على القماش", "canvasBackground": "خلفية اللوحة", "drawingCanvas": "لوحة الرسم", "layers": "الطبقات", "actions": "الإجراءات", "language": "اللغة", - "liveCollaboration": "", + "liveCollaboration": "التعاون المباشر...", "duplicateSelection": "تكرار", "untitled": "غير معنون", "name": "الاسم", @@ -108,7 +108,7 @@ "excalidrawLib": "مكتبتنا", "decreaseFontSize": "تصغير حجم الخط", "increaseFontSize": "تكبير حجم الخط", - "unbindText": "", + "unbindText": "فك ربط النص", "bindText": "", "link": { "edit": "تعديل الرابط", @@ -145,7 +145,7 @@ "scale": "مقاس", "save": "احفظ للملف الحالي", "saveAs": "حفظ كـ", - "load": "", + "load": "فتح", "getShareableLink": "احصل على رابط المشاركة", "close": "غلق", "selectLanguage": "اختر اللغة", @@ -447,10 +447,16 @@ "d9480f": "برتقالي 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/bg-BG.json b/src/locales/bg-BG.json index ef2710b41..06f45a9a7 100644 --- a/src/locales/bg-BG.json +++ b/src/locales/bg-BG.json @@ -447,10 +447,16 @@ "d9480f": "" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/bn-BD.json b/src/locales/bn-BD.json index 6dbaa9967..2bac711c1 100644 --- a/src/locales/bn-BD.json +++ b/src/locales/bn-BD.json @@ -447,10 +447,16 @@ "d9480f": "" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/ca-ES.json b/src/locales/ca-ES.json index ef6e33502..e529383b6 100644 --- a/src/locales/ca-ES.json +++ b/src/locales/ca-ES.json @@ -447,10 +447,16 @@ "d9480f": "Taronja 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/cs-CZ.json b/src/locales/cs-CZ.json index aa801607a..7dddb1116 100644 --- a/src/locales/cs-CZ.json +++ b/src/locales/cs-CZ.json @@ -447,10 +447,16 @@ "d9480f": "Oranzova" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/da-DK.json b/src/locales/da-DK.json index 8f3cde90f..6f3876dcf 100644 --- a/src/locales/da-DK.json +++ b/src/locales/da-DK.json @@ -447,10 +447,16 @@ "d9480f": "" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/de-DE.json b/src/locales/de-DE.json index e1c66ac48..f5dd739d1 100644 --- a/src/locales/de-DE.json +++ b/src/locales/de-DE.json @@ -99,14 +99,14 @@ "flipHorizontal": "Horizontal spiegeln", "flipVertical": "Vertikal spiegeln", "viewMode": "Ansichtsmodus", - "toggleExportColorScheme": "Exportfarbschema umschalten", + "toggleExportColorScheme": "Farbschema für Export umschalten", "share": "Teilen", "showStroke": "Auswahl für Strichfarbe anzeigen", "showBackground": "Hintergrundfarbe auswählen", - "toggleTheme": "Thema umschalten", + "toggleTheme": "Design umschalten", "personalLib": "Persönliche Bibliothek", - "excalidrawLib": "Excalidraw-Bibliothek", - "decreaseFontSize": "Schrift verkleinern", + "excalidrawLib": "Excalidraw Bibliothek", + "decreaseFontSize": "Schriftgröße verkleinern", "increaseFontSize": "Schrift vergrößern", "unbindText": "Text lösen", "bindText": "Text an Container binden", @@ -161,8 +161,8 @@ "resetLibrary": "Bibliothek zurücksetzen", "createNewRoom": "Neuen Raum erstellen", "fullScreen": "Vollbildanzeige", - "darkMode": "Dunkler Modus", - "lightMode": "Heller Modus", + "darkMode": "Dunkles Design", + "lightMode": "Helles Design", "zenMode": "Zen-Modus", "exitZenMode": "Zen-Modus verlassen", "cancel": "Abbrechen", @@ -447,10 +447,16 @@ "d9480f": "Orange 9" }, "welcomeScreen": { - "data": "Alle Daten werden lokal in Deinem Browser gespeichert.", - "switchToPlusApp": "Möchtest du stattdessen zu Excalidraw+ gehen?", - "menuHints": "Exportieren, Einstellungen, Sprachen, ...", - "toolbarHints": "Wähle ein Werkzeug & beginne zu zeichnen!", - "helpHints": "Kurzbefehle & Hilfe" + "app": { + "center_heading": "Alle Daten werden lokal in Deinem Browser gespeichert.", + "center_heading_plus": "Möchtest du stattdessen zu Excalidraw+ gehen?", + "menuHint": "Exportieren, Einstellungen, Sprachen, ..." + }, + "defaults": { + "menuHint": "Exportieren, Einstellungen und mehr...", + "center_heading": "Diagramme. Einfach. Gemacht.", + "toolbarHint": "Wähle ein Werkzeug & beginne zu zeichnen!", + "helpHint": "Kurzbefehle & Hilfe" + } } } diff --git a/src/locales/el-GR.json b/src/locales/el-GR.json index 0ad867f00..a603bd18f 100644 --- a/src/locales/el-GR.json +++ b/src/locales/el-GR.json @@ -1,7 +1,7 @@ { "labels": { "paste": "Επικόλληση", - "pasteAsPlaintext": "", + "pasteAsPlaintext": "Επικόλληση ως απλό κείμενο", "pasteCharts": "Επικόλληση γραφημάτων", "selectAll": "Επιλογή όλων", "multiSelect": "Προσθέστε το στοιχείο στην επιλογή", @@ -72,7 +72,7 @@ "layers": "Στρώματα", "actions": "Ενέργειες", "language": "Γλώσσα", - "liveCollaboration": "", + "liveCollaboration": "Live συνεργασία...", "duplicateSelection": "Δημιουργία αντιγράφου", "untitled": "Χωρίς τίτλο", "name": "Όνομα", @@ -116,8 +116,8 @@ "label": "Σύνδεσμος" }, "lineEditor": { - "edit": "", - "exit": "" + "edit": "Επεξεργασία γραμμής", + "exit": "Έξοδος επεξεργαστή κειμένου" }, "elementLock": { "lock": "Κλείδωμα", @@ -136,8 +136,8 @@ "buttons": { "clearReset": "Επαναφορά του καμβά", "exportJSON": "Εξαγωγή σε αρχείο", - "exportImage": "", - "export": "", + "exportImage": "Εξαγωγή εικόνας...", + "export": "Αποθήκευση ως...", "exportToPng": "Εξαγωγή σε PNG", "exportToSvg": "Εξαγωγή σε SVG", "copyToClipboard": "Αντιγραφή στο πρόχειρο", @@ -145,7 +145,7 @@ "scale": "Κλίμακα", "save": "Αποθήκευση στο τρέχον αρχείο", "saveAs": "Αποθήκευση ως", - "load": "", + "load": "Άνοιγμα", "getShareableLink": "Δημόσιος σύνδεσμος", "close": "Κλείσιμο", "selectLanguage": "Επιλογή γλώσσας", @@ -202,8 +202,8 @@ "invalidSVGString": "Μη έγκυρο SVG.", "cannotResolveCollabServer": "Αδυναμία σύνδεσης με τον διακομιστή συνεργασίας. Παρακαλώ ανανεώστε τη σελίδα και προσπαθήστε ξανά.", "importLibraryError": "Αδυναμία φόρτωσης βιβλιοθήκης", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "Η αποθήκευση στη βάση δεδομένων δεν ήταν δυνατή. Αν το προβλήματα παραμείνει, θα πρέπει να αποθηκεύσετε το αρχείο σας τοπικά για να βεβαιωθείτε ότι δεν χάνετε την εργασία σας.", + "collabSaveFailed_sizeExceeded": "Η αποθήκευση στη βάση δεδομένων δεν ήταν δυνατή, ο καμβάς φαίνεται να είναι πολύ μεγάλος. Θα πρέπει να αποθηκεύσετε το αρχείο τοπικά για να βεβαιωθείτε ότι δεν θα χάσετε την εργασία σας." }, "toolBar": { "selection": "Επιλογή", @@ -217,7 +217,7 @@ "text": "Κείμενο", "library": "Βιβλιοθήκη", "lock": "Κράτησε επιλεγμένο το εργαλείο μετά το σχέδιο", - "penMode": "", + "penMode": "Λειτουργία μολυβιού - αποτροπή αφής", "link": "Προσθήκη/ Ενημέρωση συνδέσμου για ένα επιλεγμένο σχήμα", "eraser": "Γόμα" }, @@ -238,7 +238,7 @@ "resize": "Μπορείς να περιορίσεις τις αναλογίες κρατώντας το SHIFT ενώ αλλάζεις μέγεθος,\nκράτησε πατημένο το ALT για αλλαγή μεγέθους από το κέντρο", "resizeImage": "Μπορείτε να αλλάξετε το μέγεθος ελεύθερα κρατώντας πατημένο το SHIFT,\nκρατήστε πατημένο το ALT για να αλλάξετε το μέγεθος από το κέντρο", "rotate": "Μπορείς να περιορίσεις τις γωνίες κρατώντας πατημένο το πλήκτρο SHIFT κατά την περιστροφή", - "lineEditor_info": "", + "lineEditor_info": "Κρατήστε πατημένο Ctrl ή Cmd και πατήστε το πλήκτρο Ctrl ή Cmd + Enter για επεξεργασία σημείων", "lineEditor_pointSelected": "Πατήστε Διαγραφή για αφαίρεση σημείου(ων),\nCtrlOrCmd+D για αντιγραφή, ή σύρετε για μετακίνηση", "lineEditor_nothingSelected": "Επιλέξτε ένα σημείο για να επεξεργαστείτε (κρατήστε πατημένο το SHIFT για να επιλέξετε πολλαπλά),\nή κρατήστε πατημένο το Alt και κάντε κλικ για να προσθέσετε νέα σημεία", "placeImage": "Κάντε κλικ για να τοποθετήσετε την εικόνα ή κάντε κλικ και σύρετε για να ορίσετε το μέγεθός της χειροκίνητα", @@ -314,8 +314,8 @@ "zoomToFit": "Zoom ώστε να χωρέσουν όλα τα στοιχεία", "zoomToSelection": "Ζουμ στην επιλογή", "toggleElementLock": "Κλείδωμα/Ξεκλείδωμα επιλογής", - "movePageUpDown": "", - "movePageLeftRight": "" + "movePageUpDown": "Μετακίνηση σελίδας πάνω/κάτω", + "movePageLeftRight": "Μετακίνηση σελίδας αριστερά/δεξιά" }, "clearCanvasDialog": { "title": "Καθαρισμός καμβά" @@ -397,7 +397,7 @@ "fileSavedToFilename": "Αποθηκεύτηκε στο {filename}", "canvas": "καμβάς", "selection": "επιλογή", - "pasteAsSingleElement": "" + "pasteAsSingleElement": "Χρησιμοποίησε το {{shortcut}} για να επικολλήσεις ως ένα μόνο στοιχείο,\nή να επικολλήσεις σε έναν υπάρχοντα επεξεργαστή κειμένου" }, "colors": { "ffffff": "Λευκό", @@ -447,10 +447,16 @@ "d9480f": "Πορτοκαλί 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "Όλα τα δεδομένα σας αποθηκεύονται τοπικά στο πρόγραμμα περιήγησης.", + "center_heading_plus": "Μήπως θέλατε να πάτε στο Excalidraw+;", + "menuHint": "Εξαγωγή, προτιμήσεις, γλώσσες, ..." + }, + "defaults": { + "menuHint": "Εξαγωγή, προτιμήσεις και άλλες επιλογές...", + "center_heading": "Διαγράμματα. Εύκολα. Γρήγορα.", + "toolbarHint": "Επιλέξτε ένα εργαλείο και ξεκινήστε να σχεδιάζεται!", + "helpHint": "Συντομεύσεις και βοήθεια" + } } } diff --git a/src/locales/es-ES.json b/src/locales/es-ES.json index de2d76a98..81fa8efbb 100644 --- a/src/locales/es-ES.json +++ b/src/locales/es-ES.json @@ -447,10 +447,16 @@ "d9480f": "Naranja 9" }, "welcomeScreen": { - "data": "Toda su información es guardada localmente en su navegador.", - "switchToPlusApp": "¿Quieres ir a Excalidraw+ en su lugar?", - "menuHints": "Exportar, preferencias, idiomas, ...", - "toolbarHints": "¡Escoge una herramienta & Empiece a dibujar!", - "helpHints": "Atajos & ayuda" + "app": { + "center_heading": "Toda su información es guardada localmente en su navegador.", + "center_heading_plus": "¿Quieres ir a Excalidraw+?", + "menuHint": "Exportar, preferencias, idiomas, ..." + }, + "defaults": { + "menuHint": "Exportar, preferencias y más...", + "center_heading": "Diagramas. Hecho. Simplemente.", + "toolbarHint": "¡Elige una herramienta y empieza a dibujar!", + "helpHint": "Atajos & ayuda" + } } } diff --git a/src/locales/eu-ES.json b/src/locales/eu-ES.json index 00e45209e..c606112cc 100644 --- a/src/locales/eu-ES.json +++ b/src/locales/eu-ES.json @@ -1,7 +1,7 @@ { "labels": { "paste": "Itsatsi", - "pasteAsPlaintext": "", + "pasteAsPlaintext": "Itsatsi testu arrunt gisa", "pasteCharts": "Itsatsi grafikoak", "selectAll": "Hautatu dena", "multiSelect": "Gehitu elementua hautapenera", @@ -202,8 +202,8 @@ "invalidSVGString": "SVG baliogabea.", "cannotResolveCollabServer": "Ezin izan da elkarlaneko zerbitzarira konektatu. Mesedez, berriro kargatu orria eta saiatu berriro.", "importLibraryError": "Ezin izan da liburutegia kargatu", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "Ezin izan da backend datu-basean gorde. Arazoak jarraitzen badu, zure fitxategia lokalean gorde beharko zenuke zure lana ez duzula galtzen ziurtatzeko.", + "collabSaveFailed_sizeExceeded": "Ezin izan da backend datu-basean gorde, ohiala handiegia dela dirudi. Fitxategia lokalean gorde beharko zenuke zure lana galtzen ez duzula ziurtatzeko." }, "toolBar": { "selection": "Hautapena", @@ -238,7 +238,7 @@ "resize": "Proportzioak mantendu ditzakezu SHIFT sakatuta tamaina aldatzen duzun bitartean.\nsakatu ALT erditik tamaina aldatzeko", "resizeImage": "Tamaina libreki alda dezakezu SHIFT sakatuta,\nsakatu ALT erditik tamaina aldatzeko", "rotate": "Angeluak mantendu ditzakezu SHIFT sakatuta biratzen duzun bitartean", - "lineEditor_info": "", + "lineEditor_info": "Eutsi sakatuta Ctrl edo Cmd eta egin klik bikoitza edo sakatu Ctrl edo Cmd + Sartu puntuak editatzeko", "lineEditor_pointSelected": "Sakatu Ezabatu puntuak kentzeko,\nKtrl+D bikoizteko, edo arrastatu mugitzeko", "lineEditor_nothingSelected": "Hautatu editatzeko puntu bat (SHIFT sakatuta anitz hautatzeko),\nedo eduki Alt sakatuta eta egin klik puntu berriak gehitzeko", "placeImage": "Egin klik irudia kokatzeko, edo egin klik eta arrastatu bere tamaina eskuz ezartzeko", @@ -314,8 +314,8 @@ "zoomToFit": "Egin zoom elementu guztiak ikusteko", "zoomToSelection": "Zooma hautapenera", "toggleElementLock": "Blokeatu/desbloketatu hautapena", - "movePageUpDown": "", - "movePageLeftRight": "" + "movePageUpDown": "Mugitu orria gora/behera", + "movePageLeftRight": "Mugitu orria ezker/eskuin" }, "clearCanvasDialog": { "title": "Garbitu oihala" @@ -397,7 +397,7 @@ "fileSavedToFilename": "{filename}-n gorde da", "canvas": "oihala", "selection": "hautapena", - "pasteAsSingleElement": "" + "pasteAsSingleElement": "Erabili {{shortcut}} elementu bakar gisa itsasteko,\nedo itsatsi lehendik dagoen testu-editore batean" }, "colors": { "ffffff": "Zuria", @@ -447,10 +447,16 @@ "d9480f": "Laranja 9" }, "welcomeScreen": { - "data": "Zure datu guztiak modu lokalean gordetzen dira zure nabigatzailean.", - "switchToPlusApp": "Horren ordez Excalidraw+-ra joan nahi al zenuen?", - "menuHints": "Esportatu, hobespenak, hizkuntzak,...", - "toolbarHints": "Aukeratu tresna bat eta hasi marrazten!", - "helpHints": "Lasterbideak eta laguntza" + "app": { + "center_heading": "Zure datu guztiak lokalean gordetzen dira zure nabigatzailean.", + "center_heading_plus": "Horren ordez Excalidraw+-era joan nahi al zenuen?", + "menuHint": "Esportatu, hobespenak, hizkuntzak..." + }, + "defaults": { + "menuHint": "Esportatu, hobespenak eta gehiago...", + "center_heading": "Diagramak. Egina. Sinplea.", + "toolbarHint": "Aukeratu tresna bat eta hasi marrazten!", + "helpHint": "Lasterbideak eta laguntza" + } } } diff --git a/src/locales/fa-IR.json b/src/locales/fa-IR.json index 03974771a..6d47df998 100644 --- a/src/locales/fa-IR.json +++ b/src/locales/fa-IR.json @@ -447,10 +447,16 @@ "d9480f": "نارنجی 9" }, "welcomeScreen": { - "data": "همه ی داده های شما به صورت محلی در مرورگر ذخیره میشود.", - "switchToPlusApp": "آیا ترجیح میدهید به Excalidraw+ بروید؟", - "menuHints": "خروجی گرفتن، تنظیمات، زبانها، ...", - "toolbarHints": "یک ابزار را انتخاب کنید و ترسیم را شروع کنید!", - "helpHints": "میانبرها و کمک" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/fi-FI.json b/src/locales/fi-FI.json index ba072d4fd..1f934d87b 100644 --- a/src/locales/fi-FI.json +++ b/src/locales/fi-FI.json @@ -447,10 +447,16 @@ "d9480f": "Oranssi 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/fr-FR.json b/src/locales/fr-FR.json index df733033d..2d107b5d3 100644 --- a/src/locales/fr-FR.json +++ b/src/locales/fr-FR.json @@ -447,10 +447,16 @@ "d9480f": "Orange 9" }, "welcomeScreen": { - "data": "Toutes vos données sont sauvegardées en local dans votre navigateur.", - "switchToPlusApp": "Vous vouliez plutôt aller à Excalidraw+ ?", - "menuHints": "Exportation, préférences, langues, ...", - "toolbarHints": "Choisissez un outil et commencez à dessiner !", - "helpHints": "Raccourcis et aide" + "app": { + "center_heading": "Toutes vos données sont sauvegardées en local dans votre navigateur.", + "center_heading_plus": "Vouliez-vous plutôt aller à Excalidraw+ à la place ?", + "menuHint": "Exportation, préférences, langues, ..." + }, + "defaults": { + "menuHint": "Exportation, préférences et plus...", + "center_heading": "Diagrammes. Rendus. Simples.", + "toolbarHint": "Choisissez un outil et commencez à dessiner !", + "helpHint": "Raccourcis et aide" + } } } diff --git a/src/locales/gl-ES.json b/src/locales/gl-ES.json index f843c7089..677975018 100644 --- a/src/locales/gl-ES.json +++ b/src/locales/gl-ES.json @@ -202,8 +202,8 @@ "invalidSVGString": "SVG inválido.", "cannotResolveCollabServer": "Non se puido conectar ao servidor de colaboración. Por favor recargue a páxina e probe de novo.", "importLibraryError": "Non se puido cargar a biblioteca", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "Non se puido gardar na base de datos. Se o problema persiste, deberías gardar o teu arquivo de maneira local para asegurarte de non perdelo teu traballo.", + "collabSaveFailed_sizeExceeded": "Non se puido gardar na base de datos, o lenzo semella demasiado grande. Deberías gardar o teu arquivo de maneira local para asegurarte de non perdelo teu traballo." }, "toolBar": { "selection": "Selección", @@ -447,10 +447,16 @@ "d9480f": "Laranxa 9" }, "welcomeScreen": { - "data": "Toda a información é gardada de maneira local no seu navegador.", - "switchToPlusApp": "Queres ir a Excalidraw+ no seu lugar?", - "menuHints": "Exportar, preferencias, idiomas, ...", - "toolbarHints": "Escolle unha ferramenta & Comeza a debuxar!", - "helpHints": "Atallos & axuda" + "app": { + "center_heading": "Toda a información é gardada de maneira local no seu navegador.", + "center_heading_plus": "Queres ir a Excalidraw+ no seu lugar?", + "menuHint": "Exportar, preferencias, idiomas, ..." + }, + "defaults": { + "menuHint": "Exportar, preferencias, e máis...", + "center_heading": "Diagramas. Feito. Sinxelo.", + "toolbarHint": "Escolle unha ferramenta & Comeza a debuxar!", + "helpHint": "Atallos & axuda" + } } } diff --git a/src/locales/he-IL.json b/src/locales/he-IL.json index 24d1db079..ba81af3ca 100644 --- a/src/locales/he-IL.json +++ b/src/locales/he-IL.json @@ -447,10 +447,16 @@ "d9480f": "כתום 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/hi-IN.json b/src/locales/hi-IN.json index 56fac78d8..b70c0d255 100644 --- a/src/locales/hi-IN.json +++ b/src/locales/hi-IN.json @@ -447,10 +447,16 @@ "d9480f": "नारंगी" }, "welcomeScreen": { - "data": "आपका सर्व डेटा ब्राउज़र के भीतर स्थानिक जगह पे सुरक्षित किया गया.", - "switchToPlusApp": "बजाय आपको Excalidraw+ जगह जाना है?", - "menuHints": "निर्यात, पसंद, भाषायें, ...", - "toolbarHints": "औजार चुने और चित्रकारी प्रारंभ करे!", - "helpHints": "शॉर्ट्कट & सहाय्य" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/hu-HU.json b/src/locales/hu-HU.json index 8938fe37e..84dc9f61c 100644 --- a/src/locales/hu-HU.json +++ b/src/locales/hu-HU.json @@ -447,10 +447,16 @@ "d9480f": "Narancs 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/id-ID.json b/src/locales/id-ID.json index 68d06d466..7804af62e 100644 --- a/src/locales/id-ID.json +++ b/src/locales/id-ID.json @@ -202,8 +202,8 @@ "invalidSVGString": "SVG tidak valid.", "cannotResolveCollabServer": "Tidak dapat terhubung ke server kolab. Muat ulang laman dan coba lagi.", "importLibraryError": "Tidak dapat memuat pustaka", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "Tidak dapat menyimpan ke dalam basis data server. Jika masih berlanjut, Anda sebaiknya simpan berkas Anda secara lokal untuk memastikan pekerjaan Anda tidak hilang.", + "collabSaveFailed_sizeExceeded": "Tidak dapat menyimpan ke dalam basis data server, tampaknya ukuran kanvas terlalu besar. Anda sebaiknya simpan berkas Anda secara lokal untuk memastikan pekerjaan Anda tidak hilang." }, "toolBar": { "selection": "Pilihan", @@ -447,10 +447,16 @@ "d9480f": "Jingga 9" }, "welcomeScreen": { - "data": "Semua data Anda tersimpan secara lokal di browser.", - "switchToPlusApp": "Apa Anda ingin berpindah ke Excalidraw+?", - "menuHints": "Ekspor, preferensi, bahasa, ...", - "toolbarHints": "Ambil alat & mulai menggambar!", - "helpHints": "Pintasan & bantuan" + "app": { + "center_heading": "Semua data Anda disimpan secara lokal di peramban Anda.", + "center_heading_plus": "Apa Anda ingin berpindah ke Excalidraw+?", + "menuHint": "Ekspor, preferensi, bahasa, ..." + }, + "defaults": { + "menuHint": "Ekspor, preferensi, dan selebihnya...", + "center_heading": "Diagram. Menjadi. Mudah.", + "toolbarHint": "Pilih alat & mulai menggambar!", + "helpHint": "Pintasan & bantuan" + } } } diff --git a/src/locales/it-IT.json b/src/locales/it-IT.json index 5f57b042e..9ef1fba53 100644 --- a/src/locales/it-IT.json +++ b/src/locales/it-IT.json @@ -202,8 +202,8 @@ "invalidSVGString": "SVG non valido.", "cannotResolveCollabServer": "Impossibile connettersi al server di collab. Ricarica la pagina e riprova.", "importLibraryError": "Impossibile caricare la libreria", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "Impossibile salvare nel database di backend. Se i problemi persistono, dovresti salvare il tuo file localmente per assicurarti di non perdere il tuo lavoro.", + "collabSaveFailed_sizeExceeded": "Impossibile salvare nel database di backend, la tela sembra essere troppo grande. Dovresti salvare il file localmente per assicurarti di non perdere il tuo lavoro." }, "toolBar": { "selection": "Selezione", @@ -447,10 +447,16 @@ "d9480f": "Arancio 9" }, "welcomeScreen": { - "data": "Tutti i tuoi dati sono salvati localmente nel browser.", - "switchToPlusApp": "Volevi invece andare su Excalidraw+?", - "menuHints": "Esporta, preferenze, lingue, ...", - "toolbarHints": "Scegli uno strumento & Inizia a disegnare!", - "helpHints": "Scorciatoie & aiuto" + "app": { + "center_heading": "Tutti i tuoi dati sono salvati localmente nel browser.", + "center_heading_plus": "Volevi invece andare su Excalidraw+?", + "menuHint": "Esporta, preferenze, lingue, ..." + }, + "defaults": { + "menuHint": "Esporta, preferenze, e altro...", + "center_heading": "Diagrammi. Fatto. Semplice.", + "toolbarHint": "Scegli uno strumento & Inizia a disegnare!", + "helpHint": "Scorciatoie & aiuto" + } } } diff --git a/src/locales/ja-JP.json b/src/locales/ja-JP.json index e40b15ba0..2ab2cb475 100644 --- a/src/locales/ja-JP.json +++ b/src/locales/ja-JP.json @@ -447,10 +447,16 @@ "d9480f": "オレンジ 9" }, "welcomeScreen": { - "data": "すべてのデータはブラウザにローカル保存されます。", - "switchToPlusApp": "代わりにExcalidraw+を開きますか?", - "menuHints": "エクスポート, 設定, 言語, ...", - "toolbarHints": "ツールを選んで描き始めよう!", - "helpHints": "ショートカットとヘルプ" + "app": { + "center_heading": "すべてのデータはブラウザにローカル保存されます。", + "center_heading_plus": "代わりにExcalidraw+を開きますか?", + "menuHint": "エクスポート、設定、言語..." + }, + "defaults": { + "menuHint": "エクスポート、設定、その他...", + "center_heading": "ダイアグラムを簡単に。", + "toolbarHint": "ツールを選んで描き始めよう!", + "helpHint": "ショートカットとヘルプ" + } } } diff --git a/src/locales/kab-KAB.json b/src/locales/kab-KAB.json index f2763b0f9..2818794e6 100644 --- a/src/locales/kab-KAB.json +++ b/src/locales/kab-KAB.json @@ -72,7 +72,7 @@ "layers": "Tissiyin", "actions": "Tigawin", "language": "Tutlayt", - "liveCollaboration": "", + "liveCollaboration": "Amɛiwen s srid...", "duplicateSelection": "Sisleg", "untitled": "War azwel", "name": "Isem", @@ -314,8 +314,8 @@ "zoomToFit": "Simɣur akken ad twliḍ akk iferdisen", "zoomToSelection": "Simɣur ɣer tefrayt", "toggleElementLock": "Sekkeṛ/kkes asekker i tefrayt", - "movePageUpDown": "", - "movePageLeftRight": "" + "movePageUpDown": "Smutti asebter d asawen/akessar", + "movePageLeftRight": "Smutti asebter s azelmaḍ/ayfus" }, "clearCanvasDialog": { "title": "Sfeḍ taɣzut n usuneɣ" @@ -447,10 +447,16 @@ "d9480f": "Aččinawi 9" }, "welcomeScreen": { - "data": "Akk isefka-inek•inem ttwakelsen s wudem adigan deg yiminig-inek•inem.", - "switchToPlusApp": "Tebɣiḍ ad tedduḍ ɣer Excalidraw+ deg umḍiq?", - "menuHints": "Asifeḍ, ismenyifen, tutlayin, ...", - "toolbarHints": "Fren afecku tebduḍ asuneɣ!", - "helpHints": "Inegzumen akked tallelt" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/kk-KZ.json b/src/locales/kk-KZ.json index a9601b8b1..6eae63dfc 100644 --- a/src/locales/kk-KZ.json +++ b/src/locales/kk-KZ.json @@ -447,10 +447,16 @@ "d9480f": "" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/ko-KR.json b/src/locales/ko-KR.json index 575ff41b1..fc159a2ce 100644 --- a/src/locales/ko-KR.json +++ b/src/locales/ko-KR.json @@ -1,7 +1,7 @@ { "labels": { "paste": "붙여넣기", - "pasteAsPlaintext": "", + "pasteAsPlaintext": "일반 텍스트로 붙여넣기", "pasteCharts": "차트 붙여넣기", "selectAll": "전체 선택", "multiSelect": "선택 영역에 추가하기", @@ -72,7 +72,7 @@ "layers": "레이어", "actions": "동작", "language": "언어", - "liveCollaboration": "", + "liveCollaboration": "실시간 협업...", "duplicateSelection": "복제", "untitled": "제목 없음", "name": "이름", @@ -136,8 +136,8 @@ "buttons": { "clearReset": "캔버스 초기화", "exportJSON": "파일로 내보내기", - "exportImage": "", - "export": "", + "exportImage": "이미지 내보내기", + "export": "다른 이름으로 저장...", "exportToPng": "PNG로 내보내기", "exportToSvg": "SVG로 내보내기", "copyToClipboard": "클립보드로 복사", @@ -145,7 +145,7 @@ "scale": "크기", "save": "현재 파일에 저장", "saveAs": "다른 이름으로 저장", - "load": "", + "load": "열기", "getShareableLink": "공유 가능한 링크 생성", "close": "닫기", "selectLanguage": "언어 선택", @@ -202,8 +202,8 @@ "invalidSVGString": "유효하지 않은 SVG입니다.", "cannotResolveCollabServer": "협업 서버에 접속하는데 실패했습니다. 페이지를 새로고침하고 다시 시도해보세요.", "importLibraryError": "라이브러리를 불러오지 못했습니다.", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "데이터베이스에 저장하지 못했습니다. 문제가 계속 된다면, 작업 내용을 잃지 않도록 로컬 저장소에 저장해 주세요.", + "collabSaveFailed_sizeExceeded": "데이터베이스에 저장하지 못했습니다. 캔버스가 너무 큰 거 같습니다. 문제가 계속 된다면, 작업 내용을 잃지 않도록 로컬 저장소에 저장해 주세요." }, "toolBar": { "selection": "선택", @@ -217,7 +217,7 @@ "text": "텍스트", "library": "라이브러리", "lock": "선택된 도구 유지하기", - "penMode": "", + "penMode": "펜 모드 - 터치 방지", "link": "선택한 도형에 대해서 링크를 추가/업데이트", "eraser": "지우개" }, @@ -238,7 +238,7 @@ "resize": "SHIFT 키를 누르면서 조정하면 크기의 비율이 제한됩니다.\nALT를 누르면서 조정하면 중앙을 기준으로 크기를 조정합니다.", "resizeImage": "SHIFT를 눌러서 자유롭게 크기를 변경하거나,\nALT를 눌러서 중앙을 고정하고 크기를 변경하기", "rotate": "SHIFT 키를 누르면서 회전하면 각도를 제한할 수 있습니다.", - "lineEditor_info": "", + "lineEditor_info": "포인트를 편집하려면 Ctrl/Cmd을 누르고 더블 클릭을 하거나 Ctrl/Cmd + Enter를 누르세요", "lineEditor_pointSelected": "Delete 키로 꼭짓점을 제거하거나,\nCtrlOrCmd+D 로 복제하거나, 드래그 해서 이동시키기", "lineEditor_nothingSelected": "꼭짓점을 선택해서 수정하거나 (SHIFT를 눌러서 여러개 선택),\nAlt를 누르고 클릭해서 새로운 꼭짓점 추가하기", "placeImage": "클릭해서 이미지를 배치하거나, 클릭하고 드래그해서 사이즈를 조정하기", @@ -314,8 +314,8 @@ "zoomToFit": "모든 요소가 보이도록 확대/축소", "zoomToSelection": "선택 영역으로 확대/축소", "toggleElementLock": "선택한 항목을 잠금/잠금 해제", - "movePageUpDown": "", - "movePageLeftRight": "" + "movePageUpDown": "페이지 움직이기 위/아래", + "movePageLeftRight": "페이지 움직이기 좌/우" }, "clearCanvasDialog": { "title": "캔버스 지우기" @@ -397,7 +397,7 @@ "fileSavedToFilename": "{filename} 로 저장되었습니다", "canvas": "캔버스", "selection": "선택한 요소", - "pasteAsSingleElement": "" + "pasteAsSingleElement": "단일 요소로 붙여넣거나, 기존 텍스트 에디터에 붙여넣으려면 {{shortcut}} 을 사용하세요." }, "colors": { "ffffff": "화이트", @@ -447,10 +447,16 @@ "d9480f": "주황색 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "당신의 모든 데이터는 브라우저에 저장되었습니다.", + "center_heading_plus": "대신 Excalidraw+로 이동하시겠습니까?", + "menuHint": "내보내기, 설정, 언어, ..." + }, + "defaults": { + "menuHint": "내보내기, 설정, 더 보기...", + "center_heading": "", + "toolbarHint": "도구 선택 & 그리기 시작", + "helpHint": "단축키 & 도움말" + } } } diff --git a/src/locales/ku-TR.json b/src/locales/ku-TR.json index 17180e8e9..738bf5f8e 100644 --- a/src/locales/ku-TR.json +++ b/src/locales/ku-TR.json @@ -447,10 +447,16 @@ "d9480f": "پرتەقاڵی 9" }, "welcomeScreen": { - "data": "هەموو داتاکانت لە ناو بڕاوزەرەکەتدا پاشەکەوت کراوە.", - "switchToPlusApp": "دەتویست بچیت بۆ Excalidraw+؟", - "menuHints": "هەناردەکردن، پەسندکردنەکان، زمانەکان، ...", - "toolbarHints": "ئامرازێک هەڵبژێرە و دەستبکە بە وێنەکێشان!", - "helpHints": "قەدبڕەکان و یارمەتی" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/lt-LT.json b/src/locales/lt-LT.json index 24768875f..b45b4fbb2 100644 --- a/src/locales/lt-LT.json +++ b/src/locales/lt-LT.json @@ -447,10 +447,16 @@ "d9480f": "Oranžinė 9" }, "welcomeScreen": { - "data": "Visi tavo duomenys išsaugoti lokaliai naršyklėje.", - "switchToPlusApp": "Ar vietoj to norėjai patekti į Excalidraw+?", - "menuHints": "Eksportavimas, parinktys, kalbos, ...", - "toolbarHints": "Pasirink įrankį ir Pradėk piešti!", - "helpHints": "Spartieji klavišai ir pagalba" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/lv-LV.json b/src/locales/lv-LV.json index ee98e9adb..795330a9a 100644 --- a/src/locales/lv-LV.json +++ b/src/locales/lv-LV.json @@ -447,10 +447,16 @@ "d9480f": "Oranžs 9" }, "welcomeScreen": { - "data": "Visi jūsu dati tiek glabāti uz vietas jūsu pārlūkā.", - "switchToPlusApp": "", - "menuHints": "Eksportēšana, iestatījumi, valodas...", - "toolbarHints": "Izvēlieties rīku un sāciet zīmēt!", - "helpHints": "Saīsnes un palīdzība" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/mr-IN.json b/src/locales/mr-IN.json index 07576dfd3..7ee3d0ced 100644 --- a/src/locales/mr-IN.json +++ b/src/locales/mr-IN.json @@ -447,10 +447,16 @@ "d9480f": "नारंगी 9" }, "welcomeScreen": { - "data": "तुमचा सर्व डेटा ब्राउज़र मधे स्थानिक जागेत सुरक्षित झाला.", - "switchToPlusApp": "त्याएवजी तुम्हाला Excalidraw+ पर्याय हवा आहे का?", - "menuHints": "निर्यात, पसंती, भाषा, ...", - "toolbarHints": "साधन निवडा आणि चित्रीकरण सुरु करा!", - "helpHints": "शॉर्टकट & सहाय" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/my-MM.json b/src/locales/my-MM.json index c165074a0..5f2acd026 100644 --- a/src/locales/my-MM.json +++ b/src/locales/my-MM.json @@ -447,10 +447,16 @@ "d9480f": "" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/nb-NO.json b/src/locales/nb-NO.json index 8fe2f15dc..055e33a99 100644 --- a/src/locales/nb-NO.json +++ b/src/locales/nb-NO.json @@ -447,10 +447,16 @@ "d9480f": "Oransje 9" }, "welcomeScreen": { - "data": "Alle dine data lagres lokalt i din nettleser.", - "switchToPlusApp": "Ønsker du å gå til Excalidraw+ i stedet?", - "menuHints": "Eksporter, innstillinger, språk, ...", - "toolbarHints": "Velg et verktøy og start å tegne!", - "helpHints": "Snarveier & hjelp" + "app": { + "center_heading": "Alle dine data lagres lokalt i din nettleser.", + "center_heading_plus": "Ønsker du å gå til Excalidraw+ i stedet?", + "menuHint": "Eksporter, innstillinger, språk, ..." + }, + "defaults": { + "menuHint": "Eksporter, innstillinger og mer...", + "center_heading": "Diagrammer. Gjort. Enkelt.", + "toolbarHint": "Velg et verktøy og start å tegne!", + "helpHint": "Snarveier & hjelp" + } } } diff --git a/src/locales/nl-NL.json b/src/locales/nl-NL.json index afdbbc73c..3961f10fe 100644 --- a/src/locales/nl-NL.json +++ b/src/locales/nl-NL.json @@ -343,7 +343,7 @@ }, "noteDescription": { "pre": "", - "link": "", + "link": "openbare repository", "post": "" }, "noteGuidelines": { @@ -447,10 +447,16 @@ "d9480f": "Oranje 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/nn-NO.json b/src/locales/nn-NO.json index 0375954ec..20fc77651 100644 --- a/src/locales/nn-NO.json +++ b/src/locales/nn-NO.json @@ -447,10 +447,16 @@ "d9480f": "Oransj 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/oc-FR.json b/src/locales/oc-FR.json index f04f01725..db03fb22b 100644 --- a/src/locales/oc-FR.json +++ b/src/locales/oc-FR.json @@ -447,10 +447,16 @@ "d9480f": "Irange 9" }, "welcomeScreen": { - "data": "Totas las donadas son enregistradas dins vòstre navegador.", - "switchToPlusApp": "Volètz puslèu utilizar Excalidraw+ ?", - "menuHints": "Exportar, preferéncias, lengas, ...", - "toolbarHints": "Prenètz un esplech e començatz de dessenhar !", - "helpHints": "Acorchis e ajuda" + "app": { + "center_heading": "Totas las donadas son enregistradas dins vòstre navegador.", + "center_heading_plus": "Voliatz puslèu utilizar Excalidraw+ a la plaça ?", + "menuHint": "Exportar, preferéncias, lengas, ..." + }, + "defaults": { + "menuHint": "Exportar, preferéncias, e mai...", + "center_heading": "Diagram. Tot. Simplament.", + "toolbarHint": "Prenètz un esplech e començatz de dessenhar !", + "helpHint": "Acorchis e ajuda" + } } } diff --git a/src/locales/pa-IN.json b/src/locales/pa-IN.json index 94f5c1fb1..9e1bf6436 100644 --- a/src/locales/pa-IN.json +++ b/src/locales/pa-IN.json @@ -447,10 +447,16 @@ "d9480f": "ਸੰਤਰੀ 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/percentages.json b/src/locales/percentages.json index 40b23ecd6..7a3f606ca 100644 --- a/src/locales/percentages.json +++ b/src/locales/percentages.json @@ -1,50 +1,50 @@ { - "ar-SA": 86, + "ar-SA": 87, "bg-BG": 55, "bn-BD": 60, "ca-ES": 94, "cs-CZ": 75, "da-DK": 33, "de-DE": 100, - "el-GR": 95, + "el-GR": 100, "en": 100, "es-ES": 100, - "eu-ES": 98, - "fa-IR": 98, + "eu-ES": 100, + "fa-IR": 96, "fi-FI": 93, "fr-FR": 100, - "gl-ES": 99, - "he-IL": 91, - "hi-IN": 71, - "hu-HU": 90, - "id-ID": 99, - "it-IT": 99, + "gl-ES": 100, + "he-IL": 90, + "hi-IN": 69, + "hu-HU": 89, + "id-ID": 100, + "it-IT": 100, "ja-JP": 100, - "kab-KAB": 94, + "kab-KAB": 93, "kk-KZ": 21, - "ko-KR": 95, - "ku-TR": 98, - "lt-LT": 66, - "lv-LV": 99, - "mr-IN": 100, - "my-MM": 42, + "ko-KR": 99, + "ku-TR": 96, + "lt-LT": 64, + "lv-LV": 98, + "mr-IN": 98, + "my-MM": 41, "nb-NO": 100, "nl-NL": 91, - "nn-NO": 91, + "nn-NO": 90, "oc-FR": 98, "pa-IN": 83, "pl-PL": 85, - "pt-BR": 100, - "pt-PT": 98, + "pt-BR": 98, + "pt-PT": 100, "ro-RO": 100, - "ru-RU": 100, + "ru-RU": 98, "si-LK": 8, - "sk-SK": 99, + "sk-SK": 100, "sl-SI": 100, - "sv-SE": 98, + "sv-SE": 96, "ta-IN": 93, "tr-TR": 98, - "uk-UA": 97, + "uk-UA": 96, "vi-VN": 20, "zh-CN": 100, "zh-HK": 26, diff --git a/src/locales/pl-PL.json b/src/locales/pl-PL.json index fc2862e5d..b02881e35 100644 --- a/src/locales/pl-PL.json +++ b/src/locales/pl-PL.json @@ -447,10 +447,16 @@ "d9480f": "Pomarańczowy 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/pt-BR.json b/src/locales/pt-BR.json index 343a59d78..24da24ef3 100644 --- a/src/locales/pt-BR.json +++ b/src/locales/pt-BR.json @@ -447,10 +447,16 @@ "d9480f": "Laranja 9" }, "welcomeScreen": { - "data": "Todos os dados são salvos localmente no seu navegador.", - "switchToPlusApp": "Você queria ir para o Excalidraw+ em vez disso?", - "menuHints": "Exportar, preferências, idiomas, ...", - "toolbarHints": "Escolha uma ferramenta & Comece a desenhar!", - "helpHints": "Atalhos & ajuda" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/pt-PT.json b/src/locales/pt-PT.json index f45d16935..7a9dd400c 100644 --- a/src/locales/pt-PT.json +++ b/src/locales/pt-PT.json @@ -1,7 +1,7 @@ { "labels": { "paste": "Colar", - "pasteAsPlaintext": "", + "pasteAsPlaintext": "Colar como texto simples", "pasteCharts": "Colar gráficos", "selectAll": "Selecionar tudo", "multiSelect": "Adicionar elemento à seleção", @@ -202,8 +202,8 @@ "invalidSVGString": "SVG inválido.", "cannotResolveCollabServer": "Não foi possível fazer a ligação ao servidor colaborativo. Por favor, volte a carregar a página e tente novamente.", "importLibraryError": "Não foi possível carregar a biblioteca", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "Não foi possível guardar na base de dados de backend. Se os problemas persistirem, guarde o ficheiro localmente para garantir que não perde o seu trabalho.", + "collabSaveFailed_sizeExceeded": "Não foi possível guardar na base de dados de backend, o ecrã parece estar muito grande. Deve guardar o ficheiro localmente para garantir que não perde o seu trabalho." }, "toolBar": { "selection": "Seleção", @@ -238,7 +238,7 @@ "resize": "Pode restringir as proporções mantendo a tecla SHIFT premida enquanto redimensiona,\nmantenha a tecla ALT premida para redimensionar a partir do centro", "resizeImage": "Pode redimensionar livremente mantendo pressionada a tecla SHIFT,\nmantenha pressionada a tecla ALT para redimensionar do centro", "rotate": "Pode restringir os ângulos mantendo a tecla SHIFT premida enquanto roda", - "lineEditor_info": "", + "lineEditor_info": "Pressione CtrlOrCmd e faça um duplo-clique ou pressione CtrlOrCmd + Enter para editar pontos", "lineEditor_pointSelected": "Carregue na tecla Delete para remover o(s) ponto(s), CtrlOuCmd+D para duplicar, ou arraste para mover", "lineEditor_nothingSelected": "Seleccione um ponto para editar (carregue em SHIFT para seleccionar vários),\nou carregue em Alt e clique para acrescentar novos pontos", "placeImage": "Clique para colocar a imagem ou clique e arraste para definir o seu tamanho manualmente", @@ -314,8 +314,8 @@ "zoomToFit": "Ajustar para todos os elementos caberem", "zoomToSelection": "Ampliar a seleção", "toggleElementLock": "Trancar/destrancar selecção", - "movePageUpDown": "", - "movePageLeftRight": "" + "movePageUpDown": "Mover página para cima / baixo", + "movePageLeftRight": "Mover página para esquerda / direita" }, "clearCanvasDialog": { "title": "Apagar tela" @@ -397,7 +397,7 @@ "fileSavedToFilename": "Guardado como {filename}", "canvas": "área de desenho", "selection": "seleção", - "pasteAsSingleElement": "" + "pasteAsSingleElement": "Usar {{shortcut}} para colar como um único elemento,\nou colar num editor de texto existente" }, "colors": { "ffffff": "Branco", @@ -447,10 +447,16 @@ "d9480f": "Laranja 9" }, "welcomeScreen": { - "data": "Todos os dados estão guardados no seu navegador local.", - "switchToPlusApp": "Queria antes ir para o Excalidraw+?", - "menuHints": "Exportar, preferências, idiomas...", - "toolbarHints": "Escolha uma ferramenta e comece a desenhar!", - "helpHints": "Atalhos e ajuda" + "app": { + "center_heading": "Todos os dados são guardados no seu navegador local.", + "center_heading_plus": "Queria antes ir para o Excalidraw+?", + "menuHint": "Exportar, preferências, idiomas..." + }, + "defaults": { + "menuHint": "Exportar, preferências e outros...", + "center_heading": "Diagramas. Feito. Simples.", + "toolbarHint": "Escolha uma ferramenta e comece a desenhar!", + "helpHint": "Atalhos e ajuda" + } } } diff --git a/src/locales/ro-RO.json b/src/locales/ro-RO.json index 43e817b96..4704426c1 100644 --- a/src/locales/ro-RO.json +++ b/src/locales/ro-RO.json @@ -447,10 +447,16 @@ "d9480f": "Portocaliu 9" }, "welcomeScreen": { - "data": "Toate datele tale sunt salvate local în navigatorul tău.", - "switchToPlusApp": "Ai vrut să mergi în schimb la Excalidraw+?", - "menuHints": "Exportare, preferințe, limbi, ...", - "toolbarHints": "Alege un instrument și începe să desenezi!", - "helpHints": "Comenzi rapide și ajutor" + "app": { + "center_heading": "Toate datele tale sunt salvate local în navigatorul tău.", + "center_heading_plus": "Ai vrut să mergi în schimb la Excalidraw+?", + "menuHint": "Exportare, preferințe, limbi, ..." + }, + "defaults": { + "menuHint": "Exportare, preferințe și mai multe...", + "center_heading": "Diagrame. Făcute. Simple.", + "toolbarHint": "Alege un instrument și începe să desenezi!", + "helpHint": "Comenzi rapide și ajutor" + } } } diff --git a/src/locales/ru-RU.json b/src/locales/ru-RU.json index cfc0b24ce..d97c91971 100644 --- a/src/locales/ru-RU.json +++ b/src/locales/ru-RU.json @@ -447,10 +447,16 @@ "d9480f": "Оранжевый 9" }, "welcomeScreen": { - "data": "Все ваши данные сохраняются локально в вашем браузере.", - "switchToPlusApp": "Хотите перейти на Excalidraw+?", - "menuHints": "Экспорт, настройки, языки, ...", - "toolbarHints": "Выберите инструмент и начните рисовать!", - "helpHints": "Сочетания клавиш и помощь" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/si-LK.json b/src/locales/si-LK.json index 1dc54fddb..1567273da 100644 --- a/src/locales/si-LK.json +++ b/src/locales/si-LK.json @@ -447,10 +447,16 @@ "d9480f": "" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/sk-SK.json b/src/locales/sk-SK.json index 30d3d8966..c3778c3e1 100644 --- a/src/locales/sk-SK.json +++ b/src/locales/sk-SK.json @@ -202,8 +202,8 @@ "invalidSVGString": "Nevalidné SVG.", "cannotResolveCollabServer": "Nepodarilo sa pripojiť ku kolaboračnému serveru. Prosím obnovte stránku a skúste to znovu.", "importLibraryError": "Nepodarilo sa načítať knižnicu", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "Uloženie do databázy sa nepodarilo. Ak tento problém pretrváva uložte si váš súbor lokálne aby ste nestratili vašu prácu.", + "collabSaveFailed_sizeExceeded": "Uloženie do databázy sa nepodarilo, pretože veľkosť plátna je príliš veľká. Uložte si váš súbor lokálne aby ste nestratili vašu prácu." }, "toolBar": { "selection": "Výber", @@ -447,10 +447,16 @@ "d9480f": "Oranžová 9" }, "welcomeScreen": { - "data": "Všetky vaše dáta sú uložené lokálne vo vašom prehliadači.", - "switchToPlusApp": "Chceli ste namiesto toho prejsť do Excalidraw+?", - "menuHints": "Exportovanie, nastavenia, jazyky, ...", - "toolbarHints": "Zvoľte nástroj a začnite kresliť!", - "helpHints": "Klávesové skratky a pomocník" + "app": { + "center_heading": "Všetky vaše dáta sú uložené lokálne vo vašom prehliadači.", + "center_heading_plus": "Chceli ste namiesto toho prejsť do Excalidraw+?", + "menuHint": "Exportovanie, nastavenia, jazyky, ..." + }, + "defaults": { + "menuHint": "Exportovanie, nastavenia a ďalšie...", + "center_heading": "Diagramy. Jednoducho.", + "toolbarHint": "Zvoľte nástroj a začnite kresliť!", + "helpHint": "Klávesové skratky a pomocník" + } } } diff --git a/src/locales/sl-SI.json b/src/locales/sl-SI.json index 0997d5d4b..5f2359094 100644 --- a/src/locales/sl-SI.json +++ b/src/locales/sl-SI.json @@ -447,10 +447,16 @@ "d9480f": "Oranžna 9" }, "welcomeScreen": { - "data": "Vsi vaši podatki so shranjeni lokalno v vašem brskalniku.", - "switchToPlusApp": "Ste namesto tega želeli odpreti Excalidraw+?", - "menuHints": "Izvoz, nastavitve, jeziki, ...", - "toolbarHints": "Izberi orodje in začni z risanjem!", - "helpHints": "Bljižnice in pomoč" + "app": { + "center_heading": "Vsi vaši podatki so shranjeni lokalno v vašem brskalniku.", + "center_heading_plus": "Ste namesto tega želeli odpreti Excalidraw+?", + "menuHint": "Izvoz, nastavitve, jeziki, ..." + }, + "defaults": { + "menuHint": "Izvoz, nastavitve in več ...", + "center_heading": "Diagrami. Enostavno.", + "toolbarHint": "Izberi orodje in začni z risanjem!", + "helpHint": "Bližnjice in pomoč" + } } } diff --git a/src/locales/sv-SE.json b/src/locales/sv-SE.json index a8c6ac63a..7f0ca8ab3 100644 --- a/src/locales/sv-SE.json +++ b/src/locales/sv-SE.json @@ -447,10 +447,16 @@ "d9480f": "Orange 9" }, "welcomeScreen": { - "data": "All din data sparas lokalt i din webbläsare.", - "switchToPlusApp": "Ville du gå till Excalidraw+ istället?", - "menuHints": "Export, inställningar, språk, ...", - "toolbarHints": "Välj ett verktyg och börja rita!", - "helpHints": "Genvägar och hjälp" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/ta-IN.json b/src/locales/ta-IN.json index 18d9e5f4d..d01fabce8 100644 --- a/src/locales/ta-IN.json +++ b/src/locales/ta-IN.json @@ -447,10 +447,16 @@ "d9480f": "ஆரஞ்சு 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/tr-TR.json b/src/locales/tr-TR.json index 294839f88..44a0556e0 100644 --- a/src/locales/tr-TR.json +++ b/src/locales/tr-TR.json @@ -202,8 +202,8 @@ "invalidSVGString": "Geçersiz SVG.", "cannotResolveCollabServer": "İş birliği sunucusuna bağlanılamıyor. Lütfen sayfayı yenileyip tekrar deneyin.", "importLibraryError": "Kütüphane yüklenemedi", - "collabSaveFailed": "", - "collabSaveFailed_sizeExceeded": "" + "collabSaveFailed": "Backend veritabanına kaydedilemedi. Eğer problem devam ederse, çalışmanızı korumak için dosyayı yerel olarak kaydetmelisiniz.", + "collabSaveFailed_sizeExceeded": "Backend veritabanına kaydedilemedi; tuval çok büyük. Çalışmanızı korumak için dosyayı yerel olarak kaydetmelisiniz." }, "toolBar": { "selection": "Seçme", @@ -314,8 +314,8 @@ "zoomToFit": "Tüm öğeleri sığdırmak için yakınlaştır", "zoomToSelection": "Seçime yakınlaş", "toggleElementLock": "Seçimi Kilitle/çöz", - "movePageUpDown": "", - "movePageLeftRight": "" + "movePageUpDown": "Sayfayı yukarı/aşağı kaydır", + "movePageLeftRight": "Sayfayı sola/sağa kaydır" }, "clearCanvasDialog": { "title": "Tuvali temizle" @@ -397,7 +397,7 @@ "fileSavedToFilename": "{filename} kaydedildi", "canvas": "tuval", "selection": "seçim", - "pasteAsSingleElement": "" + "pasteAsSingleElement": "Tekil obje olarak yapıştırmak için veya var olan bir metin editörüne yapıştırmak için {{shortcut}} kullanın" }, "colors": { "ffffff": "Beyaz", @@ -447,10 +447,16 @@ "d9480f": "Turuncu 9" }, "welcomeScreen": { - "data": "Tüm veri internet gezgininize yerel olarak kaydedildi.", - "switchToPlusApp": "Excalidraw+ kullanmak ister miydiniz?", - "menuHints": "Dışa aktar, seçenkeler, diller, ...", - "toolbarHints": "Bir araç seçin & Çizime başlayın!", - "helpHints": "Kısayollar & yardım" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/uk-UA.json b/src/locales/uk-UA.json index f6e559fb7..e02e0c07b 100644 --- a/src/locales/uk-UA.json +++ b/src/locales/uk-UA.json @@ -447,10 +447,16 @@ "d9480f": "Помаранчевий 9" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "Оберіть інструмент і почніть малювати!", - "helpHints": "Комбінації клавіш і допомога" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/vi-VN.json b/src/locales/vi-VN.json index 21c52a9a6..d3b1282e0 100644 --- a/src/locales/vi-VN.json +++ b/src/locales/vi-VN.json @@ -447,10 +447,16 @@ "d9480f": "" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/zh-CN.json b/src/locales/zh-CN.json index d58e475ad..cd573efd8 100644 --- a/src/locales/zh-CN.json +++ b/src/locales/zh-CN.json @@ -447,10 +447,16 @@ "d9480f": "橙 9" }, "welcomeScreen": { - "data": "您的所有数据都储存在浏览器本地。", - "switchToPlusApp": "是否前往 Excalidraw+ ?", - "menuHints": "导出、首选项、语言...", - "toolbarHints": "选择工具并开始绘图!", - "helpHints": "快捷键和帮助" + "app": { + "center_heading": "您的所有数据都储存在浏览器本地。", + "center_heading_plus": "是否前往 Excalidraw+ ?", + "menuHint": "导出、首选项、语言……" + }, + "defaults": { + "menuHint": "导出、首选项……", + "center_heading": "图,化繁为简。", + "toolbarHint": "选择工具并开始绘图!", + "helpHint": "快捷键和帮助" + } } } diff --git a/src/locales/zh-HK.json b/src/locales/zh-HK.json index c2e982b03..f8968f2b7 100644 --- a/src/locales/zh-HK.json +++ b/src/locales/zh-HK.json @@ -447,10 +447,16 @@ "d9480f": "" }, "welcomeScreen": { - "data": "", - "switchToPlusApp": "", - "menuHints": "", - "toolbarHints": "", - "helpHints": "" + "app": { + "center_heading": "", + "center_heading_plus": "", + "menuHint": "" + }, + "defaults": { + "menuHint": "", + "center_heading": "", + "toolbarHint": "", + "helpHint": "" + } } } diff --git a/src/locales/zh-TW.json b/src/locales/zh-TW.json index a4c491d42..21d7465af 100644 --- a/src/locales/zh-TW.json +++ b/src/locales/zh-TW.json @@ -447,10 +447,16 @@ "d9480f": "橘 9" }, "welcomeScreen": { - "data": "您的所有資料都儲存在本機瀏覽器。", - "switchToPlusApp": "您是否是要前往 Excalidraw+ ?", - "menuHints": "輸出、偏好設定、語言...", - "toolbarHints": "選個工具開始畫圖吧!", - "helpHints": "快速鍵與說明" + "app": { + "center_heading": "所有資料皆已在瀏覽器中儲存於本機", + "center_heading_plus": "您是否是要前往 Excalidraw+ ?", + "menuHint": "輸出、偏好設定、語言..." + }, + "defaults": { + "menuHint": "輸出、偏好設定及其他...", + "center_heading": "圖表。製作。超簡單。", + "toolbarHint": "選個工具開始畫圖吧!", + "helpHint": "快速鍵與說明" + } } } From d2b698093cace836fd50273874b179b872c40b0e Mon Sep 17 00:00:00 2001 From: David Luzar Date: Sun, 22 Jan 2023 12:33:15 +0100 Subject: [PATCH 5/9] feat: show copy-as-png export button on firefox and show steps how to enable it (#6125) * feat: hide copy-as-png shortcut from help dialog if not supported * fix: support firefox if clipboard.write supported * show shrotcut in firefox and instead show error message how to enable the flag support * widen to TypeError because minification * show copy-as-png on firefox even if it will throw --- src/actions/actionHistory.tsx | 3 ++- src/actions/actionZindex.tsx | 3 ++- src/actions/shortcuts.ts | 2 +- src/clipboard.ts | 9 ++++----- src/components/App.tsx | 2 +- src/components/HelpDialog.tsx | 16 +++++++++++----- src/components/ImageExportDialog.tsx | 6 ++++-- src/constants.ts | 8 ++++++++ src/data/index.ts | 15 +++++++++++++-- src/keys.ts | 4 +--- src/locales/en.json | 3 ++- src/utils.ts | 2 +- 12 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/actions/actionHistory.tsx b/src/actions/actionHistory.tsx index 76aa9d787..2e0f4c091 100644 --- a/src/actions/actionHistory.tsx +++ b/src/actions/actionHistory.tsx @@ -5,10 +5,11 @@ import { t } from "../i18n"; import History, { HistoryEntry } from "../history"; import { ExcalidrawElement } from "../element/types"; import { AppState } from "../types"; -import { isWindows, KEYS } from "../keys"; +import { KEYS } from "../keys"; import { newElementWith } from "../element/mutateElement"; import { fixBindingsAfterDeletion } from "../element/binding"; import { arrayToMap } from "../utils"; +import { isWindows } from "../constants"; const writeData = ( prevElements: readonly ExcalidrawElement[], diff --git a/src/actions/actionZindex.tsx b/src/actions/actionZindex.tsx index 07da26217..17ecde1a6 100644 --- a/src/actions/actionZindex.tsx +++ b/src/actions/actionZindex.tsx @@ -5,7 +5,7 @@ import { moveAllLeft, moveAllRight, } from "../zindex"; -import { KEYS, isDarwin, CODES } from "../keys"; +import { KEYS, CODES } from "../keys"; import { t } from "../i18n"; import { getShortcutKey } from "../utils"; import { register } from "./register"; @@ -15,6 +15,7 @@ import { SendBackwardIcon, SendToBackIcon, } from "../components/icons"; +import { isDarwin } from "../constants"; export const actionSendBackward = register({ name: "sendBackward", diff --git a/src/actions/shortcuts.ts b/src/actions/shortcuts.ts index 41686e521..4138ae085 100644 --- a/src/actions/shortcuts.ts +++ b/src/actions/shortcuts.ts @@ -1,5 +1,5 @@ +import { isDarwin } from "../constants"; import { t } from "../i18n"; -import { isDarwin } from "../keys"; import { getShortcutKey } from "../utils"; import { ActionName } from "./types"; diff --git a/src/clipboard.ts b/src/clipboard.ts index bf90a4b17..5f7950c53 100644 --- a/src/clipboard.ts +++ b/src/clipboard.ts @@ -180,16 +180,16 @@ export const parseClipboard = async ( }; export const copyBlobToClipboardAsPng = async (blob: Blob | Promise) => { - let promise; try { // in Safari so far we need to construct the ClipboardItem synchronously // (i.e. in the same tick) otherwise browser will complain for lack of // user intent. Using a Promise ClipboardItem constructor solves this. // https://bugs.webkit.org/show_bug.cgi?id=222262 // - // not await so that we can detect whether the thrown error likely relates - // to a lack of support for the Promise ClipboardItem constructor - promise = navigator.clipboard.write([ + // Note that Firefox (and potentially others) seems to support Promise + // ClipboardItem constructor, but throws on an unrelated MIME type error. + // So we need to await this and fallback to awaiting the blob if applicable. + await navigator.clipboard.write([ new window.ClipboardItem({ [MIME_TYPES.png]: blob, }), @@ -207,7 +207,6 @@ export const copyBlobToClipboardAsPng = async (blob: Blob | Promise) => { throw error; } } - await promise; }; export const copyTextToSystemClipboard = async (text: string | null) => { diff --git a/src/components/App.tsx b/src/components/App.tsx index e0ce0ee97..0f4b6ce0c 100644 --- a/src/components/App.tsx +++ b/src/components/App.tsx @@ -57,6 +57,7 @@ import { EVENT, GRID_SIZE, IMAGE_RENDER_TIMEOUT, + isAndroid, LINE_CONFIRM_THRESHOLD, MAX_ALLOWED_FILE_BYTES, MIME_TYPES, @@ -166,7 +167,6 @@ import { shouldRotateWithDiscreteAngle, isArrowKey, KEYS, - isAndroid, } from "../keys"; import { distance2d, getGridPoint, isPathALoop } from "../math"; import { renderScene } from "../renderer/renderScene"; diff --git a/src/components/HelpDialog.tsx b/src/components/HelpDialog.tsx index 065d0f77e..4eea5d696 100644 --- a/src/components/HelpDialog.tsx +++ b/src/components/HelpDialog.tsx @@ -1,10 +1,12 @@ import React from "react"; import { t } from "../i18n"; -import { isDarwin, isWindows, KEYS } from "../keys"; +import { KEYS } from "../keys"; import { Dialog } from "./Dialog"; import { getShortcutKey } from "../utils"; import "./HelpDialog.scss"; import { ExternalLinkIcon } from "./icons"; +import { probablySupportsClipboardBlob } from "../clipboard"; +import { isDarwin, isFirefox, isWindows } from "../constants"; const Header = () => (
@@ -304,10 +306,14 @@ export const HelpDialog = ({ onClose }: { onClose?: () => void }) => { label={t("labels.pasteAsPlaintext")} shortcuts={[getShortcutKey("CtrlOrCmd+Shift+V")]} /> - + {/* firefox supports clipboard API under a flag, so we'll + show users what they can do in the error message */} + {(probablySupportsClipboardBlob || isFirefox) && ( + + )} SVG - {probablySupportsClipboardBlob && ( + {/* firefox supports clipboard API under a flag, + so let's throw and tell people what they can do */} + {(probablySupportsClipboardBlob || isFirefox) && ( onExportToClipboard(exportedElements)} diff --git a/src/constants.ts b/src/constants.ts index d6b744bb5..20b3778e3 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,6 +2,14 @@ import cssVariables from "./css/variables.module.scss"; import { AppProps } from "./types"; import { FontFamilyValues } from "./element/types"; +export const isDarwin = /Mac|iPod|iPhone|iPad/.test(navigator.platform); +export const isWindows = /^Win/.test(navigator.platform); +export const isAndroid = /\b(android)\b/i.test(navigator.userAgent); +export const isFirefox = + "netscape" in window && + navigator.userAgent.indexOf("rv:") > 1 && + navigator.userAgent.indexOf("Gecko") > 1; + export const APP_NAME = "Excalidraw"; export const DRAGGING_THRESHOLD = 10; // px diff --git a/src/data/index.ts b/src/data/index.ts index 8ea90adf6..89877aab9 100644 --- a/src/data/index.ts +++ b/src/data/index.ts @@ -2,7 +2,7 @@ import { copyBlobToClipboardAsPng, copyTextToSystemClipboard, } from "../clipboard"; -import { DEFAULT_EXPORT_PADDING, MIME_TYPES } from "../constants"; +import { DEFAULT_EXPORT_PADDING, isFirefox, MIME_TYPES } from "../constants"; import { NonDeletedExcalidrawElement } from "../element/types"; import { t } from "../i18n"; import { exportToCanvas, exportToSvg } from "../scene/export"; @@ -97,10 +97,21 @@ export const exportCanvas = async ( const blob = canvasToBlob(tempCanvas); await copyBlobToClipboardAsPng(blob); } catch (error: any) { + console.warn(error); if (error.name === "CANVAS_POSSIBLY_TOO_BIG") { throw error; } - throw new Error(t("alerts.couldNotCopyToClipboard")); + // TypeError *probably* suggests ClipboardItem not defined, which + // people on Firefox can enable through a flag, so let's tell them. + if (isFirefox && error.name === "TypeError") { + throw new Error( + `${t("alerts.couldNotCopyToClipboard")}\n\n${t( + "hints.firefox_clipboard_write", + )}`, + ); + } else { + throw new Error(t("alerts.couldNotCopyToClipboard")); + } } finally { tempCanvas.remove(); } diff --git a/src/keys.ts b/src/keys.ts index 0cb2f384e..ce0e803c0 100644 --- a/src/keys.ts +++ b/src/keys.ts @@ -1,6 +1,4 @@ -export const isDarwin = /Mac|iPod|iPhone|iPad/.test(window.navigator.platform); -export const isWindows = /^Win/.test(window.navigator.platform); -export const isAndroid = /\b(android)\b/i.test(navigator.userAgent); +import { isDarwin } from "./constants"; export const CODES = { EQUAL: "Equal", diff --git a/src/locales/en.json b/src/locales/en.json index 2fe9e7c84..b0e5a2c57 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -246,7 +246,8 @@ "publishLibrary": "Publish your own library", "bindTextToElement": "Press enter to add text", "deepBoxSelect": "Hold CtrlOrCmd to deep select, and to prevent dragging", - "eraserRevert": "Hold Alt to revert the elements marked for deletion" + "eraserRevert": "Hold Alt to revert the elements marked for deletion", + "firefox_clipboard_write": "This feature can likely be enabled by setting the \"dom.events.asyncClipboard.clipboardItem\" flag to \"true\". To change the browser flags in Firefox, visit the \"about:config\" page." }, "canvasError": { "cannotShowPreview": "Cannot show preview", diff --git a/src/utils.ts b/src/utils.ts index d3d80560b..a332e921b 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -6,6 +6,7 @@ import { DEFAULT_VERSION, EVENT, FONT_FAMILY, + isDarwin, MIME_TYPES, THEME, WINDOWS_EMOJI_FALLBACK_FONT, @@ -13,7 +14,6 @@ import { import { FontFamilyValues, FontString } from "./element/types"; import { AppState, DataURL, LastActiveToolBeforeEraser, Zoom } from "./types"; import { unstable_batchedUpdates } from "react-dom"; -import { isDarwin } from "./keys"; import { SHAPES } from "./shapes"; import React from "react"; From f03f5c948d500c45a53ddec5c988a09c471bd741 Mon Sep 17 00:00:00 2001 From: Nishant-l <61119157+Nishant-l@users.noreply.github.com> Date: Sun, 22 Jan 2023 18:07:18 +0530 Subject: [PATCH 6/9] style: change in ExportButton style (#6147) (#6148) Co-authored-by: David Luzar --- src/components/ExportDialog.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/components/ExportDialog.scss b/src/components/ExportDialog.scss index c95a116e7..7bc0c808e 100644 --- a/src/components/ExportDialog.scss +++ b/src/components/ExportDialog.scss @@ -96,6 +96,10 @@ width: 5rem; height: 5rem; margin: 0 0.2em; + padding: 0; + display: flex; + align-items: center; + justify-content: center; border-radius: 1rem; background-color: var(--button-color); From 849e6a0c86ecb1428ba21ae4bc888f2d70db3ebf Mon Sep 17 00:00:00 2001 From: David Luzar Date: Mon, 23 Jan 2023 16:10:04 +0100 Subject: [PATCH 7/9] fix: button background and svg sizes (#6155) * fix: button background color fallback * fix svg width/height --- src/css/variables.module.scss | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/css/variables.module.scss b/src/css/variables.module.scss index 39bf4e293..779c52bff 100644 --- a/src/css/variables.module.scss +++ b/src/css/variables.module.scss @@ -65,13 +65,18 @@ background-color: var(--button-bg, var(--island-bg-color)); color: var(--button-color, var(--text-primary-color)); + svg { + width: var(--button-width, var(--lg-icon-size)); + height: var(--button-height, var(--lg-icon-size)); + } + &:hover { - background-color: var(--button-hover-bg); + background-color: var(--button-hover-bg, var(--island-bg-color)); border-color: var(--button-hover-border, var(--default-border-color)); } &:active { - background-color: var(--button-active-bg); + background-color: var(--button-active-bg, var(--island-bg-color)); border-color: var(--button-active-border, var(--color-primary-darkest)); } @@ -85,9 +90,6 @@ svg { color: var(--button-color, var(--color-primary-darker)); - - width: var(--button-width, var(--lg-icon-size)); - height: var(--button-height, var(--lg-icon-size)); } } } From d4afd6626850befdb000d86c203e7a604f8a871c Mon Sep 17 00:00:00 2001 From: David Luzar Date: Mon, 23 Jan 2023 16:12:28 +0100 Subject: [PATCH 8/9] feat: add hand/panning tool (#6141) * feat: add hand/panning tool * move hand tool right of tool lock separator * tweak i18n * rename `panning` -> `hand` * toggle between last tool and hand on `H` shortcut * hide properties sidebar when `hand` active * revert to rendering HandButton manually due to mobile toolbar --- src/actions/actionCanvas.tsx | 66 +++++++---- src/actions/actionFinalize.tsx | 2 +- src/actions/types.ts | 5 +- src/appState.ts | 10 +- src/components/Actions.tsx | 7 +- src/components/App.tsx | 31 ++++- src/components/HandButton.tsx | 32 ++++++ src/components/HelpDialog.tsx | 9 +- src/components/LayerUI.tsx | 21 +++- src/components/LockButton.tsx | 1 - src/components/MobileMenu.tsx | 24 ++-- src/components/ToolButton.tsx | 2 +- src/components/icons.tsx | 11 ++ src/css/styles.scss | 1 + src/data/restore.ts | 3 +- src/element/showSelectedShapeActions.ts | 3 +- src/locales/en.json | 5 +- .../__snapshots__/contextmenu.test.tsx.snap | 34 +++--- .../regressionTests.test.tsx.snap | 106 +++++++++--------- .../packages/__snapshots__/utils.test.ts.snap | 2 +- src/types.ts | 22 ++-- src/utils.ts | 15 ++- 22 files changed, 273 insertions(+), 139 deletions(-) create mode 100644 src/components/HandButton.tsx diff --git a/src/actions/actionCanvas.tsx b/src/actions/actionCanvas.tsx index 259b43e0c..1154d1ef1 100644 --- a/src/actions/actionCanvas.tsx +++ b/src/actions/actionCanvas.tsx @@ -1,7 +1,7 @@ import { ColorPicker } from "../components/ColorPicker"; -import { eraser, ZoomInIcon, ZoomOutIcon } from "../components/icons"; +import { ZoomInIcon, ZoomOutIcon } from "../components/icons"; import { ToolButton } from "../components/ToolButton"; -import { MIN_ZOOM, THEME, ZOOM_STEP } from "../constants"; +import { CURSOR_TYPE, MIN_ZOOM, THEME, ZOOM_STEP } from "../constants"; import { getCommonBounds, getNonDeletedElements } from "../element"; import { ExcalidrawElement } from "../element/types"; import { t } from "../i18n"; @@ -10,12 +10,15 @@ import { getNormalizedZoom, getSelectedElements } from "../scene"; import { centerScrollOn } from "../scene/scroll"; import { getStateForZoom } from "../scene/zoom"; import { AppState, NormalizedZoomValue } from "../types"; -import { getShortcutKey, updateActiveTool } from "../utils"; +import { getShortcutKey, setCursor, updateActiveTool } from "../utils"; import { register } from "./register"; import { Tooltip } from "../components/Tooltip"; import { newElementWith } from "../element/mutateElement"; -import { getDefaultAppState, isEraserActive } from "../appState"; -import clsx from "clsx"; +import { + getDefaultAppState, + isEraserActive, + isHandToolActive, +} from "../appState"; export const actionChangeViewBackgroundColor = register({ name: "changeViewBackgroundColor", @@ -306,15 +309,15 @@ export const actionToggleTheme = register({ }, }); -export const actionErase = register({ - name: "eraser", +export const actionToggleEraserTool = register({ + name: "toggleEraserTool", trackEvent: { category: "toolbar" }, perform: (elements, appState) => { let activeTool: AppState["activeTool"]; if (isEraserActive(appState)) { activeTool = updateActiveTool(appState, { - ...(appState.activeTool.lastActiveToolBeforeEraser || { + ...(appState.activeTool.lastActiveTool || { type: "selection", }), lastActiveToolBeforeEraser: null, @@ -337,17 +340,38 @@ export const actionErase = register({ }; }, keyTest: (event) => event.key === KEYS.E, - PanelComponent: ({ elements, appState, updateData, data }) => ( - { - updateData(null); - }} - size={data?.size || "medium"} - > - ), +}); + +export const actionToggleHandTool = register({ + name: "toggleHandTool", + trackEvent: { category: "toolbar" }, + perform: (elements, appState, _, app) => { + let activeTool: AppState["activeTool"]; + + if (isHandToolActive(appState)) { + activeTool = updateActiveTool(appState, { + ...(appState.activeTool.lastActiveTool || { + type: "selection", + }), + lastActiveToolBeforeEraser: null, + }); + } else { + activeTool = updateActiveTool(appState, { + type: "hand", + lastActiveToolBeforeEraser: appState.activeTool, + }); + setCursor(app.canvas, CURSOR_TYPE.GRAB); + } + + return { + appState: { + ...appState, + selectedElementIds: {}, + selectedGroupIds: {}, + activeTool, + }, + commitToHistory: true, + }; + }, + keyTest: (event) => event.key === KEYS.H, }); diff --git a/src/actions/actionFinalize.tsx b/src/actions/actionFinalize.tsx index 2e78a1a37..3508de0ad 100644 --- a/src/actions/actionFinalize.tsx +++ b/src/actions/actionFinalize.tsx @@ -145,7 +145,7 @@ export const actionFinalize = register({ let activeTool: AppState["activeTool"]; if (appState.activeTool.type === "eraser") { activeTool = updateActiveTool(appState, { - ...(appState.activeTool.lastActiveToolBeforeEraser || { + ...(appState.activeTool.lastActiveTool || { type: "selection", }), lastActiveToolBeforeEraser: null, diff --git a/src/actions/types.ts b/src/actions/types.ts index 4a7a4fe5d..54bd5a26f 100644 --- a/src/actions/types.ts +++ b/src/actions/types.ts @@ -109,10 +109,11 @@ export type ActionName = | "decreaseFontSize" | "unbindText" | "hyperlink" - | "eraser" | "bindText" | "toggleLock" - | "toggleLinearEditor"; + | "toggleLinearEditor" + | "toggleEraserTool" + | "toggleHandTool"; export type PanelComponentProps = { elements: readonly ExcalidrawElement[]; diff --git a/src/appState.ts b/src/appState.ts index d1cbe92f0..f02d5943c 100644 --- a/src/appState.ts +++ b/src/appState.ts @@ -45,7 +45,7 @@ export const getDefaultAppState = (): Omit< type: "selection", customType: null, locked: false, - lastActiveToolBeforeEraser: null, + lastActiveTool: null, }, penMode: false, penDetected: false, @@ -228,3 +228,11 @@ export const isEraserActive = ({ }: { activeTool: AppState["activeTool"]; }) => activeTool.type === "eraser"; + +export const isHandToolActive = ({ + activeTool, +}: { + activeTool: AppState["activeTool"]; +}) => { + return activeTool.type === "hand"; +}; diff --git a/src/components/Actions.tsx b/src/components/Actions.tsx index fe017f776..2ee9babfc 100644 --- a/src/components/Actions.tsx +++ b/src/components/Actions.tsx @@ -219,9 +219,10 @@ export const ShapesSwitcher = ({ <> {SHAPES.map(({ value, icon, key, numericKey, fillable }, index) => { const label = t(`toolBar.${value}`); - const letter = key && (typeof key === "string" ? key : key[0]); + const letter = + key && capitalizeString(typeof key === "string" ? key : key[0]); const shortcut = letter - ? `${capitalizeString(letter)} ${t("helpDialog.or")} ${numericKey}` + ? `${letter} ${t("helpDialog.or")} ${numericKey}` : `${numericKey}`; return ( { elements={this.scene.getNonDeletedElements()} onLockToggle={this.toggleLock} onPenModeToggle={this.togglePenMode} + onHandToolToggle={this.onHandToolToggle} onInsertElements={(elements) => this.addElementsFromPasteOrLibrary({ elements, @@ -1812,6 +1818,10 @@ class App extends React.Component { }); }; + onHandToolToggle = () => { + this.actionManager.executeAction(actionToggleHandTool); + }; + scrollToContent = ( target: | ExcalidrawElement @@ -2229,11 +2239,13 @@ class App extends React.Component { private setActiveTool = ( tool: - | { type: typeof SHAPES[number]["value"] | "eraser" } + | { type: typeof SHAPES[number]["value"] | "eraser" | "hand" } | { type: "custom"; customType: string }, ) => { const nextActiveTool = updateActiveTool(this.state, tool); - if (!isHoldingSpace) { + if (nextActiveTool.type === "hand") { + setCursor(this.canvas, CURSOR_TYPE.GRAB); + } else if (!isHoldingSpace) { setCursorForShape(this.canvas, this.state); } if (isToolIcon(document.activeElement)) { @@ -2904,7 +2916,12 @@ class App extends React.Component { null; } - if (isHoldingSpace || isPanning || isDraggingScrollBar) { + if ( + isHoldingSpace || + isPanning || + isDraggingScrollBar || + isHandToolActive(this.state) + ) { return; } @@ -3496,7 +3513,10 @@ class App extends React.Component { ); } else if (this.state.activeTool.type === "custom") { setCursor(this.canvas, CURSOR_TYPE.AUTO); - } else if (this.state.activeTool.type !== "eraser") { + } else if ( + this.state.activeTool.type !== "eraser" && + this.state.activeTool.type !== "hand" + ) { this.createGenericElementOnPointerDown( this.state.activeTool.type, pointerDownState, @@ -3607,6 +3627,7 @@ class App extends React.Component { gesture.pointers.size <= 1 && (event.button === POINTER_BUTTON.WHEEL || (event.button === POINTER_BUTTON.MAIN && isHoldingSpace) || + isHandToolActive(this.state) || this.state.viewModeEnabled) ) || isTextElement(this.state.editingElement) diff --git a/src/components/HandButton.tsx b/src/components/HandButton.tsx new file mode 100644 index 000000000..ce63791e1 --- /dev/null +++ b/src/components/HandButton.tsx @@ -0,0 +1,32 @@ +import "./ToolIcon.scss"; + +import clsx from "clsx"; +import { ToolButton } from "./ToolButton"; +import { handIcon } from "./icons"; +import { KEYS } from "../keys"; + +type LockIconProps = { + title?: string; + name?: string; + checked: boolean; + onChange?(): void; + isMobile?: boolean; +}; + +export const HandButton = (props: LockIconProps) => { + return ( + props.onChange?.()} + /> + ); +}; diff --git a/src/components/HelpDialog.tsx b/src/components/HelpDialog.tsx index 4eea5d696..69f3e6a5c 100644 --- a/src/components/HelpDialog.tsx +++ b/src/components/HelpDialog.tsx @@ -69,6 +69,10 @@ function* intersperse(as: JSX.Element[][], delim: string | null) { } } +const upperCaseSingleChars = (str: string) => { + return str.replace(/\b[a-z]\b/, (c) => c.toUpperCase()); +}; + const Shortcut = ({ label, shortcuts, @@ -83,7 +87,9 @@ const Shortcut = ({ ? [...shortcut.slice(0, -2).split("+"), "+"] : shortcut.split("+"); - return keys.map((key) => {key}); + return keys.map((key) => ( + {upperCaseSingleChars(key)} + )); }); return ( @@ -120,6 +126,7 @@ export const HelpDialog = ({ onClose }: { onClose?: () => void }) => { className="HelpDialog__island--tools" caption={t("helpDialog.tools")} > + ["setState"]; elements: readonly NonDeletedExcalidrawElement[]; onLockToggle: () => void; + onHandToolToggle: () => void; onPenModeToggle: () => void; onInsertElements: (elements: readonly NonDeletedExcalidrawElement[]) => void; showExitZenModeBtn: boolean; @@ -85,6 +88,7 @@ const LayerUI = ({ elements, canvas, onLockToggle, + onHandToolToggle, onPenModeToggle, onInsertElements, showExitZenModeBtn, @@ -304,13 +308,20 @@ const LayerUI = ({ penDetected={appState.penDetected} /> onLockToggle()} + onChange={onLockToggle} title={t("toolBar.lock")} /> +
+ onHandToolToggle()} + title={t("toolBar.hand")} + isMobile + /> + - {/* {actionManager.renderAction("eraser", { - // size: "small", - })} */} @@ -408,7 +416,8 @@ const LayerUI = ({ renderJSONExportDialog={renderJSONExportDialog} renderImageExportDialog={renderImageExportDialog} setAppState={setAppState} - onLockToggle={() => onLockToggle()} + onLockToggle={onLockToggle} + onHandToolToggle={onHandToolToggle} onPenModeToggle={onPenModeToggle} canvas={canvas} onImageAction={onImageAction} diff --git a/src/components/LockButton.tsx b/src/components/LockButton.tsx index cbcf2b33a..a039a5779 100644 --- a/src/components/LockButton.tsx +++ b/src/components/LockButton.tsx @@ -9,7 +9,6 @@ type LockIconProps = { name?: string; checked: boolean; onChange?(): void; - zenModeEnabled?: boolean; isMobile?: boolean; }; diff --git a/src/components/MobileMenu.tsx b/src/components/MobileMenu.tsx index 549292436..7c814f53e 100644 --- a/src/components/MobileMenu.tsx +++ b/src/components/MobileMenu.tsx @@ -22,6 +22,8 @@ import { LibraryButton } from "./LibraryButton"; import { PenModeButton } from "./PenModeButton"; import { Stats } from "./Stats"; import { actionToggleStats } from "../actions"; +import { HandButton } from "./HandButton"; +import { isHandToolActive } from "../appState"; type MobileMenuProps = { appState: AppState; @@ -31,6 +33,7 @@ type MobileMenuProps = { setAppState: React.Component["setState"]; elements: readonly NonDeletedExcalidrawElement[]; onLockToggle: () => void; + onHandToolToggle: () => void; onPenModeToggle: () => void; canvas: HTMLCanvasElement | null; @@ -52,6 +55,7 @@ export const MobileMenu = ({ actionManager, setAppState, onLockToggle, + onHandToolToggle, onPenModeToggle, canvas, onImageAction, @@ -88,6 +92,13 @@ export const MobileMenu = ({ {renderTopRightUI && renderTopRightUI(true, appState)}
+ {!appState.viewModeEnabled && ( + + )} - {!appState.viewModeEnabled && ( - - )} + onHandToolToggle()} + title={t("toolBar.hand")} + isMobile + />
diff --git a/src/components/ToolButton.tsx b/src/components/ToolButton.tsx index 7077898f3..446d154df 100644 --- a/src/components/ToolButton.tsx +++ b/src/components/ToolButton.tsx @@ -19,7 +19,7 @@ type ToolButtonBaseProps = { name?: string; id?: string; size?: ToolButtonSize; - keyBindingLabel?: string; + keyBindingLabel?: string | null; showAriaLabel?: boolean; hidden?: boolean; visible?: boolean; diff --git a/src/components/icons.tsx b/src/components/icons.tsx index cc43aaa49..046ee490b 100644 --- a/src/components/icons.tsx +++ b/src/components/icons.tsx @@ -1532,3 +1532,14 @@ export const publishIcon = createIcon( export const eraser = createIcon( , ); + +export const handIcon = createIcon( + + + + + + + , + tablerIconProps, +); diff --git a/src/css/styles.scss b/src/css/styles.scss index cff9aaf9e..6fe14bb59 100644 --- a/src/css/styles.scss +++ b/src/css/styles.scss @@ -549,6 +549,7 @@ border-top-left-radius: var(--border-radius-lg); border-bottom-left-radius: var(--border-radius-lg); border-right: 0; + overflow: hidden; background-color: var(--island-bg-color); diff --git a/src/data/restore.ts b/src/data/restore.ts index 976a0551b..bb779cf0f 100644 --- a/src/data/restore.ts +++ b/src/data/restore.ts @@ -55,6 +55,7 @@ export const AllowedExcalidrawActiveTools: Record< freedraw: true, eraser: false, custom: true, + hand: true, }; export type RestoredDataState = { @@ -465,7 +466,7 @@ export const restoreAppState = ( ? nextAppState.activeTool : { type: "selection" }, ), - lastActiveToolBeforeEraser: null, + lastActiveTool: null, locked: nextAppState.activeTool.locked ?? false, }, // Migrates from previous version where appState.zoom was a number diff --git a/src/element/showSelectedShapeActions.ts b/src/element/showSelectedShapeActions.ts index 14a7694e5..29f8d9fcb 100644 --- a/src/element/showSelectedShapeActions.ts +++ b/src/element/showSelectedShapeActions.ts @@ -11,6 +11,7 @@ export const showSelectedShapeActions = ( appState.activeTool.type !== "custom" && (appState.editingElement || (appState.activeTool.type !== "selection" && - appState.activeTool.type !== "eraser"))) || + appState.activeTool.type !== "eraser" && + appState.activeTool.type !== "hand"))) || getSelectedElements(elements, appState).length, ); diff --git a/src/locales/en.json b/src/locales/en.json index b0e5a2c57..1a46b20e0 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -220,7 +220,8 @@ "lock": "Keep selected tool active after drawing", "penMode": "Pen mode - prevent touch", "link": "Add/ Update link for a selected shape", - "eraser": "Eraser" + "eraser": "Eraser", + "hand": "Hand (panning tool)" }, "headings": { "canvasActions": "Canvas actions", @@ -228,7 +229,7 @@ "shapes": "Shapes" }, "hints": { - "canvasPanning": "To move canvas, hold mouse wheel or spacebar while dragging", + "canvasPanning": "To move canvas, hold mouse wheel or spacebar while dragging, or use the hand tool", "linearElement": "Click to start multiple points, drag for single line", "freeDraw": "Click and drag, release when you're finished", "text": "Tip: you can also add text by double-clicking anywhere with the selection tool", diff --git a/src/tests/__snapshots__/contextmenu.test.tsx.snap b/src/tests/__snapshots__/contextmenu.test.tsx.snap index 8633e88b0..326cde0ed 100644 --- a/src/tests/__snapshots__/contextmenu.test.tsx.snap +++ b/src/tests/__snapshots__/contextmenu.test.tsx.snap @@ -4,7 +4,7 @@ exports[`contextMenu element right-clicking on a group should select whole group Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -434,7 +434,7 @@ exports[`contextMenu element selecting 'Add to library' in context menu adds ele Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -620,7 +620,7 @@ exports[`contextMenu element selecting 'Bring forward' in context menu brings el Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -975,7 +975,7 @@ exports[`contextMenu element selecting 'Bring to front' in context menu brings e Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -1330,7 +1330,7 @@ exports[`contextMenu element selecting 'Copy styles' in context menu copies styl Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -1516,7 +1516,7 @@ exports[`contextMenu element selecting 'Delete' in context menu deletes element: Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -1738,7 +1738,7 @@ exports[`contextMenu element selecting 'Duplicate' in context menu duplicates el Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -2023,7 +2023,7 @@ exports[`contextMenu element selecting 'Group selection' in context menu groups Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -2396,7 +2396,7 @@ exports[`contextMenu element selecting 'Paste styles' in context menu pastes sty Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -3243,7 +3243,7 @@ exports[`contextMenu element selecting 'Send backward' in context menu sends ele Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -3598,7 +3598,7 @@ exports[`contextMenu element selecting 'Send to back' in context menu sends elem Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -3953,7 +3953,7 @@ exports[`contextMenu element selecting 'Ungroup selection' in context menu ungro Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -4392,7 +4392,7 @@ exports[`contextMenu element shows 'Group selection' in context menu for multipl Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -4933,7 +4933,7 @@ exports[`contextMenu element shows 'Ungroup selection' in context menu for group Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -5559,7 +5559,7 @@ exports[`contextMenu element shows context menu for canvas: [end of test] appSta Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -5773,7 +5773,7 @@ exports[`contextMenu element shows context menu for element: [end of test] appSt Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -6110,7 +6110,7 @@ exports[`contextMenu element shows context menu for element: [end of test] appSt Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, diff --git a/src/tests/__snapshots__/regressionTests.test.tsx.snap b/src/tests/__snapshots__/regressionTests.test.tsx.snap index ba2a82ac7..35f9eb7c8 100644 --- a/src/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/src/tests/__snapshots__/regressionTests.test.tsx.snap @@ -4,7 +4,7 @@ exports[`given element A and group of elements B and given both are selected whe Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -540,7 +540,7 @@ exports[`given element A and group of elements B and given both are selected whe Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -1082,7 +1082,7 @@ exports[`regression tests Cmd/Ctrl-click exclusively select element under pointe Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -1989,7 +1989,7 @@ exports[`regression tests Drags selected element when hitting only bounding box Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -2219,7 +2219,7 @@ exports[`regression tests adjusts z order when grouping: [end of test] appState Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -2752,7 +2752,7 @@ exports[`regression tests alt-drag duplicates an element: [end of test] appState Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -3041,7 +3041,7 @@ exports[`regression tests arrow keys: [end of test] appState 1`] = ` Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -3225,7 +3225,7 @@ exports[`regression tests can drag element that covers another element, while an Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -3741,7 +3741,7 @@ exports[`regression tests change the properties of a shape: [end of test] appSta Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -4009,7 +4009,7 @@ exports[`regression tests click on an element and drag it: [dragged] appState 1` Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -4239,7 +4239,7 @@ exports[`regression tests click on an element and drag it: [end of test] appStat Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -4515,7 +4515,7 @@ exports[`regression tests click to select a shape: [end of test] appState 1`] = Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -4803,7 +4803,7 @@ exports[`regression tests click-drag to select a group: [end of test] appState 1 Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -5221,7 +5221,7 @@ exports[`regression tests deselects group of selected elements on pointer down w Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -5562,7 +5562,7 @@ exports[`regression tests deselects group of selected elements on pointer up whe Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -5876,7 +5876,7 @@ exports[`regression tests deselects selected element on pointer down when pointe Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -6114,7 +6114,7 @@ exports[`regression tests deselects selected element, on pointer up, when click Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -6300,7 +6300,7 @@ exports[`regression tests double click to edit a group: [end of test] appState 1 Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -6828,7 +6828,7 @@ exports[`regression tests drags selected elements from point inside common bound Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -7193,7 +7193,7 @@ exports[`regression tests draw every type of shape: [end of test] appState 1`] = Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "freedraw", }, @@ -9545,7 +9545,7 @@ exports[`regression tests given a group of selected elements with an element tha Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -9964,7 +9964,7 @@ exports[`regression tests given a selected element A and a not selected element Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -10253,7 +10253,7 @@ exports[`regression tests given selected element A with lower z-index than unsel Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -10501,7 +10501,7 @@ exports[`regression tests given selected element A with lower z-index than unsel Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -10822,7 +10822,7 @@ exports[`regression tests key 2 selects rectangle tool: [end of test] appState 1 Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -11006,7 +11006,7 @@ exports[`regression tests key 3 selects diamond tool: [end of test] appState 1`] Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -11190,7 +11190,7 @@ exports[`regression tests key 4 selects ellipse tool: [end of test] appState 1`] Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -11374,7 +11374,7 @@ exports[`regression tests key 5 selects arrow tool: [end of test] appState 1`] = Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -11611,7 +11611,7 @@ exports[`regression tests key 6 selects line tool: [end of test] appState 1`] = Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -11848,7 +11848,7 @@ exports[`regression tests key 7 selects freedraw tool: [end of test] appState 1` Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "freedraw", }, @@ -12076,7 +12076,7 @@ exports[`regression tests key a selects arrow tool: [end of test] appState 1`] = Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -12313,7 +12313,7 @@ exports[`regression tests key d selects diamond tool: [end of test] appState 1`] Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -12497,7 +12497,7 @@ exports[`regression tests key l selects line tool: [end of test] appState 1`] = Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -12734,7 +12734,7 @@ exports[`regression tests key o selects ellipse tool: [end of test] appState 1`] Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -12918,7 +12918,7 @@ exports[`regression tests key p selects freedraw tool: [end of test] appState 1` Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "freedraw", }, @@ -13146,7 +13146,7 @@ exports[`regression tests key r selects rectangle tool: [end of test] appState 1 Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -13330,7 +13330,7 @@ exports[`regression tests make a group and duplicate it: [end of test] appState Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -14169,7 +14169,7 @@ exports[`regression tests noop interaction after undo shouldn't create history e Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -14458,7 +14458,7 @@ exports[`regression tests pinch-to-zoom works: [end of test] appState 1`] = ` Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -14569,7 +14569,7 @@ exports[`regression tests rerenders UI on language change: [end of test] appStat Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "rectangle", }, @@ -14678,7 +14678,7 @@ exports[`regression tests shift click on selected element should deselect it on Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -14865,7 +14865,7 @@ exports[`regression tests shift-click to multiselect, then drag: [end of test] a Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -15233,7 +15233,7 @@ exports[`regression tests should group elements and ungroup them: [end of test] Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -15864,7 +15864,7 @@ exports[`regression tests should show fill icons when element has non transparen Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -16090,7 +16090,7 @@ exports[`regression tests single-clicking on a subgroup of a selected group shou Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -17053,7 +17053,7 @@ exports[`regression tests spacebar + drag scrolls the canvas: [end of test] appS Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -17162,7 +17162,7 @@ exports[`regression tests supports nested groups: [end of test] appState 1`] = ` Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -18021,7 +18021,7 @@ exports[`regression tests switches from group of selected elements to another el Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -18493,7 +18493,7 @@ exports[`regression tests switches selected element on pointer down: [end of tes Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -18834,7 +18834,7 @@ exports[`regression tests two-finger scroll works: [end of test] appState 1`] = Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -18945,7 +18945,7 @@ exports[`regression tests undo/redo drawing an element: [end of test] appState 1 Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, @@ -19516,7 +19516,7 @@ exports[`regression tests updates fontSize & fontFamily appState: [end of test] Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "text", }, @@ -19625,7 +19625,7 @@ exports[`regression tests zoom hotkeys: [end of test] appState 1`] = ` Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, diff --git a/src/tests/packages/__snapshots__/utils.test.ts.snap b/src/tests/packages/__snapshots__/utils.test.ts.snap index a74da5dc8..b1002a406 100644 --- a/src/tests/packages/__snapshots__/utils.test.ts.snap +++ b/src/tests/packages/__snapshots__/utils.test.ts.snap @@ -4,7 +4,7 @@ exports[`exportToSvg with default arguments 1`] = ` Object { "activeTool": Object { "customType": null, - "lastActiveToolBeforeEraser": null, + "lastActiveTool": null, "locked": false, "type": "selection", }, diff --git a/src/types.ts b/src/types.ts index 60e25e0ec..49e09a76d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -81,9 +81,9 @@ export type BinaryFileMetadata = Omit; export type BinaryFiles = Record; -export type LastActiveToolBeforeEraser = +export type LastActiveTool = | { - type: typeof SHAPES[number]["value"] | "eraser"; + type: typeof SHAPES[number]["value"] | "eraser" | "hand"; customType: null; } | { @@ -112,19 +112,23 @@ export type AppState = { // (e.g. text element when typing into the input) editingElement: NonDeletedExcalidrawElement | null; editingLinearElement: LinearElementEditor | null; - activeTool: + activeTool: { + /** + * indicates a previous tool we should revert back to if we deselect the + * currently active tool. At the moment applies to `eraser` and `hand` tool. + */ + lastActiveTool: LastActiveTool; + locked: boolean; + } & ( | { - type: typeof SHAPES[number]["value"] | "eraser"; - lastActiveToolBeforeEraser: LastActiveToolBeforeEraser; - locked: boolean; + type: typeof SHAPES[number]["value"] | "eraser" | "hand"; customType: null; } | { type: "custom"; customType: string; - lastActiveToolBeforeEraser: LastActiveToolBeforeEraser; - locked: boolean; - }; + } + ); penMode: boolean; penDetected: boolean; exportBackground: boolean; diff --git a/src/utils.ts b/src/utils.ts index a332e921b..80aa03f1d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -12,10 +12,11 @@ import { WINDOWS_EMOJI_FALLBACK_FONT, } from "./constants"; import { FontFamilyValues, FontString } from "./element/types"; -import { AppState, DataURL, LastActiveToolBeforeEraser, Zoom } from "./types"; +import { AppState, DataURL, LastActiveTool, Zoom } from "./types"; import { unstable_batchedUpdates } from "react-dom"; import { SHAPES } from "./shapes"; import React from "react"; +import { isEraserActive, isHandToolActive } from "./appState"; let mockDateTime: string | null = null; @@ -219,9 +220,9 @@ export const distance = (x: number, y: number) => Math.abs(x - y); export const updateActiveTool = ( appState: Pick, data: ( - | { type: typeof SHAPES[number]["value"] | "eraser" } + | { type: typeof SHAPES[number]["value"] | "eraser" | "hand" } | { type: "custom"; customType: string } - ) & { lastActiveToolBeforeEraser?: LastActiveToolBeforeEraser }, + ) & { lastActiveToolBeforeEraser?: LastActiveTool }, ): AppState["activeTool"] => { if (data.type === "custom") { return { @@ -233,9 +234,9 @@ export const updateActiveTool = ( return { ...appState.activeTool, - lastActiveToolBeforeEraser: + lastActiveTool: data.lastActiveToolBeforeEraser === undefined - ? appState.activeTool.lastActiveToolBeforeEraser + ? appState.activeTool.lastActiveTool : data.lastActiveToolBeforeEraser, type: data.type, customType: null, @@ -305,7 +306,9 @@ export const setCursorForShape = ( } if (appState.activeTool.type === "selection") { resetCursor(canvas); - } else if (appState.activeTool.type === "eraser") { + } else if (isHandToolActive(appState)) { + canvas.style.cursor = CURSOR_TYPE.GRAB; + } else if (isEraserActive(appState)) { setEraserCursor(canvas, appState.theme); // do nothing if image tool is selected which suggests there's // a image-preview set as the cursor From 1db078a3dceb76c53d27932049563ed28a7c4b62 Mon Sep 17 00:00:00 2001 From: David Luzar Date: Mon, 23 Jan 2023 16:54:35 +0100 Subject: [PATCH 9/9] feat: close MainMenu and Library dropdown on item select (#6152) --- src/components/ActiveConfirmDialog.tsx | 35 +++++++++++++ src/components/LayerUI.tsx | 2 + src/components/LibraryMenuHeaderContent.tsx | 1 + .../dropdownMenu/DropdownMenuContent.tsx | 51 +++++++++++-------- .../dropdownMenu/DropdownMenuItem.tsx | 16 +++--- .../dropdownMenu/DropdownMenuItemLink.tsx | 13 ++++- src/components/dropdownMenu/common.ts | 31 +++++++++++ src/components/main-menu/DefaultItems.tsx | 45 +++++----------- src/components/main-menu/MainMenu.tsx | 20 +++++++- src/constants.ts | 1 + src/packages/excalidraw/CHANGELOG.md | 6 +++ src/utils.ts | 19 +++++++ 12 files changed, 178 insertions(+), 62 deletions(-) create mode 100644 src/components/ActiveConfirmDialog.tsx create mode 100644 src/components/dropdownMenu/common.ts diff --git a/src/components/ActiveConfirmDialog.tsx b/src/components/ActiveConfirmDialog.tsx new file mode 100644 index 000000000..3c79a5190 --- /dev/null +++ b/src/components/ActiveConfirmDialog.tsx @@ -0,0 +1,35 @@ +import { atom, useAtom } from "jotai"; +import { actionClearCanvas } from "../actions"; +import { t } from "../i18n"; +import { useExcalidrawActionManager } from "./App"; +import ConfirmDialog from "./ConfirmDialog"; + +export const activeConfirmDialogAtom = atom<"clearCanvas" | null>(null); + +export const ActiveConfirmDialog = () => { + const [activeConfirmDialog, setActiveConfirmDialog] = useAtom( + activeConfirmDialogAtom, + ); + const actionManager = useExcalidrawActionManager(); + + if (!activeConfirmDialog) { + return null; + } + + if (activeConfirmDialog === "clearCanvas") { + return ( + { + actionManager.executeAction(actionClearCanvas); + setActiveConfirmDialog(null); + }} + onCancel={() => setActiveConfirmDialog(null)} + title={t("clearCanvasDialog.title")} + > +

{t("alerts.clearReset")}

+
+ ); + } + + return null; +}; diff --git a/src/components/LayerUI.tsx b/src/components/LayerUI.tsx index 140f28e91..3defb2947 100644 --- a/src/components/LayerUI.tsx +++ b/src/components/LayerUI.tsx @@ -50,6 +50,7 @@ import { hostSidebarCountersAtom } from "./Sidebar/Sidebar"; import { jotaiScope } from "../jotai"; import { useAtom } from "jotai"; import MainMenu from "./main-menu/MainMenu"; +import { ActiveConfirmDialog } from "./ActiveConfirmDialog"; import { HandButton } from "./HandButton"; import { isHandToolActive } from "../appState"; @@ -394,6 +395,7 @@ const LayerUI = ({ }} /> )} + {renderImageExportDialog()} {renderJSONExportDialog()} {appState.pasteDialog.shown && ( diff --git a/src/components/LibraryMenuHeaderContent.tsx b/src/components/LibraryMenuHeaderContent.tsx index beeb8dd17..43ea96899 100644 --- a/src/components/LibraryMenuHeaderContent.tsx +++ b/src/components/LibraryMenuHeaderContent.tsx @@ -187,6 +187,7 @@ export const LibraryMenuHeader: React.FC<{ setIsLibraryMenuOpen(false)} + onSelect={() => setIsLibraryMenuOpen(false)} className="library-menu" > {!itemsSelected && ( diff --git a/src/components/dropdownMenu/DropdownMenuContent.tsx b/src/components/dropdownMenu/DropdownMenuContent.tsx index 873a99d8d..8ec2b6e63 100644 --- a/src/components/dropdownMenu/DropdownMenuContent.tsx +++ b/src/components/dropdownMenu/DropdownMenuContent.tsx @@ -4,16 +4,23 @@ import { Island } from "../Island"; import { useDevice } from "../App"; import clsx from "clsx"; import Stack from "../Stack"; +import React from "react"; +import { DropdownMenuContentPropsContext } from "./common"; const MenuContent = ({ children, onClickOutside, className = "", + onSelect, style, }: { children?: React.ReactNode; onClickOutside?: () => void; className?: string; + /** + * Called when any menu item is selected (clicked on). + */ + onSelect?: (event: Event) => void; style?: React.CSSProperties; }) => { const device = useDevice(); @@ -24,28 +31,32 @@ const MenuContent = ({ const classNames = clsx(`dropdown-menu ${className}`, { "dropdown-menu--mobile": device.isMobile, }).trim(); + return ( -
- {/* the zIndex ensures this menu has higher stacking order, + +
+ {/* the zIndex ensures this menu has higher stacking order, see https://github.com/excalidraw/excalidraw/pull/1445 */} - {device.isMobile ? ( - {children} - ) : ( - - {children} - - )} -
+ {device.isMobile ? ( + {children} + ) : ( + + {children} + + )} +
+ ); }; -export default MenuContent; MenuContent.displayName = "DropdownMenuContent"; + +export default MenuContent; diff --git a/src/components/dropdownMenu/DropdownMenuItem.tsx b/src/components/dropdownMenu/DropdownMenuItem.tsx index 4f8db982d..9a8e92462 100644 --- a/src/components/dropdownMenu/DropdownMenuItem.tsx +++ b/src/components/dropdownMenu/DropdownMenuItem.tsx @@ -1,10 +1,10 @@ import React from "react"; +import { + getDrodownMenuItemClassName, + useHandleDropdownMenuItemClick, +} from "./common"; import MenuItemContent from "./DropdownMenuItemContent"; -export const getDrodownMenuItemClassName = (className = "") => { - return `dropdown-menu-item dropdown-menu-item-base ${className}`.trim(); -}; - const DropdownMenuItem = ({ icon, onSelect, @@ -14,15 +14,17 @@ const DropdownMenuItem = ({ ...rest }: { icon?: JSX.Element; - onSelect: () => void; + onSelect: (event: Event) => void; children: React.ReactNode; shortcut?: string; className?: string; -} & React.ButtonHTMLAttributes) => { +} & Omit, "onSelect">) => { + const handleClick = useHandleDropdownMenuItemClick(rest.onClick, onSelect); + return (