mirror of
https://github.com/home-assistant/frontend.git
synced 2025-12-20 02:38:53 +00:00
Attempt to ensure view transitions are always ran (#28547)
This commit is contained in:
@@ -1,30 +1,45 @@
|
|||||||
/**
|
/**
|
||||||
* Executes a callback within a View Transition if supported, otherwise runs it directly.
|
* Executes a synchronous callback within a View Transition if supported, otherwise runs it directly.
|
||||||
*
|
*
|
||||||
* @param callback - Function to execute. Can be synchronous or return a Promise. The callback will be passed a boolean indicating whether the view transition is available.
|
* @param callback - Synchronous function to execute. The callback will be passed a boolean indicating whether the view transition is available.
|
||||||
* @returns Promise that resolves when the transition completes (or immediately if not supported)
|
* @returns Promise that resolves when the transition completes (or immediately if not supported)
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* ```typescript
|
* ```typescript
|
||||||
* // Synchronous callback
|
|
||||||
* withViewTransition(() => {
|
* withViewTransition(() => {
|
||||||
* this.large = !this.large;
|
* this.large = !this.large;
|
||||||
* });
|
* });
|
||||||
*
|
|
||||||
* // Async callback
|
|
||||||
* await withViewTransition(async () => {
|
|
||||||
* await this.updateData();
|
|
||||||
* });
|
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
export const withViewTransition = (
|
export const withViewTransition = (
|
||||||
callback: (viewTransitionAvailable: boolean) => void | Promise<void>
|
callback: (viewTransitionAvailable: boolean) => void
|
||||||
): Promise<void> => {
|
): Promise<void> => {
|
||||||
if (document.startViewTransition) {
|
if (!document.startViewTransition) {
|
||||||
return document.startViewTransition(() => callback(true)).finished;
|
callback(false);
|
||||||
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback: Execute callback directly without transition
|
let callbackInvoked = false;
|
||||||
const result = callback(false);
|
|
||||||
return result instanceof Promise ? result : Promise.resolve();
|
try {
|
||||||
|
// View Transitions require DOM updates to happen synchronously within
|
||||||
|
// the callback. Execute the callback immediately (synchronously).
|
||||||
|
const transition = document.startViewTransition(() => {
|
||||||
|
callbackInvoked = true;
|
||||||
|
callback(true);
|
||||||
|
});
|
||||||
|
return transition.finished;
|
||||||
|
} catch (err) {
|
||||||
|
// eslint-disable-next-line no-console
|
||||||
|
console.warn(
|
||||||
|
"View transition failed, falling back to direct execution.",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
// Make sure the callback is invoked exactly once.
|
||||||
|
if (!callbackInvoked) {
|
||||||
|
callback(false);
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
return Promise.reject(err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user