0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-06 14:50:20 -05:00

Merge remote-tracking branch 'origin/staging' into develop

This commit is contained in:
Andrey Antukh 2024-10-15 09:30:03 +02:00
commit c841ed6419
22 changed files with 173 additions and 160 deletions

View file

@ -42,6 +42,7 @@
### :bug: Bugs fixed
- Fix problem with constraints buttons [Taiga #8465](https://tree.taiga.io/project/penpot/issue/8465)
- Fix problem with go back button on error page [Taiga #8887](https://tree.taiga.io/project/penpot/issue/8887)
- Fix problem with shadows in text for Safari [Taiga #8770](https://tree.taiga.io/project/penpot/issue/8770)
- Fix a regression with feedback form subject and content limits [Taiga #8908](https://tree.taiga.io/project/penpot/issue/8908)
@ -50,6 +51,15 @@
- Fix problem with precision on boolean calculation [Taiga #8482](https://tree.taiga.io/project/penpot/issue/8482)
- Fix problem when translating multiple path points [Github #4459](https://github.com/penpot/penpot/issues/4459)
- Fix problem on importing (and exporting) files with flows [Taiga #8914](https://tree.taiga.io/project/penpot/issue/8914)
- Fix Internal Error page: "go to your penpot" wrong design [Taiga #8922](https://tree.taiga.io/project/penpot/issue/8922)
- Fix problem updating layout when toggle visibility in component copy [Github #5143](https://github.com/penpot/penpot/issues/5143)
- Fix "Done" button on toolbar on inspect mode should go to design mode [Taiga #8933](https://tree.taiga.io/project/penpot/issue/8933)
- Fix problem with shortcuts in text editor [Github #5078](https://github.com/penpot/penpot/issues/5078)
- Fix problems with show in viewer and interactions [Github #4868](https://github.com/penpot/penpot/issues/4868)
- Add visual feedback when moving an element into a board [Github #3210](https://github.com/penpot/penpot/issues/3210)
- Fix percent calculation on grid layout tracks [Github #4688](https://github.com/penpot/penpot/issues/4688)
- Fix problem with caps and inner shadows [Github #4517](https://github.com/penpot/penpot/issues/4517)
- Fix problem with horizontal/vertical lines and shadows [Github #4516](https://github.com/penpot/penpot/issues/4516)
## 2.2.1

View file

@ -135,7 +135,7 @@
(l/dbg :hint "run webhook"
:event-name (:name event)
:webhook-id (:id whook)
:webhook-id (str (:id whook))
:webhook-uri (:uri whook)
:webhook-mtype (:mtype whook))

View file

@ -328,8 +328,10 @@
:page-name page-name
:position position
:content content
:frame-id frame-id}]
(db/tx-run! cfg create-comment-thread params))))
:frame-id frame-id}
thread (db/tx-run! cfg create-comment-thread params)]
(vary-meta thread assoc ::audit/props thread))))
(defn- create-comment-thread
[{:keys [::db/conn] :as cfg}

View file

@ -60,6 +60,7 @@
filter-y (mth/min y (+ y offset-y (- spread) (- blur) -5))
filter-w (+ w (mth/abs offset-x) (* spread 2) (* blur 2) 10)
filter-h (+ h (mth/abs offset-y) (* spread 2) (* blur 2) 10)]
(grc/make-rect filter-x filter-y filter-w filter-h)))
(defn get-rect-filter-bounds
@ -101,7 +102,7 @@
(map #(case (get % :stroke-alignment :center)
:center (/ (:stroke-width % 0) 2)
:outer (:stroke-width % 0)
0))
(:stroke-width % 0)))
(reduce d/max 0))
stroke-margin

View file

@ -124,7 +124,7 @@
;; All parents of any deleted shape must be resized.
(into res (cfh/get-parent-ids objects id)))
(d/ordered-set)
ids-to-delete)
(concat ids-to-delete ids-to-hide))
all-children
(->> ids-to-delete ;; Children of deleted shapes must be also deleted.
@ -408,17 +408,12 @@
;; Resize parent containers that need to
(pcb/resize-parents parents))))
(defn change-show-in-viewer [shape hide?]
(cond-> (assoc shape :hide-in-viewer hide?)
;; When a frame is no longer shown in view mode, it cannot have interactions
hide?
(dissoc :interactions)))
(assoc shape :hide-in-viewer hide?))
(defn add-new-interaction [shape interaction]
(-> shape
(update :interactions ctsi/add-interaction interaction)
;; When a interaction is created, the frame must be shown in view mode
(dissoc :hide-in-viewer)))
(update :interactions ctsi/add-interaction interaction)))
(defn show-in-viewer [shape]
(dissoc shape :hide-in-viewer))

View file

@ -1,75 +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) KALEIDOS INC
(ns common-tests.logic.hide-in-viewer-test
(:require
[app.common.files.changes-builder :as pcb]
[app.common.logic.shapes :as cls]
[app.common.test-helpers.compositions :as tho]
[app.common.test-helpers.files :as thf]
[app.common.test-helpers.ids-map :as thi]
[app.common.test-helpers.shapes :as ths]
[app.common.types.shape.interactions :as ctsi]
[clojure.test :as t]))
(t/use-fixtures :each thi/test-fixture)
(t/deftest test-remove-show-in-view-mode-delete-interactions
(let [;; ==== Setup
file (-> (thf/sample-file :file1)
(tho/add-frame :frame-dest)
(tho/add-frame :frame-origin)
(ths/add-interaction :frame-origin :frame-dest))
frame-origin (ths/get-shape file :frame-origin)
page (thf/current-page file)
;; ==== Action
changes (-> (pcb/empty-changes nil (:id page))
(pcb/with-objects (:objects page))
(pcb/update-shapes [(:id frame-origin)] #(cls/change-show-in-viewer % true)))
file' (thf/apply-changes file changes)
;; ==== Get
frame-origin' (ths/get-shape file' :frame-origin)]
;; ==== Check
(t/is (some? (:interactions frame-origin)))
(t/is (nil? (:interactions frame-origin')))))
(t/deftest test-add-new-interaction-updates-show-in-view-mode
(let [;; ==== Setup
file (-> (thf/sample-file :file1)
(tho/add-frame :frame-dest :hide-in-viewer true)
(tho/add-frame :frame-origin :hide-in-viewer true))
frame-dest (ths/get-shape file :frame-dest)
frame-origin (ths/get-shape file :frame-origin)
page (thf/current-page file)
;; ==== Action
new-interaction (-> ctsi/default-interaction
(ctsi/set-destination (:id frame-dest))
(assoc :position-relative-to (:id frame-dest)))
changes (-> (pcb/empty-changes nil (:id page))
(pcb/with-objects (:objects page))
(pcb/update-shapes [(:id frame-origin)] #(cls/add-new-interaction % new-interaction)))
file' (thf/apply-changes file changes)
;; ==== Get
frame-origin' (ths/get-shape file' :frame-origin)]
;; ==== Check
(t/is (true? (:hide-in-viewer frame-origin)))
(t/is (nil? (:hide-in-viewer frame-origin')))))

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
export PATH=/usr/lib/jvm/openjdk/bin:/usr/local/nodejs/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin
export JAVA_OPTS="-Xmx1000m -Xms50m"
export JAVA_OPTS=${JAVA_OPTS:-"-Xmx1000m -Xms200m"};
alias l='ls --color -GFlh'
alias rm='rm -r'

View file

@ -10,7 +10,7 @@ rm -rf target
export NODE_ENV=production;
# Build the application
clojure -J-Xms100M -J-Xmx1000M -J-XX:+UseSerialGC -M:dev:shadow-cljs release main;
clojure -M:dev:shadow-cljs release main;
# Remove source
rm -rf target/app;

View file

@ -111,6 +111,7 @@
(def flex-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/"))
(def grid-help-uri (obj/get global "penpotGridHelpURI" "https://help.penpot.app/user-guide/flexible-layouts/"))
(def plugins-list-uri (obj/get global "penpotPluginsListUri" "https://penpot-docs-plugins.pages.dev/plugins/getting-started/#examples"))
(def plugins-whitelist (into #{} (obj/get global "penpotPluginsWhitelist" [])))
(defn- normalize-uri
[uri-str]

View file

@ -24,6 +24,10 @@ target.stopCallback = function (e, element, combo) {
return false
}
if ((' ' + element.className + ' ').indexOf(' mousetrap ') > -1) {
return false;
}
if ('composedPath' in e && typeof e.composedPath === 'function') {
// For open shadow trees, update `element` so that the following check works.
const initialEventTarget = e.composedPath()[0];

View file

@ -147,11 +147,15 @@
ptk/WatchEvent
(watch [_ state _]
(let [page-id (or page-id (:current-page-id state))]
(rx/of (dwsh/update-shapes
[shape-id]
(fn [shape]
(cls/add-new-interaction shape interaction))
{:page-id page-id}))))))
(rx/of (dwsh/update-shapes [shape-id]
(fn [shape]
(cls/add-new-interaction shape interaction))
{:page-id page-id})
(when (:destination interaction)
(dwsh/update-shapes [(:destination interaction)]
cls/show-in-viewer
{:page-id page-id})))))))
(defn add-new-interaction
([shape] (add-new-interaction shape nil))
@ -167,15 +171,20 @@
flows (get page :objects)
flow (ctp/get-frame-flow flows (:id frame))]
(rx/concat
(rx/of (dwsh/update-shapes [(:id shape)]
(fn [shape]
(let [new-interaction (-> ctsi/default-interaction
(ctsi/set-destination destination)
(assoc :position-relative-to (:id shape)))]
(cls/add-new-interaction shape new-interaction)))))
(when (and (not (connected-frame? objects (:id frame)))
(nil? flow))
(rx/of (add-flow (:id frame))))))))))
(rx/of (dwsh/update-shapes
[(:id shape)]
(fn [shape]
(let [new-interaction (-> ctsi/default-interaction
(ctsi/set-destination destination)
(assoc :position-relative-to (:id shape)))]
(cls/add-new-interaction shape new-interaction))))
(when destination
(dwsh/update-shapes [destination] cls/show-in-viewer))
(when (and (not (connected-frame? objects (:id frame)))
(nil? flow))
(add-flow (:id frame))))))))))
(defn remove-interaction
([shape index]
@ -186,8 +195,7 @@
(watch [_ _ _]
(rx/of (dwsh/update-shapes [(:id shape)]
(fn [shape]
(update shape :interactions
ctsi/remove-interaction index))
(update shape :interactions ctsi/remove-interaction index))
{:page-id page-id}))))))
(defn update-interaction
([shape index update-fn]
@ -196,11 +204,16 @@
(ptk/reify ::update-interaction
ptk/WatchEvent
(watch [_ _ _]
(rx/of (dwsh/update-shapes [(:id shape)]
(fn [shape]
(update shape :interactions
ctsi/update-interaction index update-fn))
options))))))
(let [interactions (ctsi/update-interaction (:interactions shape) index update-fn)
interaction (nth interactions index)]
(rx/of (dwsh/update-shapes
[(:id shape)]
(fn [shape]
(assoc shape :interactions interactions))
options)
(when (some? (:destination interaction))
(dwsh/update-shapes [(:destination interaction)] cls/show-in-viewer options))))))))
(defn remove-all-interactions-nav-to
"Remove all interactions that navigate to the given frame."

View file

@ -10,6 +10,7 @@
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.shapes.bounds :as gsb]
[app.common.math :as mth]
[app.common.uuid :as uuid]
[cuerdas.core :as str]
[rumext.v2 :as mf]))
@ -129,6 +130,34 @@
[filters]
(map #(assoc %1 :filter-in %2) filters (cons nil (map :id filters))))
(defn filter-coords
[bounds selrect padding]
(if (or (mth/close? 0.01 (:width selrect))
(mth/close? 0.01 (:height selrect)))
;; We cannot use "objectBoundingbox" if the shape doesn't have width/heigth
;; From the SVG spec (https://www.w3.org/TR/SVG11/coords.html#ObjectBoundingBox
;; Keyword objectBoundingBox should not be used when the geometry of the applicable element
;; has no width or no height, such as the case of a horizontal or vertical line, even when
;; the line has actual thickness when viewed due to having a non-zero stroke width since
;; stroke width is ignored for bounding box calculations. When the geometry of the
;; applicable element has no width or height and objectBoundingBox is specified, then
;; the given effect (e.g., a gradient or a filter) will be ignored.
(let [filter-width (+ (:width bounds) (* 2 (:horizontal padding)))
filter-height (+ (:height bounds) (* 2 (:vertical padding)))
filter-x (- (:x bounds) #_(:x selrect) (:horizontal padding))
filter-y (- (:y bounds) #_(:y selrect) (:vertical padding))
filter-units "userSpaceOnUse"]
[filter-x filter-y filter-width filter-height filter-units])
;; If the width/height is not zero we use objectBoundingBox as it's more stable
(let [filter-width (/ (+ (:width bounds) (* 2 (:horizontal padding))) (:width selrect))
filter-height (/ (+ (:height bounds) (* 2 (:vertical padding))) (:height selrect))
filter-x (/ (- (:x bounds) (:x selrect) (:horizontal padding)) (:width selrect))
filter-y (/ (- (:y bounds) (:y selrect) (:vertical padding)) (:height selrect))
filter-units "objectBoundingBox"]
[filter-x filter-y filter-width filter-height filter-units])))
(mf/defc filters
[{:keys [filter-id shape]}]
@ -136,17 +165,17 @@
bounds (gsb/get-rect-filter-bounds (:selrect shape) filters (or (-> shape :blur :value) 0))
padding (gsb/calculate-padding shape)
selrect (:selrect shape)
filter-x (/ (- (:x bounds) (:x selrect) (:horizontal padding)) (:width selrect))
filter-y (/ (- (:y bounds) (:y selrect) (:vertical padding)) (:height selrect))
filter-width (/ (+ (:width bounds) (* 2 (:horizontal padding))) (:width selrect))
filter-height (/ (+ (:height bounds) (* 2 (:vertical padding))) (:height selrect))]
[filter-x filter-y filter-width filter-height filter-units]
(filter-coords bounds selrect padding)]
(when (> (count filters) 2)
[:filter {:id filter-id
:x filter-x
:y filter-y
:width filter-width
:height filter-height
:filterUnits "objectBoundingBox"
:filterUnits filter-units
:color-interpolation-filters "sRGB"}
(for [[index entry] (d/enumerate filters)]
[:& filter-entry {:key (dm/str filter-id "-" index)

View file

@ -20,6 +20,8 @@
[app.main.ui.auth.recovery-request :refer [recovery-request-page recovery-sent-page]]
[app.main.ui.auth.register :as register]
[app.main.ui.dashboard.sidebar :refer [sidebar]]
[app.main.ui.ds.foundations.assets.icon :refer [icon*]]
[app.main.ui.ds.foundations.assets.raw-svg :refer [raw-svg*]]
[app.main.ui.icons :as i]
[app.main.ui.viewer.header :as viewer.header]
[app.util.dom :as dom]
@ -43,9 +45,9 @@
[:button
{:class (stl/css :exception-header)
:on-click on-nav-root}
i/logo-icon
[:> raw-svg* {:id "penpot-logo-icon" :class (stl/css :penpot-logo)}]
(when profile-id
(str "< " (tr "not-found.no-permission.go-dashboard")))]
[:div {:class (stl/css :go-back-wrapper)} [:> icon* {:id "arrow" :class (stl/css :back-arrow)}] [:span (tr "not-found.no-permission.go-dashboard")]])]
[:div {:class (stl/css :deco-before)} i/logo-error-screen]
(when-not profile-id
[:button {:class (stl/css :login-header)

View file

@ -66,6 +66,7 @@
justify-content: flex-end;
height: 100%;
width: 25%;
padding-bottom: $s-28;
&:first-child {
text-align: right;
@ -82,12 +83,25 @@
cursor: pointer;
display: flex;
align-items: center;
}
svg {
fill: var(--color-foreground-primary);
width: $s-48;
height: auto;
}
.penpot-logo {
fill: var(--color-foreground-primary);
width: $s-48;
height: $s-48;
}
.back-arrow {
transform: rotate(180deg);
}
.go-back-wrapper {
display: flex;
justify-content: center;
align-items: center;
gap: $s-8;
margin-left: $s-12;
font-size: $fs-14;
}
.login-header {

View file

@ -9,7 +9,7 @@
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.config :as cf]
[app.config :as cfg]
[app.main.data.events :as ev]
[app.main.data.modal :as modal]
[app.main.data.plugins :as dp]
@ -169,7 +169,7 @@
[:> i18n/tr-html*
{:class (stl/css :discover)
:on-click #(st/emit! (ptk/event ::ev/event {::ev/name "open-plugins-list"}))
:content (tr "workspace.plugins.discover" cf/plugins-list-uri)}])
:content (tr "workspace.plugins.discover" cfg/plugins-list-uri)}])
[:hr]
@ -178,7 +178,7 @@
[:div {:class (stl/css :plugins-empty-logo)} i/puzzle]
[:div {:class (stl/css :plugins-empty-text)} (tr "workspace.plugins.empty-plugins")]
[:a {:class (stl/css :plugins-link)
:href cf/plugins-list-uri
:href cfg/plugins-list-uri
:target "_blank"
:on-click #(st/emit! (ptk/event ::ev/event {::ev/name "open-plugins-list"}))}
(tr "workspace.plugins.plugin-list-link") i/external-link]]
@ -287,8 +287,9 @@
[:div {:class (stl/css :modal-content)}
[:& plugins-permission-list {:permissions permissions}]
[:div {:class (stl/css :permissions-disclaimer)}
(tr "workspace.plugins.permissions.disclaimer")]]
(when-not (contains? cfg/plugins-whitelist host)
[:div {:class (stl/css :permissions-disclaimer)}
(tr "workspace.plugins.permissions.disclaimer")])]
[:div {:class (stl/css :modal-footer)}
[:div {:class (stl/css :action-buttons)}

View file

@ -272,7 +272,7 @@ div.input-error {
@include bodySmallTypography;
padding: $s-16;
background: var(--color-background-quaternary);
color: var(--color-foreground-quaternary);
color: var(--color-foreground-primary);
border-radius: $br-4;
}

View file

@ -138,6 +138,8 @@
first-selected-shape (first selected-shapes)
shape-parent-frame (cfh/get-frame objects (:frame-id first-selected-shape))
options-mode (mf/deref refs/options-mode-global)
on-change-tab
(fn [options-mode]
(let [options-mode (keyword options-mode)]
@ -187,6 +189,7 @@
[:> tab-switcher* {:tabs tabs
:default-selected "info"
:on-change-tab on-change-tab
:selected (name options-mode)
:class (stl/css :options-tab-switcher)}]]))
;; TODO: this need optimizations, selected-objects and

View file

@ -36,32 +36,37 @@
.constraints-bottom {
@include flexCenter;
grid-area: top;
.constraint-btn,
.constraint-btn-special,
.constraint-btn-rotated {
@include buttonStyle;
@include flexCenter;
width: 100%;
height: 100%;
.resalted-area {
width: $s-32;
height: $s-3;
border-radius: $br-8;
background-color: var(--button-constraint-background-color-rest);
padding: 0;
margin: 0;
}
&.active .resalted-area {
outline: $s-4 solid var(--button-constraint-border-color-hover);
background-color: var(--button-constraint-background-color-hover);
}
&:hover .resalted-area,
&:focus .resalted-area {
outline: $s-4 solid var(--button-constraint-border-color-hover);
background-color: var(--button-constraint-background-color-hover);
}
}
.constraint-btn,
.constraint-btn-special,
.constraint-btn-rotated {
@include buttonStyle;
@include flexCenter;
width: 100%;
height: 100%;
--resalted-area-background-color: var(--button-constraint-background-color-rest);
--resalted-area-border-color: none;
&.active {
--resalted-area-border-color: var(--button-constraint-border-color-hover);
--resalted-area-background-color: var(--button-constraint-background-color-hover);
}
&:hover,
&:focus-visible {
--resalted-area-border-color: var(--button-constraint-border-color-hover);
--resalted-area-background-color: var(--button-constraint-background-color-hover);
}
}
.resalted-area {
width: $s-32;
height: $s-3;
border-radius: $br-8;
background-color: var(--resalted-area-background-color);
outline: $s-4 solid var(--resalted-area-border-color);
padding: 0;
margin: 0;
}
.constraints-left {
grid-area: left;
.constraint-btn-rotated {
@ -73,6 +78,7 @@
}
}
}
.constraints-center {
grid-area: center;
position: relative;
@ -113,7 +119,7 @@
grid-area: bottom;
}
.contraints-selects {
.constraints-selects {
@include flexColumn;
}

View file

@ -677,7 +677,7 @@
[{:keys [type value]}]
(case type
:auto "auto"
:percent (fmt/format-percent value)
:percent (fmt/format-percent (/ value 100))
:flex (fmt/format-frs value)
:fixed (fmt/format-pixels value)
value))

View file

@ -150,6 +150,7 @@
.grid-layout-menu {
@include flexColumn;
gap: $s-8;
overflow: hidden;
.row {
@include flexRow;

View file

@ -397,7 +397,7 @@
(->> @hover-ids
(filter #(cfh/frame-shape? (get base-objects %)))
(remove selected)
(first))
(last))
outlined-frame (get objects outlined-frame-id)]
[:*
[:& outline/shape-outlines

View file

@ -7,6 +7,9 @@ export DEVENV_PNAME="penpotdev";
export CURRENT_USER_ID=$(id -u);
export CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD);
# Set default java options
export JAVA_OPTS=${JAVA_OPTS:-"-Xmx1000m -Xms50m"};
set -e
function print-current-version {
@ -95,10 +98,12 @@ function run-devenv-shell {
if [[ ! $(docker ps -f "name=penpot-devenv-main" -q) ]]; then
start-devenv
fi
docker exec -ti penpot-devenv-main sudo -EH -u penpot bash
docker exec -ti \
-e JAVA_OPTS="$JAVA_OPTS" \
-e EXTERNAL_UID=$CURRENT_USER_ID \
penpot-devenv-main sudo -EH -u penpot bash;
}
function build {
echo ">> build start: $1"
local version=$(print-current-version);
@ -111,6 +116,7 @@ function build {
-e EXTERNAL_UID=$CURRENT_USER_ID \
-e BUILD_STORYBOOK=$BUILD_STORYBOOK \
-e SHADOWCLJS_EXTRA_PARAMS=$SHADOWCLJS_EXTRA_PARAMS \
-e JAVA_OPTS="$JAVA_OPTS" \
-w /home/penpot/penpot/$1 \
$DEVENV_IMGNAME:latest sudo -EH -u penpot ./scripts/build $version