Compare commits

...

34 Commits

Author SHA1 Message Date
Andrey Antukh
60af8d0bcb Merge pull request #5520 from penpot/azazeln28-fix-text-editor-issue-9285
Fix Copy/Paste text into the text block
2025-01-07 14:26:11 +01:00
Juanfran
d652ed8e68 Merge pull request #5519 from penpot/alotor-fix-plugins-current-user
🐛 Fix problem with currentUser in plugins
2025-01-07 14:05:07 +01:00
AzazelN28
09d73a2f51 🐛 Fix pasting text changes opacity to 0 2025-01-07 13:48:32 +01:00
alonso.torres
7d4535ebd4 🐛 Fix problem with currentUser in plugins 2025-01-07 13:03:56 +01:00
Andrey Antukh
a5a53219bf Merge remote-tracking branch 'origin/main' into staging 2025-01-07 12:00:09 +01:00
Marina López
8716f81765 Merge pull request #5456 from daledesilva/patch-1
📚 Add submission form link to deployment page
2025-01-07 10:58:05 +01:00
Andrey Antukh
7aa46a1f62 🔥 Remove 2.4.1 from changelog 2025-01-07 10:51:46 +01:00
Andrey Antukh
d62eb3d3f4 Merge pull request #5504 from penpot/palba-add-feature-flags-to-events
 Add feature flags info to posthog events
2025-01-07 09:34:22 +01:00
Pablo Alba
e4c427609d Add feature flags info to posthog events 2025-01-07 09:19:04 +01:00
Aitor Moreno
883a26845a Merge pull request #5510 from penpot/alotor-fix-thumbnail-generation
🐛 Fix problem with thumbnail generation when changing between ver…
2025-01-02 12:46:59 +01:00
alonso.torres
bcdf5d86ae 🐛 Fix problem with thumbnail generation when changing between versions 2025-01-02 12:01:30 +01:00
Pablo Alba
3eab9da74e Merge pull request #5492 from penpot/alotor-christmas-bugfixes
🐛 Fix problem with component swap style
2024-12-26 16:39:23 +01:00
alonso.torres
2813fda136 🐛 Fix problem with component swap style 2024-12-23 12:37:24 +01:00
Andrey Antukh
a0022a804b Merge branch 'backrunner-patch/backrunner_nginx-conf' into staging 2024-12-23 10:28:34 +01:00
BackRunner
068acb4303 🐛 Fix assets proxy ssl handshake error 2024-12-23 10:28:10 +01:00
Andrey Antukh
d6f98a6c79 📎 Add externs for worker build 2024-12-23 10:03:10 +01:00
Andrey Antukh
7b6c2da6da 📎 Add externs for main build
With all combinations of small symbols for indicate
to compiler to not use them for internal renaming
2024-12-23 10:03:10 +01:00
Andrey Antukh
affed049ee Merge remote-tracking branch 'origin/main' into staging 2024-12-19 10:27:12 +01:00
alonso.torres
377f636b8e 🐛 Fix problem with reorder on grid layout layers 2024-12-18 13:32:30 +01:00
Alejandro Alonso
2d512ef273 🐛 Fix path edition for plugins 2024-12-18 10:12:01 +01:00
Andrey Antukh
b8ebbe8c3c Merge pull request #5468 from penpot/palba-abtest-add-library-button2
 Add test AB renaming "Libraries" to "Add library"
2024-12-13 12:20:56 +01:00
Pablo Alba
09c184200d Merge pull request #5471 from penpot/niwinz-bugfix-5
🐛 Fix unhandled exception on accepting invitation
2024-12-13 12:15:35 +01:00
Andrey Antukh
bbe0b22a8b 🐛 Fix unhandled exception on accepting invitation
In an interaction with the audit log; happens when an old invitation
(with created-by as nil) is accepted.
2024-12-13 11:48:37 +01:00
Andrey Antukh
8603085a69 Merge pull request #5470 from penpot/palba-add-config-not-show-release
🎉 Add config flag to hide release info
2024-12-13 11:28:27 +01:00
Andrey Antukh
29ec44482d Merge pull request #5463 from penpot/andy-docs-adjustments
📚 Remove broken video about History versions
2024-12-13 11:17:27 +01:00
Andrey Antukh
fd4d4ec6e3 Merge pull request #5465 from penpot/palba-fix-viewer-role-thumbnails
🐛 Fix viewer role is unable to generate thumbnails on dashboard
2024-12-13 11:16:32 +01:00
Pablo Alba
0945dd2920 🎉 Add config flag to hide release info 2024-12-13 11:14:59 +01:00
Pablo Alba
664cacbe9d Add test AB renaming "Libraries" to "Add library" 2024-12-13 10:51:41 +01:00
Pablo Alba
08516ac7ca Revert " Add test AB renaming "Libraries" to "Add library""
This reverts commit ec7f8a6aa7.
2024-12-13 10:51:25 +01:00
Pablo Alba
24e51eef5b 🐛 Fix viewer role is unable to generate thumbnails on dashboard 2024-12-12 15:15:27 +01:00
Andrey Antukh
ee62016c34 Merge pull request #5462 from penpot/palba-dont-show-release-info
🐛 Fix a new user shouldn't see the "What's new" popup
2024-12-12 12:27:14 +01:00
andy
7c10f20b95 📚 Remove deprecated video at History version 2024-12-12 11:57:08 +01:00
Pablo Alba
4958da63e5 🐛 Fix a new user shouldn't see the "What's new" popup 2024-12-12 11:45:58 +01:00
Dale de Silva
dbeebf181f 📚 Add submission form link to deployment page
The plugin submission page is hard to find while looking at the plugin help docs (As it's not linked from there). It should eventually be a page of its own but there isn't enough content yet (or an illustration) to support it.
2024-12-11 23:51:11 +11:00
24 changed files with 3528 additions and 162 deletions

View File

@@ -31,6 +31,8 @@
### :bug: Bugs fixed
- Fix problem with some texts desynchronization [Taiga #9379](https://tree.taiga.io/project/penpot/issue/9379)
- Fix problem with reoder grid layers [#5446](https://github.com/penpot/penpot/issues/5446)
- Fix problem with swap component style [#9542](https://tree.taiga.io/project/penpot/issue/9542)
## 2.3.3

View File

@@ -273,7 +273,8 @@
(merge {:viewed-tutorial? false
:viewed-walkthrough? false
:nudge {:big 10 :small 1}
:v2-info-shown true})
:v2-info-shown true
:release-notes-viewed (:main cf/version)})
(db/tjson))
password (or (:password params) "!")

View File

@@ -402,7 +402,10 @@
[cfg {:keys [::rpc/profile-id file-id] :as params}]
(db/tx-run! cfg (fn [{:keys [::db/conn] :as cfg}]
(files/check-edition-permissions! conn profile-id file-id)
;; TODO For now we check read permissions instead of write,
;; to allow viewer users to update thumbnails. We might
;; review this approach on the future.
(files/check-read-permissions! conn profile-id file-id)
(when-not (db/read-only? conn)
(let [media (create-file-thumbnail! cfg params)]
{:uri (files/resolve-public-uri (:id media))

View File

@@ -166,23 +166,26 @@
;; invited team.
(let [props {:team-id (:team-id claims)
:role (:role claims)
:invitation-id (:id invitation)}
:invitation-id (:id invitation)}]
accept-invitation-event
(-> (audit/event-from-rpc-params params)
(assoc ::audit/name "accept-team-invitation")
(assoc ::audit/props props))
(audit/submit!
cfg
(-> (audit/event-from-rpc-params params)
(assoc ::audit/name "accept-team-invitation")
(assoc ::audit/props props)))
accept-invitation-from-event
(-> (audit/event-from-rpc-params params)
(assoc ::audit/profile-id (:created-by invitation))
(assoc ::audit/name "accept-team-invitation-from")
(assoc ::audit/props (assoc props
:profile-id (:id profile)
:email (:email profile))))]
(audit/submit! cfg accept-invitation-event)
(audit/submit! cfg accept-invitation-from-event)
;; NOTE: Backward compatibility; old invitations can
;; have the `created-by` to be nil; so in this case we
;; don't submit this event to the audit-log
(when-let [created-by (:created-by invitation)]
(audit/submit!
cfg
(-> (audit/event-from-rpc-params params)
(assoc ::audit/profile-id created-by)
(assoc ::audit/name "accept-team-invitation-from")
(assoc ::audit/props (assoc props
:profile-id (:id profile)
:email (:email profile))))))
(accept-invitation cfg claims invitation profile)
(assoc claims :state :created))

View File

@@ -304,7 +304,9 @@
(->> ids
(mapcat #(ctn/get-child-heads objects %))
(map :id)))
cell (or cell (ctl/get-cell-by-index parent to-index))]
index-cell-data (when to-index (ctl/get-cell-by-index parent to-index))
cell (or cell (and index-cell-data [(:row index-cell-data) (:column index-cell-data)]))]
(-> changes
(pcb/with-page-id page-id)

View File

@@ -1479,7 +1479,7 @@
(defn get-cell-by-index
[parent to-index]
(let [cells (get-cells parent {:sort? true :remove-empty? true})
to-index (- (count cells) to-index)]
to-index (- (count cells) to-index 1)]
(nth cells to-index nil)))
(defn add-children-to-index

View File

@@ -90,6 +90,7 @@ http {
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_pass $redirect_uri;
proxy_ssl_server_name on;
add_header x-internal-redirect "$redirect_uri";
add_header x-cache-control "$redirect_cache_control";

View File

@@ -92,6 +92,7 @@ http {
proxy_hide_header x-amz-request-id;
proxy_hide_header x-amz-meta-server-side-encryption;
proxy_hide_header x-amz-server-side-encryption;
proxy_ssl_server_name on;
proxy_pass $redirect_uri;
add_header x-internal-redirect "$redirect_uri";

View File

@@ -216,3 +216,9 @@ Success! - Published to example-plugin-penpot.surge.sh
```
5. Done!
## 3.5. Submitting to Penpot
To make your finished plugin available in our catalog, submit in on the [plugin submission page](https://penpot.app/penpothub/plugins/create-plugin). Once it becomes available any Penpot user will be able to install and use it.

View File

@@ -250,11 +250,6 @@ geometric structure. In Penpot there are three types of guides:
<h4>Navigate actions</h4>
<p>To navigate through the actions press <kbd>Ctrl/⌘</kbd> + <kbd>Z</kbd> to go backwards and <kbd>Ctrl/⌘</kbd> + <kbd>Shift/⇧</kbd> + <kbd>Z</kbd> to go forward.</p>
<p>You can also press any item of the actions list to get to this specific state.</p>
<figure>
<video title="Navigate history" muted="" playsinline="" controls="" width="auto" poster="/img/workspace-basics/history-navigate.webp" height="auto">
<source src="/img/workspace-basics/history-navigate.mp4" type="video/mp4">
</video>
</figure>
<h2 id="comments">Comments</h2>
<p>Comments allow the team to have one priceless conversation getting and providing feedback right over the designs and prototypes.<p>

3392
frontend/externs/main.txt Normal file
View File

File diff suppressed because it is too large Load Diff

1
frontend/externs/worker.txt Symbolic link
View File

@@ -0,0 +1 @@
main.txt

View File

@@ -143,6 +143,11 @@
(let [f (obj/get global "externalSessionId")]
(when (fn? f) (f))))
(defn external-context-info
[]
(let [f (obj/get global "externalContextInfo")]
(when (fn? f) (f))))
;; --- Helper Functions
(defn ^boolean check-browser? [candidate]

View File

@@ -8,6 +8,7 @@
(:require
["ua-parser-js" :as ua]
[app.common.data :as d]
[app.common.json :as json]
[app.common.logging :as l]
[app.config :as cf]
[app.main.repo :as rp]
@@ -93,6 +94,11 @@
data
data))
(defn add-external-context-info
[context]
(let [external-context-info (json/->clj (cf/external-context-info))]
(merge context external-context-info)))
(defn- process-event-by-proto
[event]
(let [data (d/deep-merge (-data event) (meta event))
@@ -102,6 +108,7 @@
(assoc :event-origin (::origin data))
(assoc :event-namespace (namespace type))
(assoc :event-symbol ev-name)
(add-external-context-info)
(d/without-nils))
props (-> data d/without-qualified simplify-props)]
@@ -119,6 +126,7 @@
(let [type (::type data "action")
context (-> (::context data)
(assoc :event-origin (::origin data))
(add-external-context-info)
(d/without-nils))
props (-> data d/without-qualified simplify-props)]
{:type type

View File

@@ -52,6 +52,11 @@
(defonce queue
(q/create find-request (/ 1000 30)))
(defn clear-queue!
[]
(l/dbg :hint "clearing thumbnail queue")
(q/clear! queue))
;; This function first renders the HTML calling `render/render-frame` that
;; returns HTML as a string, then we send that data to the iframe rasterizer
;; that returns the image as a Blob. Finally we create a URI for that blob.

View File

@@ -11,6 +11,7 @@
[app.main.data.events :as ev]
[app.main.data.persistence :as dwp]
[app.main.data.workspace :as dw]
[app.main.data.workspace.thumbnails :as th]
[app.main.refs :as refs]
[app.main.repo :as rp]
[app.util.time :as dt]
@@ -132,6 +133,7 @@
(rx/filter #(or (nil? %) (= :saved %)))
(rx/take 1)
(rx/mapcat #(rp/cmd! :restore-file-snapshot {:file-id file-id :id id}))
(rx/tap #(th/clear-queue!))
(rx/map #(dw/initialize-file project-id file-id)))
(case origin
:version

View File

@@ -67,6 +67,7 @@
show-release-modal?
(and (contains? cf/flags :onboarding)
(not (contains? cf/flags :hide-release-modal))
(:onboarding-viewed props)
(not= (:release-notes-viewed props) (:main cf/version))
(not= "0.0" (:main cf/version)))]

View File

@@ -89,6 +89,9 @@
reverse-sort? (= :desc ordering)
num-libs (count (mf/deref refs/workspace-libraries))
show-templates-02-test?
(and (cf/external-feature-flag "templates-02" "test") (zero? num-libs))
toggle-ordering
(mf/use-fn
(mf/deps ordering)
@@ -157,8 +160,7 @@
[:article {:class (stl/css :assets-bar)}
[:div {:class (stl/css :assets-header)}
(when-not ^boolean read-only?
(if (and (cf/external-feature-flag "templates-02" "test")
(zero? num-libs))
(if show-templates-02-test?
[:button {:class (stl/css :add-library-button)
:on-click show-libraries-dialog
:data-testid "libraries"}
@@ -170,31 +172,32 @@
i/library]
(tr "workspace.assets.libraries")]))
[:div {:class (stl/css :search-wrapper)}
[:& search-bar {:on-change on-search-term-change
:value term
:placeholder (tr "workspace.assets.search")}
[:button
{:on-click on-open-menu
:title (tr "workspace.assets.filter")
:class (stl/css-case :section-button true
:opened menu-open?)}
i/filter-icon]]
[:> context-menu*
{:on-close on-menu-close
:selectable true
:selected section
:show menu-open?
:fixed true
:min-width true
:width size
:top 158
:left 18
:options options}]
[:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.assets.sort")
:on-click toggle-ordering
:icon (if reverse-sort? "asc-sort" "desc-sort")}]]]
(when-not show-templates-02-test?
[:div {:class (stl/css :search-wrapper)}
[:& search-bar {:on-change on-search-term-change
:value term
:placeholder (tr "workspace.assets.search")}
[:button
{:on-click on-open-menu
:title (tr "workspace.assets.filter")
:class (stl/css-case :section-button true
:opened menu-open?)}
i/filter-icon]]
[:> context-menu*
{:on-close on-menu-close
:selectable true
:selected section
:show menu-open?
:fixed true
:min-width true
:width size
:top 158
:left 18
:options options}]
[:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.assets.sort")
:on-click toggle-ordering
:icon (if reverse-sort? "asc-sort" "desc-sort")}]])]
[:& (mf/provider cmm/assets-filters) {:value filters}
[:& (mf/provider cmm/assets-toggle-ordering) {:value toggle-ordering}

View File

@@ -402,6 +402,7 @@
.component-swap {
padding-top: $s-12;
max-width: $s-248;
}
.component-swap-content {

View File

@@ -340,76 +340,6 @@
(when (some? guides)
(into [] (map parse-frame-guide) guides)))
;;interface PathCommand {
;; command:
;; | 'M' | 'move-to'
;; | 'Z' | 'close-path'
;; | 'L' | 'line-to'
;; | 'H' | 'line-to-horizontal'
;; | 'V' | 'line-to-vertical'
;; | 'C' | 'curve-to'
;; | 'S' | 'smooth-curve-to'
;; | 'Q' | 'quadratic-bezier-curve-to'
;; | 'T' | 'smooth-quadratic-bezier-curve-to'
;; | 'A' | 'elliptical-arc';
;;
;; params?: {
;; x?: number;
;; y?: number;
;; c1x: number;
;; c1y: number;
;; c2x: number;
;; c2y: number;
;; rx?: number;
;; ry?: number;
;; xAxisRotation?: number;
;; largeArcFlag?: boolean;
;; sweepFlag?: boolean;
;; };
;;}
(defn parse-command-type
[^string command-type]
(case command-type
"M" :move-to
"Z" :close-path
"L" :line-to
"H" :line-to-horizontal
"V" :line-to-vertical
"C" :curve-to
"S" :smooth-curve-to
"Q" :quadratic-bezier-curve-to
"T" :smooth-quadratic-bezier-curve-to
"A" :elliptical-arc
(parse-keyword command-type)))
(defn parse-command-params
[^js params]
(when (some? params)
(d/without-nils
{:x (obj/get params "x")
:y (obj/get params "y")
:c1x (obj/get params "c1x")
:c1y (obj/get params "c1y")
:c2x (obj/get params "c2x")
:c2y (obj/get params "c2y")
:rx (obj/get params "rx")
:ry (obj/get params "ry")
:x-axis-rotation (obj/get params "xAxisRotation")
:large-arc-flag (obj/get params "largeArcFlag")
:sweep-flag (obj/get params "sweepFlag")})))
(defn parse-command
[^js command]
(when (some? command)
(d/without-nils
{:command (-> (obj/get command "command") parse-command-type)
:params (-> (obj/get command "params") parse-command-params)})))
(defn parse-path-content
[^js content]
(when (some? content)
(into [] (map parse-command) content)))
;; export interface Dissolve {
;; type: 'dissolve';
;; duration: number;

View File

@@ -15,7 +15,7 @@
[app.common.record :as crc]
[app.common.schema :as sm]
[app.common.spec :as us]
[app.common.svg.path.legacy-parser2 :as spp]
[app.common.svg.path :as path]
[app.common.text :as txt]
[app.common.types.component :as ctk]
[app.common.types.container :as ctn]
@@ -1326,12 +1326,10 @@
(cond-> (or (cfh/path-shape? data) (cfh/bool-shape? data))
(crc/add-properties!
{:name "content"
:get #(-> % u/proxy->shape :content format/format-path-content)
:get #(-> % u/proxy->shape :content upf/format-path)
:set
(fn [_ value]
(let [content
(->> (parser/parse-path-content value)
(spp/simplify-commands))]
(let [content (->> (path/parse value))]
(cond
(not (cfh/path-shape? data))
(u/display-not-valid :content-type type)

View File

@@ -18,26 +18,24 @@
(defn- add-session-properties
[user-proxy session-id]
(let [plugin-id (obj/get user-proxy "$plugin")]
(crc/add-properties!
user-proxy
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
{:name "$session" :enumerable false :get (constantly session-id)}
(crc/add-properties!
user-proxy
{:name "$session" :enumerable false :get (constantly session-id)}
{:name "id"
:get (fn [_] (-> (u/locate-profile session-id) :id str))}
{:name "id"
:get (fn [_] (-> (u/locate-profile session-id) :id str))}
{:name "name"
:get (fn [_] (-> (u/locate-profile session-id) :fullname))}
{:name "name"
:get (fn [_] (-> (u/locate-profile session-id) :fullname))}
{:name "avatarUrl"
:get (fn [_] (cfg/resolve-profile-photo-url (u/locate-profile session-id)))}
{:name "avatarUrl"
:get (fn [_] (cfg/resolve-profile-photo-url (u/locate-profile session-id)))}
{:name "color"
:get (fn [_] (-> (u/locate-presence session-id) :color))}
{:name "color"
:get (fn [_] (-> (u/locate-presence session-id) :color))}
{:name "sessionId"
:get (fn [_] (str session-id))})))
{:name "sessionId"
:get (fn [_] (str session-id))}))
(defn current-user-proxy? [p]
@@ -46,7 +44,8 @@
(defn current-user-proxy
[plugin-id session-id]
(-> (obj/reify {:name "CurrentUserProxy"}
:$plugin {:enumerable false :get (fn [] plugin-id)})
:$plugin
{:enumerable false :get (fn [] plugin-id)})
(add-session-properties session-id)))
(defn active-user-proxy? [p]
@@ -55,7 +54,8 @@
(defn active-user-proxy
[plugin-id session-id]
(-> (obj/reify {:name "ActiveUserProxy"}
:$plugin {:enumerable false :get (fn [] plugin-id)}
:$plugin
{:enumerable false :get (fn [] plugin-id)}
:position
{:get (fn [] (-> (u/locate-presence session-id) :point format/format-point))}
@@ -66,19 +66,16 @@
(defn- add-user-properties
[user-proxy data]
(let [plugin-id (obj/get user-proxy "$plugin")]
(crc/add-properties!
user-proxy
{:name "$plugin" :enumerable false :get (constantly plugin-id)}
(crc/add-properties!
user-proxy
{:name "id"
:get (fn [_] (-> data :id str))}
{:name "id"
:get (fn [_] (-> data :id str))}
{:name "name"
:get (fn [_] (-> data :fullname))}
{:name "name"
:get (fn [_] (-> data :fullname))}
{:name "avatarUrl"
:get (fn [_] (cfg/resolve-profile-photo-url data))})))
{:name "avatarUrl"
:get (fn [_] (cfg/resolve-profile-photo-url data))}))
(defn user-proxy
[plugin-id data]

View File

@@ -9,6 +9,7 @@
(:require
[app.common.logging :as l]
[app.common.math :as mth]
[app.util.object :as obj]
[app.util.time :as t]
[beicon.v2.core :as rx]))
@@ -47,13 +48,14 @@
;; NOTE: Right now there are no cases where we need to cancel a process
;; but if we do, we can use this function
;; (defn- cancel-process
;; [queue]
;; (l/dbg :hint "queue::cancel-process")
;; (let [timeout (unchecked-get queue "timeout")]
;; (when (some? timeout)
;; (js/clearTimeout timeout))
;; (unchecked-set queue "timeout" nil)))
(defn- cancel-process!
[queue]
(l/dbg :hint "queue::cancel-process")
(let [timeout (unchecked-get queue "timeout")]
(when (some? timeout)
(js/clearTimeout timeout))
(unchecked-set queue "timeout" nil))
queue)
(defn- process
[queue iterations]
@@ -131,3 +133,10 @@
(enqueue-last queue request))))
(rx/to-observable result)))
(defn clear!
[queue]
(-> queue
(cancel-process!)
(obj/set! "items" #js [])
(obj/set! "time" 0)))

View File

@@ -139,7 +139,7 @@ export function normalizeStyles(node, styleDefaults = getStyleDefaultsDeclaratio
// a --fills CSS variable property.
const fills = styleDeclaration.getPropertyValue("--fills");
const color = styleDeclaration.getPropertyValue("color");
if (color) {
if (color && !fills) {
styleDeclaration.removeProperty("color");
styleDeclaration.setProperty("--fills", getFills(color));
} else {