diff --git a/CHANGES.md b/CHANGES.md index 792bf7ae7..e772f5caa 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,7 @@ - Fix weird numeration creating new elements in dashboard [Taiga #4755](https://tree.taiga.io/project/penpot/issue/4755) - Fix can move shape with lens zoom active [Taiga #4787](https://tree.taiga.io/project/penpot/issue/4787) - Fix social links broken [Taiga #4759](https://tree.taiga.io/project/penpot/issue/4759) +- Fix tooltips on left toolbar [Taiga #4793](https://tree.taiga.io/project/penpot/issue/4793) ## 1.17.0 diff --git a/backend/src/app/auth/oidc.clj b/backend/src/app/auth/oidc.clj index d6030025a..14d479e35 100644 --- a/backend/src/app/auth/oidc.clj +++ b/backend/src/app/auth/oidc.clj @@ -50,7 +50,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defn- discover-oidc-config - [cfg {:keys [::base-uri] :as opts}] + [cfg {:keys [base-uri] :as opts}] (let [discovery-uri (u/join base-uri ".well-known/openid-configuration") response (ex/try! (http/req! cfg {:method :get :uri (str discovery-uri)} diff --git a/common/src/app/common/geom/shapes/flex_layout/bounds.cljc b/common/src/app/common/geom/shapes/flex_layout/bounds.cljc index 31f0317a1..fea42fcad 100644 --- a/common/src/app/common/geom/shapes/flex_layout/bounds.cljc +++ b/common/src/app/common/geom/shapes/flex_layout/bounds.cljc @@ -64,8 +64,11 @@ min-width (max min-width 0.01) min-height (max min-height 0.01)] - (cond-> [base-p] - (or col? h-start?) + (cond-> [base-p + (gpt/add base-p (hv 0.01)) + (gpt/add base-p (vv 0.01))] + + (and col? h-start?) (conj (gpt/add base-p (hv min-width))) (and col? h-center?) @@ -74,7 +77,7 @@ (and col? h-center?) (conj (gpt/subtract base-p (hv min-width))) - (or row? v-start?) + (and row? v-start?) (conj (gpt/add base-p (vv min-height))) (and row? v-center?) diff --git a/common/src/app/common/geom/shapes/points.cljc b/common/src/app/common/geom/shapes/points.cljc index 206494d49..3722beb9e 100644 --- a/common/src/app/common/geom/shapes/points.cljc +++ b/common/src/app/common/geom/shapes/points.cljc @@ -6,6 +6,7 @@ (ns app.common.geom.shapes.points (:require + [app.common.data :as d] [app.common.geom.point :as gpt] [app.common.geom.shapes.common :as gco] [app.common.geom.shapes.intersect :as gsi] @@ -115,7 +116,9 @@ (max tv-max ctv)])) [th-min th-max tv-min tv-max] - (->> child-bounds (reduce find-boundary-ts [##Inf ##-Inf ##Inf ##-Inf])) + (->> child-bounds + (filter #(and (d/num? (:x %)) (d/num? (:y %)))) + (reduce find-boundary-ts [##Inf ##-Inf ##Inf ##-Inf])) minv-start (pv tv-min) minv-end (gpt/add minv-start hv) diff --git a/common/src/app/common/types/shape/layout.cljc b/common/src/app/common/types/shape/layout.cljc index 9be46671f..a7001cd37 100644 --- a/common/src/app/common/types/shape/layout.cljc +++ b/common/src/app/common/types/shape/layout.cljc @@ -134,25 +134,41 @@ (defn wrap? [{:keys [layout-wrap-type]}] (= layout-wrap-type :wrap)) -(defn fill-width? [child] - (= :fill (:layout-item-h-sizing child))) +(defn fill-width? + ([objects id] + (= :fill (dm/get-in objects [id :layout-item-h-sizing]))) + ([child] + (= :fill (:layout-item-h-sizing child)))) -(defn fill-height? [child] - (= :fill (:layout-item-v-sizing child))) +(defn fill-height? + ([objects id] + (= :fill (dm/get-in objects [id :layout-item-v-sizing]))) + ([child] + (= :fill (:layout-item-v-sizing child)))) -(defn auto-width? [child] - (= :auto (:layout-item-h-sizing child))) +(defn auto-width? + ([objects id] + (= :auto (dm/get-in objects [id :layout-item-h-sizing]))) + ([child] + (= :auto (:layout-item-h-sizing child)))) -(defn auto-height? [child] - (= :auto (:layout-item-v-sizing child))) +(defn auto-height? + ([objects id] + (= :auto (dm/get-in objects [id :layout-item-v-sizing]))) + ([child] + (= :auto (:layout-item-v-sizing child)))) (defn col? - [{:keys [layout-flex-dir]}] - (or (= :column layout-flex-dir) (= :column-reverse layout-flex-dir))) + ([objects id] + (col? (get objects id))) + ([{:keys [layout-flex-dir]}] + (or (= :column layout-flex-dir) (= :column-reverse layout-flex-dir)))) (defn row? - [{:keys [layout-flex-dir]}] - (or (= :row layout-flex-dir) (= :row-reverse layout-flex-dir))) + ([objects id] + (row? (get objects id))) + ([{:keys [layout-flex-dir]}] + (or (= :row layout-flex-dir) (= :row-reverse layout-flex-dir)))) (defn gaps [{:keys [layout-gap]}] @@ -315,3 +331,22 @@ (defn align-self-stretch? [{:keys [layout-item-align-self]}] (= :stretch layout-item-align-self)) + +(defn change-h-sizing? + [frame-id objects children-ids] + (and (layout? objects frame-id) + (auto-width? objects frame-id) + (or (and (col? objects frame-id) + (every? (partial fill-width? objects) children-ids)) + (and (row? objects frame-id) + (some (partial fill-width? objects) children-ids))))) + +(defn change-v-sizing? + [frame-id objects children-ids] + (and (layout? objects frame-id) + (auto-height? objects frame-id) + (or (and (col? objects frame-id) + (some (partial fill-height? objects) children-ids)) + (and (row? objects frame-id) + (every? (partial fill-height? objects) children-ids))))) + diff --git a/docker/devenv/docker-compose.yaml b/docker/devenv/docker-compose.yaml index 93fc93a0c..a8f7c4cff 100644 --- a/docker/devenv/docker-compose.yaml +++ b/docker/devenv/docker-compose.yaml @@ -11,6 +11,7 @@ volumes: postgres_data_pg15: user_data: minio_data: + redis_data: services: main: @@ -80,22 +81,6 @@ services: - 9000:9000 - 9001:9001 - # keycloak: - # image: "quay.io/keycloak/keycloak:15.0.2" - # environment: - # - DB_VENDOR=POSTGRES - # - DB_ADDR=postgres - # - DB_DATABASE=keycloak - # - DB_USER=keycloak - # - DB_SCHEMA=public - # - DB_PASSWORD=keycloak - # - KEYCLOAK_USER=admin - # - KEYCLOAK_PASSWORD=admin - # expose: - # - '8080' - # ports: - # - "8080:8080" - postgres: image: postgres:15 command: postgres -c config_file=/etc/postgresql.conf @@ -116,6 +101,8 @@ services: hostname: "penpot-devenv-redis" container_name: "penpot-devenv-redis" restart: always + volumes: + - "redis_data:/data" mailer: image: sj26/mailcatcher:latest diff --git a/docker/images/Dockerfile.backend b/docker/images/Dockerfile.backend index be6cdaa75..7b6a4ee5b 100644 --- a/docker/images/Dockerfile.backend +++ b/docker/images/Dockerfile.backend @@ -28,8 +28,10 @@ RUN set -ex; \ ; \ echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; \ locale-gen; \ - mkdir -p /opt/penpot/assets; \ + mkdir -p /opt/data; \ + mkdir -p /opt/penpot; \ chown -R penpot:penpot /opt/penpot; \ + chown -R penpot:penpot /opt/data; \ rm -rf /var/lib/apt/lists/*; RUN set -eux; \ diff --git a/docker/images/docker-compose.yaml b/docker/images/docker-compose.yaml index 6302178cd..975b08dd7 100644 --- a/docker/images/docker-compose.yaml +++ b/docker/images/docker-compose.yaml @@ -40,7 +40,7 @@ services: - 9001:80 volumes: - - penpot_assets:/opt/penpot/assets + - penpot_assets:/opt/data/assets depends_on: - penpot-backend @@ -180,7 +180,7 @@ services: ## stored in a docker volume. - PENPOT_ASSETS_STORAGE_BACKEND=assets-fs - - PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/penpot/assets + - PENPOT_STORAGE_ASSETS_FS_DIRECTORY=/opt/data/assets ## Also can be configured to to use a S3 compatible storage ## service like MiniIO. Look below for minio service setup. diff --git a/docker/images/files/nginx.conf b/docker/images/files/nginx.conf index f628aacfe..a43f3bf66 100644 --- a/docker/images/files/nginx.conf +++ b/docker/images/files/nginx.conf @@ -90,7 +90,7 @@ http { location /internal/assets { internal; - alias /opt/penpot/assets; + alias /opt/data/assets; add_header x-internal-redirect "$upstream_http_x_accel_redirect"; } diff --git a/frontend/resources/styles/main/partials/workspace.scss b/frontend/resources/styles/main/partials/workspace.scss index 1331b47e0..da78e187a 100644 --- a/frontend/resources/styles/main/partials/workspace.scss +++ b/frontend/resources/styles/main/partials/workspace.scss @@ -37,7 +37,7 @@ $height-palette-max: 80px; .left-toolbar { grid-area: toolbar; width: $width-left-toolbar; - overflow-y: scroll; + overflow-y: auto; overflow-x: hidden; } diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 717182b9a..4b2179ceb 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -651,20 +651,20 @@ (-> (pcb/empty-changes it page-id) (pcb/with-objects objects) - ; Move the shapes + ;; Move the shapes (pcb/change-parent parent-id shapes to-index) - ; Remove empty groups + ;; Remove empty groups (pcb/remove-objects groups-to-delete) - ; Unmask groups whose mask have moved outside + ;; Unmask groups whose mask have moved outside (pcb/update-shapes groups-to-unmask (fn [shape] (assoc shape :masked-group? false))) - ; Detach shapes moved out of their component + ;; Detach shapes moved out of their component (pcb/update-shapes shapes-to-detach (fn [shape] (assoc shape :component-id nil @@ -674,17 +674,17 @@ :shape-ref nil :touched nil))) - ; Make non root a component moved inside another one + ;; Make non root a component moved inside another one (pcb/update-shapes shapes-to-deroot (fn [shape] (assoc shape :component-root? nil))) - ; Make root a subcomponent moved outside its parent component + ;; Make root a subcomponent moved outside its parent component (pcb/update-shapes shapes-to-reroot (fn [shape] (assoc shape :component-root? true))) - ; Reset constraints depending on the new parent + ;; Reset constraints depending on the new parent (pcb/update-shapes shapes-to-unconstraint (fn [shape] (let [parent (get objects parent-id) @@ -699,7 +699,19 @@ :constraints-v (gsh/default-constraints-v moved-shape)))) {:ignore-touched true}) - ; Resize parent containers that need to + ;; Fix the sizing when moving a shape + (pcb/update-shapes parents + (fn [parent] + (if (ctl/layout? parent) + (cond-> parent + (ctl/change-h-sizing? (:id parent) objects (:shapes parent)) + (assoc :layout-item-h-sizing :fix) + + (ctl/change-v-sizing? (:id parent) objects (:shapes parent)) + (assoc :layout-item-v-sizing :fix)) + parent))) + + ;; Resize parent containers that need to (pcb/resize-parents parents)))) (defn relocate-shapes @@ -719,9 +731,9 @@ ;; If we try to move a parent into a child we remove it ids (filter #(not (cph/is-parent? objects parent-id %)) ids) - parents (if ignore-parents? - #{parent-id} - (into #{parent-id} (map #(cph/get-parent-id objects %)) ids)) + + all-parents (into #{parent-id} (map #(cph/get-parent-id objects %)) ids) + parents (if ignore-parents? #{parent-id} all-parents) groups-to-delete (loop [current-id (first parents) @@ -814,17 +826,12 @@ shapes-to-reroot shapes-to-deroot ids) - - layouts-to-update - (into #{} - (filter (partial ctl/layout? objects)) - (concat [parent-id] (cph/get-parent-ids objects parent-id))) undo-id (js/Symbol)] (rx/of (dwu/start-undo-transaction undo-id) (dch/commit-changes changes) (dwco/expand-collapse parent-id) - (ptk/data-event :layout/update layouts-to-update) + (ptk/data-event :layout/update (concat all-parents ids)) (dwu/commit-undo-transaction undo-id)))))) (defn relocate-selected-shapes diff --git a/frontend/src/app/main/data/workspace/modifiers.cljs b/frontend/src/app/main/data/workspace/modifiers.cljs index 965fa5e8b..1eaf6a688 100644 --- a/frontend/src/app/main/data/workspace/modifiers.cljs +++ b/frontend/src/app/main/data/workspace/modifiers.cljs @@ -174,42 +174,62 @@ modif-tree))) (defn build-change-frame-modifiers - [modif-tree objects selected target-frame drop-index] + [modif-tree objects selected target-frame-id drop-index] (let [origin-frame-ids (->> selected (group-by #(get-in objects [% :frame-id]))) - child-set (set (get-in objects [target-frame :shapes])) - layout? (ctl/layout? objects target-frame) + child-set (set (get-in objects [target-frame-id :shapes])) + + target-frame (get objects target-frame-id) + target-layout? (ctl/layout? target-frame) + + children-ids (concat (:shapes target-frame) selected) set-parent-ids - (fn [modif-tree shapes target-frame] + (fn [modif-tree shapes target-frame-id] (reduce (fn [modif-tree id] (update-in modif-tree [id :modifiers] #(-> % - (ctm/change-property :frame-id target-frame) - (ctm/change-property :parent-id target-frame)))) + (ctm/change-property :frame-id target-frame-id) + (ctm/change-property :parent-id target-frame-id)))) modif-tree shapes)) update-frame-modifiers (fn [modif-tree [original-frame shapes]] - (let [shapes (->> shapes (d/removev #(= target-frame %))) + (let [shapes (->> shapes (d/removev #(= target-frame-id %))) shapes (cond->> shapes - (and layout? (= original-frame target-frame)) + (and target-layout? (= original-frame target-frame-id)) ;; When movining inside a layout frame remove the shapes that are not immediate children - (filterv #(contains? child-set %)))] + (filterv #(contains? child-set %))) + children-ids (->> (dm/get-in objects [original-frame :shapes]) + (remove (set selected))) + + h-sizing? (ctl/change-h-sizing? original-frame objects children-ids) + v-sizing? (ctl/change-v-sizing? original-frame objects children-ids)] (cond-> modif-tree - (not= original-frame target-frame) + (not= original-frame target-frame-id) (-> (modifier-remove-from-parent objects shapes) - (update-in [target-frame :modifiers] ctm/add-children shapes drop-index) - (set-parent-ids shapes target-frame)) + (update-in [target-frame-id :modifiers] ctm/add-children shapes drop-index) + (set-parent-ids shapes target-frame-id) + (cond-> h-sizing? + (update-in [original-frame :modifiers] ctm/change-property :layout-item-h-sizing :fix)) + (cond-> v-sizing? + (update-in [original-frame :modifiers] ctm/change-property :layout-item-v-sizing :fix))) - (and layout? (= original-frame target-frame)) - (update-in [target-frame :modifiers] ctm/add-children shapes drop-index))))] + (and target-layout? (= original-frame target-frame-id)) + (update-in [target-frame-id :modifiers] ctm/add-children shapes drop-index))))] - (reduce update-frame-modifiers modif-tree origin-frame-ids))) + (as-> modif-tree $ + (reduce update-frame-modifiers $ origin-frame-ids) + (cond-> $ + (ctl/change-h-sizing? target-frame-id objects children-ids) + (update-in [target-frame-id :modifiers] ctm/change-property :layout-item-h-sizing :fix)) + (cond-> $ + (ctl/change-v-sizing? target-frame-id objects children-ids) + (update-in [target-frame-id :modifiers] ctm/change-property :layout-item-v-sizing :fix))))) (defn modif->js [modif-tree objects] diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index 0fd5f0cd7..5ad25a7df 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -84,7 +84,9 @@ :color (if show-text? text-color "transparent") :caretColor (or text-color "black") :overflowWrap "initial" - :lineBreak "auto"} + :lineBreak "auto" + :whiteSpace "break-spaces" + :textRendering "geometricPrecision"} fills (cond (some? (:fills data)) diff --git a/frontend/src/app/main/ui/workspace/left_toolbar.cljs b/frontend/src/app/main/ui/workspace/left_toolbar.cljs index de16a19c3..33776155f 100644 --- a/frontend/src/app/main/ui/workspace/left_toolbar.cljs +++ b/frontend/src/app/main/ui/workspace/left_toolbar.cljs @@ -49,8 +49,8 @@ (st/emit! (dwm/upload-media-workspace params)))))] [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.image" (sc/get-tooltip :insert-image)) + [:button + {:title (tr "workspace.toolbar.image" (sc/get-tooltip :insert-image)) :aria-label (tr "workspace.toolbar.image" (sc/get-tooltip :insert-image)) :on-click on-click} [:* @@ -73,8 +73,8 @@ [:aside.left-toolbar [:ul.left-toolbar-options [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.move" (sc/get-tooltip :move)) + [:button + {:title (tr "workspace.toolbar.move" (sc/get-tooltip :move)) :aria-label (tr "workspace.toolbar.move" (sc/get-tooltip :move)) :class (when (and (nil? selected-drawtool) (not edition)) "selected") @@ -83,32 +83,32 @@ (when-not workspace-read-only? [:* [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.frame" (sc/get-tooltip :draw-frame)) + [:button + {:title (tr "workspace.toolbar.frame" (sc/get-tooltip :draw-frame)) :aria-label (tr "workspace.toolbar.frame" (sc/get-tooltip :draw-frame)) :class (when (= selected-drawtool :frame) "selected") :on-click (partial select-drawtool :frame) :data-test "artboard-btn"} i/artboard]] [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.rect" (sc/get-tooltip :draw-rect)) + [:button + {:title (tr "workspace.toolbar.rect" (sc/get-tooltip :draw-rect)) :aria-label (tr "workspace.toolbar.rect" (sc/get-tooltip :draw-rect)) :class (when (= selected-drawtool :rect) "selected") :on-click (partial select-drawtool :rect) :data-test "rect-btn"} i/box]] [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.ellipse" (sc/get-tooltip :draw-ellipse)) + [:button + {:title (tr "workspace.toolbar.ellipse" (sc/get-tooltip :draw-ellipse)) :aria-label (tr "workspace.toolbar.ellipse" (sc/get-tooltip :draw-ellipse)) :class (when (= selected-drawtool :circle) "selected") :on-click (partial select-drawtool :circle) :data-test "ellipse-btn"} i/circle]] [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.text" (sc/get-tooltip :draw-text)) + [:button + {:title (tr "workspace.toolbar.text" (sc/get-tooltip :draw-text)) :aria-label (tr "workspace.toolbar.text" (sc/get-tooltip :draw-text)) :class (when (= selected-drawtool :text) "selected") :on-click (partial select-drawtool :text)} @@ -117,16 +117,16 @@ [:& image-upload] [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.curve" (sc/get-tooltip :draw-curve)) + [:button + {:title (tr "workspace.toolbar.curve" (sc/get-tooltip :draw-curve)) :aria-label (tr "workspace.toolbar.curve" (sc/get-tooltip :draw-curve)) :class (when (= selected-drawtool :curve) "selected") :on-click (partial select-drawtool :curve) :data-test "curve-btn"} i/pencil]] [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.path" (sc/get-tooltip :draw-path)) + [:button + {:title (tr "workspace.toolbar.path" (sc/get-tooltip :draw-path)) :aria-label (tr "workspace.toolbar.path" (sc/get-tooltip :draw-path)) :class (when (= selected-drawtool :path) "selected") :on-click (partial select-drawtool :path) @@ -134,8 +134,8 @@ i/pen]]]) [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.comments" (sc/get-tooltip :add-comment)) + [:button + {:title (tr "workspace.toolbar.comments" (sc/get-tooltip :add-comment)) :aria-label (tr "workspace.toolbar.comments" (sc/get-tooltip :add-comment)) :class (when (= selected-drawtool :comments) "selected") :on-click (partial select-drawtool :comments)} @@ -145,8 +145,8 @@ (when-not workspace-read-only? [:* [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette)) + [:button + {:title (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette)) :aria-label (tr "workspace.toolbar.text-palette" (sc/get-tooltip :toggle-textpalette)) :class (when (contains? layout :textpalette) "selected") :on-click (fn [] @@ -158,8 +158,8 @@ "Ag"]] [:li - [:button.tooltip.tooltip-right - {:alt (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette)) + [:button + {:title (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette)) :aria-label (tr "workspace.toolbar.color-palette" (sc/get-tooltip :toggle-colorpalette)) :class (when (contains? layout :colorpalette) "selected") :on-click (fn [] @@ -170,8 +170,8 @@ (vary-meta assoc ::ev/origin "workspace-left-toolbar")))))} i/palette]]]) [:li - [:button.tooltip.tooltip-right.separator - {:alt (tr "workspace.toolbar.shortcuts" (sc/get-tooltip :show-shortcuts)) + [:button + {:title (tr "workspace.toolbar.shortcuts" (sc/get-tooltip :show-shortcuts)) :aria-label (tr "workspace.toolbar.shortcuts" (sc/get-tooltip :show-shortcuts)) :class (when (contains? layout :shortcuts) "selected") :on-click (fn [] @@ -183,8 +183,8 @@ i/shortcut] (when *assert* - [:button.tooltip.tooltip-right - {:alt "Debugging tool" + [:button + {:title "Debugging tool" :class (when (contains? layout :debug-panel) "selected") :on-click (fn [] (let [is-sidebar-closed? (contains? layout :collapse-left-sidebar)]