From 23e4915d60d70dbde3afd7b6c5aeb2d0877f3076 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Wed, 14 Jul 2021 11:10:03 +0200 Subject: [PATCH 01/35] :arrow_up: Set next version number (1.8.0) --- version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.txt b/version.txt index d9c26f23be..1d16151a4e 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.7.0-alpha +1.8.0-alpha From 9ec23ceed64e28c230f18f1a3263056fad2d527e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 14 Jul 2021 14:15:53 +0200 Subject: [PATCH 02/35] :bug: Hide popup messages when navigating out --- frontend/src/app/main/data/messages.cljs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/main/data/messages.cljs b/frontend/src/app/main/data/messages.cljs index 1a834fa3c6..acd1564306 100644 --- a/frontend/src/app/main/data/messages.cljs +++ b/frontend/src/app/main/data/messages.cljs @@ -52,11 +52,17 @@ ptk/WatchEvent (watch [_ _ stream] - (when (:timeout data) - (let [stoper (rx/filter (ptk/type? ::show) stream)] - (->> (rx/of hide) - (rx/delay (:timeout data)) - (rx/take-until stoper))))))) + (rx/merge + (let [stoper (rx/filter (ptk/type? ::hide) stream)] + (->> stream + (rx/filter (ptk/type? :app.util.router/navigate)) + (rx/map (constantly hide)) + (rx/take-until stoper))) + (when (:timeout data) + (let [stoper (rx/filter (ptk/type? ::show) stream)] + (->> (rx/of hide) + (rx/delay (:timeout data)) + (rx/take-until stoper)))))))) (def hide (ptk/reify ::hide From 69e256ab8604d3c18fc455a288b04fbca3c823e6 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 12 Jul 2021 12:38:41 +0200 Subject: [PATCH 03/35] :sparkles: Moves cursor to position when clicking in the text box --- .../src/app/main/data/workspace/texts.cljs | 7 ++++++ .../main/ui/workspace/shapes/text/editor.cljs | 10 ++++++-- frontend/src/app/util/text_editor.cljs | 4 +++ frontend/src/app/util/text_editor_impl.js | 25 +++++++++++++++++++ 4 files changed, 44 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index f928c01cec..289800da83 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -101,6 +101,13 @@ (update [_ state] (d/update-in-when state [:workspace-editor-state id] ted/editor-select-all)))) +(defn cursor-to-end + [{:keys [id] :as shape}] + (ptk/reify ::cursor-to-end + ptk/UpdateEvent + (update [_ state] + (d/update-in-when state [:workspace-editor-state id] ted/cursor-to-end)))) + ;; --- Helpers (defn- shape-current-values diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 2859344226..0ba3a332f6 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -126,7 +126,13 @@ (fn [_ state] (st/emit! (dwt/update-editor-state shape (ted/editor-split-block state))) "handled")) - ] + + on-click + (mf/use-callback + (fn [event] + (when (dom/class? (dom/get-target event) "DraftEditor-root") + (st/emit! (dwt/cursor-to-end shape))) + (st/emit! (dwt/focus-editor))))] (mf/use-layout-effect on-mount) @@ -135,7 +141,7 @@ :style {:cursor cur/text :width (:width shape) :height (:height shape)} - :on-click (st/emitf (dwt/focus-editor)) + :on-click on-click :class (dom/classnames :align-top (= (:vertical-align content "top") "top") :align-center (= (:vertical-align content) "center") diff --git a/frontend/src/app/util/text_editor.cljs b/frontend/src/app/util/text_editor.cljs index 370f17f2de..c5336cf68a 100644 --- a/frontend/src/app/util/text_editor.cljs +++ b/frontend/src/app/util/text_editor.cljs @@ -92,3 +92,7 @@ (defn remove-editor-blur-selection [state] (impl/removeBlurSelectionEntity state)) + +(defn cursor-to-end + [state] + (impl/cursorToEnd state)) diff --git a/frontend/src/app/util/text_editor_impl.js b/frontend/src/app/util/text_editor_impl.js index 9255ec621b..c966f05278 100644 --- a/frontend/src/app/util/text_editor_impl.js +++ b/frontend/src/app/util/text_editor_impl.js @@ -56,6 +56,18 @@ function getSelectAllSelection(state) { }); } +function getCursorInEndPosition(state) { + const content = state.getCurrentContent(); + const lastBlock = content.getBlockMap().last(); + + return new SelectionState({ + "anchorKey": lastBlock.getKey(), + "anchorOffset": lastBlock.getLength(), + "focusKey": lastBlock.getKey(), + "focusOffset": lastBlock.getLength() + }); +} + export function selectAll(state) { return EditorState.forceSelection(state, getSelectAllSelection(state)); } @@ -209,3 +221,16 @@ export function removeInlineStylePrefix(contentState, selectionState, stylePrefi return block.set("characterList", chars); }); } + +export function cursorToEnd(state) { + const newSelection = getCursorInEndPosition(state); + const selection = state.getSelection(); + + let content = state.getCurrentContent(); + content = Modifier.applyEntity(content, newSelection, null); + + state = EditorState.forceSelection(state, newSelection); + state = EditorState.push(state, content, "apply-entity"); + + return state; +} From 26467187c48687e4eae1f01dab62e5b577838587 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 14 Jul 2021 14:45:03 +0200 Subject: [PATCH 04/35] :sparkles: Fix text editor issues --- .../src/app/main/data/workspace/texts.cljs | 10 ++ .../main/ui/workspace/shapes/text/editor.cljs | 67 +++++++-- .../workspace/sidebar/options/menus/text.cljs | 5 +- frontend/src/app/util/text_editor.cljs | 36 ++++- frontend/src/app/util/text_editor_impl.js | 127 ++++++++++++++++-- 5 files changed, 218 insertions(+), 27 deletions(-) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 289800da83..11dad4b706 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -316,3 +316,13 @@ (rx/race resize-batch change-page) (rx/of #(dissoc % ::handling-texts)))) (rx/empty)))))) + +(defn save-font + [data] + (ptk/reify ::save-font + ptk/UpdateEvent + (update [_ state] + ;; Check if the data has any multiple + (assoc-in state + [:workspace-local :defaults :font] + data)))) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 0ba3a332f6..26617eb3e3 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -7,6 +7,7 @@ (ns app.main.ui.workspace.shapes.text.editor (:require ["draft-js" :as draft] + [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.common.text :as txt] [app.main.data.workspace :as dw] @@ -32,7 +33,7 @@ (let [bprops (obj/get props "blockProps") data (obj/get bprops "data") style (sts/generate-paragraph-styles (obj/get bprops "shape") - (obj/get bprops "data")) + (obj/get bprops "data")) dir (:text-direction data "auto")] @@ -56,12 +57,35 @@ :shape shape}} nil))) +(defn styles-fn [styles content] + (if (= (.getText content) "") + (-> (.getData content) + (.toJS) + (js->clj :keywordize-keys true) + (sts/generate-text-styles)) + (-> (txt/styles-to-attrs styles) + (sts/generate-text-styles)))) + (def default-decorator (ted/create-decorator "PENPOT_SELECTION" selection-component)) (def empty-editor-state (ted/create-editor-state nil default-decorator)) +(defn get-content-changes + [old-state state] + (let [old-blocks (js->clj (.toJS (.getBlockMap (.getCurrentContent ^js old-state))) + :keywordize-keys false) + new-blocks (js->clj (.toJS (.getBlockMap (.getCurrentContent ^js state))) + :keywordize-keys false)] + (->> old-blocks + (d/mapm + (fn [bkey bstate] + {:old (get bstate "text") + :new (get-in new-blocks [bkey "text"])})) + (filter #(contains? new-blocks (first %))) + (into {})))) + (mf/defc text-shape-edit-html {::mf/wrap [mf/memo] ::mf/wrap-props false @@ -106,13 +130,38 @@ (fn [_] (reset! blured false))) + prev-value (mf/use-ref state) + + ;; Effect that keeps updated the `prev-value` reference + _ (mf/use-effect + (mf/deps state) + #(mf/set-ref-val! prev-value state)) + + handle-change + (mf/use-callback + (fn [state] + (let [old-state (mf/ref-val prev-value)] + (if (and (some? state) (some? old-state)) + (let [block-states (get-content-changes old-state state) + + block-to-add-styles + (->> block-states + (filter + (fn [[_ v]] + (and (not= (:old v) (:new v)) + (= (:old v) "")))) + (mapv first))] + (ted/apply-block-styles-to-content state block-to-add-styles)) + state)))) + on-change (mf/use-callback (fn [val] - (let [val (if (true? @blured) - (ted/add-editor-blur-selection val) - (ted/remove-editor-blur-selection val))] - (st/emit! (dwt/update-editor-state shape val))))) + (let [val (handle-change val)] + (let [val (if (true? @blured) + (ted/add-editor-blur-selection val) + (ted/remove-editor-blur-selection val))] + (st/emit! (dwt/update-editor-state shape val)))))) on-editor (mf/use-callback @@ -124,7 +173,9 @@ handle-return (mf/use-callback (fn [_ state] - (st/emit! (dwt/update-editor-state shape (ted/editor-split-block state))) + (let [state (ted/editor-split-block state) + state (handle-change state)] + (st/emit! (dwt/update-editor-state shape state))) "handled")) on-click @@ -152,9 +203,7 @@ :on-focus on-focus :handle-return handle-return :strip-pasted-styles true - :custom-style-fn (fn [styles _] - (-> (txt/styles-to-attrs styles) - (sts/generate-text-styles))) + :custom-style-fn styles-fn :block-renderer-fn #(render-block % shape) :ref on-editor :editor-state state}]])) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs index d9f9ec455b..6bd83ade72 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs @@ -220,7 +220,10 @@ emit-update! (mf/use-callback + (mf/deps values) (fn [id attrs] + (st/emit! (dwt/save-font (merge values attrs))) + (let [attrs (select-keys attrs root-attrs)] (when-not (empty? attrs) (st/emit! (dwt/update-root-attrs {:id id :attrs attrs})))) @@ -235,7 +238,7 @@ on-change (mf/use-callback - (mf/deps ids) + (mf/deps ids emit-update!) (fn [attrs] (run! #(emit-update! % attrs) ids))) diff --git a/frontend/src/app/util/text_editor.cljs b/frontend/src/app/util/text_editor.cljs index c5336cf68a..790609f6f2 100644 --- a/frontend/src/app/util/text_editor.cljs +++ b/frontend/src/app/util/text_editor.cljs @@ -70,8 +70,11 @@ (defn get-editor-current-inline-styles [state] - (-> (.getCurrentInlineStyle ^js state) - (txt/styles-to-attrs))) + (if (impl/isCurrentEmpty state) + (let [block (impl/getCurrentBlock state)] + (get-editor-block-data block)) + (-> (.getCurrentInlineStyle ^js state) + (txt/styles-to-attrs)))) (defn update-editor-current-block-data [state attrs] @@ -79,7 +82,18 @@ (defn update-editor-current-inline-styles [state attrs] - (impl/applyInlineStyle state (txt/attrs-to-styles attrs))) + (let [update-blocks + (fn [state block-key] + (if (empty? (impl/getBlockContent state block-key)) + (impl/updateBlockData state block-key (clj->js attrs)) + + (let [attrs (-> (impl/getInlineStyle state block-key 0) + (txt/styles-to-attrs))] + (impl/updateBlockData state block-key (clj->js attrs))))) + + state (impl/applyInlineStyle state (txt/attrs-to-styles attrs)) + selected (impl/getSelectedBlocks state)] + (reduce update-blocks state selected))) (defn editor-split-block [state] @@ -96,3 +110,19 @@ (defn cursor-to-end [state] (impl/cursorToEnd state)) + +(defn apply-block-styles-to-content + [state blocks] + (if (empty? blocks) + state + (let [selection (impl/getSelection state) + redfn + (fn [state bkey] + (let [attrs (-> (impl/getBlockData state bkey) + (js->clj :keywordize-keys true))] + (-> state + (impl/selectBlock bkey) + (impl/applyInlineStyle (txt/attrs-to-styles attrs)))))] + (as-> state $ + (reduce redfn $ blocks) + (impl/setSelection $ selection))))) diff --git a/frontend/src/app/util/text_editor_impl.js b/frontend/src/app/util/text_editor_impl.js index c966f05278..6eb1983cb4 100644 --- a/frontend/src/app/util/text_editor_impl.js +++ b/frontend/src/app/util/text_editor_impl.js @@ -22,6 +22,23 @@ function isDefined(v) { return v !== undefined && v !== null; } +function mergeBlockData(block, newData) { + let data = block.getData(); + + for (let key of Object.keys(newData)) { + const oldVal = data.get(key); + if (oldVal === newData[key]) { + data = data.delete(key); + } else { + data = data.set(key, newData[key]); + } + } + + return block.merge({ + data: data + }); +} + export function createEditorState(content, decorator) { if (content === null) { return EditorState.createEmpty(decorator); @@ -95,26 +112,19 @@ export function updateCurrentBlockData(state, attrs) { let content = state.getCurrentContent(); content = modifySelectedBlocks(content, selection, (block) => { - let data = block.getData(); - for (let key of Object.keys(attrs)) { - const oldVal = data.get(key); - if (oldVal === attrs[key]) { - data = data.delete(key); - } else { - data = data.set(key, attrs[key]); - } - } - - return block.merge({ - data: data - }); + return mergeBlockData(block, attrs); }); return EditorState.push(state, content, "change-block-data"); } export function applyInlineStyle(state, styles) { - const selection = state.getSelection(); + let selection = state.getSelection(); + + if (selection.isCollapsed()) { + selection = selection.set("anchorOffset", 0); + } + let content = null; for (let style of styles) { @@ -234,3 +244,92 @@ export function cursorToEnd(state) { return state; } + +export function isCurrentEmpty(state) { + const selection = state.getSelection(); + + if (!selection.isCollapsed()) { + return false; + } + + const blockKey = selection.getStartKey(); + const content = state.getCurrentContent(); + + const block = content.getBlockForKey(blockKey); + + return block.getText() === ""; +} + +/* + Returns the block keys between a selection +*/ +export function getSelectedBlocks(state) { + const selection = state.getSelection(); + const startKey = selection.getStartKey(); + const endKey = selection.getEndKey(); + const content = state.getCurrentContent(); + const result = [ startKey ]; + + let currentKey = startKey; + + while (currentKey !== endKey) { + const currentBlock = content.getBlockAfter(currentKey); + currentKey = currentBlock.getKey(); + result.push(currentKey); + } + + return result; +} + +export function getBlockContent(state, blockKey) { + const content = state.getCurrentContent(); + const block = content.getBlockForKey(blockKey); + return block.getText(); +} + +export function getBlockData(state, blockKey) { + const content = state.getCurrentContent(); + const block = content.getBlockForKey(blockKey); + return block && block.getData().toJS(); +} + +export function updateBlockData(state, blockKey, data) { + const userSelection = state.getSelection(); + const content = state.getCurrentContent(); + const block = content.getBlockForKey(blockKey); + const newBlock = mergeBlockData(block, data); + + const blockData = newBlock.getData(); + + const newContent = Modifier.setBlockData( + state.getCurrentContent(), + SelectionState.createEmpty(blockKey), + blockData + ); + + const result = EditorState.push(state, newContent, 'change-block-data'); + return EditorState.acceptSelection(result, userSelection) +} + +export function getSelection(state) { + return state.getSelection(); +} + +export function setSelection(state, selection) { + return EditorState.acceptSelection(state, selection); +} + +export function selectBlock(state, blockKey) { + const block = state.getCurrentContent().getBlockForKey(blockKey); + const length = block.getText().length; + const selection = SelectionState.createEmpty(blockKey).merge({ + focusOffset: length + }); + return EditorState.acceptSelection(state, selection); +} + +export function getInlineStyle(state, blockKey, offset) { + const content = state.getCurrentContent(); + const block = content.getBlockForKey(blockKey); + return block.getInlineStyleAt(offset).toJS(); +} From 9ebafddac21d99f6772d38cdce97d8939317d376 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Wed, 14 Jul 2021 21:51:30 +0200 Subject: [PATCH 05/35] :sparkles: Make last font used the default for next text box --- common/src/app/common/text.cljc | 3 ++- frontend/src/app/main/data/workspace.cljs | 18 ++++++++++++++---- .../src/app/main/data/workspace/texts.cljs | 14 +++++++++----- .../src/app/main/ui/shapes/text/styles.cljs | 4 ++-- .../workspace/sidebar/options/menus/text.cljs | 2 +- .../workspace/sidebar/options/shapes/text.cljs | 2 ++ frontend/src/app/util/text_editor_impl.js | 2 +- 7 files changed, 31 insertions(+), 14 deletions(-) diff --git a/common/src/app/common/text.cljc b/common/src/app/common/text.cljc index 9f184e7e9d..f4c450f1a1 100644 --- a/common/src/app/common/text.cljc +++ b/common/src/app/common/text.cljc @@ -64,7 +64,8 @@ (defn ^boolean is-text-node? [node] - (string? (:text node))) + (and (string? (:text node)) + (not= (:text node) ""))) (defn ^boolean is-paragraph-node? [node] diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 7c0a57c7d9..8ec75ebf37 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -207,7 +207,16 @@ :workspace-file :workspace-project :workspace-media-objects - :workspace-persistence)) + :workspace-persistence + :workspace-local + :workspace-data + :workspace-editor-state + :workspace-undo + :current-file-id + :current-project-id + :workspace-layout + :workspace-libraries + :workspace-presence)) ptk/WatchEvent (watch [_ _ _] @@ -242,9 +251,10 @@ (update [_ state] (let [page-id (or page-id (get-in state [:workspace-data :pages 0])) local (-> (:workspace-local state) - (dissoc :edition) - (dissoc :edit-path) - (dissoc :selected))] + (dissoc + :edition + :edit-path + :selected))] (-> state (assoc-in [:workspace-cache page-id] local) (dissoc :current-page-id :workspace-local :trimmed-page :workspace-drawing)))))) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 11dad4b706..390e415db4 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -75,11 +75,14 @@ (ptk/reify ::initialize-editor-state ptk/UpdateEvent (update [_ state] - (update-in state [:workspace-editor-state id] - (fn [_] - (ted/create-editor-state - (some->> content ted/import-content) - decorator)))) + (let [text-state (some->> content ted/import-content) + attrs (get-in state [:workspace-local :defaults :font]) + + editor (cond-> (ted/create-editor-state text-state decorator) + (and (nil? content) (some? attrs)) + (ted/update-editor-current-block-data attrs))] + (-> state + (assoc-in [:workspace-editor-state id] editor)))) ptk/WatchEvent (watch [_ _ stream] @@ -326,3 +329,4 @@ (assoc-in state [:workspace-local :defaults :font] data)))) + diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index 9d247e13fd..ec76c8f610 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -47,8 +47,8 @@ text-align (:text-align data "start") grow-type (:grow-type shape) - base #js {:fontSize (str (:font-size txt/default-text-attrs) "px") - :lineHeight (:line-height txt/default-text-attrs) + base #js {:fontSize (str (:font-size data (:font-size txt/default-text-attrs)) "px") + :lineHeight (:line-height data (:line-height txt/default-text-attrs)) :margin "inherit"}] (cond-> base (some? line-height) (obj/set! "lineHeight" line-height) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs index 6bd83ade72..ac2dc026fe 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs @@ -222,7 +222,7 @@ (mf/use-callback (mf/deps values) (fn [id attrs] - (st/emit! (dwt/save-font (merge values attrs))) + (st/emit! (dwt/save-font (merge txt/default-text-attrs values attrs))) (let [attrs (select-keys attrs root-attrs)] (when-not (empty? attrs) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs index 2989834322..a15c66e02a 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs @@ -9,6 +9,7 @@ [app.common.data :as d] [app.main.data.workspace.texts :as dwt] [app.main.refs :as refs] + [app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]] @@ -42,6 +43,7 @@ text-values (d/merge (select-keys shape [:grow-type]) + (select-keys shape fill-attrs) (dwt/current-root-values {:shape shape :attrs root-attrs}) diff --git a/frontend/src/app/util/text_editor_impl.js b/frontend/src/app/util/text_editor_impl.js index 6eb1983cb4..3c735b97cf 100644 --- a/frontend/src/app/util/text_editor_impl.js +++ b/frontend/src/app/util/text_editor_impl.js @@ -122,7 +122,7 @@ export function applyInlineStyle(state, styles) { let selection = state.getSelection(); if (selection.isCollapsed()) { - selection = selection.set("anchorOffset", 0); + selection = getSelectAllSelection(state); } let content = null; From 1fc518297926f1051c3b959f18299b4ffc24df6c Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 16 Jul 2021 13:09:57 +0200 Subject: [PATCH 06/35] :bug: Fix text focus issues --- backend/src/app/loggers/mattermost.clj | 2 +- common/src/app/common/pages/migrations.cljc | 2 +- .../src/app/main/data/workspace/texts.cljs | 13 +++--- .../main/ui/components/editable_select.cljs | 37 ++++++++++++---- .../main/ui/workspace/shapes/text/editor.cljs | 10 ++--- .../workspace/sidebar/options/menus/text.cljs | 42 +++++++++++++------ .../sidebar/options/menus/typography.cljs | 41 ++++++++++++------ .../sidebar/options/shapes/text.cljs | 3 +- frontend/src/app/util/dom.cljs | 11 +++-- frontend/src/app/util/text_editor_impl.js | 14 ++++--- 10 files changed, 118 insertions(+), 57 deletions(-) diff --git a/backend/src/app/loggers/mattermost.clj b/backend/src/app/loggers/mattermost.clj index fc0109bdda..f4a60e5c1f 100644 --- a/backend/src/app/loggers/mattermost.clj +++ b/backend/src/app/loggers/mattermost.clj @@ -60,7 +60,7 @@ (a/close! output))) (defn- send-mattermost-notification! - [cfg {:keys [host version id] :as cdata}] + [cfg {:keys [host id] :as cdata}] (try (let [uri (:uri cfg) text (str "Unhandled exception (host: " host ", url: " (cfg/get :public-uri) "/dbg/error-by-id/" id "\n" diff --git a/common/src/app/common/pages/migrations.cljc b/common/src/app/common/pages/migrations.cljc index f06c79563f..104e1fe4c5 100644 --- a/common/src/app/common/pages/migrations.cljc +++ b/common/src/app/common/pages/migrations.cljc @@ -258,7 +258,7 @@ (defmethod migrate 11 [data] - (letfn [(update-object [objects id shape] + (letfn [(update-object [objects _id shape] (if (= :frame (:type shape)) (d/update-when shape :shapes (fn [shapes] (filterv (fn [id] (contains? objects id)) shapes))) diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 390e415db4..1163a56873 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -203,8 +203,11 @@ (when-not (some? (get-in state [:workspace-editor-state id])) (let [objects (wsh/lookup-page-objects state) shape (get objects id) + update-node? (fn [node] + (or (txt/is-text-node? node) + (txt/is-paragraph-node? node))) - update-fn #(update-shape % txt/is-text-node? attrs/merge attrs) + update-fn #(update-shape % update-node? attrs/merge attrs) shape-ids (cond (= (:type shape) :text) [id] (= (:type shape) :group) (cp/get-children id objects))] (rx/of (dch/update-shapes shape-ids update-fn))))))) @@ -325,8 +328,8 @@ (ptk/reify ::save-font ptk/UpdateEvent (update [_ state] - ;; Check if the data has any multiple - (assoc-in state - [:workspace-local :defaults :font] - data)))) + (let [multiple? (->> data vals (d/seek #(= % :multiple)))] + (cond-> state + (not multiple?) + (assoc-in [:workspace-local :defaults :font] data)))))) diff --git a/frontend/src/app/main/ui/components/editable_select.cljs b/frontend/src/app/main/ui/components/editable_select.cljs index 40c13e7702..127e0e403e 100644 --- a/frontend/src/app/main/ui/components/editable_select.cljs +++ b/frontend/src/app/main/ui/components/editable_select.cljs @@ -14,19 +14,23 @@ [app.util.timers :as timers] [rumext.alpha :as mf])) -(mf/defc editable-select [{:keys [value type options class on-change placeholder]}] +(mf/defc editable-select [{:keys [value type options class on-change placeholder on-blur]}] (let [state (mf/use-state {:id (uuid/next) :is-open? false :current-value value :top nil :left nil :bottom nil}) + + emit-blur? (mf/use-ref nil) + open-dropdown #(swap! state assoc :is-open? true) close-dropdown #(swap! state assoc :is-open? false) select-item (fn [value] (fn [_] (swap! state assoc :current-value value) - (when on-change (on-change value)))) + (when on-change (on-change value)) + (when on-blur (on-blur)))) as-key-value (fn [item] (if (map? item) [(:value item) (:label item)] [item item])) @@ -55,21 +59,38 @@ assoc :left left :top top - :bottom bottom))))))] + :bottom bottom)))))) + + handle-focus + (mf/use-callback + (fn [] + (mf/set-ref-val! emit-blur? false))) + + handle-blur + (mf/use-callback + (fn [] + (mf/set-ref-val! emit-blur? true) + (timers/schedule + 200 + (fn [] + (when (and on-blur (mf/ref-val emit-blur?)) (on-blur))))))] (mf/use-effect - (mf/deps value) - #(reset! state {:current-value value})) + (mf/deps value (:current-value @state)) + #(when (not= value (:current-value @state)) + (reset! state {:current-value value}))) (mf/use-effect - (mf/deps options) - #(reset! state {:is-open? false - :current-value value})) + (mf/deps (:is-open? @state)) + (fn [] + (mf/set-ref-val! emit-blur? (not (:is-open? @state))))) [:div.editable-select {:class class :ref on-node-load} [:input.input-text {:value (or (-> @state :current-value value->label) "") :on-change handle-change-input + :on-focus handle-focus + :on-blur handle-blur :placeholder placeholder :type type}] [:span.dropdown-button {:on-click open-dropdown} i/arrow-down] diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 26617eb3e3..e2321b4de6 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -157,11 +157,11 @@ on-change (mf/use-callback (fn [val] - (let [val (handle-change val)] - (let [val (if (true? @blured) - (ted/add-editor-blur-selection val) - (ted/remove-editor-blur-selection val))] - (st/emit! (dwt/update-editor-state shape val)))))) + (let [val (handle-change val) + val (if (true? @blured) + (ted/add-editor-blur-selection val) + (ted/remove-editor-blur-selection val))] + (st/emit! (dwt/update-editor-state shape val))))) on-editor (mf/use-callback diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs index ac2dc026fe..5f55a9ab2e 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/text.cljs @@ -20,6 +20,7 @@ [app.main.ui.workspace.sidebar.options.menus.typography :refer [typography-entry typography-options]] [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] + [app.util.timers :as tm] [cuerdas.core :as str] [rumext.alpha :as mf])) @@ -80,11 +81,12 @@ (def attrs (d/concat #{} shape-attrs root-attrs paragraph-attrs text-attrs)) (mf/defc text-align-options - [{:keys [values on-change] :as props}] + [{:keys [values on-change on-blur] :as props}] (let [{:keys [text-align]} values handle-change (fn [_ new-align] - (on-change {:text-align new-align}))] + (on-change {:text-align new-align}) + (when (some? on-blur) (on-blur)))] ;; --- Align [:div.align-icons @@ -110,10 +112,12 @@ i/text-align-justify]])) (mf/defc text-direction-options - [{:keys [values on-change] :as props}] + [{:keys [values on-change on-blur] :as props}] (let [direction (:text-direction values) - handle-change (fn [_ val] - (on-change {:text-direction val}))] + handle-change + (fn [_ val] + (on-change {:text-direction val}) + (when (some? on-blur) (on-blur)))] ;; --- Align [:div.align-icons [:span.tooltip.tooltip-bottom-left @@ -128,12 +132,13 @@ i/text-direction-rtl]])) (mf/defc vertical-align - [{:keys [values on-change] :as props}] + [{:keys [values on-change on-blur] :as props}] (let [{:keys [vertical-align]} values vertical-align (or vertical-align "top") handle-change (fn [_ new-align] - (on-change {:vertical-align new-align}))] + (on-change {:vertical-align new-align}) + (when (some? on-blur) (on-blur)))] [:div.align-icons [:span.tooltip.tooltip-bottom-left @@ -153,11 +158,12 @@ i/align-bottom]])) (mf/defc grow-options - [{:keys [ids values] :as props}] + [{:keys [ids values on-blur] :as props}] (let [grow-type (:grow-type values) handle-change-grow (fn [_ grow-type] - (st/emit! (dch/update-shapes ids #(assoc % :grow-type grow-type))))] + (st/emit! (dch/update-shapes ids #(assoc % :grow-type grow-type))) + (when (some? on-blur) (on-blur)))] [:div.align-icons [:span.tooltip.tooltip-bottom @@ -177,11 +183,12 @@ i/auto-height]])) (mf/defc text-decoration-options - [{:keys [values on-change] :as props}] + [{:keys [values on-change on-blur] :as props}] (let [text-decoration (or (:text-decoration values) "none") handle-change (fn [_ type] - (on-change {:text-decoration type}))] + (on-change {:text-decoration type}) + (when (some? on-blur) (on-blur)))] [:div.align-icons [:span.tooltip.tooltip-bottom {:alt (tr "workspace.options.text-options.none") @@ -222,7 +229,8 @@ (mf/use-callback (mf/deps values) (fn [id attrs] - (st/emit! (dwt/save-font (merge txt/default-text-attrs values attrs))) + (st/emit! (dwt/save-font (-> (merge txt/default-text-attrs values attrs) + (select-keys text-attrs)))) (let [attrs (select-keys attrs root-attrs)] (when-not (empty? attrs) @@ -290,7 +298,15 @@ opts #js {:ids ids :values values - :on-change on-change}] + :on-change on-change + :on-blur + (fn [] + (tm/schedule + 100 + (fn [] + (when (not= "INPUT" (-> (dom/get-active) (dom/get-tag-name))) + (let [node (dom/get-element-by-class "public-DraftEditor-content")] + (dom/focus! node))))))}] [:div.element-set [:div.element-set-title diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs index ca5e77631a..68c503fcca 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs @@ -230,7 +230,7 @@ :current? (= (:id font) (:id selected))}]))) (mf/defc font-options - [{:keys [values on-change] :as props}] + [{:keys [values on-change on-blur] :as props}] (let [{:keys [font-id font-size font-variant-id]} values font-id (or font-id (:font-id txt/default-text-attrs)) @@ -271,18 +271,26 @@ :font-family (:family font) :font-variant-id new-variant-id :font-weight (:weight variant) - :font-style (:style variant)})))) + :font-style (:style variant)}) + (dom/blur! (dom/get-target event))))) on-font-select (mf/use-callback (mf/deps change-font) (fn [font*] (when (not= font font*) - (change-font (:id font*))))) + (change-font (:id font*))) + + (when (some? on-blur) + (on-blur)))) on-font-selector-close (mf/use-callback - #(reset! open-selector? false))] + (fn [] + (reset! open-selector? false) + (when (some? on-blur) + (on-blur)) + ))] [:* (when @open-selector? @@ -314,12 +322,14 @@ :options size-options :type "number" :placeholder "--" - :on-change on-font-size-change}]) + :on-change on-font-size-change + :on-blur on-blur}]) [:select.input-select.variant-option {:disabled (= font-id :multiple) :value (attr->string font-variant-id) - :on-change on-font-variant-change} + :on-change on-font-variant-change + :on-blur on-blur} (when (or (= font-id :multiple) (= font-variant-id :multiple)) [:option {:value ""} "--"]) (for [variant (:variants font)] @@ -329,7 +339,7 @@ (mf/defc spacing-options - [{:keys [values on-change] :as props}] + [{:keys [values on-change on-blur] :as props}] (let [{:keys [line-height letter-spacing]} values @@ -353,7 +363,8 @@ :max "200" :value (attr->string line-height) :placeholder (tr "settings.multiple") - :on-change #(handle-change % :line-height)}]] + :on-change #(handle-change % :line-height) + :on-blur on-blur}]] [:div.input-icon [:span.icon-before.tooltip.tooltip-bottom @@ -366,18 +377,21 @@ :max "200" :value (attr->string letter-spacing) :placeholder (tr "settings.multiple") - :on-change #(handle-change % :letter-spacing)}]]])) + :on-change #(handle-change % :letter-spacing) + :on-blur on-blur}]]])) (mf/defc text-transform-options - [{:keys [values on-change] :as props}] + [{:keys [values on-change on-blur] :as props}] (let [text-transform (or (:text-transform values) "none") handle-change (fn [_ type] - (on-change {:text-transform type}))] + (on-change {:text-transform type}) + (when (some? on-blur) (on-blur)))] [:div.align-icons [:span.tooltip.tooltip-bottom {:alt (tr "workspace.options.text-options.none") :class (dom/classnames :current (= "none" text-transform)) + :focus #(dom/prevent-default %) :on-click #(handle-change % "none")} i/minus] [:span.tooltip.tooltip-bottom @@ -397,11 +411,12 @@ i/titlecase]])) (mf/defc typography-options - [{:keys [ids editor values on-change]}] + [{:keys [ids editor values on-change on-blur]}] (let [opts #js {:editor editor :ids ids :values values - :on-change on-change}] + :on-change on-change + :on-blur on-blur}] [:div.element-set-content [:> font-options opts] [:div.row-flex diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs index a15c66e02a..a8eccfa4d5 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/text.cljs @@ -9,10 +9,9 @@ [app.common.data :as d] [app.main.data.workspace.texts :as dwt] [app.main.refs :as refs] - [app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] - [app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]] + [app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu fill-attrs]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu]] [app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu]] diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index f05f2a1a5f..dfa4f4467a 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -223,11 +223,13 @@ (defn focus! [node] - (.focus node)) + (when (some? node) + (.focus node))) (defn blur! [node] - (.blur node)) + (when (some? node) + (.blur node))) (defn fullscreen? [] @@ -291,8 +293,11 @@ (defn get-user-agent [] (.-userAgent globals/navigator)) +(defn get-active [] + (.-activeElement globals/document)) + (defn active? [node] - (= (.-activeElement globals/document) node)) + (= (get-active) node)) (defn get-data [^js node ^string attr] (.getAttribute node (str "data-" attr))) diff --git a/frontend/src/app/util/text_editor_impl.js b/frontend/src/app/util/text_editor_impl.js index 3c735b97cf..18de4ec8f0 100644 --- a/frontend/src/app/util/text_editor_impl.js +++ b/frontend/src/app/util/text_editor_impl.js @@ -34,7 +34,7 @@ function mergeBlockData(block, newData) { } } - return block.merge({ + return block.mergeDeep({ data: data }); } @@ -119,29 +119,31 @@ export function updateCurrentBlockData(state, attrs) { } export function applyInlineStyle(state, styles) { - let selection = state.getSelection(); + const userSelection = state.getSelection(); + let selection = userSelection; if (selection.isCollapsed()) { selection = getSelectAllSelection(state); } + let result = state; let content = null; for (let style of styles) { const [p, k, v] = style.split("$$$"); const prefix = [p, k, ""].join("$$$"); - content = state.getCurrentContent(); + content = result.getCurrentContent(); content = removeInlineStylePrefix(content, selection, prefix); if (v !== "z:null") { content = Modifier.applyInlineStyle(content, selection, style); } - state = EditorState.push(state, content, "change-inline-style"); + result = EditorState.push(result, content, "change-inline-style"); } - return state; + return EditorState.acceptSelection(result, userSelection); } export function splitBlockPreservingData(state) { @@ -308,7 +310,7 @@ export function updateBlockData(state, blockKey, data) { ); const result = EditorState.push(state, newContent, 'change-block-data'); - return EditorState.acceptSelection(result, userSelection) + return EditorState.acceptSelection(result, userSelection); } export function getSelection(state) { From 3ed593e4b68ad96d975a8aa8dd7ec7eba5174b0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Thu, 15 Jul 2021 16:43:03 +0200 Subject: [PATCH 07/35] :bug: Fix scroll in teams dropdown at dashboard --- CHANGES.md | 2 ++ frontend/resources/styles/main/partials/dashboard-sidebar.scss | 1 + 2 files changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index fbf3a026c5..7f5c390354 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -6,6 +6,8 @@ ### :bug: Bugs fixed +- Add scroll bar to Teams menu [Taiga #1894](https://tree.taiga.io/project/penpot/issue/1894). + ### :arrow_up: Deps updates ### :boom: Breaking changes ### :heart: Community contributions by (Thank you!) diff --git a/frontend/resources/styles/main/partials/dashboard-sidebar.scss b/frontend/resources/styles/main/partials/dashboard-sidebar.scss index 2c4a0b8d15..2e90557595 100644 --- a/frontend/resources/styles/main/partials/dashboard-sidebar.scss +++ b/frontend/resources/styles/main/partials/dashboard-sidebar.scss @@ -38,6 +38,7 @@ z-index: 12; max-height: 30rem; min-width: 230px; + overflow-y: auto; } .options-dropdown { From 008134fde8dd753ea79c82189a9ed304bd08549b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 16 Jul 2021 13:54:55 +0200 Subject: [PATCH 08/35] :bug: Fix repeated names when duplicating object trees. --- CHANGES.md | 1 + .../app/main/data/workspace/selection.cljs | 54 +++++++++---------- 2 files changed, 28 insertions(+), 27 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7f5c390354..bf28391445 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ ### :bug: Bugs fixed - Add scroll bar to Teams menu [Taiga #1894](https://tree.taiga.io/project/penpot/issue/1894). +- Fix repeated names when duplicating artboards or groups [Taiga #1892](https://tree.taiga.io/project/penpot/issue/1892). ### :arrow_up: Deps updates ### :boom: Breaking changes diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 386e8f3b9f..c04bfbedf6 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -257,8 +257,6 @@ (declare prepare-duplicate-frame-change) (declare prepare-duplicate-shape-change) -(def ^:private change->name #(get-in % [:obj :name])) - (defn update-indices "Fixes the indices for a set of changes after a duplication. We need to fix the indices to take into the account the movement of indices. @@ -290,19 +288,19 @@ "Prepare objects to paste: generate new id, give them unique names, move to the position of mouse pointer, and find in what frame they fit." - [objects page-id names ids delta] - (loop [names names - ids (seq ids) - chgs []] - (if ids - (let [id (first ids) - result (prepare-duplicate-change objects page-id names id delta) - result (if (vector? result) result [result])] - (recur - (into names (map change->name) result) - (next ids) - (into chgs result))) - chgs))) + [objects page-id unames ids delta] + (let [unames (volatile! unames) + update-unames! (fn [new-name] (vswap! unames conj new-name))] + (loop [ids (seq ids) + chgs []] + (if ids + (let [id (first ids) + result (prepare-duplicate-change objects page-id unames update-unames! id delta) + result (if (vector? result) result [result])] + (recur + (next ids) + (into chgs result))) + chgs)))) (defn duplicate-changes-update-indices "Parses the change set when duplicating to set-up the appropiate indices" @@ -317,32 +315,32 @@ (-> changes (update-indices index-map)))) (defn- prepare-duplicate-change - [objects page-id names id delta] + [objects page-id unames update-unames! id delta] (let [obj (get objects id)] (if (= :frame (:type obj)) - (prepare-duplicate-frame-change objects page-id names obj delta) - (prepare-duplicate-shape-change objects page-id names obj delta (:frame-id obj) (:parent-id obj))))) + (prepare-duplicate-frame-change objects page-id unames update-unames! obj delta) + (prepare-duplicate-shape-change objects page-id unames update-unames! obj delta (:frame-id obj) (:parent-id obj))))) (defn- prepare-duplicate-shape-change - [objects page-id names obj delta frame-id parent-id] + [objects page-id unames update-unames! obj delta frame-id parent-id] (when (some? obj) (let [id (uuid/next) - name (dwc/generate-unique-name names (:name obj)) + name (dwc/generate-unique-name @unames (:name obj)) + _ (update-unames! name) + renamed-obj (assoc obj :id id :name name) moved-obj (geom/move renamed-obj delta) parent-id (or parent-id frame-id) children-changes - (loop [names names - result [] + (loop [result [] cid (first (:shapes obj)) cids (rest (:shapes obj))] (if (nil? cid) result (let [obj (get objects cid) - changes (prepare-duplicate-shape-change objects page-id names obj delta frame-id id)] + changes (prepare-duplicate-shape-change objects page-id unames update-unames! obj delta frame-id id)] (recur - (into names (map change->name changes)) (into result changes) (first cids) (rest cids))))) @@ -361,11 +359,13 @@ children-changes)))) (defn- prepare-duplicate-frame-change - [objects page-id names obj delta] + [objects page-id unames update-unames! obj delta] (let [frame-id (uuid/next) - frame-name (dwc/generate-unique-name names (:name obj)) + frame-name (dwc/generate-unique-name @unames (:name obj)) + _ (update-unames! frame-name) + sch (->> (map #(get objects %) (:shapes obj)) - (mapcat #(prepare-duplicate-shape-change objects page-id names % delta frame-id frame-id))) + (mapcat #(prepare-duplicate-shape-change objects page-id unames update-unames! % delta frame-id frame-id))) frame (-> obj (assoc :id frame-id) From 6ced56301cd9a0b03aec82dff849541ab26644a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 16 Jul 2021 15:11:29 +0200 Subject: [PATCH 09/35] :recycle: Optimice a bit of performance --- frontend/src/app/main/data/workspace/libraries.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index b267fb3885..20d97a2106 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -382,7 +382,7 @@ page-id (:current-page-id state) objects (wsh/lookup-page-objects state page-id) - unames (atom (dwc/retrieve-used-names objects)) + unames (volatile! (dwc/retrieve-used-names objects)) frame-id (cp/frame-id-by-position objects (gpt/add orig-pos delta)) @@ -391,7 +391,7 @@ (let [new-name (dwc/generate-unique-name @unames (:name new-shape))] (when (nil? (:parent-id original-shape)) - (swap! unames conj new-name)) + (vswap! unames conj new-name)) (cond-> new-shape true From fa99dea8fe21cfa33233fd602c68472deb46f623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Fri, 16 Jul 2021 15:25:22 +0200 Subject: [PATCH 10/35] :books: Add some comments about possible code enhancements --- frontend/src/app/main/data/workspace.cljs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 7c0a57c7d9..953479dea7 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1474,8 +1474,8 @@ (= :frame (get-in objects [(first selected) :type]))))) (defn- paste-shape - [{:keys [selected objects images] :as data} in-viewport?] - (letfn [;; Given a file-id and img (part generated by the + [{:keys [selected objects images] :as data} in-viewport?] ;; TODO: perhaps rename 'objects' to 'shapes', because it contains only + (letfn [;; Given a file-id and img (part generated by the ;; the shapes to paste, not the whole page tree of shapes ;; copy-selected event), uploads the new media. (upload-media [file-id imgpart] (->> (http/send! {:uri (:file-data imgpart) @@ -1583,7 +1583,7 @@ page-id (:current-page-id state) unames (-> (wsh/lookup-page-objects state page-id) - (dwc/retrieve-used-names)) + (dwc/retrieve-used-names)) ;; TODO: move this calculation inside prepare-duplcate-changes? rchanges (->> (dws/prepare-duplicate-changes objects page-id unames selected delta) (mapv (partial process-rchange media-idx)) From 9d372301edf3a8fdc503b891b554222447f16bcb Mon Sep 17 00:00:00 2001 From: soultipsy <40300919+soultipsy@users.noreply.github.com> Date: Tue, 20 Jul 2021 15:44:51 +0800 Subject: [PATCH 11/35] =?UTF-8?q?Update=20and=20rename=20frontend/src/app/?= =?UTF-8?q?main/ui/workspace/viewport/path=5Factions.cljs=20to=20=E5=89=8D?= =?UTF-8?q?=E7=AB=AF=20/src=20/app=20/main=20/ui=20/=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E5=8C=BA=20/=E8=A7=86=E5=8F=A3=20/path=5Factions.cljs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tooltip errors:move nodes and draw nodes are swapped. --- .../src /app /main /ui /工作区 /视口 }/path_actions.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename {frontend/src/app/main/ui/workspace/viewport => 前端 /src /app /main /ui /工作区 /视口 }/path_actions.cljs (100%) diff --git a/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs b/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs similarity index 100% rename from frontend/src/app/main/ui/workspace/viewport/path_actions.cljs rename to 前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs index f6d85e32cf..1aef9a82f7 100644 --- a/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs +++ b/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs @@ -108,14 +108,14 @@ ;; Draw Mode [:div.viewport-actions-entry.tooltip.tooltip-bottom {:class (when (= edit-mode :draw) "is-toggled") - :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) + :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) :on-click on-select-draw-mode} i/pen] ;; Edit mode [:div.viewport-actions-entry.tooltip.tooltip-bottom {:class (when (= edit-mode :move) "is-toggled") - :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) + :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) :on-click on-select-edit-mode} i/pointer-inner]] From 0a3cd4f8e4d622e00a15a916914b59864a683496 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 26 Jul 2021 11:32:46 +0200 Subject: [PATCH 12/35] :arrow_up: Update deps. --- docker/devenv/Dockerfile | 6 +++--- frontend/deps.edn | 2 +- frontend/package.json | 2 +- frontend/yarn.lock | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docker/devenv/Dockerfile b/docker/devenv/Dockerfile index 5508f5a7da..e6deb917ca 100644 --- a/docker/devenv/Dockerfile +++ b/docker/devenv/Dockerfile @@ -3,10 +3,10 @@ LABEL maintainer="Andrey Antukh " ARG DEBIAN_FRONTEND=noninteractive -ENV NODE_VERSION=v14.17.2 \ - CLOJURE_VERSION=1.10.3.882 \ +ENV NODE_VERSION=v14.17.3 \ + CLOJURE_VERSION=1.10.3.929 \ CLJKONDO_VERSION=2021.06.18 \ - BABASHKA_VERSION=0.4.6 \ + BABASHKA_VERSION=0.5.0 \ LANG=en_US.UTF-8 \ LC_ALL=en_US.UTF-8 diff --git a/frontend/deps.edn b/frontend/deps.edn index 2695bf8460..7467b3e658 100644 --- a/frontend/deps.edn +++ b/frontend/deps.edn @@ -23,7 +23,7 @@ :dev {:extra-deps - {thheller/shadow-cljs {:mvn/version "2.15.1"}}} + {thheller/shadow-cljs {:mvn/version "2.15.2"}}} :shadow-cljs {:main-opts ["-m" "shadow.cljs.devtools.cli"]} diff --git a/frontend/package.json b/frontend/package.json index e5f371b46f..13261d45a2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -33,7 +33,7 @@ "postcss-clean": "^1.2.2", "rimraf": "^3.0.0", "sass": "^1.35.1", - "shadow-cljs": "2.15.1" + "shadow-cljs": "2.15.2" }, "dependencies": { "date-fns": "^2.22.1", diff --git a/frontend/yarn.lock b/frontend/yarn.lock index a0ac4205e6..ca1890d131 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -4258,10 +4258,10 @@ shadow-cljs-jar@1.3.2: resolved "https://registry.yarnpkg.com/shadow-cljs-jar/-/shadow-cljs-jar-1.3.2.tgz#97273afe1747b6a2311917c1c88d9e243c81957b" integrity sha512-XmeffAZHv8z7451kzeq9oKh8fh278Ak+UIOGGrapyqrFBB773xN8vMQ3O7J7TYLnb9BUwcqadKkmgaq7q6fhZg== -shadow-cljs@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/shadow-cljs/-/shadow-cljs-2.15.1.tgz#9f4b642efafeb84480396f46af2a8e59351d5986" - integrity sha512-X0ueBJksdBg5FIuFOFguyZtAP9gzZZI6lmednxQ/eOsN9tGhpTXh5Y8/7lGzkfIFXxONe9THZx4f2m4JX5jBYA== +shadow-cljs@2.15.2: + version "2.15.2" + resolved "https://registry.yarnpkg.com/shadow-cljs/-/shadow-cljs-2.15.2.tgz#195ad2cc45d3334920e629721f06c6d63802b1ac" + integrity sha512-WPlSMkGgbU5b2nrt+Y1A1TsPs5Rip/JvCxGG2t2Pvzo+pLJ+RcpkZgAxjNQNNA7VYWEh5Pqwyvq5KzQ+0LMsxw== dependencies: node-libs-browser "^2.2.1" readline-sync "^1.4.7" From c5b23816e98576538afc1a685dd34a931d248859 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 26 Jul 2021 11:33:05 +0200 Subject: [PATCH 13/35] :fire: Remove file. --- .../main /ui /工作区 /视口 /path_actions.cljs | 180 ------------------ 1 file changed, 180 deletions(-) delete mode 100644 前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs diff --git a/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs b/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs deleted file mode 100644 index 1aef9a82f7..0000000000 --- a/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs +++ /dev/null @@ -1,180 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; Copyright (c) UXBOX Labs SL - -(ns app.main.ui.workspace.viewport.path-actions - (:require - [app.main.data.workspace.path :as drp] - [app.main.data.workspace.path.shortcuts :as sc] - [app.main.store :as st] - [app.main.ui.icons :as i] - [app.main.ui.workspace.shapes.path.common :as pc] - [app.util.i18n :as i18n :refer [tr]] - [app.util.path.tools :as upt] - [rumext.alpha :as mf])) - -(defn check-enabled [content selected-points] - (let [segments (upt/get-segments content selected-points) - num-points (count selected-points) - points-selected? (seq selected-points) - segments-selected? (seq segments)] - {:make-corner points-selected? - :make-curve points-selected? - :add-node segments-selected? - :remove-node points-selected? - :merge-nodes segments-selected? - :join-nodes (and points-selected? (>= num-points 2)) - :separate-nodes segments-selected?})) - -(mf/defc path-actions [{:keys [shape]}] - (let [{:keys [edit-mode selected-points snap-toggled] :as all} (mf/deref pc/current-edit-path-ref) - content (:content shape) - - enabled-buttons - (mf/use-memo - (mf/deps content selected-points) - #(check-enabled content selected-points)) - - on-select-draw-mode - (mf/use-callback - (fn [_] - (st/emit! (drp/change-edit-mode :draw)))) - - on-select-edit-mode - (mf/use-callback - (fn [_] - (st/emit! (drp/change-edit-mode :move)))) - - on-add-node - (mf/use-callback - (mf/deps (:add-node enabled-buttons)) - (fn [_] - (when (:add-node enabled-buttons) - (st/emit! (drp/add-node))))) - - on-remove-node - (mf/use-callback - (mf/deps (:remove-node enabled-buttons)) - (fn [_] - (when (:remove-node enabled-buttons) - (st/emit! (drp/remove-node))))) - - on-merge-nodes - (mf/use-callback - (mf/deps (:merge-nodes enabled-buttons)) - (fn [_] - (when (:merge-nodes enabled-buttons) - (st/emit! (drp/merge-nodes))))) - - on-join-nodes - (mf/use-callback - (mf/deps (:join-nodes enabled-buttons)) - (fn [_] - (when (:join-nodes enabled-buttons) - (st/emit! (drp/join-nodes))))) - - on-separate-nodes - (mf/use-callback - (mf/deps (:separate-nodes enabled-buttons)) - (fn [_] - (when (:separate-nodes enabled-buttons) - (st/emit! (drp/separate-nodes))))) - - on-make-corner - (mf/use-callback - (mf/deps (:make-corner enabled-buttons)) - (fn [_] - (when (:make-corner enabled-buttons) - (st/emit! (drp/make-corner))))) - - on-make-curve - (mf/use-callback - (mf/deps (:make-curve enabled-buttons)) - (fn [_] - (when (:make-curve enabled-buttons) - (st/emit! (drp/make-curve))))) - - on-toggle-snap - (mf/use-callback - (fn [_] - (st/emit! (drp/toggle-snap)))) - - ] - [:div.path-actions - [:div.viewport-actions-group - - ;; Draw Mode - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when (= edit-mode :draw) "is-toggled") - :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) - :on-click on-select-draw-mode} - i/pen] - - ;; Edit mode - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when (= edit-mode :move) "is-toggled") - :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) - :on-click on-select-edit-mode} - i/pointer-inner]] - - [:div.viewport-actions-group - ;; Add Node - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when-not (:add-node enabled-buttons) "is-disabled") - :alt (tr "workspace.path.actions.add-node" (sc/get-tooltip :add-node)) - :on-click on-add-node} - i/nodes-add] - - ;; Remove node - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when-not (:remove-node enabled-buttons) "is-disabled") - :alt (tr "workspace.path.actions.delete-node" (sc/get-tooltip :delete-node)) - :on-click on-remove-node} - i/nodes-remove]] - - [:div.viewport-actions-group - ;; Merge Nodes - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when-not (:merge-nodes enabled-buttons) "is-disabled") - :alt (tr "workspace.path.actions.merge-nodes" (sc/get-tooltip :merge-nodes)) - :on-click on-merge-nodes} - i/nodes-merge] - - ;; Join Nodes - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when-not (:join-nodes enabled-buttons) "is-disabled") - :alt (tr "workspace.path.actions.join-nodes" (sc/get-tooltip :join-nodes)) - :on-click on-join-nodes} - i/nodes-join] - - ;; Separate Nodes - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when-not (:separate-nodes enabled-buttons) "is-disabled") - :alt (tr "workspace.path.actions.separate-nodes" (sc/get-tooltip :separate-nodes)) - :on-click on-separate-nodes} - i/nodes-separate]] - - ;; Make Corner - [:div.viewport-actions-group - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when-not (:make-corner enabled-buttons) "is-disabled") - :alt (tr "workspace.path.actions.make-corner" (sc/get-tooltip :make-corner)) - :on-click on-make-corner} - i/nodes-corner] - - ;; Make Curve - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when-not (:make-curve enabled-buttons) "is-disabled") - :alt (tr "workspace.path.actions.make-curve" (sc/get-tooltip :make-curve)) - :on-click on-make-curve} - i/nodes-curve]] - - ;; Toggle snap - [:div.viewport-actions-group - [:div.viewport-actions-entry.tooltip.tooltip-bottom - {:class (when snap-toggled "is-toggled") - :alt (tr "workspace.path.actions.snap-nodes" (sc/get-tooltip :snap-nodes)) - :on-click on-toggle-snap} - i/nodes-snap]]])) From 8e3eb98789826f2a4fafbc1cf9af5a76ee25002c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 26 Jul 2021 12:08:14 +0200 Subject: [PATCH 14/35] Revert ":fire: Remove file." This reverts commit c5b23816e98576538afc1a685dd34a931d248859. --- .../main /ui /工作区 /视口 /path_actions.cljs | 180 ++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs diff --git a/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs b/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs new file mode 100644 index 0000000000..1aef9a82f7 --- /dev/null +++ b/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs @@ -0,0 +1,180 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) UXBOX Labs SL + +(ns app.main.ui.workspace.viewport.path-actions + (:require + [app.main.data.workspace.path :as drp] + [app.main.data.workspace.path.shortcuts :as sc] + [app.main.store :as st] + [app.main.ui.icons :as i] + [app.main.ui.workspace.shapes.path.common :as pc] + [app.util.i18n :as i18n :refer [tr]] + [app.util.path.tools :as upt] + [rumext.alpha :as mf])) + +(defn check-enabled [content selected-points] + (let [segments (upt/get-segments content selected-points) + num-points (count selected-points) + points-selected? (seq selected-points) + segments-selected? (seq segments)] + {:make-corner points-selected? + :make-curve points-selected? + :add-node segments-selected? + :remove-node points-selected? + :merge-nodes segments-selected? + :join-nodes (and points-selected? (>= num-points 2)) + :separate-nodes segments-selected?})) + +(mf/defc path-actions [{:keys [shape]}] + (let [{:keys [edit-mode selected-points snap-toggled] :as all} (mf/deref pc/current-edit-path-ref) + content (:content shape) + + enabled-buttons + (mf/use-memo + (mf/deps content selected-points) + #(check-enabled content selected-points)) + + on-select-draw-mode + (mf/use-callback + (fn [_] + (st/emit! (drp/change-edit-mode :draw)))) + + on-select-edit-mode + (mf/use-callback + (fn [_] + (st/emit! (drp/change-edit-mode :move)))) + + on-add-node + (mf/use-callback + (mf/deps (:add-node enabled-buttons)) + (fn [_] + (when (:add-node enabled-buttons) + (st/emit! (drp/add-node))))) + + on-remove-node + (mf/use-callback + (mf/deps (:remove-node enabled-buttons)) + (fn [_] + (when (:remove-node enabled-buttons) + (st/emit! (drp/remove-node))))) + + on-merge-nodes + (mf/use-callback + (mf/deps (:merge-nodes enabled-buttons)) + (fn [_] + (when (:merge-nodes enabled-buttons) + (st/emit! (drp/merge-nodes))))) + + on-join-nodes + (mf/use-callback + (mf/deps (:join-nodes enabled-buttons)) + (fn [_] + (when (:join-nodes enabled-buttons) + (st/emit! (drp/join-nodes))))) + + on-separate-nodes + (mf/use-callback + (mf/deps (:separate-nodes enabled-buttons)) + (fn [_] + (when (:separate-nodes enabled-buttons) + (st/emit! (drp/separate-nodes))))) + + on-make-corner + (mf/use-callback + (mf/deps (:make-corner enabled-buttons)) + (fn [_] + (when (:make-corner enabled-buttons) + (st/emit! (drp/make-corner))))) + + on-make-curve + (mf/use-callback + (mf/deps (:make-curve enabled-buttons)) + (fn [_] + (when (:make-curve enabled-buttons) + (st/emit! (drp/make-curve))))) + + on-toggle-snap + (mf/use-callback + (fn [_] + (st/emit! (drp/toggle-snap)))) + + ] + [:div.path-actions + [:div.viewport-actions-group + + ;; Draw Mode + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when (= edit-mode :draw) "is-toggled") + :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) + :on-click on-select-draw-mode} + i/pen] + + ;; Edit mode + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when (= edit-mode :move) "is-toggled") + :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) + :on-click on-select-edit-mode} + i/pointer-inner]] + + [:div.viewport-actions-group + ;; Add Node + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when-not (:add-node enabled-buttons) "is-disabled") + :alt (tr "workspace.path.actions.add-node" (sc/get-tooltip :add-node)) + :on-click on-add-node} + i/nodes-add] + + ;; Remove node + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when-not (:remove-node enabled-buttons) "is-disabled") + :alt (tr "workspace.path.actions.delete-node" (sc/get-tooltip :delete-node)) + :on-click on-remove-node} + i/nodes-remove]] + + [:div.viewport-actions-group + ;; Merge Nodes + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when-not (:merge-nodes enabled-buttons) "is-disabled") + :alt (tr "workspace.path.actions.merge-nodes" (sc/get-tooltip :merge-nodes)) + :on-click on-merge-nodes} + i/nodes-merge] + + ;; Join Nodes + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when-not (:join-nodes enabled-buttons) "is-disabled") + :alt (tr "workspace.path.actions.join-nodes" (sc/get-tooltip :join-nodes)) + :on-click on-join-nodes} + i/nodes-join] + + ;; Separate Nodes + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when-not (:separate-nodes enabled-buttons) "is-disabled") + :alt (tr "workspace.path.actions.separate-nodes" (sc/get-tooltip :separate-nodes)) + :on-click on-separate-nodes} + i/nodes-separate]] + + ;; Make Corner + [:div.viewport-actions-group + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when-not (:make-corner enabled-buttons) "is-disabled") + :alt (tr "workspace.path.actions.make-corner" (sc/get-tooltip :make-corner)) + :on-click on-make-corner} + i/nodes-corner] + + ;; Make Curve + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when-not (:make-curve enabled-buttons) "is-disabled") + :alt (tr "workspace.path.actions.make-curve" (sc/get-tooltip :make-curve)) + :on-click on-make-curve} + i/nodes-curve]] + + ;; Toggle snap + [:div.viewport-actions-group + [:div.viewport-actions-entry.tooltip.tooltip-bottom + {:class (when snap-toggled "is-toggled") + :alt (tr "workspace.path.actions.snap-nodes" (sc/get-tooltip :snap-nodes)) + :on-click on-toggle-snap} + i/nodes-snap]]])) From 6ee6a03e4af40e313fb397d7b8829497a5cb0e31 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 26 Jul 2021 12:08:24 +0200 Subject: [PATCH 15/35] =?UTF-8?q?Revert=20"Update=20and=20rename=20fronten?= =?UTF-8?q?d/src/app/main/ui/workspace/viewport/path=5Factions.cljs=20to?= =?UTF-8?q?=20=E5=89=8D=E7=AB=AF=20/src=20/app=20/main=20/ui=20/=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E5=8C=BA=20/=E8=A7=86=E5=8F=A3=20/path=5Factions.cljs?= =?UTF-8?q?"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 9d372301edf3a8fdc503b891b554222447f16bcb. --- .../src/app/main/ui/workspace/viewport}/path_actions.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename {前端 /src /app /main /ui /工作区 /视口 => frontend/src/app/main/ui/workspace/viewport}/path_actions.cljs (100%) diff --git a/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs b/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs similarity index 100% rename from 前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs rename to frontend/src/app/main/ui/workspace/viewport/path_actions.cljs index 1aef9a82f7..f6d85e32cf 100644 --- a/前端 /src /app /main /ui /工作区 /视口 /path_actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs @@ -108,14 +108,14 @@ ;; Draw Mode [:div.viewport-actions-entry.tooltip.tooltip-bottom {:class (when (= edit-mode :draw) "is-toggled") - :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) + :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) :on-click on-select-draw-mode} i/pen] ;; Edit mode [:div.viewport-actions-entry.tooltip.tooltip-bottom {:class (when (= edit-mode :move) "is-toggled") - :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) + :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) :on-click on-select-edit-mode} i/pointer-inner]] From 07eeb76a5f7675f84fb8db695807c476e5ffe4e2 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 26 Jul 2021 13:43:39 +0200 Subject: [PATCH 16/35] :sparkles: Stream all transit responses. Instead of buffering for etag. The etags are temporary disabled. --- backend/src/app/http.clj | 4 +++- backend/src/app/http/middleware.clj | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/backend/src/app/http.clj b/backend/src/app/http.clj index a3fbc02c62..248a125dd2 100644 --- a/backend/src/app/http.clj +++ b/backend/src/app/http.clj @@ -136,7 +136,9 @@ ["/webhooks" ["/sns" {:post (:sns-webhook cfg)}]] - ["/api" {:middleware [[middleware/etag] + ["/api" {:middleware [ + ;; Temporary disabled + #_[middleware/etag] [middleware/format-response-body] [middleware/params] [middleware/multipart-params] diff --git a/backend/src/app/http/middleware.clj b/backend/src/app/http/middleware.clj index b979b8431a..cd3af606de 100644 --- a/backend/src/app/http/middleware.clj +++ b/backend/src/app/http/middleware.clj @@ -92,10 +92,15 @@ (coll? body) (-> response (update :headers assoc "content-type" "application/transit+json") - (assoc :body - (if (= :post (:request-method request)) - (transit-streamable-body body opts) - (t/encode body opts)))) + (assoc :body (transit-streamable-body body opts))) + + ;; ;; Temporary disabled + ;; (-> response + ;; (update :headers assoc "content-type" "application/transit+json") + ;; (assoc :body + ;; (if (= :post (:request-method request)) + ;; (transit-streamable-body body opts) + ;; (t/encode body opts)))) (nil? body) (assoc response :status 204 :body "") From 8493e510705130d07285953d454e15b3e8ee98cc Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 26 Jul 2021 11:54:23 +0200 Subject: [PATCH 17/35] :bug: Fix problem with svg's viewbox --- .../app/main/data/workspace/svg_upload.cljs | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 048e4bb965..49942812a2 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -7,10 +7,13 @@ (ns app.main.data.workspace.svg-upload (:require [app.common.data :as d] + [app.common.exceptions :as ex] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] + [app.common.math :as mth] [app.common.pages :as cp] + [app.common.spec :refer [max-safe-int min-safe-int]] [app.common.uuid :as uuid] [app.main.data.workspace.changes :as dch] [app.main.data.workspace.common :as dwc] @@ -28,13 +31,36 @@ (defonce default-circle {:r 0 :cx 0 :cy 0}) (defonce default-image {:x 0 :y 0 :width 1 :height 1}) +(defn- assert-valid-num [attr num] + (when (or (nil? num) + (mth/nan? num) + (not (mth/finite? num)) + (>= num max-safe-int ) + (<= num min-safe-int)) + (ex/raise (str (d/name attr) " attribute invalid: " num))) + + ;; If the number is between 0-1 we round to 1 (same in negative form + (cond + (and (> num 0) (< num 1)) 1 + (and (< num 0) (> num -1)) -1 + :else num)) + +(defn- assert-valid-pos-num [attr num] + (let [num (assert-valid-num attr num)] + (when (< num 0) + (ex/raise (str (d/name attr) " attribute invalid: " num))) + num)) + (defn- svg-dimensions [data] (let [width (get-in data [:attrs :width] 100) height (get-in data [:attrs :height] 100) viewbox (get-in data [:attrs :viewBox] (str "0 0 " width " " height)) - [x y width height] (->> (str/split viewbox " ") + [x y width height] (->> (str/split viewbox #"\s+") (map d/parse-double))] - [x y width height])) + [(assert-valid-num :x x) + (assert-valid-num :y y) + (assert-valid-pos-num :width width) + (assert-valid-pos-num :height height)])) (defn tag->name "Given a tag returns its layer name" @@ -467,4 +493,6 @@ (dwc/select-shapes (d/ordered-set root-id)))) (catch :default e - (.error js/console "Error upload" e)))))) + (.error js/console "Error SVG" e) + (rx/throw {:type :svg-parser + :data e})))))) From 43198eb263d96658fa5453d9f55ea4ecb5d17af3 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 26 Jul 2021 14:10:19 +0200 Subject: [PATCH 18/35] :bug: Improved object deletion --- .../src/app/main/data/workspace/common.cljs | 107 ++++++++++-------- .../src/app/main/data/workspace/texts.cljs | 6 +- frontend/src/app/main/ui/workspace.cljs | 7 +- 3 files changed, 67 insertions(+), 53 deletions(-) diff --git a/frontend/src/app/main/data/workspace/common.cljs b/frontend/src/app/main/data/workspace/common.cljs index 5d6d7c00f3..b76dce9749 100644 --- a/frontend/src/app/main/data/workspace/common.cljs +++ b/frontend/src/app/main/data/workspace/common.cljs @@ -400,67 +400,74 @@ (into (d/ordered-set) empty-parents-xform all-parents) mk-del-obj-xf - (map (fn [id] - {:type :del-obj - :page-id page-id - :id id})) + (comp (filter (partial contains? objects)) + (map (fn [id] + {:type :del-obj + :page-id page-id + :id id}))) mk-add-obj-xf - (map (fn [id] - (let [item (get objects id)] - {:type :add-obj - :id (:id item) - :page-id page-id - :index (cp/position-on-parent id objects) - :frame-id (:frame-id item) - :parent-id (:parent-id item) - :obj item}))) + (comp (filter (partial contains? objects)) + (map (fn [id] + (let [item (get objects id)] + {:type :add-obj + :id (:id item) + :page-id page-id + :index (cp/position-on-parent id objects) + :frame-id (:frame-id item) + :parent-id (:parent-id item) + :obj item})))) mk-mod-touched-xf - (map (fn [id] - (let [parent (get objects id)] - {:type :mod-obj - :page-id page-id - :id (:id parent) - :operations [{:type :set-touched - :touched (:touched parent)}]}))) + (comp (filter (partial contains? objects)) + (map (fn [id] + (let [parent (get objects id)] + {:type :mod-obj + :page-id page-id + :id (:id parent) + :operations [{:type :set-touched + :touched (:touched parent)}]})))) mk-mod-int-del-xf - (map (fn [obj] - {:type :mod-obj - :page-id page-id - :id (:id obj) - :operations [{:type :set - :attr :interactions - :val (vec (remove (fn [interaction] - (contains? ids (:destination interaction))) - (:interactions obj)))}]})) + (comp (filter some?) + (map (fn [obj] + {:type :mod-obj + :page-id page-id + :id (:id obj) + :operations [{:type :set + :attr :interactions + :val (vec (remove (fn [interaction] + (contains? ids (:destination interaction))) + (:interactions obj)))}]}))) mk-mod-int-add-xf - (map (fn [obj] - {:type :mod-obj - :page-id page-id - :id (:id obj) - :operations [{:type :set - :attr :interactions - :val (:interactions obj)}]})) + (comp (filter some?) + (map (fn [obj] + {:type :mod-obj + :page-id page-id + :id (:id obj) + :operations [{:type :set + :attr :interactions + :val (:interactions obj)}]}))) mk-mod-unmask-xf - (map (fn [id] - {:type :mod-obj - :page-id page-id - :id id - :operations [{:type :set - :attr :masked-group? - :val false}]})) + (comp (filter (partial contains? objects)) + (map (fn [id] + {:type :mod-obj + :page-id page-id + :id id + :operations [{:type :set + :attr :masked-group? + :val false}]}))) mk-mod-mask-xf - (map (fn [id] - {:type :mod-obj - :page-id page-id - :id id - :operations [{:type :set - :attr :masked-group? - :val true}]})) + (comp (filter (partial contains? objects)) + (map (fn [id] + {:type :mod-obj + :page-id page-id + :id id + :operations [{:type :set + :attr :masked-group? + :val true}]}))) rchanges (-> [] diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index 1163a56873..841bf01819 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -67,8 +67,10 @@ (rx/of (dch/update-shapes [id] #(assoc % :content content)) (dwu/commit-undo-transaction))))) - (rx/of (dws/deselect-shape id) - (dwc/delete-shapes #{id}))))))) + + (when (some? id) + (rx/of (dws/deselect-shape id) + (dwc/delete-shapes #{id})))))))) (defn initialize-editor-state [{:keys [id content] :as shape} decorator] diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index 2086412dfb..533ce45248 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -6,8 +6,10 @@ (ns app.main.ui.workspace (:require + [app.util.timers :as ts] [app.main.data.messages :as dm] [app.main.data.workspace :as dw] + [app.main.data.workspace.persistence :as dwp] [app.main.refs :as refs] [app.main.store :as st] [app.main.ui.context :as ctx] @@ -122,7 +124,10 @@ (mf/deps project-id file-id) (fn [] (st/emit! (dw/initialize-file project-id file-id)) - (st/emitf (dw/finalize-file project-id file-id)))) + (fn [] + ;; Schedule to 100ms so we can do the update before the file is finalized + (st/emit! ::dwp/force-persist) + (ts/schedule 100 (st/emitf (dw/finalize-file project-id file-id)))))) (mf/use-effect (fn [] From d61a86cad1daeb88ef493b2c7478b4328649b67e Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 26 Jul 2021 14:47:20 +0200 Subject: [PATCH 19/35] :bug: Frame moving with title with button different than left --- backend/src/app/http/middleware.clj | 2 +- frontend/src/app/main/ui/workspace.cljs | 2 +- .../src/app/main/ui/workspace/viewport/widgets.cljs | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/backend/src/app/http/middleware.clj b/backend/src/app/http/middleware.clj index cd3af606de..42babf3dc8 100644 --- a/backend/src/app/http/middleware.clj +++ b/backend/src/app/http/middleware.clj @@ -85,7 +85,7 @@ (.close ^java.io.OutputStream output-stream)))))) (defn- impl-format-response-body - [response request] + [response _request] (let [body (:body response) opts {:type :json-verbose}] (cond diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index 533ce45248..a4e3f03558 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.workspace (:require - [app.util.timers :as ts] [app.main.data.messages :as dm] [app.main.data.workspace :as dw] [app.main.data.workspace.persistence :as dwp] @@ -27,6 +26,7 @@ [app.util.dom :as dom] [app.util.i18n :as i18n :refer [tr]] [app.util.object :as obj] + [app.util.timers :as ts] [okulary.core :as l] [rumext.alpha :as mf])) diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs index 1fe2dce1db..9ca6c54a11 100644 --- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs @@ -95,10 +95,12 @@ on-mouse-down (mf/use-callback (mf/deps (:id frame) on-frame-select) - (fn [event] - (dom/prevent-default event) - (dom/stop-propagation event) - (on-frame-select event (:id frame)))) + (fn [bevent] + (let [event (.-nativeEvent bevent)] + (when (= 1 (.-which event)) + (dom/prevent-default event) + (dom/stop-propagation event) + (on-frame-select event (:id frame)))))) on-double-click (mf/use-callback From 394e6b08adbf0c21910ee500e795514156fe726c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 26 Jul 2021 21:06:39 +0200 Subject: [PATCH 20/35] :tada: Add many improvements on nil handling and code structure on changes impl. --- common/src/app/common/pages/changes.cljc | 183 ++++++++++++----------- common/src/app/common/pages/helpers.cljc | 8 +- 2 files changed, 100 insertions(+), 91 deletions(-) diff --git a/common/src/app/common/pages/changes.cljc b/common/src/app/common/pages/changes.cljc index 1172de76e2..997edc170e 100644 --- a/common/src/app/common/pages/changes.cljc +++ b/common/src/app/common/pages/changes.cljc @@ -15,6 +15,20 @@ [app.common.pages.spec :as spec] [app.common.spec :as us])) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Specific helpers +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn- without-obj + "Clear collection from specified obj and without nil values." + [coll o] + (into [] (filter #(not= % o)) coll)) + +(defn vec-without-nils + [coll] + (into [] (remove nil?) coll)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Page Transformation Changes ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -54,45 +68,50 @@ (assoc data :options (d/dissoc-in (:options data) path))))))) (defmethod process-change :add-obj - [data {:keys [id obj page-id component-id frame-id parent-id - index ignore-touched]}] - (letfn [(update-fn [data] - (let [parent-id (or parent-id frame-id) - objects (:objects data) - obj (assoc obj - :frame-id frame-id - :parent-id parent-id - :id id)] - (if (and (or (nil? parent-id) (contains? objects parent-id)) - (or (nil? frame-id) (contains? objects frame-id))) - (-> data - (update :objects assoc id obj) - (update-in [:objects parent-id :shapes] - (fn [shapes] - (let [shapes (or shapes [])] - (cond - (some #{id} shapes) - shapes + [data {:keys [id obj page-id component-id frame-id parent-id index ignore-touched]}] + (letfn [(update-parent-shapes [shapes] + ;; Ensure that shapes is always a vector. + (let [shapes (into [] shapes)] + (cond + (some #{id} shapes) + shapes - (nil? index) - (if (= :frame (:type obj)) - (d/concat [id] shapes) - (conj shapes id)) + (nil? index) + (if (= :frame (:type obj)) + (into [id] shapes) + (conj shapes id)) - :else - (cph/insert-at-index shapes index [id]))))) + :else + (cph/insert-at-index shapes index [id])))) + + (update-parent [parent] + (-> parent + (update :shapes update-parent-shapes) + (update :shapes vec-without-nils) + (cond-> (and (:shape-ref parent) + (not= (:id parent) frame-id) + (not ignore-touched)) + (-> (update :touched cph/set-touched-group :shapes-group) + (dissoc :remote-synced?))))) + + (update-objects [objects parent-id] + (if (and (or (nil? parent-id) (contains? objects parent-id)) + (or (nil? frame-id) (contains? objects frame-id))) + (-> objects + (assoc id (-> obj + (assoc :frame-id frame-id) + (assoc :parent-id parent-id) + (assoc :id id))) + (update parent-id update-parent)) + objects)) + + (update-container [data] + (let [parent-id (or parent-id frame-id)] + (update data :objects update-objects parent-id)))] - (cond-> (and (:shape-ref (get-in data [:objects parent-id])) - (not= parent-id frame-id) - (not ignore-touched)) - (-> - (update-in [:objects parent-id :touched] - cph/set-touched-group :shapes-group) - (d/dissoc-in [:objects parent-id :remote-synced?])))) - data)))] (if page-id - (d/update-in-when data [:pages-index page-id] update-fn) - (d/update-in-when data [:components component-id] update-fn)))) + (d/update-in-when data [:pages-index page-id] update-container) + (d/update-in-when data [:components component-id] update-container)))) (defmethod process-change :mod-obj [data {:keys [id page-id component-id operations]}] @@ -107,32 +126,27 @@ (defmethod process-change :del-obj [data {:keys [page-id component-id id ignore-touched]}] - (letfn [(delete-object [objects id] + (letfn [(delete-from-parent [parent] + (let [parent (update parent :shapes without-obj id)] + (cond-> parent + (and (:shape-ref parent) + (not ignore-touched)) + (-> (update :touched cph/set-touched-group :shapes-group) + (dissoc :remote-synced?))))) + + (delete-from-objects [objects] (if-let [target (get objects id)] - (let [parent-id (cph/get-parent id objects) - frame-id (:frame-id target) - parent (get objects parent-id) - objects (dissoc objects id)] - (cond-> objects - (and (not= parent-id frame-id) - (#{:group :svg-raw} (:type parent))) - (update-in [parent-id :shapes] (fn [s] (filterv #(not= % id) s))) - - (and (:shape-ref parent) (not ignore-touched)) - (-> - (update-in [parent-id :touched] cph/set-touched-group :shapes-group) - (d/dissoc-in [parent-id :remote-synced?])) - - (contains? objects frame-id) - (update-in [frame-id :shapes] (fn [s] (filterv #(not= % id) s))) - - (seq (:shapes target)) ; Recursive delete all - ; dependend objects - (as-> $ (reduce delete-object $ (:shapes target))))) + (let [parent-id (or (:parent-id target) + (:frame-id target)) + children (cph/get-children id objects)] + (-> (reduce dissoc objects children) + (dissoc id) + (d/update-when parent-id delete-from-parent))) objects))] + (if page-id - (d/update-in-when data [:pages-index page-id :objects] delete-object id) - (d/update-in-when data [:components component-id :objects] delete-object id)))) + (d/update-in-when data [:pages-index page-id :objects] delete-from-objects) + (d/update-in-when data [:components component-id :objects] delete-from-objects)))) ;; reg-objects operation "regenerates" the geometry and selrect of the parent groups (defmethod process-change :reg-objects @@ -191,25 +205,24 @@ (insert-items prev-shapes index shapes) ;; For masked groups, the first shape is the mask ;; and it cannot be moved. - (let [mask-id (first prev-shapes) - other-ids (rest prev-shapes) - not-mask-shapes (strip-id shapes mask-id) - new-index (if (nil? index) nil (max (dec index) 0)) - new-shapes (insert-items other-ids new-index not-mask-shapes)] + (let [mask-id (first prev-shapes) + other-ids (rest prev-shapes) + not-mask-shapes (without-obj shapes mask-id) + new-index (if (nil? index) nil (max (dec index) 0)) + new-shapes (insert-items other-ids new-index not-mask-shapes)] (d/concat [mask-id] new-shapes)))) - (strip-id [coll id] - (filterv #(not= % id) coll)) - (add-to-parent [parent index shapes] - (cond-> parent - true - (update :shapes check-insert-items parent index shapes) - - (and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched)) - (-> - (update :touched cph/set-touched-group :shapes-group) - (dissoc :remote-synced?)))) + (let [parent (-> parent + (update :shapes check-insert-items parent index shapes) + ;; We need to ensure that no `nil` in the + ;; shapes list after adding all the + ;; incoming shapes to the parent. + (update :shapes vec-without-nils))] + (cond-> parent + (and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched)) + (-> (update :touched cph/set-touched-group :shapes-group) + (dissoc :remote-synced?))))) (remove-from-old-parent [cpindex objects shape-id] (let [prev-parent-id (get cpindex shape-id)] @@ -217,22 +230,19 @@ ;; the new destination target parent id. (if (= prev-parent-id parent-id) objects - (let [sid shape-id - pid prev-parent-id - obj (get objects pid) + (let [sid shape-id + pid prev-parent-id + obj (get objects pid) component? (and (:shape-ref obj) (= (:type obj) :group) (not ignore-touched))] (-> objects - (d/update-in-when [pid :shapes] strip-id sid) - - (cond-> component? - (d/update-when - pid - #(-> % - (update :touched cph/set-touched-group :shapes-group) - (dissoc :remote-synced?))))))))) + (d/update-in-when [pid :shapes] without-obj sid) + (d/update-in-when [pid :shapes] vec-without-nils) + (cond-> component? (d/update-when pid #(-> % + (update :touched cph/set-touched-group :shapes-group) + (dissoc :remote-synced?))))))))) (update-parent-id [objects id] (-> objects @@ -240,8 +250,7 @@ ;; Updates the frame-id references that might be outdated (assign-frame-id [frame-id objects id] - (let [objects (-> objects - (d/update-when id assoc :frame-id frame-id)) + (let [objects (d/update-when objects id assoc :frame-id frame-id) obj (get objects id)] (cond-> objects ;; If we moving frame, the parent frame is the root diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index 37d7febeea..6b30e3a9e3 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -103,16 +103,16 @@ children's order will be breadth first." [id objects] - (loop [result (transient []) + (loop [result (transient []) pending (transient []) - next id] + next id] (let [children (get-in objects [next :shapes] []) [result pending] ;; Iterate through children and add them to the result ;; also add them in pending to check for their children (loop [result result pending pending - current (first children) + current (first children) children (rest children)] (if current (recur (conj! result current) @@ -214,7 +214,7 @@ (if (some #{id} acc) acc (conj acc id))) - prev-ids + (vec prev-ids) ids)) (defn select-toplevel-shapes From bff35de39f047afc7aae738dde146dce75e99a67 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 27 Jul 2021 00:08:12 +0200 Subject: [PATCH 21/35] :bug: Don't remove :workspace-layout on finalize-file. --- frontend/src/app/main/data/workspace.cljs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index f953476097..8428c09102 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -204,19 +204,19 @@ ptk/UpdateEvent (update [_ state] (dissoc state - :workspace-file - :workspace-project - :workspace-media-objects - :workspace-persistence - :workspace-local - :workspace-data - :workspace-editor-state - :workspace-undo :current-file-id :current-project-id - :workspace-layout + :current-team-id + :workspace-data + :workspace-editor-state + :workspace-file :workspace-libraries - :workspace-presence)) + :workspace-media-objects + :workspace-persistence + :workspace-presence + :workspace-project + :workspace-project + :workspace-undo)) ptk/WatchEvent (watch [_ _ _] From 08062e8ce8ffbd090391f666dce7b84eb0e41d2e Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 27 Jul 2021 12:01:46 +0200 Subject: [PATCH 22/35] :books: Add better docstring to group creation internal function. --- .../src/app/main/data/workspace/groups.cljs | 87 ++++++++++--------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index fc88141b31..a49b8c0b03 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -36,8 +36,14 @@ (gsh/setup selrect) (assoc :shapes (mapv :id shapes))))) -(defn get-empty-groups - "Retrieve emtpy groups after group creation" +(defn- get-empty-groups-after-group-creation + "An auxiliar function that finds and returns a set of ids that + corresponds to groups that should be deleted after a group creation. + + The corner case happens when you selects two (or more) shapes that + belongs each one to different groups, and after creating the new + group, one (or many) groups can become empty because they have had a + single shape which is moved to the created group." [objects parent-id shapes] (let [ids (cp/clean-loops objects (into #{} (map :id) shapes)) parents (->> ids @@ -72,55 +78,56 @@ (defn prepare-create-group [objects page-id shapes prefix keep-name] - (let [group (make-group shapes prefix keep-name) - frame-id (:frame-id (first shapes)) + (let [group (make-group shapes prefix keep-name) + frame-id (:frame-id (first shapes)) parent-id (:parent-id (first shapes)) - rchanges [{:type :add-obj - :id (:id group) - :page-id page-id - :frame-id frame-id - :parent-id parent-id - :obj group - :index (::index (first shapes))} - {:type :mov-objects - :page-id page-id - :parent-id (:id group) - :shapes (mapv :id shapes)}] + rchanges [{:type :add-obj + :id (:id group) + :page-id page-id + :frame-id frame-id + :parent-id parent-id + :obj group + :index (::index (first shapes))} - uchanges (-> (mapv - (fn [obj] - {:type :mov-objects - :page-id page-id - :parent-id (:parent-id obj) - :index (::index obj) - :shapes [(:id obj)]}) shapes) - (conj - {:type :del-obj - :id (:id group) - :page-id page-id})) + {:type :mov-objects + :page-id page-id + :parent-id (:id group) + :shapes (mapv :id shapes)}] - ids-to-delete (get-empty-groups objects parent-id shapes) + uchanges (-> (mapv (fn [obj] + {:type :mov-objects + :page-id page-id + :parent-id (:parent-id obj) + :index (::index obj) + :shapes [(:id obj)]}) + shapes) + (conj {:type :del-obj + :id (:id group) + :page-id page-id})) + + ;; Look at the `get-empty-groups-after-group-creation` + ;; doctring to understand the real purpuse of this code + ids-to-delete (get-empty-groups-after-group-creation objects parent-id shapes) delete-group (fn [changes id] - (-> changes - (conj {:type :del-obj - :id id - :page-id page-id}))) + (conj changes {:type :del-obj + :id id + :page-id page-id})) add-deleted-group (fn [changes id] (let [obj (-> (get objects id) - (d/without-keys [:shapes]))] - - (d/concat [{:type :add-obj - :id id - :page-id page-id - :frame-id (:frame-id obj) - :parent-id (:parent-id obj) - :obj obj - :index (::index obj)}] changes))) + (dissoc :shapes))] + (into [{:type :add-obj + :id id + :page-id page-id + :frame-id (:frame-id obj) + :parent-id (:parent-id obj) + :obj obj + :index (::index obj)}] + changes))) rchanges (->> ids-to-delete (reduce delete-group rchanges)) From 38292bcda765b075e4179b607e55b7da65d82234 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 27 Jul 2021 12:14:37 +0200 Subject: [PATCH 23/35] :bug: Properly handle group naming on group creation. --- .../src/app/main/data/workspace/groups.cljs | 33 +++++++++---------- .../data/workspace/libraries_helpers.cljs | 2 +- frontend/test/app/components_basic_test.cljs | 18 +++++----- frontend/test/app/test_helpers/pages.cljs | 9 ++--- 4 files changed, 30 insertions(+), 32 deletions(-) diff --git a/frontend/src/app/main/data/workspace/groups.cljs b/frontend/src/app/main/data/workspace/groups.cljs index a49b8c0b03..db26140a8d 100644 --- a/frontend/src/app/main/data/workspace/groups.cljs +++ b/frontend/src/app/main/data/workspace/groups.cljs @@ -23,19 +23,6 @@ (map #(assoc % ::index (cp/position-on-parent (:id %) objects))) (sort-by ::index))) -(defn- make-group - [shapes prefix keep-name] - (let [selrect (gsh/selection-rect shapes) - frame-id (-> shapes first :frame-id) - group-name (if (and keep-name - (= (count shapes) 1) - (= (:type (first shapes)) :group)) - (:name (first shapes)) - (name (gensym prefix)))] ; TODO: we should something like in new shapes - (-> (cp/make-minimal-group frame-id selrect group-name) - (gsh/setup selrect) - (assoc :shapes (mapv :id shapes))))) - (defn- get-empty-groups-after-group-creation "An auxiliar function that finds and returns a set of ids that corresponds to groups that should be deleted after a group creation. @@ -77,10 +64,20 @@ result))))))) (defn prepare-create-group - [objects page-id shapes prefix keep-name] - (let [group (make-group shapes prefix keep-name) - frame-id (:frame-id (first shapes)) + [objects page-id shapes base-name keep-name?] + (let [frame-id (:frame-id (first shapes)) parent-id (:parent-id (first shapes)) + gname (if (and keep-name? + (= (count shapes) 1) + (= (:type (first shapes)) :group)) + (:name (first shapes)) + (-> (dwc/retrieve-used-names objects) + (dwc/generate-unique-name base-name))) + + selrect (gsh/selection-rect shapes) + group (-> (cp/make-minimal-group frame-id selrect gname) + (gsh/setup selrect) + (assoc :shapes (mapv :id shapes))) rchanges [{:type :add-obj :id (:id group) @@ -185,7 +182,7 @@ shapes (shapes-for-grouping objects selected)] (when-not (empty? shapes) (let [[group rchanges uchanges] - (prepare-create-group objects page-id shapes "Group-" false)] + (prepare-create-group objects page-id shapes "Group" false)] (rx/of (dch/commit-changes {:redo-changes rchanges :undo-changes uchanges :origin it}) @@ -224,7 +221,7 @@ (if (and (= (count shapes) 1) (= (:type (first shapes)) :group)) [(first shapes) [] []] - (prepare-create-group objects page-id shapes "Group-" true)) + (prepare-create-group objects page-id shapes "Group" true)) rchanges (d/concat rchanges [{:type :mod-obj diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 788b2453a0..25a1c2c4f4 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -129,7 +129,7 @@ (if (and (= (count shapes) 1) (= (:type (first shapes)) :group)) [(first shapes) [] []] - (dwg/prepare-create-group objects page-id shapes "Component-" true)) + (dwg/prepare-create-group objects page-id shapes "Component" true)) [new-shape new-shapes updated-shapes] (make-component-shape group objects file-id) diff --git a/frontend/test/app/components_basic_test.cljs b/frontend/test/app/components_basic_test.cljs index 702b36cadd..e4ecfca84e 100644 --- a/frontend/test/app/components_basic_test.cljs +++ b/frontend/test/app/components_basic_test.cljs @@ -89,11 +89,11 @@ ;; NOTE: the group name depends on having executed ;; the previous test. - (t/is (= (:name group) "Component-2")) + (t/is (= (:name group) "Component-1")) (t/is (= (:name shape1) "Rect 1")) (t/is (= (:name shape2) "Rect 2")) - (t/is (= (:name component) "Component-2")) - (t/is (= (:name c-group) "Component-2")) + (t/is (= (:name component) "Component-1")) + (t/is (= (:name c-group) "Component-1")) (t/is (= (:name c-shape1) "Rect 1")) (t/is (= (:name c-shape2) "Rect 2")) @@ -139,11 +139,11 @@ (t/is (= (:name shape1) "Rect 1")) (t/is (= (:name shape2) "Rect 2")) - (t/is (= (:name group) "Group-3")) - (t/is (= (:name component) "Group-3")) + (t/is (= (:name group) "Group-1")) + (t/is (= (:name component) "Group-1")) (t/is (= (:name c-shape1) "Rect 1")) (t/is (= (:name c-shape2) "Rect 2")) - (t/is (= (:name c-group) "Group-3")) + (t/is (= (:name c-group) "Group-1")) (thl/is-from-file group file)))) @@ -234,7 +234,7 @@ new-component-id)] (t/is (= (:name component2) - "Component-6"))))) + "Component-2"))))) (rx/subs done @@ -322,9 +322,9 @@ (t/is (not= (:id instance1) (:id instance2))) (t/is (= (:id component) component-id)) - (t/is (= (:name instance2) "Component-8")) + (t/is (= (:name instance2) "Component-2")) (t/is (= (:name shape2) "Rect 1")) - (t/is (= (:name c-instance2) "Component-7")) + (t/is (= (:name c-instance2) "Component-1")) (t/is (= (:name c-shape2) "Rect 1"))))) (rx/subs diff --git a/frontend/test/app/test_helpers/pages.cljs b/frontend/test/app/test_helpers/pages.cljs index 4ea7265aac..d4f0ab03b1 100644 --- a/frontend/test/app/test_helpers/pages.cljs +++ b/frontend/test/app/test_helpers/pages.cljs @@ -10,6 +10,7 @@ [app.common.pages :as cp] [app.common.pages.helpers :as cph] [app.main.data.workspace :as dw] + [app.main.data.workspace.state-helpers :as wsh] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.libraries-helpers :as dwlh])) @@ -79,7 +80,7 @@ :obj shape}])))) (defn group-shapes - ([state label ids] (group-shapes state label ids "Group-")) + ([state label ids] (group-shapes state label ids "Group")) ([state label ids prefix] (let [page (current-page state) shapes (dwg/shapes-for-grouping (:objects page) ids)] @@ -94,9 +95,9 @@ (defn make-component [state label ids] - (let [page (current-page state) - objects (wsh/lookup-page-objects state page-id) - shapes (dwg/shapes-for-grouping objects ids) + (let [page (current-page state) + objects (wsh/lookup-page-objects state (:id page)) + shapes (dwg/shapes-for-grouping objects ids) [group rchanges uchanges] (dwlh/generate-add-component shapes From 55ddf9cc38720a0828855fea03be05b74edc3afb Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 27 Jul 2021 14:02:35 +0200 Subject: [PATCH 24/35] :tada: Add some missing js hints. --- frontend/src/app/util/dom.cljs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/util/dom.cljs b/frontend/src/app/util/dom.cljs index dfa4f4467a..9cf48d13de 100644 --- a/frontend/src/app/util/dom.cljs +++ b/frontend/src/app/util/dom.cljs @@ -98,7 +98,7 @@ (defn get-attribute "Extract the value of one attribute of a dom node." [node attr-name] - (.getAttribute node attr-name)) + (.getAttribute ^js node attr-name)) (def get-target-val (comp get-value get-target)) @@ -382,5 +382,5 @@ (trigger-download-uri filename mtype uri))) (defn left-mouse? [bevent] - (let [event (.-nativeEvent bevent)] + (let [event (.-nativeEvent ^js bevent)] (= 1 (.-which event)))) From 7fe419ecb0c6f08a716ec07e1de0017217880184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Tue, 27 Jul 2021 17:02:27 +0200 Subject: [PATCH 25/35] :bug: Fix error when editing texts --- .../app/main/ui/workspace/sidebar/options/menus/typography.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs index 68c503fcca..6af685f846 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/typography.cljs @@ -391,7 +391,7 @@ [:span.tooltip.tooltip-bottom {:alt (tr "workspace.options.text-options.none") :class (dom/classnames :current (= "none" text-transform)) - :focus #(dom/prevent-default %) + :on-focus #(dom/prevent-default %) :on-click #(handle-change % "none")} i/minus] [:span.tooltip.tooltip-bottom From 9d545004cb8d28845cfa77f2bd1a61626aff867b Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 27 Jul 2021 15:53:58 +0200 Subject: [PATCH 26/35] :bug: Fix problem with pasting text into text editor --- .../main/ui/workspace/shapes/text/editor.cljs | 18 +++++-- frontend/src/app/util/text_editor.cljs | 4 ++ frontend/src/app/util/text_editor_impl.js | 47 +++++++++++++++++-- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index e2321b4de6..1f74c8e283 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -77,6 +77,7 @@ (let [old-blocks (js->clj (.toJS (.getBlockMap (.getCurrentContent ^js old-state))) :keywordize-keys false) new-blocks (js->clj (.toJS (.getBlockMap (.getCurrentContent ^js state))) + :keywordize-keys false)] (->> old-blocks (d/mapm @@ -173,8 +174,9 @@ handle-return (mf/use-callback (fn [_ state] - (let [state (ted/editor-split-block state) - state (handle-change state)] + (let [style (ted/get-editor-current-inline-styles state) + state (-> (ted/insert-text state "\n" style) + (handle-change))] (st/emit! (dwt/update-editor-state shape state))) "handled")) @@ -183,7 +185,16 @@ (fn [event] (when (dom/class? (dom/get-target event) "DraftEditor-root") (st/emit! (dwt/cursor-to-end shape))) - (st/emit! (dwt/focus-editor))))] + (st/emit! (dwt/focus-editor)))) + + handle-pasted-text + (fn [text _ editor] + (let [style (ted/get-editor-current-inline-styles state) + state (-> (ted/insert-text state text style) + (handle-change))] + (st/emit! (dwt/update-editor-state shape state))) + + "handled")] (mf/use-layout-effect on-mount) @@ -203,6 +214,7 @@ :on-focus on-focus :handle-return handle-return :strip-pasted-styles true + :handle-pasted-text handle-pasted-text :custom-style-fn styles-fn :block-renderer-fn #(render-block % shape) :ref on-editor diff --git a/frontend/src/app/util/text_editor.cljs b/frontend/src/app/util/text_editor.cljs index 790609f6f2..06738d20ef 100644 --- a/frontend/src/app/util/text_editor.cljs +++ b/frontend/src/app/util/text_editor.cljs @@ -126,3 +126,7 @@ (as-> state $ (reduce redfn $ blocks) (impl/setSelection $ selection))))) + +(defn insert-text [state text attrs] + (let [style (txt/attrs-to-styles attrs)] + (impl/insertText state text (clj->js attrs) (clj->js style)))) diff --git a/frontend/src/app/util/text_editor_impl.js b/frontend/src/app/util/text_editor_impl.js index 18de4ec8f0..92b01533bf 100644 --- a/frontend/src/app/util/text_editor_impl.js +++ b/frontend/src/app/util/text_editor_impl.js @@ -9,14 +9,17 @@ 'use strict'; import { + BlockMapBuilder, CharacterMetadata, - EditorState, CompositeDecorator, + EditorState, + Modifier, + RichTextEditorUtil, SelectionState, - Modifier } from "draft-js"; -import {Map} from "immutable"; +import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor'; +import {Map, OrderedSet} from "immutable"; function isDefined(v) { return v !== undefined && v !== null; @@ -335,3 +338,41 @@ export function getInlineStyle(state, blockKey, offset) { const block = content.getBlockForKey(blockKey); return block.getInlineStyleAt(offset).toJS(); } + +const NEWLINE_REGEX = /\r\n?|\n/g; + +function splitTextIntoTextBlocks(text) { + return text.split(NEWLINE_REGEX); +} + +export function insertText(state, text, attrs, inlineStyles) { + const blocks = splitTextIntoTextBlocks(text); + + const character = CharacterMetadata.create({style: OrderedSet(inlineStyles)}); + + let blockArray = DraftPasteProcessor.processText( + blocks, + character, + "unstyled", + ); + + blockArray = blockArray.map((b) => { + if (b.getText() === "") { + return mergeBlockData(b, attrs) + } + return b; + }); + + const fragment = BlockMapBuilder.createFromArray(blockArray); + const content = state.getCurrentContent(); + const selection = state.getSelection(); + + const newContent = Modifier.replaceWithFragment( + content, + selection, + fragment + ); + + const resultSelection = SelectionState.createEmpty(selection.getStartKey()); + return EditorState.push(state, newContent, 'insert-fragment'); +} From c6fe19c321683051b9bbf6a12a2c627b3ec2c4cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Tue, 27 Jul 2021 10:23:19 +0200 Subject: [PATCH 27/35] :bug: Protect against broken component refs #1114 --- .../data/workspace/libraries_helpers.cljs | 303 +++++++++--------- 1 file changed, 155 insertions(+), 148 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 25a1c2c4f4..16115953e6 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -204,6 +204,7 @@ "Generate changes to remove the links between a shape and all its children with a component." [shape-id container] + (log/debug :msg "Detach instance" :shape-id shape-id :container (:id container)) (let [shapes (cp/get-object-with-children shape-id (:objects container)) rchanges (mapv (fn [obj] (make-change @@ -646,89 +647,92 @@ :shape (str (:name shape-inst)) :component (:name component)) - (let [omit-touched? (not reset?) - clear-remote-synced? (and initial-root? reset?) - set-remote-synced? (and (not initial-root?) reset?) + (if (nil? shape-main) + ;; This should not occur, but protect against it in any case + (generate-detach-instance (:id shape-inst) container) + (let [omit-touched? (not reset?) + clear-remote-synced? (and initial-root? reset?) + set-remote-synced? (and (not initial-root?) reset?) - [rchanges uchanges] - (concat-changes - (update-attrs shape-inst - shape-main - root-inst - root-main - container - omit-touched?) + [rchanges uchanges] (concat-changes - (if reset? - (change-touched shape-inst - shape-main - container - {:reset-touched? true}) - empty-changes) + (update-attrs shape-inst + shape-main + root-inst + root-main + container + omit-touched?) (concat-changes - (if clear-remote-synced? - (change-remote-synced shape-inst container nil) + (if reset? + (change-touched shape-inst + shape-main + container + {:reset-touched? true}) empty-changes) - (if set-remote-synced? - (change-remote-synced shape-inst container true) - empty-changes)))) + (concat-changes + (if clear-remote-synced? + (change-remote-synced shape-inst container nil) + empty-changes) + (if set-remote-synced? + (change-remote-synced shape-inst container true) + empty-changes)))) - children-inst (mapv #(cp/get-shape container %) - (:shapes shape-inst)) - children-main (mapv #(cp/get-shape component %) - (:shapes shape-main)) + children-inst (mapv #(cp/get-shape container %) + (:shapes shape-inst)) + children-main (mapv #(cp/get-shape component %) + (:shapes shape-main)) - only-inst (fn [child-inst] - (when-not (and omit-touched? - (contains? (:touched shape-inst) - :shapes-group)) - (remove-shape child-inst - container - omit-touched?))) + only-inst (fn [child-inst] + (when-not (and omit-touched? + (contains? (:touched shape-inst) + :shapes-group)) + (remove-shape child-inst + container + omit-touched?))) - only-main (fn [child-main] - (when-not (and omit-touched? - (contains? (:touched shape-inst) - :shapes-group)) - (add-shape-to-instance child-main - (d/index-of children-main - child-main) - component - container - root-inst - root-main - omit-touched? - set-remote-synced?))) + only-main (fn [child-main] + (when-not (and omit-touched? + (contains? (:touched shape-inst) + :shapes-group)) + (add-shape-to-instance child-main + (d/index-of children-main + child-main) + component + container + root-inst + root-main + omit-touched? + set-remote-synced?))) - both (fn [child-inst child-main] - (generate-sync-shape-direct-recursive container - child-inst - component - child-main - root-inst - root-main - reset? - initial-root?)) + both (fn [child-inst child-main] + (generate-sync-shape-direct-recursive container + child-inst + component + child-main + root-inst + root-main + reset? + initial-root?)) - moved (fn [child-inst child-main] - (move-shape - child-inst - (d/index-of children-inst child-inst) - (d/index-of children-main child-main) - container - omit-touched?)) + moved (fn [child-inst child-main] + (move-shape + child-inst + (d/index-of children-inst child-inst) + (d/index-of children-main child-main) + container + omit-touched?)) - [child-rchanges child-uchanges] - (compare-children children-inst - children-main - only-inst - only-main - both - moved - false)] + [child-rchanges child-uchanges] + (compare-children children-inst + children-main + only-inst + only-main + both + moved + false)] - [(d/concat rchanges child-rchanges) - (d/concat uchanges child-uchanges)])) + [(d/concat rchanges child-rchanges) + (d/concat uchanges child-uchanges)]))) (defn generate-sync-shape-inverse "Generate changes to update the component a shape is linked to, from @@ -764,96 +768,99 @@ :shape (str (:name shape-inst)) :component (:name component)) - (let [component-container (cp/make-container component :component) + (if (nil? shape-main) + ;; This should not occur, but protect against it in any case + empty-changes + (let [component-container (cp/make-container component :component) - omit-touched? false - set-remote-synced? (not initial-root?) - clear-remote-synced? initial-root? + omit-touched? false + set-remote-synced? (not initial-root?) + clear-remote-synced? initial-root? - [rchanges uchanges] - (concat-changes - (update-attrs shape-main - shape-inst - root-main - root-inst - component-container - omit-touched?) + [rchanges uchanges] (concat-changes - (change-touched shape-inst - shape-main - container - {:reset-touched? true}) + (update-attrs shape-main + shape-inst + root-main + root-inst + component-container + omit-touched?) (concat-changes - (change-touched shape-main - shape-inst - component-container - {:copy-touched? true}) + (change-touched shape-inst + shape-main + container + {:reset-touched? true}) (concat-changes - (if clear-remote-synced? - (change-remote-synced shape-inst container nil) - empty-changes) - (if set-remote-synced? - (change-remote-synced shape-inst container true) - empty-changes))))) + (change-touched shape-main + shape-inst + component-container + {:copy-touched? true}) + (concat-changes + (if clear-remote-synced? + (change-remote-synced shape-inst container nil) + empty-changes) + (if set-remote-synced? + (change-remote-synced shape-inst container true) + empty-changes))))) - children-inst (mapv #(cp/get-shape container %) - (:shapes shape-inst)) - children-main (mapv #(cp/get-shape component %) - (:shapes shape-main)) + children-inst (mapv #(cp/get-shape container %) + (:shapes shape-inst)) + children-main (mapv #(cp/get-shape component %) + (:shapes shape-main)) - only-inst (fn [child-inst] - (add-shape-to-main child-inst - (d/index-of children-inst - child-inst) - component - container - root-inst - root-main)) + only-inst (fn [child-inst] + (add-shape-to-main child-inst + (d/index-of children-inst + child-inst) + component + container + root-inst + root-main)) - only-main (fn [child-main] - (remove-shape child-main - component-container - false)) + only-main (fn [child-main] + (remove-shape child-main + component-container + false)) - both (fn [child-inst child-main] - (generate-sync-shape-inverse-recursive container - child-inst - component - child-main - root-inst - root-main - initial-root?)) + both (fn [child-inst child-main] + (generate-sync-shape-inverse-recursive container + child-inst + component + child-main + root-inst + root-main + initial-root?)) - moved (fn [child-inst child-main] - (move-shape - child-main - (d/index-of children-main child-main) - (d/index-of children-inst child-inst) - component-container - false)) + moved (fn [child-inst child-main] + (move-shape + child-main + (d/index-of children-main child-main) + (d/index-of children-inst child-inst) + component-container + false)) - [child-rchanges child-uchanges] - (compare-children children-inst - children-main - only-inst - only-main - both - moved - true) + [child-rchanges child-uchanges] + (compare-children children-inst + children-main + only-inst + only-main + both + moved + true) - ;; The inverse sync may be made on a component that is inside a - ;; remote library. We need to separate changes that are from - ;; local and remote files. - check-local (fn [change] - (cond-> change - (= (:id change) (:id shape-inst)) - (assoc :local-change? true))) + ;; The inverse sync may be made on a component that is inside a + ;; remote library. We need to separate changes that are from + ;; local and remote files. + check-local (fn [change] + (cond-> change + (= (:id change) (:id shape-inst)) + (assoc :local-change? true))) - rchanges (mapv check-local rchanges) - uchanges (mapv check-local uchanges)] + rchanges (mapv check-local rchanges) + uchanges (mapv check-local uchanges)] - [(d/concat rchanges child-rchanges) - (d/concat uchanges child-uchanges)])) + [(d/concat rchanges child-rchanges) + (d/concat uchanges child-uchanges)]))) ; ---- Operation generation helpers ---- From 259b405526ebec1e0e1b455fa0c2d6a55603bb10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Tue, 27 Jul 2021 16:26:19 +0200 Subject: [PATCH 28/35] :sparkles: Detach all assets when unlinking an external lib --- frontend/src/app/main/data/workspace/libraries.cljs | 2 +- frontend/src/app/main/data/workspace/persistence.cljs | 11 +++++++---- frontend/src/app/main/ui/workspace/libraries.cljs | 6 +++++- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 20d97a2106..77b15d1b9d 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -594,7 +594,7 @@ ptk/UpdateEvent (update [_ state] (if (not= library-id (:current-file-id state)) - (assoc-in state [:workspace-libraries library-id :synced-at] (dt/now)) + (d/assoc-in-when state [:workspace-libraries library-id :synced-at] (dt/now)) state)) ptk/WatchEvent diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index 76609c41a9..9471a58287 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -326,13 +326,16 @@ (defn unlink-file-from-library [file-id library-id] (ptk/reify ::unlink-file-from-library + ptk/UpdateEvent + (update [_ state] + (d/dissoc-in state [:workspace-libraries library-id])) + ptk/WatchEvent (watch [_ _ _] - (let [unlinked #(d/dissoc-in % [:workspace-libraries library-id]) - params {:file-id file-id - :library-id library-id}] + (let [params {:file-id file-id + :library-id library-id}] (->> (rp/mutation :unlink-file-from-library params) - (rx/map (constantly unlinked))))))) + (rx/ignore)))))) ;; --- Upload File Media objects diff --git a/frontend/src/app/main/ui/workspace/libraries.cljs b/frontend/src/app/main/ui/workspace/libraries.cljs index f48d73b454..b9aa0dbc65 100644 --- a/frontend/src/app/main/ui/workspace/libraries.cljs +++ b/frontend/src/app/main/ui/workspace/libraries.cljs @@ -75,7 +75,11 @@ (mf/use-callback (mf/deps file) #(st/emit! (dw/link-file-to-library (:id file) %))) unlink-library - (mf/use-callback (mf/deps file) #(st/emit! (dw/unlink-file-from-library (:id file) %)))] + (mf/use-callback + (mf/deps file) + (fn [library-id] + (st/emit! (dw/unlink-file-from-library (:id file) library-id) + (dwl/sync-file (:id file) library-id))))] [:* [:div.section [:div.section-title (tr "workspace.libraries.in-this-file")] From 53620b9f1b0f82b7c076e3e82a453c7282d3cb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 28 Jul 2021 16:15:56 +0200 Subject: [PATCH 29/35] =?UTF-8?q?:bug:=20Fix=20tooltip=20errors=EF=BC=9Amo?= =?UTF-8?q?ve=20nodes=20and=20draw=20nodes=20are=20swapped?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From PR https://github.com/penpot/penpot/pull/1100 by @soultipsy --- CHANGES.md | 3 +++ frontend/src/app/main/ui/workspace/viewport/path_actions.cljs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index abec28d9f7..1786d3b37c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -13,6 +13,9 @@ ### :boom: Breaking changes ### :heart: Community contributions by (Thank you!) +- soultipsy [#1100](https://github.com/penpot/penpot/pull/1100) + + ## 1.7.1-alpha ### :bug: Bugs fixed diff --git a/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs b/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs index f6d85e32cf..1aef9a82f7 100644 --- a/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/path_actions.cljs @@ -108,14 +108,14 @@ ;; Draw Mode [:div.viewport-actions-entry.tooltip.tooltip-bottom {:class (when (= edit-mode :draw) "is-toggled") - :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) + :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) :on-click on-select-draw-mode} i/pen] ;; Edit mode [:div.viewport-actions-entry.tooltip.tooltip-bottom {:class (when (= edit-mode :move) "is-toggled") - :alt (tr "workspace.path.actions.draw-nodes" (sc/get-tooltip :draw-nodes)) + :alt (tr "workspace.path.actions.move-nodes" (sc/get-tooltip :move-nodes)) :on-click on-select-edit-mode} i/pointer-inner]] From 80ab6bbda2acffa3285b5975f9467d4993859edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Moya?= Date: Wed, 28 Jul 2021 16:23:15 +0200 Subject: [PATCH 30/35] :bug: Fix linter error --- frontend/src/app/main/ui/workspace/shapes/text/editor.cljs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index 1f74c8e283..db9d70aad0 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -188,7 +188,7 @@ (st/emit! (dwt/focus-editor)))) handle-pasted-text - (fn [text _ editor] + (fn [text _ _] (let [style (ted/get-editor-current-inline-styles state) state (-> (ted/insert-text state text style) (handle-change))] From efa5120fac6d775f41af5b21680b95ccdf336c8c Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 29 Jul 2021 12:34:17 +0200 Subject: [PATCH 31/35] :sparkles: Fix inconsistencies on storage backend usage. --- backend/src/app/config.clj | 2 +- backend/src/app/main.clj | 5 +---- backend/src/app/media.clj | 19 +++++++++++++++---- backend/src/app/rpc/mutations/files.clj | 3 +-- backend/src/app/rpc/mutations/media.clj | 4 +--- backend/src/app/rpc/mutations/profile.clj | 19 +++++++++++-------- backend/src/app/rpc/mutations/teams.clj | 10 ++++++---- backend/src/app/rpc/queries/files.clj | 3 +-- backend/src/app/storage.clj | 6 ++---- docker/images/config.env | 4 ++-- 10 files changed, 41 insertions(+), 34 deletions(-) diff --git a/backend/src/app/config.clj b/backend/src/app/config.clj index f7c587d487..27df0e7785 100644 --- a/backend/src/app/config.clj +++ b/backend/src/app/config.clj @@ -58,7 +58,7 @@ :srepl-host "127.0.0.1" :srepl-port 6062 - :assets-storage-backend :fs + :assets-storage-backend :assets-fs :storage-assets-fs-directory "assets" :feedback-destination "info@example.com" diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index dc43559107..15275370fb 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -322,13 +322,10 @@ :app.storage/storage {:pool (ig/ref :app.db/pool) :executor (ig/ref :app.worker/executor) - :backend (cf/get :assets-storage-backend :assets-fs) + :backends {:assets-s3 (ig/ref [::assets :app.storage.s3/backend]) :assets-db (ig/ref [::assets :app.storage.db/backend]) :assets-fs (ig/ref [::assets :app.storage.fs/backend]) - :s3 (ig/ref [::assets :app.storage.s3/backend]) - :db (ig/ref [::assets :app.storage.db/backend]) - :fs (ig/ref [::assets :app.storage.fs/backend]) :tmp (ig/ref [::tmp :app.storage.fs/backend]) :fdata-s3 (ig/ref [::fdata :app.storage.s3/backend])}} diff --git a/backend/src/app/media.clj b/backend/src/app/media.clj index b2aeefa184..59019558d6 100644 --- a/backend/src/app/media.clj +++ b/backend/src/app/media.clj @@ -11,6 +11,7 @@ [app.common.exceptions :as ex] [app.common.media :as cm] [app.common.spec :as us] + [app.config :as cf] [app.rlimits :as rlm] [app.rpc.queries.svg :as svg] [buddy.core.bytes :as bb] @@ -28,10 +29,6 @@ org.im4java.core.IMOperation org.im4java.core.Info)) -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; --- Utility functions -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - (s/def ::image-content-type cm/valid-image-types) (s/def ::font-content-type cm/valid-font-types) @@ -330,3 +327,17 @@ (= stype :ttf) (-> (assoc "font/otf" (ttf->otf sfnt)) (assoc "font/ttf" sfnt))))))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Utility functions +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +(defn configure-assets-storage + "Given storage map, returns a storage configured with the apropriate + backend for assets." + [storage conn] + (-> storage + (assoc :conn conn) + (assoc :backend (cf/get :assets-storage-backend :assets-fs)))) + diff --git a/backend/src/app/rpc/mutations/files.clj b/backend/src/app/rpc/mutations/files.clj index 3c266268d3..6436f0fc92 100644 --- a/backend/src/app/rpc/mutations/files.clj +++ b/backend/src/app/rpc/mutations/files.clj @@ -11,7 +11,6 @@ [app.common.pages.migrations :as pmg] [app.common.spec :as us] [app.common.uuid :as uuid] - [app.config :as cf] [app.db :as db] [app.rpc.permissions :as perms] [app.rpc.queries.files :as files] @@ -288,7 +287,7 @@ (defn- delete-from-storage [{:keys [storage] :as cfg} file] - (when-let [backend (simpl/resolve-backend storage (cf/get :fdata-storage-backend))] + (when-let [backend (simpl/resolve-backend storage (:data-backend file))] (simpl/del-object backend file))) (defn- update-file diff --git a/backend/src/app/rpc/mutations/media.clj b/backend/src/app/rpc/mutations/media.clj index 3467522f1d..bfe876df1e 100644 --- a/backend/src/app/rpc/mutations/media.clj +++ b/backend/src/app/rpc/mutations/media.clj @@ -32,7 +32,6 @@ (s/def ::file-id ::us/uuid) (s/def ::team-id ::us/uuid) - ;; --- Create File Media object (upload) (declare create-file-media-object) @@ -94,10 +93,9 @@ (defn create-file-media-object [{:keys [conn storage] :as cfg} {:keys [id file-id is-local name content] :as params}] (media/validate-media-type (:content-type content)) - (let [storage (assoc storage :conn conn) + (let [storage (media/configure-assets-storage storage conn) source-path (fs/path (:tempfile content)) source-mtype (:content-type content) - source-info (media/run cfg {:cmd :info :input {:path source-path :mtype source-mtype}}) thumb (when (and (not (svg-image? source-info)) diff --git a/backend/src/app/rpc/mutations/profile.clj b/backend/src/app/rpc/mutations/profile.clj index 17c52869a7..cc1dce0799 100644 --- a/backend/src/app/rpc/mutations/profile.clj +++ b/backend/src/app/rpc/mutations/profile.clj @@ -9,7 +9,7 @@ [app.common.exceptions :as ex] [app.common.spec :as us] [app.common.uuid :as uuid] - [app.config :as cfg] + [app.config :as cf] [app.db :as db] [app.emails :as eml] [app.http.oauth :refer [extract-props]] @@ -99,11 +99,11 @@ (sv/defmethod ::prepare-register-profile {:auth false} [{:keys [pool tokens] :as cfg} params] - (when-not (cfg/get :registration-enabled) + (when-not (cf/get :registration-enabled) (ex/raise :type :restriction :code :registration-disabled)) - (when-let [domains (cfg/get :registration-domain-whitelist)] + (when-let [domains (cf/get :registration-domain-whitelist)] (when-not (email-domain-in-whitelist? domains (:email params)) (ex/raise :type :validation :code :email-domain-is-not-allowed))) @@ -402,6 +402,7 @@ {:password (derive-password password)} {:id id})) + ;; --- MUTATION: Update Photo (declare update-profile-photo) @@ -416,11 +417,13 @@ [{:keys [pool storage] :as cfg} {:keys [profile-id file] :as params}] (db/with-atomic [conn pool] (media/validate-media-type (:content-type file) #{"image/jpeg" "image/png" "image/webp"}) + (media/run cfg {:cmd :info :input {:path (:tempfile file) + :mtype (:content-type file)}}) + (let [profile (db/get-by-id conn :profile profile-id) - _ (media/run cfg {:cmd :info :input {:path (:tempfile file) - :mtype (:content-type file)}}) - photo (teams/upload-photo cfg params) - storage (assoc storage :conn conn)] + storage (media/configure-assets-storage storage conn) + cfg (assoc cfg :storage storage) + photo (teams/upload-photo cfg params)] ;; Schedule deletion of old photo (when-let [id (:photo-id profile)] @@ -453,7 +456,7 @@ params (assoc params :profile profile :email (str/lower email))] - (if (cfg/get :smtp-enabled) + (if (cf/get :smtp-enabled) (request-email-change cfg params) (change-email-inmediatelly cfg params))))) diff --git a/backend/src/app/rpc/mutations/teams.clj b/backend/src/app/rpc/mutations/teams.clj index 3b71c43c48..d0eae6dee5 100644 --- a/backend/src/app/rpc/mutations/teams.clj +++ b/backend/src/app/rpc/mutations/teams.clj @@ -251,10 +251,12 @@ (db/with-atomic [conn pool] (teams/check-edition-permissions! conn profile-id team-id) (media/validate-media-type (:content-type file) #{"image/jpeg" "image/png" "image/webp"}) + (media/run cfg {:cmd :info :input {:path (:tempfile file) + :mtype (:content-type file)}}) (let [team (teams/retrieve-team conn profile-id team-id) - _ (media/run cfg {:cmd :info :input {:path (:tempfile file) - :mtype (:content-type file)}}) + storage (media/configure-assets-storage storage conn) + cfg (assoc cfg :storage storage) photo (upload-photo cfg params)] ;; Schedule deletion of old photo @@ -263,8 +265,8 @@ ;; Save new photo (db/update! conn :team - {:photo-id (:id photo)} - {:id team-id}) + {:photo-id (:id photo)} + {:id team-id}) (assoc team :photo-id (:id photo))))) diff --git a/backend/src/app/rpc/queries/files.clj b/backend/src/app/rpc/queries/files.clj index 74938feb23..55f536d5f3 100644 --- a/backend/src/app/rpc/queries/files.clj +++ b/backend/src/app/rpc/queries/files.clj @@ -9,7 +9,6 @@ [app.common.pages.migrations :as pmg] [app.common.spec :as us] [app.common.uuid :as uuid] - [app.config :as cf] [app.db :as db] [app.rpc.permissions :as perms] [app.rpc.queries.projects :as projects] @@ -175,7 +174,7 @@ (defn- retrieve-data* [{:keys [storage] :as cfg} file] - (when-let [backend (simpl/resolve-backend storage (cf/get :fdata-storage-backend))] + (when-let [backend (simpl/resolve-backend storage (:data-backend file))] (simpl/get-object-bytes backend file))) (defn retrieve-data diff --git a/backend/src/app/storage.clj b/backend/src/app/storage.clj index f8a923a2de..e6acb07763 100644 --- a/backend/src/app/storage.clj +++ b/backend/src/app/storage.clj @@ -28,8 +28,6 @@ ;; Storage Module State ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(s/def ::backend ::us/keyword) - (s/def ::s3 ::ss3/backend) (s/def ::fs ::sfs/backend) (s/def ::db ::sdb/backend) @@ -42,7 +40,7 @@ :db ::sdb/backend)))) (defmethod ig/pre-init-spec ::storage [_] - (s/keys :req-un [::backend ::wrk/executor ::db/pool ::backends])) + (s/keys :req-un [::wrk/executor ::db/pool ::backends])) (defmethod ig/prep-key ::storage [_ {:keys [backends] :as cfg}] @@ -55,7 +53,7 @@ (assoc :backends (d/without-nils backends)))) (s/def ::storage - (s/keys :req-un [::backends ::wrk/executor ::db/pool ::backend])) + (s/keys :req-un [::backends ::wrk/executor ::db/pool])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Database Objects diff --git a/docker/images/config.env b/docker/images/config.env index 6d1f76bd27..157d2be434 100644 --- a/docker/images/config.env +++ b/docker/images/config.env @@ -13,8 +13,8 @@ PENPOT_REDIS_URI=redis://penpot-redis/0 # can be configured to store in AWS S3 or completely in de the database. # Storing in the database makes the backups more easy but will make access to # media less performant. -PENPOT_STORAGE_BACKEND=fs -PENPOT_STORAGE_FS_DIRECTORY=/opt/data/assets +ASSETS_STORAGE_BACKEND=assets-fs +PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/data/assets # Telemetry. When enabled, a periodical process will send anonymous data about # this instance. Telemetry data will enable us to learn on how the application From 06733ea7cd27794539ec69c1db20cbe4ae9180a0 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 29 Jul 2021 12:35:41 +0200 Subject: [PATCH 32/35] :bug: Fix exporter bug on docker images. --- docker/images/files/nginx-entrypoint.sh | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/docker/images/files/nginx-entrypoint.sh b/docker/images/files/nginx-entrypoint.sh index cf292de0a9..8e2c645f8b 100644 --- a/docker/images/files/nginx-entrypoint.sh +++ b/docker/images/files/nginx-entrypoint.sh @@ -9,17 +9,6 @@ log() { ## App Frontend config ######################################### - -update_public_uri() { - if [ -n "$PENPOT_PUBLIC_URI" ]; then - log "Updating Public URI: $PENPOT_PUBLIC_URI" - sed -i \ - -e "s|^//var penpotPublicURI = \".*\";|var penpotPublicURI = \"$PENPOT_PUBLIC_URI\";|g" \ - "$1" - fi -} - - update_demo_warning() { if [ -n "$PENPOT_DEMO_WARNING" ]; then log "Updating Demo Warning: $PENPOT_DEMO_WARNING" @@ -113,7 +102,6 @@ update_flags() { fi } -update_public_uri /var/www/app/js/config.js update_demo_warning /var/www/app/js/config.js update_allow_demo_users /var/www/app/js/config.js update_google_client_id /var/www/app/js/config.js From 4d5b0731bed7fadf7df3aae08b04d08d41770a10 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 29 Jul 2021 14:54:30 +0200 Subject: [PATCH 33/35] :paperclip: Prepare 1.7.2-alpha release. --- CHANGES.md | 22 ++++++++++++++++++++++ version.txt | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1786d3b37c..247d756936 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,15 +1,37 @@ # CHANGELOG # + + + ## :rocket: Next ### :sparkles: New features +### :bug: Bugs fixed +### :arrow_up: Deps updates +### :boom: Breaking changes +### :heart: Community contributions by (Thank you!) + + +## 1.7.2-alpha + +### :sparkles: New features + +- Add many improvements to text tool. + ### :bug: Bugs fixed - Add scroll bar to Teams menu [Taiga #1894](https://tree.taiga.io/project/penpot/issue/1894). - Fix repeated names when duplicating artboards or groups [Taiga #1892](https://tree.taiga.io/project/penpot/issue/1892). +- Fix properly messages lifecycle on navigate. +- Fix handling repeated names on duplicate object trees. +- Fix group naming on group creation. +- Fix some issues in svg transformation. ### :arrow_up: Deps updates + +- Update frontend build tooling. + ### :boom: Breaking changes ### :heart: Community contributions by (Thank you!) diff --git a/version.txt b/version.txt index 1d16151a4e..e6bff99f22 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -1.8.0-alpha +1.7.2-alpha From e4f755416db2f5457ca34d7a8665662a41cb5ac8 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Thu, 29 Jul 2021 16:44:25 +0200 Subject: [PATCH 34/35] :bug: Fix backward compatibility introduced in previous commit. Related to stroage. --- backend/src/app/main.clj | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/src/app/main.clj b/backend/src/app/main.clj index 15275370fb..e882f71658 100644 --- a/backend/src/app/main.clj +++ b/backend/src/app/main.clj @@ -323,11 +323,16 @@ {:pool (ig/ref :app.db/pool) :executor (ig/ref :app.worker/executor) - :backends {:assets-s3 (ig/ref [::assets :app.storage.s3/backend]) + :backends { + :assets-s3 (ig/ref [::assets :app.storage.s3/backend]) :assets-db (ig/ref [::assets :app.storage.db/backend]) :assets-fs (ig/ref [::assets :app.storage.fs/backend]) :tmp (ig/ref [::tmp :app.storage.fs/backend]) - :fdata-s3 (ig/ref [::fdata :app.storage.s3/backend])}} + :fdata-s3 (ig/ref [::fdata :app.storage.s3/backend]) + + ;; keep this for backward compatibility + :s3 (ig/ref [::assets :app.storage.s3/backend]) + :fs (ig/ref [::assets :app.storage.fs/backend])}} [::fdata :app.storage.s3/backend] {:region (cf/get :storage-fdata-s3-region) From bed702d8de68295aab4887a465d3606e6bf86205 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 2 Aug 2021 23:12:22 +0200 Subject: [PATCH 35/35] :bug: Fix font uploading (related to storage internal changes). --- backend/src/app/rpc/mutations/fonts.clj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/app/rpc/mutations/fonts.clj b/backend/src/app/rpc/mutations/fonts.clj index 9037550f13..fd3291e6d3 100644 --- a/backend/src/app/rpc/mutations/fonts.clj +++ b/backend/src/app/rpc/mutations/fonts.clj @@ -47,7 +47,8 @@ (defn create-font-variant [{:keys [conn storage] :as cfg} {:keys [data] :as params}] (let [data (media/run cfg {:cmd :generate-fonts :input data :rlimit :font}) - storage (assoc storage :conn conn) + storage (media/configure-assets-storage storage conn) + otf (when-let [fdata (get data "font/otf")] (sto/put-object storage {:content (sto/content fdata) :content-type "font/otf"}))