From 1321bdeac5e2ae58b53799debfc24b4ebd244fb3 Mon Sep 17 00:00:00 2001 From: Alejandro Alonso Date: Wed, 5 Jan 2022 13:27:14 +0100 Subject: [PATCH] :sparkles: Add opacity shortcuts --- CHANGES.md | 1 + frontend/src/app/main/data/workspace.cljs | 2 + .../src/app/main/data/workspace/layers.cljs | 81 +++++++++++++++++++ .../app/main/data/workspace/shortcuts.cljs | 14 +++- .../app/main/data/workspace/transforms.cljs | 4 - 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 frontend/src/app/main/data/workspace/layers.cljs diff --git a/CHANGES.md b/CHANGES.md index e42ea60076..3dcc34db5b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ ### :boom: Breaking changes ### :sparkles: New features +- Add shortcut for opacity [Taiga #2442](https://tree.taiga.io/project/penpot/us/2442). - Setting fill automatically for new texts [Taiga #2441](https://tree.taiga.io/project/penpot/us/2441). - Add shortcut to move action [Github #1213](https://github.com/penpot/penpot/issues/1213). - Add alt as mod key to add stroke color from library menu [Taiga #2207](https://tree.taiga.io/project/penpot/us/2207). diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 0ac199c3a4..0993504af2 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -31,6 +31,7 @@ [app.main.data.workspace.fix-bool-contents :as fbc] [app.main.data.workspace.groups :as dwg] [app.main.data.workspace.interactions :as dwi] + [app.main.data.workspace.layers :as dwly] [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.notifications :as dwn] [app.main.data.workspace.path :as dwdp] @@ -1914,6 +1915,7 @@ (d/export dwt/update-position) (d/export dwt/flip-horizontal-selected) (d/export dwt/flip-vertical-selected) +(d/export dwly/set-opacity) ;; Persistence diff --git a/frontend/src/app/main/data/workspace/layers.cljs b/frontend/src/app/main/data/workspace/layers.cljs new file mode 100644 index 0000000000..4344e13e89 --- /dev/null +++ b/frontend/src/app/main/data/workspace/layers.cljs @@ -0,0 +1,81 @@ +;; 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.data.workspace.layers + "Events related with layers transformations" + (:require + [app.common.data :as d] + [app.common.math :as mth] + [app.main.data.workspace.changes :as dch] + [app.main.data.workspace.state-helpers :as wsh] + [beicon.core :as rx] + [cuerdas.core :as str] + [potok.core :as ptk])) + +;; -- Opacity ---------------------------------------------------------- + +;; The opacity of an element can be changed by typing numbers on the keyboard: +;; 1 --> 0.1 +;; 2 --> 0.2 +;; 3 --> 0.3 +;; 4 --> 0.4 +;; ... +;; 9 --> 0.9 +;; 0 --> 1 +;; 00 --> 0% +;; The user can also type a more exact number: +;; 45 --> 45% +;; 05 --> 5% + +(defn calculate-opacity [numbers] + (let [total (->> numbers + (str/join "") + (d/parse-integer))] + (if (= numbers [0]) + 1 + (/ total (mth/pow 10 (count numbers)))))) + +(defn set-opacity + [opacity] + (ptk/reify ::set-opacity + ptk/WatchEvent + (watch [_ state _] + (let [objects (wsh/lookup-page-objects state) + selected (wsh/lookup-selected state {:omit-blocked? true}) + shapes (map #(get objects %) selected) + shapes-ids (->> shapes + (map :id))] + (rx/of (dch/update-shapes shapes-ids #(assoc % :opacity opacity))))))) + +(defn pressed-opacity + [opacity] + (let [same-event (js/Symbol "same-event")] + (ptk/reify ::pressed-opacity + IDeref + (-deref [_] opacity) + + ptk/UpdateEvent + (update [_ state] + (if (nil? (:press-opacity-id state)) ;; avoiding duplicated events + (assoc state :press-opacity-id same-event) + state)) + + ptk/WatchEvent + (watch [_ state stream] + (if (not= same-event (:press-opacity-id state)) + (rx/empty) + (let [opacity-events (->> stream ;; Stop buffering after time without opacities + (rx/filter (ptk/type? ::pressed-opacity)) + (rx/buffer-time 600) + (rx/first) + (rx/map #(set-opacity (calculate-opacity (map deref %)))))] + (rx/concat + (rx/of (set-opacity (calculate-opacity [opacity]))) ;; First opacity is always fired + (rx/merge + opacity-events + (rx/of (pressed-opacity opacity))) + (rx/of (fn [state] + (dissoc state :press-opacity-id)))))))))) diff --git a/frontend/src/app/main/data/workspace/shortcuts.cljs b/frontend/src/app/main/data/workspace/shortcuts.cljs index 57bd15270d..9aa6d1d673 100644 --- a/frontend/src/app/main/data/workspace/shortcuts.cljs +++ b/frontend/src/app/main/data/workspace/shortcuts.cljs @@ -11,6 +11,7 @@ [app.main.data.workspace.colors :as mdc] [app.main.data.workspace.common :as dwc] [app.main.data.workspace.drawing :as dwd] + [app.main.data.workspace.layers :as dwly] [app.main.data.workspace.libraries :as dwl] [app.main.data.workspace.texts :as dwtxt] [app.main.data.workspace.transforms :as dwt] @@ -24,7 +25,7 @@ ;; Shortcuts format https://github.com/ccampbell/mousetrap -(def shortcuts +(def base-shortcuts {:toggle-layers {:tooltip (ds/alt "L") :command (ds/a-mod "l") :fn #(st/emit! (dw/go-to-layout :layers))} @@ -333,6 +334,17 @@ :command (ds/c-mod "alt+l") :fn #(st/emit! (dw/toggle-proportion-lock))}}) +(def opacity-shortcuts + (into {} (->> + (range 10) + (map (fn [n] [(keyword (str "opacity-" n)) + {:tooltip (str n) + :command (str n) + :fn #(st/emit! (dwly/pressed-opacity n))}]))))) + +(def shortcuts + (merge base-shortcuts opacity-shortcuts)) + (defn get-tooltip [shortcut] (assert (contains? shortcuts shortcut) (str shortcut)) (get-in shortcuts [shortcut :tooltip])) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 250fa536dc..94c3c3af0f 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -735,7 +735,3 @@ :displacement (gmt/translate-matrix (gpt/point 0 (- (:height selrect))))} true) (apply-modifiers selected)))))) - - -;; -- Transform to path --------------------------------------------- -