mirror of
https://github.com/penpot/penpot.git
synced 2026-01-09 14:58:59 -05:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
04b7d8e1e2 | ||
|
|
745cf1c79d | ||
|
|
9e35229ebd | ||
|
|
e8027d3316 | ||
|
|
ad34ebff89 | ||
|
|
f733497f0f | ||
|
|
ed917fa194 | ||
|
|
313df74202 | ||
|
|
91c12ca34f | ||
|
|
9f66e8e5d1 | ||
|
|
82e402c271 | ||
|
|
827ce6c42a | ||
|
|
dec854a012 | ||
|
|
03d4e97ad7 | ||
|
|
e061ba8123 | ||
|
|
9a272f69c7 | ||
|
|
fc1f2b2a9f | ||
|
|
89fbe28ed1 | ||
|
|
216d101e56 | ||
|
|
ccf91a129c | ||
|
|
1f3f6ce1e9 | ||
|
|
8f2e3d5fe4 | ||
|
|
47481986a1 | ||
|
|
9af0e6ca44 |
21
CHANGES.md
21
CHANGES.md
@@ -1,4 +1,21 @@
|
||||
# CHANGELOG
|
||||
|
||||
## 1.17.3
|
||||
|
||||
### :bug: Bugs fixed
|
||||
- Fix copy and paste very nested inside itself [Taiga #4848](https://tree.taiga.io/project/penpot/issue/4848)
|
||||
- Fix custom fonts not rendered correctly [Taiga #4874](https://tree.taiga.io/project/penpot/issue/4874)
|
||||
- Fix problem with shadows and blur on multiple selection
|
||||
- Fix problem with redo shortcut
|
||||
- Fix Component texts not displayed in assets panel [Taiga #4907](https://tree.taiga.io/project/penpot/issue/4907)
|
||||
- Fix search field has implemented shared styles for "close icon" and "search icon" [Taiga #4927](https://tree.taiga.io/project/penpot/issue/4927)
|
||||
- Fix Handling correctly slashes "/" in emails [Taiga #4906](https://tree.taiga.io/project/penpot/issue/4906)
|
||||
- Fix Change text color from selected colors [Taiga #4933](https://tree.taiga.io/project/penpot/issue/4933)
|
||||
|
||||
### :sparkles: Enhancements
|
||||
|
||||
- Adds environment variables for specifying the export and backend URI for the frontend docker image, thanks to @Supernova3339 for the initial PR and suggestion [Github #2984](https://github.com/penpot/penpot/issues/2984)
|
||||
|
||||
## 1.17.2
|
||||
|
||||
### :bug: Bugs fixed
|
||||
@@ -8,10 +25,6 @@
|
||||
- Fix correct behaviour for space-around and added space-evenly option
|
||||
- Fix duplicate with alt and undo only undo one step [Taiga #4746](https://tree.taiga.io/project/penpot/issue/4746)
|
||||
- Fix problem creating frames inside layout [Taiga #4844](https://tree.taiga.io/project/penpot/issue/4844)
|
||||
|
||||
## 1.17.2
|
||||
|
||||
### :bug: Bugs fixed
|
||||
- Fix paste board inside itself [Taiga #4775](https://tree.taiga.io/project/penpot/issue/4775)
|
||||
- Fix middle button panning can drag guides [Taiga #4266](https://tree.taiga.io/project/penpot/issue/4266)
|
||||
|
||||
|
||||
@@ -318,8 +318,10 @@
|
||||
(defn unit
|
||||
[p1]
|
||||
(let [p-length (length p1)]
|
||||
(Point. (/ (dm/get-prop p1 :x) p-length)
|
||||
(/ (dm/get-prop p1 :y) p-length))))
|
||||
(if (mth/almost-zero? p-length)
|
||||
(Point. 0 0)
|
||||
(Point. (/ (dm/get-prop p1 :x) p-length)
|
||||
(/ (dm/get-prop p1 :y) p-length)))))
|
||||
|
||||
(defn perpendicular
|
||||
[pt]
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.matrix :as gmt]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.rect :as gpr]))
|
||||
[app.common.geom.shapes.rect :as gpr]
|
||||
[app.common.math :as mth]))
|
||||
|
||||
(defn center-rect
|
||||
[{:keys [x y width height]}]
|
||||
@@ -71,3 +72,15 @@
|
||||
[{:keys [x1 y1 x2 y2] :as sr} matrix]
|
||||
(let [[c1 c2] (transform-points [(gpt/point x1 y1) (gpt/point x2 y2)] matrix)]
|
||||
(gpr/corners->selrect c1 c2)))
|
||||
|
||||
(defn invalid-geometry?
|
||||
[{:keys [points selrect]}]
|
||||
|
||||
(or (mth/nan? (:x selrect))
|
||||
(mth/nan? (:y selrect))
|
||||
(mth/nan? (:width selrect))
|
||||
(mth/nan? (:height selrect))
|
||||
(some (fn [p]
|
||||
(or (mth/nan? (:x p))
|
||||
(mth/nan? (:y p))))
|
||||
points)))
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.geom.shapes.flex-layout.positions :as fpo]
|
||||
[app.common.geom.shapes.points :as gpo]
|
||||
[app.common.geom.shapes.transforms :as gtr]
|
||||
[app.common.math :as mth]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]))
|
||||
|
||||
@@ -33,7 +34,7 @@
|
||||
(let [line-width (min line-width (or to-bound-width line-width))
|
||||
target-width (max (- line-width (ctl/child-width-margin child)) 0.01)
|
||||
max-width (max (ctl/child-max-width child) 0.01)
|
||||
target-width (min max-width target-width)
|
||||
target-width (mth/clamp target-width (ctl/child-min-width child) max-width)
|
||||
fill-scale (/ target-width child-width)]
|
||||
{:width target-width
|
||||
:modifiers (ctm/resize-modifiers (gpt/point fill-scale 1) child-origin transform transform-inverse)})))
|
||||
@@ -57,7 +58,7 @@
|
||||
(let [line-height (min line-height (or to-bound-height line-height))
|
||||
target-height (max (- line-height (ctl/child-height-margin child)) 0.01)
|
||||
max-height (max (ctl/child-max-height child) 0.01)
|
||||
target-height (min max-height target-height)
|
||||
target-height (mth/clamp target-height (ctl/child-min-height child) max-height)
|
||||
fill-scale (/ target-height child-height)]
|
||||
{:height target-height
|
||||
:modifiers (ctm/resize-modifiers (gpt/point 1 fill-scale) child-origin transform transform-inverse)})))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes.common :as gco]
|
||||
[app.common.geom.shapes.constraints :as gct]
|
||||
[app.common.geom.shapes.flex-layout :as gcl]
|
||||
[app.common.geom.shapes.pixel-precision :as gpp]
|
||||
@@ -175,6 +176,7 @@
|
||||
|
||||
(let [children (->> (cph/get-immediate-children objects (:id parent))
|
||||
(remove :hidden)
|
||||
(remove gco/invalid-geometry?)
|
||||
(map apply-modifiers))
|
||||
layout-data (gcl/calc-layout-data parent children @transformed-parent-bounds)
|
||||
children (into [] (cond-> children (not (:reverse? layout-data)) reverse))
|
||||
@@ -215,7 +217,8 @@
|
||||
(ctm/resize-parent (gpt/point 1 scale-height) origin (:transform parent) (:transform-inverse parent)))))
|
||||
|
||||
children (->> (cph/get-immediate-children objects parent-id)
|
||||
(remove :hidden))
|
||||
(remove :hidden)
|
||||
(remove gco/invalid-geometry?))
|
||||
|
||||
content-bounds
|
||||
(when (and (d/not-empty? children) (or (ctl/auto-height? parent) (ctl/auto-width? parent)))
|
||||
|
||||
@@ -123,6 +123,10 @@
|
||||
:blocked
|
||||
:hidden
|
||||
|
||||
:shadow
|
||||
|
||||
:blur
|
||||
|
||||
:fills
|
||||
:fill-color
|
||||
:fill-opacity
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
|
||||
;; --- SPEC: email
|
||||
|
||||
(def email-re #"[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+")
|
||||
(def email-re #"[a-zA-Z0-9_.+-\\\\]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+")
|
||||
|
||||
(defn parse-email
|
||||
[s]
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN set -ex; \
|
||||
|
||||
ADD ./bundle-frontend/ /var/www/app/
|
||||
ADD ./files/config.js /var/www/app/js/config.js
|
||||
ADD ./files/nginx.conf /etc/nginx/nginx.conf
|
||||
ADD ./files/nginx.conf /etc/nginx/nginx.conf.template
|
||||
ADD ./files/nginx-entrypoint.sh /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
log() {
|
||||
echo "[$(date +%Y-%m-%dT%H:%M:%S%:z)] $*"
|
||||
}
|
||||
|
||||
#########################################
|
||||
## App Frontend config
|
||||
#########################################
|
||||
@@ -17,4 +13,15 @@ update_flags() {
|
||||
}
|
||||
|
||||
update_flags /var/www/app/js/config.js
|
||||
|
||||
|
||||
#########################################
|
||||
## Nginx Config
|
||||
#########################################
|
||||
|
||||
export PENPOT_BACKEND_URI=${PENPOT_BACKEND_URI:-http://penpot-backend:6060};
|
||||
export PENPOT_EXPORTER_URI=${PENPOT_EXPORTER_URI:-http://penpot-exporter};
|
||||
|
||||
envsubst "\$PENPOT_BACKEND_URI,\$PENPOT_EXPORTER_URI" < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
|
||||
|
||||
exec "$@";
|
||||
|
||||
@@ -82,7 +82,7 @@ http {
|
||||
}
|
||||
|
||||
location /assets {
|
||||
proxy_pass http://penpot-backend:6060/assets;
|
||||
proxy_pass $PENPOT_BACKEND_URI/assets;
|
||||
recursive_error_pages on;
|
||||
proxy_intercept_errors on;
|
||||
error_page 301 302 307 = @handle_redirect;
|
||||
@@ -95,21 +95,17 @@ http {
|
||||
}
|
||||
|
||||
location /api/export {
|
||||
proxy_pass http://penpot-exporter:6061;
|
||||
proxy_pass $PENPOT_EXPORTER_URI;
|
||||
}
|
||||
|
||||
location /api {
|
||||
proxy_pass http://penpot-backend:6060/api;
|
||||
proxy_pass $PENPOT_BACKEND_URI/api;
|
||||
}
|
||||
|
||||
# location /admin {
|
||||
# proxy_pass http://penpot-admin:6065/admin;
|
||||
# }
|
||||
|
||||
location /ws/notifications {
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_pass http://penpot-backend:6060/ws/notifications;
|
||||
proxy_pass $PENPOT_BACKEND_URI/ws/notifications;
|
||||
}
|
||||
|
||||
location / {
|
||||
|
||||
@@ -28,7 +28,7 @@ $width-settings-bar: 256px;
|
||||
top: 0;
|
||||
transition: top 400ms ease 300ms;
|
||||
margin-bottom: 0;
|
||||
z-index: 2;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
& .viewer-bottom {
|
||||
@@ -46,7 +46,7 @@ $width-settings-bar: 256px;
|
||||
top: -48px;
|
||||
left: 0;
|
||||
transition: top 400ms ease 300ms;
|
||||
z-index: 2;
|
||||
z-index: 10;
|
||||
margin-bottom: 48px;
|
||||
|
||||
&::after {
|
||||
|
||||
@@ -337,15 +337,15 @@
|
||||
fill: $color-gray-30;
|
||||
height: 15px;
|
||||
width: 15px;
|
||||
|
||||
&:hover {
|
||||
fill: $color-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.clear-search svg {
|
||||
transform: rotate(45deg);
|
||||
|
||||
&:hover {
|
||||
fill: $color-danger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
|
||||
> * {
|
||||
margin-left: $size-5;
|
||||
|
||||
@@ -177,56 +177,64 @@
|
||||
(watch [_ _ stream]
|
||||
(let [team-id (:team-id project)
|
||||
stoper (rx/filter (ptk/type? ::bundle-fetched) stream)]
|
||||
(->> (rx/merge
|
||||
;; Initialize notifications & load team fonts
|
||||
(->> (rx/concat
|
||||
;; Initialize notifications
|
||||
(rx/of (dwn/initialize team-id id)
|
||||
(dwsl/initialize)
|
||||
(df/load-team-fonts team-id))
|
||||
(dwsl/initialize))
|
||||
|
||||
;; Load all pages, independently if they are pointers or already
|
||||
;; resolved values.
|
||||
(->> (rx/from (seq (:pages-index data)))
|
||||
(rx/merge-map
|
||||
(fn [[_ page :as kp]]
|
||||
(if (t/pointer? page)
|
||||
(resolve-pointer id kp)
|
||||
(rx/of kp))))
|
||||
(rx/merge-map
|
||||
(fn [[id page]]
|
||||
(let [page (update page :objects ctst/start-page-index)]
|
||||
(->> (uw/ask! {:cmd :initialize-page-index :page page})
|
||||
(rx/map (constantly [id page]))))))
|
||||
(rx/reduce conj {})
|
||||
(rx/map (fn [pages-index]
|
||||
(-> data
|
||||
(assoc :pages-index pages-index)
|
||||
(workspace-data-loaded)))))
|
||||
;; Load team fonts. We must ensure custom fonts are fully loadad before starting the workspace load
|
||||
(rx/merge
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? :app.main.data.fonts/team-fonts-loaded))
|
||||
(rx/take 1)
|
||||
(rx/ignore))
|
||||
(rx/of (df/load-team-fonts team-id)))
|
||||
|
||||
;; Once workspace data is loaded, proceed asynchronously load
|
||||
;; the local library and all referenced libraries, without
|
||||
;; blocking the main workspace load process.
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::workspace-data-loaded))
|
||||
(rx/take 1)
|
||||
(rx/merge-map
|
||||
(fn [_]
|
||||
(rx/merge
|
||||
(rx/of (workspace-initialized))
|
||||
(rx/merge
|
||||
;; Load all pages, independently if they are pointers or already
|
||||
;; resolved values.
|
||||
(->> (rx/from (seq (:pages-index data)))
|
||||
(rx/merge-map
|
||||
(fn [[_ page :as kp]]
|
||||
(if (t/pointer? page)
|
||||
(resolve-pointer id kp)
|
||||
(rx/of kp))))
|
||||
(rx/merge-map
|
||||
(fn [[id page]]
|
||||
(let [page (update page :objects ctst/start-page-index)]
|
||||
(->> (uw/ask! {:cmd :initialize-page-index :page page})
|
||||
(rx/map (constantly [id page]))))))
|
||||
(rx/reduce conj {})
|
||||
(rx/map (fn [pages-index]
|
||||
(-> data
|
||||
(assoc :pages-index pages-index)
|
||||
(workspace-data-loaded)))))
|
||||
|
||||
(->> data
|
||||
(filter (comp t/pointer? val))
|
||||
(resolve-pointers id)
|
||||
(rx/map workspace-data-pointers-loaded))
|
||||
;; Once workspace data is loaded, proceed asynchronously load
|
||||
;; the local library and all referenced libraries, without
|
||||
;; blocking the main workspace load process.
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::workspace-data-loaded))
|
||||
(rx/take 1)
|
||||
(rx/merge-map
|
||||
(fn [_]
|
||||
(rx/merge
|
||||
(rx/of (workspace-initialized))
|
||||
|
||||
(->> (rp/cmd! :get-file-libraries {:file-id id :features features})
|
||||
(rx/mapcat identity)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [id data] :as file}]
|
||||
(->> (filter (comp t/pointer? val) data)
|
||||
(resolve-pointers id)
|
||||
(rx/map #(update file :data merge %)))))
|
||||
(rx/reduce conj [])
|
||||
(rx/map libraries-fetched)))))))
|
||||
(->> data
|
||||
(filter (comp t/pointer? val))
|
||||
(resolve-pointers id)
|
||||
(rx/map workspace-data-pointers-loaded))
|
||||
|
||||
(->> (rp/cmd! :get-file-libraries {:file-id id :features features})
|
||||
(rx/mapcat identity)
|
||||
(rx/mapcat
|
||||
(fn [{:keys [id data] :as file}]
|
||||
(->> (filter (comp t/pointer? val) data)
|
||||
(resolve-pointers id)
|
||||
(rx/map #(update file :data merge %)))))
|
||||
(rx/reduce conj [])
|
||||
(rx/map libraries-fetched))))))))
|
||||
|
||||
(rx/take-until stoper)))))))
|
||||
|
||||
@@ -429,7 +437,7 @@
|
||||
name (cp/generate-unique-name unames (:name page))
|
||||
|
||||
no_thumbnails_objects (->> (:objects page)
|
||||
(d/mapm (fn [_ val] (dissoc val :use-for-thumbnail?))))
|
||||
(d/mapm (fn [_ val] (dissoc val :use-for-thumbnail?))))
|
||||
|
||||
page (-> page (assoc :name name :id id :objects no_thumbnails_objects))
|
||||
|
||||
@@ -1099,13 +1107,13 @@
|
||||
qparams {:page-id page-id}]
|
||||
;; qparams {:page-id page-id :layout :assets}]
|
||||
(rx/merge
|
||||
(rx/of (rt/nav :workspace pparams qparams))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dwv/initialize-viewport))
|
||||
(rx/take 1)
|
||||
(rx/mapcat #(do
|
||||
(on-page-selected)
|
||||
(rx/of (dws/select-shapes (lks/set shape-id)))))))))))))
|
||||
(rx/of (rt/nav :workspace pparams qparams))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::dwv/initialize-viewport))
|
||||
(rx/take 1)
|
||||
(rx/mapcat #(do
|
||||
(on-page-selected)
|
||||
(rx/of (dws/select-shapes (lks/set shape-id)))))))))))))
|
||||
|
||||
(defn go-to-component
|
||||
[component-id]
|
||||
@@ -1440,9 +1448,17 @@
|
||||
(and (= 1 (count selected))
|
||||
(= :frame (get-in objects [(first selected) :type])))))
|
||||
|
||||
(defn same-frame-from-selected? [state frame-id]
|
||||
(let [selected (wsh/lookup-selected state)]
|
||||
(contains? frame-id (first selected))))
|
||||
(defn get-tree-root-shapes [tree]
|
||||
;; This fn gets a map of shapes and finds what shapes are parent of the rest
|
||||
(let [shapes-in-tree (vals tree)
|
||||
shape-ids (keys tree)
|
||||
parent-ids (set (map #(:parent-id %) shapes-in-tree))]
|
||||
(->> shape-ids
|
||||
(filter #(contains? parent-ids %)))))
|
||||
|
||||
(defn any-same-frame-from-selected? [state frame-ids]
|
||||
(let [selected (first (wsh/lookup-selected state))]
|
||||
(< 0 (count (filter #(= % selected) frame-ids)))))
|
||||
|
||||
(defn frame-same-size?
|
||||
[paste-obj frame-obj]
|
||||
@@ -1491,22 +1507,27 @@
|
||||
item))
|
||||
|
||||
(calculate-paste-position [state mouse-pos in-viewport?]
|
||||
(let [page-objects (wsh/lookup-page-objects state)
|
||||
selected-objs (map #(get paste-objects %) selected)
|
||||
first-selected-obj (first selected-objs)
|
||||
page-selected (wsh/lookup-selected state)
|
||||
wrapper (gsh/selection-rect selected-objs)
|
||||
orig-pos (gpt/point (:x1 wrapper) (:y1 wrapper))
|
||||
frame-id (first page-selected)
|
||||
frame-object (get page-objects frame-id)
|
||||
base (cph/get-base-shape page-objects page-selected)
|
||||
index (cph/get-position-on-parent page-objects (:id base))]
|
||||
(let [page-objects (wsh/lookup-page-objects state)
|
||||
selected-objs (map #(get paste-objects %) selected)
|
||||
first-selected-obj (first selected-objs)
|
||||
page-selected (wsh/lookup-selected state)
|
||||
wrapper (gsh/selection-rect selected-objs)
|
||||
orig-pos (gpt/point (:x1 wrapper) (:y1 wrapper))
|
||||
frame-id (first page-selected)
|
||||
frame-object (get page-objects frame-id)
|
||||
base (cph/get-base-shape page-objects page-selected)
|
||||
index (cph/get-position-on-parent page-objects (:id base))
|
||||
tree-root (get-tree-root-shapes paste-objects)
|
||||
only-one-root-shape? (and
|
||||
(< 1 (count paste-objects))
|
||||
(= 1 (count tree-root)))]
|
||||
|
||||
(cond
|
||||
(selected-frame? state)
|
||||
|
||||
(if (or (same-frame-from-selected? state (first (vals paste-objects)))
|
||||
(frame-same-size? paste-objects frame-object))
|
||||
(if (or (any-same-frame-from-selected? state (keys paste-objects))
|
||||
(and only-one-root-shape?
|
||||
(frame-same-size? paste-objects (first tree-root))))
|
||||
;; Paste next to selected frame, if selected is itself or of the same size as the copied
|
||||
(let [selected-frame-obj (get page-objects (first page-selected))
|
||||
parent-id (:parent-id base)
|
||||
@@ -1544,7 +1565,7 @@
|
||||
;; - Respect the distance of the object to the right and bottom in the original frame
|
||||
(gpt/point paste-x paste-y))]
|
||||
[frame-id frame-id delta]))
|
||||
|
||||
|
||||
(empty? page-selected)
|
||||
(let [frame-id (ctst/top-nested-frame page-objects mouse-pos)
|
||||
delta (gpt/subtract mouse-pos orig-pos)]
|
||||
@@ -1837,8 +1858,8 @@
|
||||
(dwm/create-shapes-img pos media-obj))]
|
||||
|
||||
(->> (rx/concat
|
||||
(rx/of (update-remove-graphics index))
|
||||
(rx/map process-shapes shapes))
|
||||
(rx/of (update-remove-graphics index))
|
||||
(rx/map process-shapes shapes))
|
||||
(rx/catch #(do
|
||||
(log/error :msg (str "Error removing " (:name media-obj))
|
||||
:hint (ex-message %)
|
||||
@@ -1872,15 +1893,15 @@
|
||||
(ctst/generate-shape-grid media-points start-pos grid-gap)]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (modal/show {:type :remove-graphics-dialog :file-name file-name})
|
||||
(initialize-remove-graphics (count media)))
|
||||
(when new-page?
|
||||
(rx/of (dch/commit-changes (-> (pcb/empty-changes it)
|
||||
(pcb/set-save-undo? false)
|
||||
(pcb/add-page (:id page) page)))))
|
||||
(rx/mapcat (partial remove-graphic it file-data' page)
|
||||
(rx/from (d/enumerate (d/zip media shape-grid))))
|
||||
(rx/of (complete-remove-graphics)))))))
|
||||
(rx/of (modal/show {:type :remove-graphics-dialog :file-name file-name})
|
||||
(initialize-remove-graphics (count media)))
|
||||
(when new-page?
|
||||
(rx/of (dch/commit-changes (-> (pcb/empty-changes it)
|
||||
(pcb/set-save-undo? false)
|
||||
(pcb/add-page (:id page) page)))))
|
||||
(rx/mapcat (partial remove-graphic it file-data' page)
|
||||
(rx/from (d/enumerate (d/zip media shape-grid))))
|
||||
(rx/of (complete-remove-graphics)))))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Read only
|
||||
|
||||
@@ -337,7 +337,7 @@
|
||||
|
||||
(defn change-text-color
|
||||
[old-color new-color index node]
|
||||
(let [fills (:fills node)
|
||||
(let [fills (map #(dissoc % :fill-color-ref-id :fill-color-ref-file) (:fills node))
|
||||
parsed-color (d/without-nils (color-att->text old-color))
|
||||
parsed-new-color (d/without-nils (color-att->text new-color))
|
||||
has-color? (d/index-of fills parsed-color)]
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
(watch [it state _]
|
||||
(let [edition (get-in state [:workspace-local :edition])
|
||||
drawing (get state :workspace-drawing)]
|
||||
(when (and (nil? edition) (or (empty drawing) (= :curve (:tool drawing))))
|
||||
(when (and (nil? edition) (or (empty? drawing) (= :curve (:tool drawing))))
|
||||
(let [undo (:workspace-undo state)
|
||||
items (:items undo)
|
||||
index (or (:index undo) (dec (count items)))]
|
||||
|
||||
@@ -183,6 +183,13 @@
|
||||
(-> shape
|
||||
(assoc :layout-item-h-sizing :auto
|
||||
:layout-item-v-sizing :auto))))
|
||||
;; Set the children to fixed to remove strange interactions
|
||||
(dwc/update-shapes
|
||||
selected
|
||||
(fn [shape]
|
||||
(-> shape
|
||||
(assoc :layout-item-h-sizing :fix
|
||||
:layout-item-v-sizing :fix))))
|
||||
|
||||
(ptk/data-event :layout/update [new-shape-id])
|
||||
(dws/delete-shapes page-id selected)
|
||||
@@ -204,6 +211,13 @@
|
||||
(merge flex-params)
|
||||
(assoc :layout-item-h-sizing :auto
|
||||
:layout-item-v-sizing :auto))))
|
||||
;; Set the children to fixed to remove strange interactions
|
||||
(dwc/update-shapes
|
||||
selected
|
||||
(fn [shape]
|
||||
(-> shape
|
||||
(assoc :layout-item-h-sizing :fix
|
||||
:layout-item-v-sizing :fix))))
|
||||
|
||||
(ptk/data-event :layout/update [new-shape-id])
|
||||
(dwu/commit-undo-transaction undo-id))))))))
|
||||
|
||||
@@ -287,7 +287,6 @@
|
||||
:fill "none"}
|
||||
[:& shape-wrapper {:shape frame}]]]))
|
||||
|
||||
|
||||
;; Component for rendering a thumbnail of a single componenent. Mainly
|
||||
;; used to render thumbnails on assets panel.
|
||||
(mf/defc component-svg
|
||||
@@ -334,7 +333,8 @@
|
||||
:fill "none"}
|
||||
|
||||
[:> shape-container {:shape root-shape}
|
||||
[:& root-shape-wrapper {:shape root-shape :view-box vbox}]]]))
|
||||
[:& (mf/provider muc/is-component?) {:value true}
|
||||
[:& root-shape-wrapper {:shape root-shape :view-box vbox}]]]]))
|
||||
|
||||
(mf/defc object-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
@@ -468,7 +468,7 @@
|
||||
(let [texts (->> objects
|
||||
(vals)
|
||||
(filterv #(= (:type %) :text))
|
||||
(mapv :content)) ]
|
||||
(mapv :content))]
|
||||
|
||||
(->> (rx/from texts)
|
||||
(rx/map fonts/get-content-fonts)
|
||||
|
||||
@@ -27,3 +27,4 @@
|
||||
(def current-zoom (mf/create-context nil))
|
||||
|
||||
(def workspace-read-only? (mf/create-context nil))
|
||||
(def is-component? (mf/create-context false))
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
(:require
|
||||
[app.common.text :as txt]
|
||||
[app.main.fonts :as fonts]
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.shapes.text.fo-text :as fo]
|
||||
[app.main.ui.shapes.text.svg-text :as svg]
|
||||
[app.util.object :as obj]
|
||||
[rumext.v2 :as mf]))
|
||||
@@ -22,10 +24,13 @@
|
||||
(mf/defc text-shape
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [{:keys [position-data content] :as shape} (obj/get props "shape")]
|
||||
(let [{:keys [position-data content] :as shape} (obj/get props "shape")
|
||||
is-component? (mf/use-ctx ctx/is-component?)]
|
||||
|
||||
(mf/with-memo [content]
|
||||
(load-fonts! content))
|
||||
|
||||
(when (some? position-data)
|
||||
[:> svg/text-shape props])))
|
||||
;; Old components can have texts without position data that must be rendered via foreign key
|
||||
(cond
|
||||
(some? position-data) [:> svg/text-shape props]
|
||||
is-component? [:> fo/text-shape props])))
|
||||
|
||||
@@ -118,13 +118,13 @@
|
||||
[:*
|
||||
[:button.tooltip.tooltip-bottom
|
||||
{:class (dom/classnames :active (= wrap-type :nowrap))
|
||||
:alt "Nowrap"
|
||||
:alt "No wrap"
|
||||
:on-click #(set-wrap :nowrap)
|
||||
:style {:padding 0}}
|
||||
[:span.no-wrap i/minus]]
|
||||
[:button.wrap.tooltip.tooltip-bottom
|
||||
{:class (dom/classnames :active (= wrap-type :wrap))
|
||||
:alt "wrap"
|
||||
:alt "Wrap"
|
||||
:on-click #(set-wrap :wrap)}
|
||||
i/auto-wrap]])
|
||||
|
||||
@@ -159,8 +159,8 @@
|
||||
(for [align [:space-between :space-around :space-evenly]]
|
||||
[:button.align-content.tooltip
|
||||
{:class (dom/classnames :active (= align-content align)
|
||||
:tooltip-bottom-left (not= align :start)
|
||||
:tooltip-bottom (= align :start))
|
||||
:tooltip-bottom-left (not= align :space-between)
|
||||
:tooltip-bottom (= align :space-between))
|
||||
:alt (dm/str "Align content " (d/name align))
|
||||
:on-click #(set-align-content align)
|
||||
:key (dm/str "align-content" (d/name align))}
|
||||
@@ -183,8 +183,8 @@
|
||||
(for [justify [:space-between :space-around :space-evenly]]
|
||||
[:button.justify.tooltip
|
||||
{:class (dom/classnames :active (= justify-content justify)
|
||||
:tooltip-bottom-left (not= justify :space-around)
|
||||
:tooltip-bottom (= justify :space-around))
|
||||
:tooltip-bottom-left (not= justify :space-between)
|
||||
:tooltip-bottom (= justify :space-between))
|
||||
:alt (dm/str "Justify content " (d/name justify))
|
||||
:on-click #(set-justify justify)
|
||||
:key (dm/str "justify-content" (d/name justify))}
|
||||
|
||||
@@ -112,7 +112,7 @@
|
||||
{:alt "Width 100%"
|
||||
:class (dom/classnames :active (= layout-item-h-sizing :fill))
|
||||
:on-click #(on-change-behavior :h :fill)}
|
||||
i/auto-fill])
|
||||
i/auto-fill])
|
||||
(when auto?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
{:alt "Fit content"
|
||||
@@ -125,9 +125,9 @@
|
||||
{:alt "Fix height"
|
||||
:class (dom/classnames :active (= layout-item-v-sizing :fix))
|
||||
:on-click #(on-change-behavior :v :fix)}
|
||||
i/auto-fix-layout]
|
||||
i/auto-fix-layout]
|
||||
(when fill?
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom
|
||||
[:button.behavior-btn.tooltip.tooltip-bottom-left
|
||||
{:alt "Height 100%"
|
||||
:class (dom/classnames :active (= layout-item-v-sizing :fill))
|
||||
:on-click #(on-change-behavior :v :fill)}
|
||||
@@ -207,7 +207,7 @@
|
||||
:layout-item-v-sizing (or (:layout-item-v-sizing values) :fix)
|
||||
:layout-item-h-sizing (or (:layout-item-h-sizing values) :fix)
|
||||
:on-change-behavior on-change-behavior}]]
|
||||
|
||||
|
||||
(when is-layout-child?
|
||||
[:div.layout-row
|
||||
[:div.row-title "Align"]
|
||||
|
||||
@@ -40,8 +40,8 @@
|
||||
:layer :shape
|
||||
:constraint :shape
|
||||
:fill :shape
|
||||
:shadow :children
|
||||
:blur :children
|
||||
:shadow :shape
|
||||
:blur :shape
|
||||
:stroke :shape
|
||||
:text :children
|
||||
:exports :shape
|
||||
|
||||
@@ -400,6 +400,7 @@ msgstr[3] "عدد قليل من الخطوط المضافة"
|
||||
msgstr[4] "تمت إضافة العديد من الخطوط"
|
||||
msgstr[5] ""
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text1"
|
||||
msgstr ""
|
||||
"ستتم إضافة أي خط ويب تقوم بتحميله هنا إلى قائمة عائلة الخطوط المتوفرة في "
|
||||
@@ -407,6 +408,7 @@ msgstr ""
|
||||
"عائلة الخطوط على أنها ** عائلة خط واحدة **. يمكنك تحميل الخطوط بالتنسيقات "
|
||||
"التالية: ** TTF و OTF و WOFF ** (ستحتاج إلى تنسيق واحد فقط)."
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text2"
|
||||
msgstr ""
|
||||
"يجب عليك فقط تحميل الخطوط التي تمتلكها أو لديك ترخيص لاستخدامها في Penpot. "
|
||||
|
||||
@@ -409,6 +409,7 @@ msgid_plural "dashboard.fonts.fonts-added"
|
||||
msgstr[0] "1 Schriftart hinzugefügt"
|
||||
msgstr[1] "%s Schriftarten hinzugefügt"
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text1"
|
||||
msgstr ""
|
||||
"Jede Webschriftart, die Sie hier hochladen, wird der Liste der Schriftarten "
|
||||
@@ -418,6 +419,7 @@ msgstr ""
|
||||
"den folgenden Formaten hochladen: **TTF, OTF und WOFF** (nur eine wird "
|
||||
"benötigt)."
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text2"
|
||||
msgstr ""
|
||||
"Sie sollten nur Schriftarten hochladen, die Sie besitzen oder für die Sie "
|
||||
|
||||
@@ -831,7 +831,7 @@ msgstr "The email «%s» has been reported as spam or permanently bounce."
|
||||
#: src/app/main/errors.cljs
|
||||
msgid "errors.feature-mismatch"
|
||||
msgstr ""
|
||||
"Looks like you are opening a file that has the feature '%s' enabled bug "
|
||||
"Looks like you are opening a file that has the feature '%s' enabled but "
|
||||
"your penpot frontend does not supports it or has it disabled."
|
||||
|
||||
#: src/app/main/errors.cljs
|
||||
|
||||
@@ -407,6 +407,7 @@ msgid_plural "dashboard.fonts.fonts-added"
|
||||
msgstr[0] "1 fuente añadida"
|
||||
msgstr[1] "%s fuentes añadidas"
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text1"
|
||||
msgstr ""
|
||||
"Cualquier fuente personalizada añadida aquí aparecerá en la lista de "
|
||||
@@ -415,6 +416,7 @@ msgstr ""
|
||||
"como una **única familia de fuentes**. Se pueden cargar fuentes con los "
|
||||
"siguientes formatos: **TTF, OTF and WOFF** (con uno es suficiente)."
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text2"
|
||||
msgstr ""
|
||||
"Sólo deberías cargar fuentes que te pertenecen o de las que tienes una "
|
||||
|
||||
@@ -411,6 +411,7 @@ msgid_plural "dashboard.fonts.fonts-added"
|
||||
msgstr[0] "1 police ajoutée"
|
||||
msgstr[1] "%s polices ajoutées"
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text1"
|
||||
msgstr ""
|
||||
"Toute police Web que vous téléchargez sera ajoutée à la liste de polices de "
|
||||
@@ -419,6 +420,7 @@ msgstr ""
|
||||
"**une seule famille de polices**. Vous pouvez télécharger les polices au "
|
||||
"formats suivants : **TTF, OTF et WOFF** (un seul format est nécessaire)."
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text2"
|
||||
msgstr ""
|
||||
"Ne téléchargez que des polices que vous possédez ou dont la license vous "
|
||||
|
||||
@@ -401,6 +401,7 @@ msgid_plural "dashboard.fonts.fonts-added"
|
||||
msgstr[0] "Engadiuse 1 fonte"
|
||||
msgstr[1] "Engadíronse % fontes"
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text1"
|
||||
msgstr ""
|
||||
"Calquera fonte que cargues aquí engadirase na listaxe de familias de fontes "
|
||||
@@ -409,6 +410,7 @@ msgstr ""
|
||||
"Podes cargar fontes cos seguintes formatos: **TTF, OFT e WOFF** (só se "
|
||||
"precisa un)."
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text2"
|
||||
msgstr ""
|
||||
"Só debes cargar fontes da túa propiedade ou das que teñas licenza para usar "
|
||||
|
||||
@@ -390,6 +390,7 @@ msgstr[1] "נוספו 2 גופנים"
|
||||
msgstr[2] "נוספו %s גופנים"
|
||||
msgstr[3] "נוספו %s גופנים"
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text1"
|
||||
msgstr ""
|
||||
"כל גופן דפדפן שיועלה כאן יתווסף לרשימת משפחת הגופנים שזמין במאפייני הטקסט "
|
||||
@@ -397,6 +398,7 @@ msgstr ""
|
||||
"גופנים יחידה**. ניתן להעלות גופנים מהסוגים הבאים: **TTF, OTF ו־WOFF** (אחד "
|
||||
"הסוגים יספיק)."
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text2"
|
||||
msgstr ""
|
||||
"עליך להעלות גופנים בבעלותך או שיש לך רישיון להשתמש בהם ב־Penpot. ניתן למצוא "
|
||||
|
||||
@@ -398,6 +398,7 @@ msgid_plural "dashboard.fonts.fonts-added"
|
||||
msgstr[0] "1 font aggiunto"
|
||||
msgstr[1] "%s font aggiunti"
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text1"
|
||||
msgstr ""
|
||||
"Qualsiasi font web caricato qui verrà aggiunto alla lista dei font family "
|
||||
@@ -406,6 +407,7 @@ msgstr ""
|
||||
"**singolo font family**. È possibile caricare font con i seguenti "
|
||||
"formati:**TTF, OTF e WOFF**(uno solo di questi è necessario)."
|
||||
|
||||
#, markdown
|
||||
msgid "dashboard.fonts.hero-text2"
|
||||
msgstr ""
|
||||
"È consigliabile caricare unicamente font di cui si è proprietari o dei "
|
||||
|
||||
Reference in New Issue
Block a user