Improvements to baseline based on porting exercise#5055
Merged
Conversation
A coherent set of framework, build-tool, and theme additions surfaced
by porting Immich's Flutter client to Codename One. Each item was driven
by a concrete pain point in that port; the Immich port is the
regression fixture for the cn1:compliance-check + Rest builder + typed
binding paths.
Java API subset (Ports/CLDC11 + vm/JavaAPI):
- Map: 11 Java 8 default methods (getOrDefault, putIfAbsent,
remove(K,V), replace(K,V) / replace(K,V,V), forEach, replaceAll,
computeIfAbsent, computeIfPresent, compute, merge).
- BiFunction added to java.util.function (was missing).
- Iterable.forEach(Consumer), Collection.removeIf(Predicate),
List.replaceAll(UnaryOperator), List.sort(Comparator).
- All four primitive atomics: AtomicReference (already in vm/JavaAPI,
mirrored to CLDC11), AtomicInteger, AtomicLong, AtomicBoolean.
Core framework:
- Rest.fetchAsJsonList -- top-level JSON arrays unwrap automatically
rather than forcing callers through the {"root":[...]} envelope trick.
- Rest.fetchAsMapped(Class<T>) / fetchAsMappedList(Class<T>) -- typed
POJO responses via the @mapped binding framework merged in PR #5047.
- Component.setPullToRefresh(Runnable) alias for addPullToRefresh
(more discoverable; same single-task slot).
- URLImage.RequestDecorator interface + setDefaultRequestDecorator +
setDefaultBearerToken + per-call decorator overload on
createToStorage. Eliminates the "URLImage doesn't pass headers"
workaround for authenticated image endpoints.
- JSONWriter -- mirror of JSONParser. One-shot toJson(Object) plus
fluent JSONWriter.object().put(...).toJson() / JSONWriter.array()
builders. Streaming variants for writer / OutputStream.
- Tabs.setAnimatedIndicator(boolean) -- Material 3 NavigationBar /
iOS 26 sliding-underline indicator. Gated by tabsAnimatedIndicatorBool
theme constant + duration/thickness constants + TabIndicator UIID
color. Off by default in framework, on by default in modern native
themes.
- MorphTransition.snapshotMode(boolean) -- opt-in image-snapshot path
that captures source/dest as clipped Images at initTransition() and
tweens those rather than re-painting the live components. Solves the
source-inside-scrolling-container off-viewport-leak case. Default
(live-paint) path unchanged.
- DefaultLookAndFeel.drawModernPullToRefresh -- Material 3 arc-spinner
pull-to-refresh painted directly via Graphics.drawArc. Sweep grows
0deg -> 330deg as the user pulls, then spins continuously while the
refresh task runs. Gated by pullToRefreshModernBool theme constant;
on by default in modern themes.
- com.codename1.io.websocket package -- WebSocket Java API moved from
the cn1-websockets cn1lib into core. Per-platform native impls
remain in the cn1lib repo for a follow-up.
Maven plugin:
- StubGenerator.isValidType accepts String[] (was rejected). All
primitive arrays were already accepted.
- New cn1:generate-openapi-client mojo -- reads an OpenAPI 3.x JSON
spec (URL or local file), emits one @mapped POJO per
components.schemas entry and one <Tag>Api.java per tag. Each
generated method routes through Rest.<verb> + Mappers.toJson +
fetchAsMapped / fetchAsMappedList. Tested end-to-end against the
Swagger Petstore reference spec: 6 models + 3 Api classes generated,
compiles cleanly against codenameone-core. Four JUnit tests in
OpenApiCodegenTest cover inline-spec generation, identifier /
class-name sanitisation, and a real-Petstore round-trip.
- codenameone-core moved from test to compile scope in the plugin
pom so the codegen can use com.codename1.io.JSONParser for spec
parsing.
Native themes:
- iOS Modern + Android Material both enable tabsAnimatedIndicatorBool,
pullToRefreshModernBool, plus the supporting duration / thickness /
diameter constants. New TabIndicator UIID with light + dark variants
pinned to --accent-color / --accent-color-dark. Binary
Themes/*.res files regenerated via scripts/build-native-themes.sh.
Tests (scripts/hellocodenameone):
- MorphTransitionTest -- baseline live-paint morph.
- MorphTransitionScrolledSourceTest -- source in a scrolling list
(the case snapshotMode is designed to solve).
- MorphTransitionSnapshotTest -- snapshot-mode baseline.
- All three registered in Cn1ssDeviceRunner.DEFAULT_TEST_CLASSES and
the HTML5 skip list.
Documentation:
- docs/developer-guide/io.asciidoc -- new sections for
fetchAsJsonList / fetchAsMapped / fetchAsMappedList, JSONWriter,
WebSocket.
- docs/developer-guide/graphics.asciidoc -- URLImage RequestDecorator
+ setDefaultBearerToken.
- docs/developer-guide/Animations.asciidoc -- MorphTransition
snapshotMode.
- docs/developer-guide/The-Components-Of-Codename-One.asciidoc --
animated tab indicator under the Tabs section.
- docs/developer-guide/Miscellaneous-Features.asciidoc -- modern
arc-spinner pull-to-refresh under the existing Pull to refresh
section.
- docs/developer-guide/Native-Themes.asciidoc -- the six new theme
constants (3 tabs, 3 pull-to-refresh) added to the tuning-constants
table.
- docs/developer-guide/appendix_goal_generate_openapi_client.adoc --
new Maven goal documentation page.
- docs/developer-guide/Maven-Appendix-Goals.adoc -- includes the new
goal in the appendix.
Skill (scripts/initializr/.../skill/):
- references/java-api-subset.md -- fetchAsMapped section,
URLImage.RequestDecorator section, JSONWriter section, OidcClient
section, WebSocket-in-core mention, refreshed subset gotchas.
- references/ui-components.md -- MorphTransition.snapshotMode,
Tabs animated indicator, modern pull-to-refresh, package-split
table for components / spinner / ui.
- references/build-and-run.md -- Hot Reload modes,
cn1:generate-openapi-client invocation.
- references/native-interfaces.md -- corrected allowed-types list
to include String[] and primitive arrays; iOS NSData* marshal
caveat.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two corrections to the previous round, both PR feedback: 1. WebSocket: replace WebSocketNativeImpl (NativeInterface pattern) with WebSocketImpl + createWebSocketImpl factory on CodenameOneImplementation. The Java API still lives under com.codename1.io.websocket but each per-platform port now subclasses WebSocketImpl directly and returns it from createWebSocketImpl -- same pattern Media / Storage / LocationManager use. The WebSocketImpl talks directly to the native WebSocket API (no NativeInterface marshaling, no static-callback string-id round-trip). Util gets a narrow Util.createWebSocketImpl(parent) delegate so WebSocket (in a sub-package) can reach the impl accessor; pattern matches Util.secureRandomBytes. 2. CLDC11 contains stubs, not implementations. AtomicReference / AtomicInteger / AtomicLong / AtomicBoolean now have empty stub bodies (return 0 / null / false). The Java 8 default methods on Map / Collection / List / Iterable also drop their real implementations -- stubbed bodies returning null / false / no-op. Actual runtime behaviour comes from the platform (Android JDK on Android, vm/JavaAPI on ParparVM, the host JDK in the JavaSE simulator); CLDC11 java-runtime.jar is only used by the compile-time compliance check. Also fixes the validate-java25-markdown-docs.sh CI step which rejected the classic /** Javadoc markers introduced in the new atomic classes -- all four are now /// markdown comments. Verified: full mvn install green, errorprone clean, validate-java25-markdown-docs passes, the immich-cn1-port external fixture still passes cn1:compliance-check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Compared 47 screenshots: 47 matched. |
Contributor
|
Developer Guide build artifacts are available for download from this workflow run:
Developer Guide quality checks: |
Contributor
Cloudflare Preview
|
Collaborator
Author
|
Compared 121 screenshots: 121 matched. Native Android coverage
✅ Native Android screenshot tests passed. Native Android coverage
Benchmark ResultsDetailed Performance Metrics
|
- SpotBugs: drop redundant null checks where getComponentStyle() /
getThemeConstant() return non-null by contract (Tabs, DefaultLookAndFeel).
Guard the snapshot-mode draw path against an uninitialised
fromToComponents array even though the field is populated by
initTransition() before paint() is ever called -- SpotBugs is
flow-insensitive and complains otherwise.
- Vale: US-English spellings (behaviour -> behavior, colour -> color,
serialisation -> serialization, etc.) across the new doc sections.
Remove a "cannot" -> "can't" and two "e.g." -> "for example".
Rephrase one parenthetical to drop a stray first-person "I" that
vale was flagging on a downstream line via cumulative column
tracking. Drop a couple of unnecessary hyphens
("currently-selected" -> "currently selected" etc).
- Asciidoctor: replace HTML entity ° with the literal degree
symbol (asciidoctor doesn't recognise ° and errors out parsing
the formatted-text run).
- LanguageTool: add "unobfuscated" to the accept list (existing prose
on master uses the word but no LT run had previously been triggered
there since the term was introduced).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
✅ ByteCodeTranslator Quality ReportTest & Coverage
Benchmark Results
Static Analysis
Generated automatically by the PR CI workflow. |
- URLImage:895 -- drop the redundant
com.codename1.util.FailureCallback fully-qualified reference; the
short form FailureCallback is already imported at the top of the
file. PMD's UnnecessaryFullyQualifiedName rule.
- LanguageTool accept-list -- add "Petstore", "Swagger", "Api", and
the "tween" family ("tween", "tweens", "tweened", "tweening").
All four are technical terms LanguageTool's English dictionary
doesn't recognise but that the new docs use as prose ("the indicator
tweens its x / width", "the Swagger Petstore reference spec",
"Each generated Api method").
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…elines
PMD: shorten redundant FQNs in RequestBuilder/URLImage/MorphTransition.
Docs: replace ambiguous hyphenated "class-loading" wording flagged by
LanguageTool with "classloader" in two Annotation-* chapters.
Android baselines: capture MorphTransition{,Scrolled,Snapshot}Test PNGs
extracted from CI logs; refresh TabsTheme_dark/light for the animated
indicator visual flag.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Compared 120 screenshots: 120 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
Split combined int declarations in Tabs.java and reword "tweens its" in the Tabs animated-indicator chapter to "animates its" so it no longer trips MORFOLOGIK_RULE_EN_US. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Compared 121 screenshots: 121 matched. Benchmark Results
Build and Run Timing
Detailed Performance Metrics
|
Brace the two type-test branches that returned without curly braces. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wrap the single-statement bodies of two if checks and one for loop that PMD flagged in writeJson and writeString. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wrap the early-continue body where MorphTransition skips zero-area morph entries; satisfies PMD ControlStatementBraces. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wrap the inline `if (f > 0) return f;` bodies in modernIndicatorDiameterMm and modernIndicatorStrokeMm so they pass PMD ControlStatementBraces. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…aintAnimation The Form host parameter was never read inside the Animation closure -- the repaint runs against `cmp` directly. Drop the parameter and the call site arg. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Break the inline `{ return ... }` bodies in ObjectBuilder/ArrayBuilder
across multiple lines so they satisfy the LeftCurlyCheck rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
✅ Continuous Quality ReportTest & Coverage
Static Analysis
Generated automatically by the PR CI workflow. |
Baselines captured from the green Test iOS UI build scripts run on this branch (artifacts ios-ui-tests / ios-ui-tests-metal). The screenshots show the expected source → destination interpolation across six animation frames. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Input validation gesture suite was failing on cache-miss every run because its src_hash differs from build-port's even on the same SHA. Mirror the workaround already in scripts-ios.yml by reusing needs.build-port.outputs.cn1_built_cache_key instead of recomputing the hash here. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The com.codename1.io.websocket package landed without iOS, Android, JavaSE, or JavaScript port implementations -- isSupported() returned false everywhere, leaving callers stranded. Drop the public API (WebSocket, WebSocketImpl, WebSocketState), the framework factory hooks (CodenameOneImplementation.createWebSocketImpl, Util's delegate), and the developer-guide + initializr skill sections that documented the half-wired contract. The existing cn1-websockets cn1lib remains the supported transport until a fully-ported in-core replacement is ready. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…h tests; trim skill - Strip the "guess from Flutter" alias rationale on Component.setPullToRefresh and the Flutter "hot reload" comparison in the build-and-run skill ref. - DefaultLookAndFeel.modernSpinStartTime now reads AnimationTime.now() so screenshot tests can drive the rotation deterministically. - Add TabsAnimatedIndicatorScreenshotTest and PullToRefreshSpinnerScreenshotTest under scripts/hellocodenameone -- both extend AbstractAnimationScreenshotTest so the 2x3 grid harness produces a baseline image of each animation phase. - Compress the Tabs animated-indicator and modern pull-to-refresh sections in ui-components.md to a single short paragraph; the LLM doesn't need the per-constant table when both features are on by default in the modern themes. Same trim for MorphTransition.snapshotMode. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove OpenApiCodegen.java, GenerateOpenApiClientMojo.java,
OpenApiCodegenTest.java and the matching developer-guide appendix.
- Add com.codename1.annotations.rest.{RestClient, GET, POST, PUT,
DELETE, PATCH, Path, Query, Header, Body} -- the contract the new
cn1:generate-openapi mojo emits onto each interface method.
- Add com.codename1.io.rest.RestClients -- the runtime registry the
generated cn1app.RestClientBootstrap fills in; each interface's
static of(baseUrl) factory routes through it so the generated impl
class never appears in project source.
- New appendix_goal_generate_openapi.adoc describes the redesign;
skill references point at cn1:generate-openapi instead of the
removed generate-openapi-client goal.
Build-time processor + mojo + records-support follow in subsequent
phases on this branch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AnnotatedClass.isRecord() reads the ACC_RECORD bit from the class
file's access flags (inlined constant for ASM-version safety).
MappingAnnotationProcessor:
- For records, skip the concrete-class / public-no-arg-ctor checks
and walk non-public component fields (record components are
private final but carry component names).
- Reject Property / ListProperty components on records -- they imply
mutation and records are immutable.
- emit* helpers thread `isRecord` so reads go through `o.name()`
accessors and writes target local variables `_name` instead of
`o.name` field assignment.
- For records, `fromMap` and `readXml` declare per-component locals
with kind-appropriate defaults, populate them, and return via the
canonical constructor `new T(_a, _b, ...)` in bytecode declaration
order (= canonical-ctor parameter order).
RecordMappingTest exercises a Pet record end-to-end on JDK 17;
skipped on JDK 8. POJO regression tests remain green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…pi mojo
RestClientAnnotationProcessor (sibling to MappingAnnotationProcessor):
- Scans `@RestClient`-annotated interfaces.
- Per method, reads the one HTTP-verb annotation (@GET/@POST/@PUT/
@DELETE/@patch) plus the parameter-level @Path/@Query/@Header/@Body
annotations now exposed by ClassScanner.
- Resolves the response payload type from the trailing
`OnComplete<Response<T>>` generic signature -- `List<X>` routes
through `fetchAsMappedList`, `String` through `fetchAsString`,
everything else through `fetchAsMapped(T.class, ...)`.
- Emits `<Tag>ApiImpl` (final class implementing the user interface)
plus a sibling `cn1app.RestClientBootstrap` that registers each
impl with `RestClients` -- the build-server splice pattern
`MapperBootstrap` already uses applies here unchanged.
GenerateOpenApiMojo (`cn1:generate-openapi`):
- Inputs `-Dcn1.openapi.spec=<path|url>` and
`-Dcn1.openapi.basePackage=<pkg>`. Optional outputDirectory /
overwrite knobs.
- Detects `maven.compiler.release` / `target`. >= 17 emits Java
records, otherwise classes. The `@Mapped` processor already
handles both shapes.
- Schema unification: identical property shapes collapse to a
single record/class.
- Per OpenAPI tag emits one `@RestClient`-annotated interface
under <basePackage> with a static `of(String baseUrl)` factory
that delegates to `RestClients.create(...)`.
Supporting changes:
- ClassScanner / MethodInfo now capture per-parameter annotations
and the method's generic signature.
- META-INF service registration adds the new processor.
- skill ref + appendix updated to the actual mojo flag form.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Asciidoctor parsed `<path|url>` as an in-table cell delimiter and dropped the surrounding row. Switch to angle-bracket-free PATH / PKG / DIR placeholders matching other appendices. Vale: "is not" -> "isn't", "fully-qualified" -> "fully qualified". LanguageTool: replace "bookkeep imports" with "track imports". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…r.fieldType REFERENCE / PROPERTY / LIST_PROPERTY all fall back to the binaryName shape; SpotBugs DB_DUPLICATE_SWITCH_CLAUSES wants them folded into a single case label. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The runner registers each screenshot test explicitly (no auto-scan); the new animation tests need both a `new XScreenshotTest()` line in the suite array and an entry in `isJsSkippedAnimationTest` (matching how Morph* are already gated -- JS chunk-emission is unreliable for animation grids today). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DB_DUPLICATE_BRANCHES on the substring offset: both arms of `sign > 0 ? 0 : 0` evaluated to the same value. `start` already points at the sign character so the substring offset is just `start..i`. The `sign` local was load-bearing for nothing else, so drop it too. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add com.codename1.annotations.rest.Cookie parameter annotation. - RestClientAnnotationProcessor recognises @cookie, collapses any @cookie params on a method into a single `Cookie: a=1; b=2` header with URL-encoded values. - GenerateOpenApiMojo emits @cookie for OpenAPI `in: cookie` parameters instead of dropping them. - Appendix loses the apologetic "Scope (MVP)" framing and the "tracked as follow-ups" trailer; the supported-feature list is now declarative. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Private fields with a matching public `getX()` (or `isX()` for booleans) plus `setX(FieldType)` are now first-class @mapped targets. Property / ListProperty fields only need the getter -- the field itself isn't replaced, only its inner value mutated. MappingAnnotationProcessor: - Per-field strategy stored as `useAccessor` + `getterName` + `setterName` on MappedField; `findGetter` / `findSetter` probe the declared methods on the class. - The `readExpr` / `writeStmt` helpers picks between record- accessor / bean-getter / public-field at each emit site so the record, public-field, and accessor-POJO paths converge. - `URL` -> `getURL` matches `java.beans.Introspector` (literal first, lowercased variant `getUrl` as a fallback). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DefaultLookAndFeel only takes the arc-spinner path when `pullToRefreshModernBool` is on. The bare framework theme defaults to off, so the previous render fell through to the legacy rotating arrow and the new Android baseline showed nothing modern. Overlay the constant via addThemeProps -- same mechanism the iOS Modern / Android Material native themes use -- and restore the theme on finishCapture so subsequent suite tests aren't affected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
actions/setup-java@v4 has been hitting Cloudflare 520 on Zulu's mirror repeatedly today (Build Android JDK 21 + javascript-screenshots keep failing at the Setup JDK step). Adoptium Temurin is hosted on GitHub's own infrastructure and matches the OpenJDK reference distribution, so it's both more reliable and more conventional. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Collaborator
Author
|
Compared 11 screenshots: 11 matched. |
Six baselines captured from the green Android (JDK 8/17/21) and
iOS (regular + metal) screenshot runs:
- Tabs frames show the indicator tweening from tab 0 to tab 2
via Motion.createEaseInOutMotion driven by AnimationTime.
- PullToRefresh frames show the modern arc spinner rotating;
the test overlays pullToRefreshModernBool=true via addThemeProps
so DefaultLookAndFeel takes the arc path even when the
framework default theme is loaded.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DefaultLookAndFeel.drawModernPullToRefresh now paints a white circular backdrop sized to the arc radius + stroke padding, with a soft three-layer translucent shadow offset down-right, before the arc itself. The arc was invisible against same-colour backdrops before; the disc lifts it off any surface the way the Material 3 RefreshIndicator does. Test fix: PullToRefreshSpinnerScreenshotTest was double-painting the indicator -- once via the host form's normal paint chain (which positions it after the title bar offset) and again with an explicit drawPullToRefresh call (which used the un-translated origin). Drop the second call; the host paint already renders the modern arc because the container carries `$pullToRelease=updating`. The three PNG baselines (Android + iOS regular + iOS metal) are removed so CI re-captures them with the new rendering. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Android baseline now clearly shows the Material 3 white disc with soft shadow under the rotating arc. The iOS variants render the arc more lightly (no visible status bar in the test form), but each cell has the expected single indicator -- no more double-paint over the title and content list. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 29, 2026
shai-almog
added a commit
that referenced
this pull request
May 29, 2026
Final consolidated follow-up to the May 29 weekly index. Pulls together six PRs that share the same architectural shape: emit Java at build time, validate at build time, fail fast, and let R8 / ParparVM rename the generated code together with the rest of the app. - PR #5037: bytecode AnnotationProcessor SPI in the Maven plugin, the declarative router that is its first consumer (@route with guards, redirects, per-tab navigation shell, location listeners), the unified cold + warm DeepLink API, iOS Universal Links / Android App Links JSON generators, and the JavaScript-port window.history bridge. - PR #5047: three more processors on the same SPI -- SQLite ORM (@entity / @id / @column), JSON / XML mapping (@mapped / @JsonProperty / @xmlelement), and component binding (@bindable / @Bind with the new BindAttr enum). - PR #5062: validation annotations (@required, @Length, @regex, @Email, @url, @Numeric, @existin, @Validate) that compose with @Bind and surface through Binding.getValidator(). - PR #5055: the Immich-port baseline -- Map default methods, BiFunction, atomics, Rest.fetchAsJsonList / fetchAsMapped(List), URLImage.RequestDecorator / setDefaultBearerToken, JSONWriter, modern animated tab indicator + arc-spinner pull-to-refresh, MorphTransition.snapshotMode, WebSocket in core, and the new cn1:generate-openapi-client mojo. - PR #5042: build-time SVG transcoder that lowers SVG (and SMIL animations) into Codename One Image subclasses via the shape API. - PR #5066: Lottie / Bodymovin transcoder reusing the same SVGDocument model, JavaCodeGenerator, and SVGRegistry. - PR #5049: the iOS Metal stencil-clip + drawString and Android LinearGradientPaint fixes the SVG screenshot tests exposed. Calls out the Metal-only caveat on iOS for SVG / Lottie (the GL ES 2 path does not have the shape coverage) -- a non-issue on most apps now that Metal is the default.
shai-almog
added a commit
that referenced
this pull request
May 29, 2026
Final consolidated follow-up to the May 29 weekly index. Pulls together six PRs that share the same architectural shape: emit Java at build time, validate at build time, fail fast, and let R8 / ParparVM rename the generated code together with the rest of the app. - PR #5037: bytecode AnnotationProcessor SPI in the Maven plugin, the declarative router that is its first consumer (@route with guards, redirects, per-tab navigation shell, location listeners), the unified cold + warm DeepLink API, iOS Universal Links / Android App Links JSON generators, and the JavaScript-port window.history bridge. - PR #5047: three more processors on the same SPI -- SQLite ORM (@entity / @id / @column), JSON / XML mapping (@mapped / @JsonProperty / @xmlelement), and component binding (@bindable / @Bind with the new BindAttr enum). - PR #5062: validation annotations (@required, @Length, @regex, @Email, @url, @Numeric, @existin, @Validate) that compose with @Bind and surface through Binding.getValidator(). - PR #5055: the Immich-port baseline -- Map default methods, BiFunction, atomics, Rest.fetchAsJsonList / fetchAsMapped(List), URLImage.RequestDecorator / setDefaultBearerToken, JSONWriter, modern animated tab indicator + arc-spinner pull-to-refresh, MorphTransition.snapshotMode, WebSocket in core, and the new cn1:generate-openapi-client mojo. - PR #5042: build-time SVG transcoder that lowers SVG (and SMIL animations) into Codename One Image subclasses via the shape API. - PR #5066: Lottie / Bodymovin transcoder reusing the same SVGDocument model, JavaCodeGenerator, and SVGRegistry. - PR #5049: the iOS Metal stencil-clip + drawString and Android LinearGradientPaint fixes the SVG screenshot tests exposed. Calls out the Metal-only caveat on iOS for SVG / Lottie (the GL ES 2 path does not have the shape coverage) -- a non-issue on most apps now that Metal is the default.
shai-almog
added a commit
that referenced
this pull request
May 29, 2026
Final consolidated follow-up to the May 29 weekly index. Pulls together six PRs that share the same architectural shape: emit Java at build time, validate at build time, fail fast, and let R8 / ParparVM rename the generated code together with the rest of the app. - PR #5037: bytecode AnnotationProcessor SPI in the Maven plugin, the declarative router that is its first consumer (@route with guards, redirects, per-tab navigation shell, location listeners), the unified cold + warm DeepLink API, iOS Universal Links / Android App Links JSON generators, and the JavaScript-port window.history bridge. - PR #5047: three more processors on the same SPI -- SQLite ORM (@entity / @id / @column), JSON / XML mapping (@mapped / @JsonProperty / @xmlelement), and component binding (@bindable / @Bind with the new BindAttr enum). - PR #5062: validation annotations (@required, @Length, @regex, @Email, @url, @Numeric, @existin, @Validate) that compose with @Bind and surface through Binding.getValidator(). - PR #5055: the Immich-port baseline -- Map default methods, BiFunction, atomics, Rest.fetchAsJsonList / fetchAsMapped(List), URLImage.RequestDecorator / setDefaultBearerToken, JSONWriter, modern animated tab indicator + arc-spinner pull-to-refresh, MorphTransition.snapshotMode, WebSocket in core, and the new cn1:generate-openapi-client mojo. - PR #5042: build-time SVG transcoder that lowers SVG (and SMIL animations) into Codename One Image subclasses via the shape API. - PR #5066: Lottie / Bodymovin transcoder reusing the same SVGDocument model, JavaCodeGenerator, and SVGRegistry. - PR #5049: the iOS Metal stencil-clip + drawString and Android LinearGradientPaint fixes the SVG screenshot tests exposed. Calls out the Metal-only caveat on iOS for SVG / Lottie (the GL ES 2 path does not have the shape coverage) -- a non-issue on most apps now that Metal is the default.
shai-almog
added a commit
that referenced
this pull request
May 29, 2026
Final consolidated follow-up to the May 29 weekly index. Pulls together six PRs that share the same architectural shape: emit Java at build time, validate at build time, fail fast, and let R8 / ParparVM rename the generated code together with the rest of the app. - PR #5037: bytecode AnnotationProcessor SPI in the Maven plugin, the declarative router that is its first consumer (@route with guards, redirects, per-tab navigation shell, location listeners), the unified cold + warm DeepLink API, iOS Universal Links / Android App Links JSON generators, and the JavaScript-port window.history bridge. - PR #5047: three more processors on the same SPI -- SQLite ORM (@entity / @id / @column), JSON / XML mapping (@mapped / @JsonProperty / @xmlelement), and component binding (@bindable / @Bind with the new BindAttr enum). - PR #5062: validation annotations (@required, @Length, @regex, @Email, @url, @Numeric, @existin, @Validate) that compose with @Bind and surface through Binding.getValidator(). - PR #5055: the Immich-port baseline -- Map default methods, BiFunction, atomics, Rest.fetchAsJsonList / fetchAsMapped(List), URLImage.RequestDecorator / setDefaultBearerToken, JSONWriter, modern animated tab indicator + arc-spinner pull-to-refresh, MorphTransition.snapshotMode, WebSocket in core, and the new cn1:generate-openapi-client mojo. - PR #5042: build-time SVG transcoder that lowers SVG (and SMIL animations) into Codename One Image subclasses via the shape API. - PR #5066: Lottie / Bodymovin transcoder reusing the same SVGDocument model, JavaCodeGenerator, and SVGRegistry. - PR #5049: the iOS Metal stencil-clip + drawString and Android LinearGradientPaint fixes the SVG screenshot tests exposed. Calls out the Metal-only caveat on iOS for SVG / Lottie (the GL ES 2 path does not have the shape coverage) -- a non-issue on most apps now that Metal is the default.
shai-almog
added a commit
that referenced
this pull request
May 29, 2026
Final consolidated follow-up to the May 29 weekly index. Pulls together six PRs that share the same architectural shape: emit Java at build time, validate at build time, fail fast, and let R8 / ParparVM rename the generated code together with the rest of the app. - PR #5037: bytecode AnnotationProcessor SPI in the Maven plugin, the declarative router that is its first consumer (@route with guards, redirects, per-tab navigation shell, location listeners), the unified cold + warm DeepLink API, iOS Universal Links / Android App Links JSON generators, and the JavaScript-port window.history bridge. - PR #5047: three more processors on the same SPI -- SQLite ORM (@entity / @id / @column), JSON / XML mapping (@mapped / @JsonProperty / @xmlelement), and component binding (@bindable / @Bind with the new BindAttr enum). - PR #5062: validation annotations (@required, @Length, @regex, @Email, @url, @Numeric, @existin, @Validate) that compose with @Bind and surface through Binding.getValidator(). - PR #5055: the Immich-port baseline -- Map default methods, BiFunction, atomics, Rest.fetchAsJsonList / fetchAsMapped(List), URLImage.RequestDecorator / setDefaultBearerToken, JSONWriter, modern animated tab indicator + arc-spinner pull-to-refresh, MorphTransition.snapshotMode, WebSocket in core, and the new cn1:generate-openapi-client mojo. - PR #5042: build-time SVG transcoder that lowers SVG (and SMIL animations) into Codename One Image subclasses via the shape API. - PR #5066: Lottie / Bodymovin transcoder reusing the same SVGDocument model, JavaCodeGenerator, and SVGRegistry. - PR #5049: the iOS Metal stencil-clip + drawString and Android LinearGradientPaint fixes the SVG screenshot tests exposed. Calls out the Metal-only caveat on iOS for SVG / Lottie (the GL ES 2 path does not have the shape coverage) -- a non-issue on most apps now that Metal is the default.
shai-almog
added a commit
that referenced
this pull request
May 29, 2026
Final consolidated follow-up to the May 29 weekly index. Pulls together six PRs that share the same architectural shape: emit Java at build time, validate at build time, fail fast, and let R8 / ParparVM rename the generated code together with the rest of the app. - PR #5037: bytecode AnnotationProcessor SPI in the Maven plugin, the declarative router that is its first consumer (@route with guards, redirects, per-tab navigation shell, location listeners), the unified cold + warm DeepLink API, iOS Universal Links / Android App Links JSON generators, and the JavaScript-port window.history bridge. - PR #5047: three more processors on the same SPI -- SQLite ORM (@entity / @id / @column), JSON / XML mapping (@mapped / @JsonProperty / @xmlelement), and component binding (@bindable / @Bind with the new BindAttr enum). - PR #5062: validation annotations (@required, @Length, @regex, @Email, @url, @Numeric, @existin, @Validate) that compose with @Bind and surface through Binding.getValidator(). - PR #5055: the Immich-port baseline -- Map default methods, BiFunction, atomics, Rest.fetchAsJsonList / fetchAsMapped(List), URLImage.RequestDecorator / setDefaultBearerToken, JSONWriter, modern animated tab indicator + arc-spinner pull-to-refresh, MorphTransition.snapshotMode, WebSocket in core, and the new cn1:generate-openapi-client mojo. - PR #5042: build-time SVG transcoder that lowers SVG (and SMIL animations) into Codename One Image subclasses via the shape API. - PR #5066: Lottie / Bodymovin transcoder reusing the same SVGDocument model, JavaCodeGenerator, and SVGRegistry. - PR #5049: the iOS Metal stencil-clip + drawString and Android LinearGradientPaint fixes the SVG screenshot tests exposed. Calls out the Metal-only caveat on iOS for SVG / Lottie (the GL ES 2 path does not have the shape coverage) -- a non-issue on most apps now that Metal is the default.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A coherent set of framework, build-tool, and theme additions surfaced by porting the Immich Flutter mobile client to Codename One. Each item was driven by a concrete pain point in that port; the port itself is the regression fixture (it still compiles + passes
cn1:compliance-checkafter every change in this branch).Subset additions (
Ports/CLDC11+vm/JavaAPI)Map: 11 Java 8 default methods (getOrDefault,putIfAbsent,remove(K,V),replace(K,V)/replace(K,V,V),forEach,replaceAll,computeIfAbsent,computeIfPresent,compute,merge).BiFunction(was missing in the function package).Iterable.forEach(Consumer),Collection.removeIf(Predicate),List.replaceAll(UnaryOperator),List.sort(Comparator).AtomicReference,AtomicInteger,AtomicLong,AtomicBoolean.Core framework
Rest.fetchAsJsonList— top-level JSON arrays no longer need the{"root":[...]}envelope trick.Rest.fetchAsMapped(Class<T>)/fetchAsMappedList(Class<T>)— typed POJO responses via the@Mappedbinding framework from Build-time POJO annotation frameworks: JSON/XML mapping, component binding, SQLite ORM #5047.Component.setPullToRefresh(Runnable)alias foraddPullToRefresh.URLImage.RequestDecorator+setDefaultRequestDecorator+setDefaultBearerToken+ per-call decorator overload oncreateToStorage. Eliminates the "URLImage doesn't pass headers" workaround for authenticated image endpoints.JSONWriter— complement ofJSONParser. One-shottoJson(Object)plus fluentJSONWriter.object().put(...).toJson()/JSONWriter.array()builders. Streaming variants forWriter/OutputStream.Tabs.setAnimatedIndicator(boolean)— Material 3 / iOS 26 sliding-underline indicator. Gated bytabsAnimatedIndicatorBool+ duration / thickness constants +TabIndicatorUIID color. Off in framework default, on by default in modern native themes.MorphTransition.snapshotMode(boolean)— opt-in image-snapshot path that captures source / dest as clippedImages atinitTransition()and tweens those rather than re-painting live components. Solves the source-inside-scrolling-container off-viewport-leak case. Default (live-paint) path unchanged for back-compat.DefaultLookAndFeel.drawModernPullToRefresh— Material 3 arc-spinner pull-to-refresh painted viaGraphics.drawArc. Sweep grows 0°→330° as the user pulls, then spins continuously while the task runs. Gated bypullToRefreshModernBooltheme constant; on by default in modern themes.com.codename1.io.websocketpackage —WebSocketJava API moved from thecn1-websocketscn1lib into core. Per-platform native impls remain in the cn1lib repo for a follow-up.Maven plugin
StubGenerator.isValidTypeacceptsString[](was rejected). All primitive arrays were already accepted.cn1:generate-openapi-clientmojo — reads an OpenAPI 3.x JSON spec (URL or local file), emits one@MappedPOJO percomponents.schemasentry and one<Tag>Api.javaper tag. Each generated method routes throughRest.<verb>+Mappers.toJson+fetchAsMapped/fetchAsMappedList. Four JUnit tests inOpenApiCodegenTest, plus the Petstore reference spec is exercised end-to-end (6 models + 3 Api classes generated, 9 .class files compile cleanly againstcodenameone-core).codenameone-coremoved from test to compile scope in the plugin pom so the codegen can usecom.codename1.io.JSONParserfor spec parsing.Native themes
iOS Modern + Android Material both enable
tabsAnimatedIndicatorBool,pullToRefreshModernBool, plus the supporting duration / thickness / diameter constants. NewTabIndicatorUIID with light + dark variants pinned to--accent-color/--accent-color-dark. BinaryThemes/*.resfiles regenerated viascripts/build-native-themes.sh.Screenshot tests
Three new screenshot-grid tests under
scripts/hellocodenameone/.../tests/, registered inCn1ssDeviceRunnerand the HTML5 skip list:MorphTransitionTest— baseline live-paint morph.MorphTransitionScrolledSourceTest— source in a scrolling list (the casesnapshotModeis designed to solve).MorphTransitionSnapshotTest— locks the snapshot-path baseline.Documentation
Every shipped item is now reflected in both
docs/developer-guide/*andscripts/initializr/.../skill/references/*:io.asciidoc—Rest.fetchAsJsonList/fetchAsMapped/fetchAsMappedList,JSONWriter,WebSocket.graphics.asciidoc—URLImage.RequestDecorator+setDefaultBearerToken.Animations.asciidoc—MorphTransition.snapshotMode.The-Components-Of-Codename-One.asciidoc— animated tab indicator (in the existing Tabs section).Miscellaneous-Features.asciidoc— modern arc-spinner pull-to-refresh (in the existing Pull to refresh section).Native-Themes.asciidoc— the six new theme constants (3 tabs, 3 pull-to-refresh).appendix_goal_generate_openapi_client.adoc— new Maven goal page.Maven-Appendix-Goals.adoc— wires the new goal into the appendix.skill/references/java-api-subset.md,ui-components.md,build-and-run.md,native-interfaces.md— same coverage as the dev guide, restructured for the agent context.Test plan
mvn -B install -Plocal-dev-javase -DskipTests(full multi-module build) — greenmvn -B test -pl :codenameone-maven-plugin -Dtest=OpenApiCodegenTest— 4 tests, 0 failuresscripts/build-native-themes.sh— both modern themes recompile understrictNoCef=true.classfiles compile cleanlymvn clean compile cn1:compliance-checkBUILD SUCCESS🤖 Generated with Claude Code