Commit Graph

21065 Commits

Author SHA1 Message Date
Andrey Antukh
d67c7f1c8e Add retry mechanism for idenpotent get repo requests on frontend (#8792)
* ♻️ Handle fetch-error gracefully with toast instead of full-page error

Network-level failures (lost connectivity, DNS failure, etc.) on RPC
calls were propagating as :internal/:fetch-error to the global error
handler, which replaced the entire UI with a full-page error screen.

Now the :internal handler distinguishes :fetch-error from other internal
errors and shows a non-intrusive toast notification instead, allowing
the user to continue working.

*  Add automatic retry with backoff for idempotent RPC requests

Idempotent (GET) RPC requests are now automatically retried up to 3
times with exponential back-off (1s, 2s, 4s) when a transient error
occurs.  Retryable errors include: network-level failures
(:fetch-error), 502 Bad Gateway, 503 Service Unavailable, and browser
offline (status 0).

Mutation (POST) requests are never retried to avoid unintended
side-effects.  Non-transient errors (4xx client errors, auth errors,
validation errors) propagate immediately without retry.

* ♻️ Make retry helpers public with configurable parameters

Make retryable-error? and with-retry public functions, and replace
private constants with a default-retry-config map.  with-retry now
accepts an optional config map (:max-retries, :base-delay-ms) enabling
callers and tests to customize retry behavior.

*  Add tests for RPC retry mechanism

Comprehensive tests for the retry helpers in app.main.repo:
- retryable-error? predicate: covers all retryable types (fetch-error,
  bad-gateway, service-unavailable, offline) and non-retryable types
  (validation, authentication, authorization, plain errors)
- with-retry observable wrapper: verifies immediate success, recovery
  after transient failures, max-retries exhaustion, no retry for
  non-retryable errors, fetch-error retry, custom config, and mixed
  error scenarios

* ♻️ Introduce :network error type for fetch-level failures

Replace the awkward {:type :internal :code :fetch-error} combination
with a proper {:type :network} type in app.util.http/fetch.  This makes
the error taxonomy self-explanatory and removes the special-case branch
in the :internal handler.

Consequences:
- http.cljs: emit {:type :network} instead of {:type :internal :code :fetch-error}
- errors.cljs: add a dedicated ptk/handle-error :network method (toast);
  restore :internal handler to its original unconditional full-page error form
- repo.cljs: simplify retryable-types and retryable-error? — :network
  replaces the former :internal special-case, no code check needed
- repo_test.cljs: update tests to use {:type :network}

* 📚 Add comment explaining the use of bit-shift-left
2026-03-27 11:10:26 +01:00
Alejandro Alonso
8db63c9770 Merge pull request #8785 from penpot/ladybenko-fix-repeatable-key
🐛 Fix repeateable keys triggering an infinite React loop in text editor v2
2026-03-27 10:17:44 +01:00
Alejandro Alonso
0da6b87b5f 🎉 Allow get param to set antialias threshold 2026-03-27 10:00:54 +01:00
Belén Albeza
85425e2ccd 🐛 Fix repeateable keys triggering an infinite React loop in text editor v2 2026-03-26 13:17:09 +01:00
Andrey Antukh
448d85febb 🐛 Fix regression on mcp server listen port 2026-03-26 12:28:27 +01:00
Elena Torró
5ae4b21046 Merge pull request #8791 from penpot/superalex-update-new-render-screenshots
🎉 Updating wasm render screenshots
2026-03-26 12:00:53 +01:00
Elena Torró
72cfd5d996 Merge pull request #8770 from penpot/superalex-fix-text-v2-firefox-word-selection-styles
🐛 Fix wrong typography font size in sidebar when selecting text in Firefox (editor v2)
2026-03-26 11:59:23 +01:00
Elena Torro
1641eec672 🎉 Add stroke to path 2026-03-26 11:43:06 +01:00
Alejandro Alonso
ab404340f8 Merge remote-tracking branch 'origin/main' into staging 2026-03-26 11:36:42 +01:00
alonso.torres
6e03a191a3 🐛 Fix return type for combineAsVariants methods 2026-03-26 09:37:31 +01:00
Luis de Dios
a7e3d7963a 🐛 Fix do not manage tab notifications when MCP flag is disabled 2026-03-26 09:37:24 +01:00
alonso.torres
52a576dc4d 🐛 Fix problem with fills in text range 2026-03-26 09:14:50 +01:00
andrés gonzález
1740d2e3d1 🌐 Differentiate MCP key copy from access token copy (#8786) 2026-03-26 08:21:44 +01:00
Alejandro Alonso
b32a2d32d8 🎉 Updating wasm render screenshots 2026-03-26 08:06:36 +01:00
Alejandro Alonso
85cfb8161a 📎 Rename skills 2026-03-25 23:50:29 +01:00
Alejandro Alonso
a34a668f94 📎 Add opencode skills 2026-03-25 23:48:18 +01:00
Alejandro Alonso
811d53be12 Merge remote-tracking branch 'origin/main' into staging 2026-03-25 18:27:22 +01:00
andrés gonzález
a60020ea98 💄 Change link from Integrations to MCP docs (#8784) 2026-03-25 18:07:37 +01:00
Alejandro Alonso
d2c609f8a4 Merge pull request #8783 from penpot/alotor-fix-shadows
🐛 Fix problem with shadows
2026-03-25 17:51:08 +01:00
alonso.torres
7c5aec4274 🐛 Fix problem with shadows 2026-03-25 17:16:41 +01:00
andrés gonzález
f01bfb7a26 🐛 Adding missing images to mcp doc (#8782) 2026-03-25 16:30:47 +01:00
Alejandro Alonso
efd6b95ff6 🐛 Clear cache canvas on zoom. Teep textures-only invalidation on pan 2026-03-25 16:18:47 +01:00
Alejandro Alonso
3c2430b16c Merge pull request #8778 from penpot/alotor-bugfix-z-index
🐛 Fix problem with z-index
2026-03-25 15:59:15 +01:00
alonso.torres
a5d908629b 🐛 Fix problems with z-index 2026-03-25 15:56:56 +01:00
Andrey Antukh
737e04fe2c 🐛 Fix nil deref on missing bounds in layout modifier propagation (#8735)
* 🐛 Fix nil deref on missing bounds in layout modifier propagation

When a parent shape has a child ID in its shapes vector that does
not exist in the objects map, the layout modifier code crashes
because it derefs nil from the bounds map.

The root cause is that children from the parent shapes list are
not validated against the objects map before being passed to the
layout modifier pipeline. Children with missing IDs pass through
unchecked and reach apply-modifiers where bounds lookup fails.

Fix by adding nil guards in apply-modifiers to skip children
without bounds, and changing map to keep to filter them out.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

* 📎 Add tests for nil bounds in layout modifier propagation

Tests cover flex and grid layout scenarios where a parent
frame has child IDs in its shapes vector that do not exist
in the objects map, verifying that set-objects-modifiers
handles these gracefully without crashing.

Tests:
- Flex layout with normal children (baseline)
- Flex layout with non-existent child in shapes
- Flex layout with only non-existent children
- Grid layout with non-existent child in shapes
- Flex layout resize propagation with ghost children
- Nested flex layout with non-existent child in outer frame

Signed-off-by: Andrey Antukh <niwi@niwi.nz>

---------

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-03-25 15:36:21 +01:00
andrés gonzález
38bf6c3603 📚 Add MCP docs (#8772) 2026-03-25 15:32:24 +01:00
alonso.torres
28b4c14b95 🐛 Fix problem when removing margin 2026-03-25 13:28:56 +01:00
Eva Marco
ba8b552df2 🐛 Fix shared button variant and title (#8696)
Co-authored-by: Luis de Dios <luis.dedios@kaleidos.net>
2026-03-25 13:08:41 +01:00
moktamd
4e3dc6532a 🐛 Default MCP listen addresses to localhost instead of 0.0.0.0
Signed-off-by: moktamd <moktamd@users.noreply.github.com>
2026-03-25 12:34:33 +01:00
Andrey Antukh
a2672a598c 🐛 Fix TypeError when token error map lacks :error/fn key (#8767)
* 🐛 Fix TypeError when token error map lacks :error/fn key

Guard against missing :error/fn in token form control resolve streams.
When schema validation errors are produced they may not carry an
:error/fn key; calling nil as a function caused a TypeError crash.
Apply an if-let guard at all 7 affected sites across input.cljs,
color_input.cljs and fonts_combobox.cljs, falling back to :message
or returning the error map unchanged.

* ♻️ Extract token error helpers and add unit tests

Extract resolve-error-message and resolve-error-assoc-message helpers
into errors.cljs, replacing the seven duplicated inline lambdas in
input.cljs, color_input.cljs and fonts_combobox.cljs with named
function references.  Add frontend-tests.tokens.token-errors-test
covering both helpers for the normal path (:error/fn present) and the
fallback path (schema-validation errors that lack :error/fn).

Signed-off-by: Penpot Dev <dev@penpot.app>

---------

Signed-off-by: Penpot Dev <dev@penpot.app>
2.14.1-RC1
2026-03-25 12:12:18 +01:00
Andrey Antukh
af4548a6ed Merge remote-tracking branch 'origin/main' into staging 2026-03-25 12:02:49 +01:00
Alejandro Alonso
b5b51e21c2 Merge pull request #8741 from penpot/superalex-fix-text-align-empty-paragraph-v2
🐛 Fix text align empty paragraph v2
2026-03-25 10:42:05 +01:00
Alejandro Alonso
334039668d 🐛 Fix wrong typography font size in sidebar when selecting text in Firefox (editor v2) 2026-03-25 10:38:56 +01:00
Alejandro Alonso
6268a8aaf1 Merge pull request #8764 from penpot/alotor-fix-issue-text-sizing
🐛 Fix resize text modifiers
2026-03-25 07:45:25 +01:00
alonso.torres
6b609566e1 🐛 Fix resize text modifiers 2026-03-25 07:29:20 +01:00
Andrey Antukh
0dfac801a4 Improve error handling and exception formatting (#8757)
*  Improve error handling and exception formatting

- Enhance exception formatting with visual separators and cause chaining
- Add new handler for :internal error type
- Refine error types: change assertion-related errors to :assertion type
- Improve error messages and hints consistency
- Clean up error handling in zip utilities and HTTP modules

* 🐛 Properly handle AbortError on fetch request unsubscription

When a fetch request in-flight is cancelled due to RxJS unsubscription
(e.g. navigating away from the workspace while thumbnail loads are
pending), the AbortController.abort() call triggers a catch handler
that previously relied solely on a @unsubscribed? flag to suppress the
error.

This was unreliable: nested observables spawned inside rx/mapcat (such
as datauri->blob-uri conversions within get-file-object-thumbnails)
could abort independently, with their own AbortController instances,
meaning the outer unsubscribed? flag was never set and the AbortError
propagated as an unhandled exception.

Add an explicit AbortError name check as a disjunctive condition so
that abort errors originating from any observable in the chain are
suppressed at the source, regardless of subscription state.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-03-24 19:55:23 +01:00
Andrey Antukh
01284e2a00 Improve error handling and exception formatting (#8757)
*  Improve error handling and exception formatting

- Enhance exception formatting with visual separators and cause chaining
- Add new handler for :internal error type
- Refine error types: change assertion-related errors to :assertion type
- Improve error messages and hints consistency
- Clean up error handling in zip utilities and HTTP modules

* 🐛 Properly handle AbortError on fetch request unsubscription

When a fetch request in-flight is cancelled due to RxJS unsubscription
(e.g. navigating away from the workspace while thumbnail loads are
pending), the AbortController.abort() call triggers a catch handler
that previously relied solely on a @unsubscribed? flag to suppress the
error.

This was unreliable: nested observables spawned inside rx/mapcat (such
as datauri->blob-uri conversions within get-file-object-thumbnails)
could abort independently, with their own AbortController instances,
meaning the outer unsubscribed? flag was never set and the AbortError
propagated as an unhandled exception.

Add an explicit AbortError name check as a disjunctive condition so
that abort errors originating from any observable in the chain are
suppressed at the source, regardless of subscription state.

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
2026-03-24 19:54:05 +01:00
Andrey Antukh
cc73a768d5 Add comprehensive tests for path and descendant namespaces (#8755)
Add tests for app.common.types.path.subpath, helpers, segment,
bool operations (union/difference/intersection/exclude), top-level
path API, and shape-to-path conversion. Covers previously untested
functions across all path sub-namespaces. Tests pass on both JVM
and JS (ClojureScript/Node) platforms.
2026-03-24 19:53:22 +01:00
Andrey Antukh
3ef100427b 🎉 Add tests for app.common.data namespace (#8750)
*  Add tests for predicates and ordered data structures

Adds tests for boolean-or-nil?, in-range?, ordered-set/map creation
and ordering, oassoc/oassoc-in/oupdate-in/oassoc-before, and the
ordered collection index helpers (adds/inserts/addm/insertm-at-index).

*  Add tests for lazy and sequence helpers

Adds tests for concat-all, mapcat, zip, zip-all, enumerate,
interleave-all, add-at-index, take-until, safe-subvec and domap.

*  Add tests for collection lookup and map manipulation

Adds tests for group-by, seek, index-by, index-of-pred/of,
replace-by-id, getf, vec-without-nils, without-nils,
without-qualified, without-keys, deep-merge, dissoc-in, patch-object,
without-obj, update-vals, update-in-when, update-when, assoc-in-when,
assoc-when, merge, txt-merge, mapm, removev, filterm, removem,
map-perm, distinct-xf and deep-mapm.

*  Add tests for parsing, numeric and utility helpers

Adds tests for nan?, safe+, max, min, parse-integer, parse-double,
parse-uuid, coalesce-str, coalesce, read-string, name, prefix-keyword,
kebab-keys, regexp?, nilf, nilv, any-key?, tap, tap-r, map-diff,
unique-name, toggle-selection, invert-map, obfuscate-string,
unstable-sort, opacity-to-hex, format-precision, format-number
and append-class.

*  Add tests for remaining untested helpers in data ns

Cover percent?, parse-percent, num-string?, num?, not-empty?,
editable-collection?, oreorder-before, oassoc-in-before,
lazy-map and reorder.

Platform-specific assertions use reader conditionals where
CLJS and JVM behaviour differ (js/isFinite string coercion,
js/isNaN empty-string coercion).
2026-03-24 19:52:52 +01:00
Andrey Antukh
7461c5304c Add comprehensive tests for app.common.colors ns (#8758)
Cover all public functions: valid-hex-color?, parse-rgb,
valid-rgb-color?, rgb->str, hex->rgb, rgb->hex, rgb->hsv,
hsv->rgb, rgb->hsl, hsl->rgb, hex->hsl, hex->hsv, hex->rgba,
hex->hsla, hex->lum, hsl->hex, hsl->hsv, hsv->hex, hsv->hsl,
format-hsla, format-rgba, expand-hex, prepend-hash, remove-hash,
color-string?, parse, next-rgb, reduce-range, interpolate-color,
uniform-spread, uniform-spread? and interpolate-gradient.

Tests pass on both JVM and JS (ClojureScript) platforms.
Platform differences (NaN saturation for achromatic colors,
integer vs float return types) are handled with mth/close?.
2026-03-24 19:10:44 +01:00
Andrey Antukh
0f19bc02d7 📎 Add testing engineer agent (opencode) 2026-03-24 18:49:30 +01:00
Andrey Antukh
53f4c6fede Merge remote-tracking branch 'origin/main' into staging 2026-03-24 18:19:09 +01:00
Andrey Antukh
edfa437ce7 📚 Improve CONTRIBUTING.md file 2026-03-24 18:18:38 +01:00
Andrey Antukh
8928e274fc Merge remote-tracking branch 'origin/main' into staging 2026-03-24 18:01:38 +01:00
Andrey Antukh
cc03f3f884 📚 Add minor improvements to ai agents documentation 2026-03-24 18:00:39 +01:00
alonso.torres
b6e300a6c7 🐛 Fix plugins addToken schema validation 2026-03-24 16:27:59 +01:00
Belén Albeza
44689d3f9c 🐛 Fix internal error on invalid max-h/max-w values (wasm) 2026-03-24 16:02:40 +01:00
Dominik Jain
ccaeb49354 📚 Add instructions on MCP usage via npx #8535 2026-03-24 15:57:04 +01:00
Dominik Jain
38f2ec1339 📎 Update Serena project file 2026-03-24 15:57:04 +01:00
Dominik Jain
7b5699b59f Improve instructions on Text elements 2026-03-24 15:57:04 +01:00