Skip to content

Conversation

@Artur-
Copy link
Member

@Artur- Artur- commented Nov 12, 2025

Browser details (ExtendedClientDetails) are now automatically fetched
during UI initialization and available immediately in the UI constructor,
eliminating the need for asynchronous callbacks in most cases.

API changes:

  • Page.getExtendedClientDetails(): Now always returns a non-null instance
    (creates placeholder with default values if not yet fetched). Browser
    details are automatically populated during normal UI initialization.

  • ExtendedClientDetails.refresh(Consumer): New method to refresh cached
    browser details with fresh values from the browser. Callback is invoked
    when refresh completes.

  • Page.retrieveExtendedClientDetails(ExtendedClientDetailsReceiver):
    Deprecated. Use getExtendedClientDetails() to access cached details, or
    ExtendedClientDetails.refresh() to update them.

Migration guide:
Before:

    page.retrieveExtendedClientDetails(details -> {
        int width = details.getScreenWidth();
    });

After:

   ExtendedClientDetails details = page.getExtendedClientDetails();
   int width = details.getScreenWidth(); // Available immediately

   // Or refresh if needed:
   details.refresh(updated -> {
       int width = updated.getScreenWidth();
   });

@vaadin vaadin deleted a comment from github-actions bot Nov 12, 2025
@github-actions
Copy link

github-actions bot commented Nov 12, 2025

Test Results

1 291 files  ± 0  1 291 suites  ±0   1h 14m 43s ⏱️ +18s
9 010 tests ± 0  8 943 ✅ + 1  67 💤 ±0  0 ❌ ±0 
9 441 runs   - 22  9 363 ✅  - 21  78 💤 ±0  0 ❌ ±0 

Results for commit 80e1f47. ± Comparison against base commit aebe283.

This pull request removes 1 and adds 1 tests. Note that renamed tests count towards both.
com.vaadin.flow.component.page.PageTest ‑ retrieveExtendedClientDetails_twice_theSecondResultComesDifferentBeforeCachedValueIsSet
com.vaadin.flow.uitest.ui.ExtendedClientDetailsIT ‑ testExtendedClientDetails_availableImmediately[any_Chrome_]

♻️ This comment has been updated with latest results.

@Artur- Artur- force-pushed the flow-eager-browserdetails branch from 5a0a95e to c04b976 Compare November 12, 2025 19:34
@github-actions github-actions bot added +0.1.0 and removed +1.0.0 labels Nov 12, 2025
@Artur- Artur- force-pushed the flow-eager-browserdetails branch from c04b976 to 08c4c51 Compare November 12, 2025 20:10
@Artur- Artur- changed the title refactor: add synchronous getter for ExtendedClientDetails with refresh support feat: eagerly load ExtendedClientDetails during UI initialization Nov 12, 2025
@Artur- Artur- marked this pull request as ready for review November 12, 2025 20:13
@Artur- Artur- force-pushed the flow-eager-browserdetails branch from 08c4c51 to 4dd166d Compare November 12, 2025 20:51
@vaadin vaadin deleted a comment from github-actions bot Nov 12, 2025
@Artur- Artur- force-pushed the flow-eager-browserdetails branch from bbc6348 to 4ea9379 Compare November 13, 2025 17:40
@github-actions github-actions bot added +1.0.0 and removed +0.1.0 labels Nov 13, 2025
@Artur- Artur- marked this pull request as draft November 13, 2025 17:50
Browser details (ExtendedClientDetails) are now automatically fetched
during UI initialization and available immediately in the UI constructor,
eliminating the need for asynchronous callbacks in most cases.

API changes:
- Page.getExtendedClientDetails(): Now always returns a non-null instance
  (creates placeholder with default values if not yet fetched). Browser
  details are automatically populated during normal UI initialization.

- ExtendedClientDetails.refresh(Consumer): New method to refresh cached
  browser details with fresh values from the browser. Callback is invoked
  when refresh completes.

- Page.retrieveExtendedClientDetails(ExtendedClientDetailsReceiver):
  Deprecated. Use getExtendedClientDetails() to access cached details, or
  ExtendedClientDetails.refresh() to update them.

Migration guide:
  Before:
    page.retrieveExtendedClientDetails(details -> {
        int width = details.getScreenWidth();
    });

  After:
    ExtendedClientDetails details = page.getExtendedClientDetails();
    int width = details.getScreenWidth(); // Available immediately

    // Or refresh if needed:
    details.refresh(updated -> {
        int width = updated.getScreenWidth();
    });

Benefits:
- No null checks needed when accessing browser details
- Browser details available immediately in UI constructor/onAttach
- Simpler synchronous API for common use cases
- Full backward compatibility maintained
The browser details collection function getBrowserDetailsParameters was
previously defined in FlowBootstrap.js, which was loaded after the init
request. This caused the function to be undefined when Flow.ts tried to
collect browser details to send with the ?v-r=init request.

This change moves the browser details collection logic from
FlowBootstrap.js into Flow.ts as a private method collectBrowserDetails(),
and registers it as window.Vaadin.Flow.getBrowserDetailsParameters in the
Flow constructor. This ensures the function is available when needed
during the init request, while maintaining backward compatibility for code
that calls the function via the global window object.

The TypeScript implementation uses ($wnd as any) casts to access window
properties like screen, document, navigator, etc., since the $wnd type
doesn't include all browser DOM APIs. Values are stringified before
returning to match the original JavaScript implementation.

Also adds integration test to verify browser details are available
immediately on page load without user interaction.
Browser details are now sent eagerly with the init request, but
getExtendedClientDetails() could still return null before the data
arrives. This changes the API to always return a non-null instance,
using a placeholder with default values (screenWidth = -1, windowName
= null) until actual browser details are available.

For PreserveOnRefresh functionality, the code now checks if windowName
is null rather than checking if the entire ExtendedClientDetails object
is null. This is necessary because:
- Screen dimensions are always sent with the init request
- But window.name may be empty/undefined in new browser windows
- This causes windowName = null even when other details are present
- Different windows with windowName = null would incorrectly share
  cached components

Changes:
- Made ExtendedClientDetails constructor public (marked as internal-only)
- UIInternals.getExtendedClientDetails() creates placeholder if null
- Page.getExtendedClientDetails() simplified to delegate to UIInternals
- Page.retrieveExtendedClientDetails() checks screenWidth == -1
- AbstractNavigationStateRenderer: Changed 3 locations to check
  windowName == null instead of details == null
- WebComponentUI: Changed to check windowName == null

This fixes PreserveOnRefreshIT.refreshInDifferentWindow_componentIsRecreated
test failure where components were incorrectly preserved across different
browser windows due to cache key collisions.
@Artur- Artur- marked this pull request as ready for review November 14, 2025 06:53
@Artur- Artur- force-pushed the flow-eager-browserdetails branch from 4ea9379 to 992063d Compare November 14, 2025 06:53
@github-actions github-actions bot added +0.1.0 and removed +1.0.0 labels Nov 14, 2025
@Artur- Artur- requested review from Legioth and caalador November 14, 2025 12:43
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants