Files
paseo/patches/react-native-unistyles+3.2.4.patch
T
946b6e58fd Keep transcript colors in sync after a hidden theme change (#8199)
* fix(app): preserve adaptive theme events while hidden

Read the current scheme through fresh matchMedia lists so hidden runtime
reads do not consume the pending events on listener-owned lists.

Carry Dan Sabin's fix from #7172 into the current combined Unistyles patch,
and cover both transition directions with a real Electron regression in
the existing desktop browser suite.

Co-authored-by: Dan Sabin <dan@freethinking.it>

* test(desktop): run adaptive theme regression on Linux

Electron retains --no-sandbox in argv, so the positional lookup used the script filename as the artifact directory. Read the final argument so the same real Electron regression exercises Linux as well as macOS.

Co-authored-by: Nurşat Bülbül <85260051+Nurshot@users.noreply.github.com>
Co-authored-by: Dan Sabin <dan@freethinking.it>

---------

Co-authored-by: Nurshot <85260051+Nurshot@users.noreply.github.com>
Co-authored-by: Dan Sabin <dan@freethinking.it>
Co-authored-by: paseo-bot[bot] <266920839+paseo-bot[bot]@users.noreply.github.com>
2026-10-29 11:16:48 +00:00

560 lines
25 KiB
Diff

diff --git a/node_modules/react-native-unistyles/lib/commonjs/web/registry.js b/node_modules/react-native-unistyles/lib/commonjs/web/registry.js
index 120ff60..d1ff102 100644
--- a/node_modules/react-native-unistyles/lib/commonjs/web/registry.js
+++ b/node_modules/react-native-unistyles/lib/commonjs/web/registry.js
@@ -10,6 +10,17 @@ class UnistylesRegistry {
stylesheets = new Map();
stylesCache = new Set();
stylesCounter = new Map();
+ cleanupGeneration = 0;
+ finalizerTokens = new WeakMap();
+ finalizationRegistry = typeof FinalizationRegistry === 'undefined' ? undefined : new FinalizationRegistry(({
+ hash,
+ generation
+ }) => {
+ if (generation !== this.cleanupGeneration) {
+ return;
+ }
+ this.decrementAndMaybeCleanup(hash);
+ });
disposeListenersMap = new Map();
dependenciesMap = new Map();
constructor(services) {
@@ -50,26 +61,48 @@ class UnistylesRegistry {
this.disposeListenersMap.set(stylesheet, dispose);
};
connect = (ref, hash) => {
- const stylesCounter = this.stylesCounter.get(hash) ?? new Set();
- stylesCounter.add(ref);
- this.stylesCounter.set(hash, stylesCounter);
+ this.stylesCounter.set(hash, (this.stylesCounter.get(hash) ?? 0) + 1);
+ if (!this.finalizationRegistry) {
+ return;
+ }
+ const token = {};
+ const tokensByHash = this.finalizerTokens.get(ref) ?? new Map();
+ const tokens = tokensByHash.get(hash) ?? [];
+ tokens.push(token);
+ tokensByHash.set(hash, tokens);
+ this.finalizerTokens.set(ref, tokensByHash);
+ this.finalizationRegistry.register(ref, {
+ hash,
+ generation: this.cleanupGeneration
+ }, token);
};
remove = (ref, hash) => {
- const stylesCounter = this.stylesCounter.get(hash) ?? new Set();
- stylesCounter.delete(ref);
- if (stylesCounter.size === 0) {
- // Move this to the end of the event loop so the element is removed from the DOM
- return Promise.resolve().then(() => {
- // Check if element is still in the DOM
- if (document.querySelector(`.${hash}`)) {
- return false;
- }
- this.css.remove(hash);
- this.stylesCache.delete(hash);
- return true;
- });
+ const token = this.finalizerTokens.get(ref)?.get(hash)?.pop();
+ if (token) {
+ this.finalizationRegistry?.unregister(token);
+ }
+ return this.decrementAndMaybeCleanup(hash);
+ };
+ decrementAndMaybeCleanup = hash => {
+ const next = (this.stylesCounter.get(hash) ?? 0) - 1;
+ if (next > 0) {
+ this.stylesCounter.set(hash, next);
+ return Promise.resolve(false);
}
- return Promise.resolve(false);
+ this.stylesCounter.delete(hash);
+ // Move this to the end of the event loop so the element is removed from the DOM
+ return Promise.resolve().then(() => {
+ // Check if element is still in the DOM
+ if ((this.stylesCounter.get(hash) ?? 0) > 0) {
+ return false;
+ }
+ if (document.querySelector(`.${hash}`)) {
+ return false;
+ }
+ this.css.remove(hash);
+ this.stylesCache.delete(hash);
+ return true;
+ });
};
add = (value, forChild) => {
const generatedHash = (0, _utils.generateHash)(value);
@@ -91,7 +124,10 @@ class UnistylesRegistry {
this.css.add(hash, value);
};
reset = () => {
+ this.cleanupGeneration += 1;
+ this.disposeListenersMap.forEach(dispose => dispose());
this.css.reset();
+ this.stylesheets.clear();
this.stylesCache.clear();
this.dependenciesMap.clear();
this.disposeListenersMap.clear();
diff --git a/node_modules/react-native-unistyles/lib/module/web/registry.js b/node_modules/react-native-unistyles/lib/module/web/registry.js
index 6362f43..8e769f8 100644
--- a/node_modules/react-native-unistyles/lib/module/web/registry.js
+++ b/node_modules/react-native-unistyles/lib/module/web/registry.js
@@ -6,6 +6,17 @@ export class UnistylesRegistry {
stylesheets = new Map();
stylesCache = new Set();
stylesCounter = new Map();
+ cleanupGeneration = 0;
+ finalizerTokens = new WeakMap();
+ finalizationRegistry = typeof FinalizationRegistry === 'undefined' ? undefined : new FinalizationRegistry(({
+ hash,
+ generation
+ }) => {
+ if (generation !== this.cleanupGeneration) {
+ return;
+ }
+ this.decrementAndMaybeCleanup(hash);
+ });
disposeListenersMap = new Map();
dependenciesMap = new Map();
constructor(services) {
@@ -46,26 +57,48 @@ export class UnistylesRegistry {
this.disposeListenersMap.set(stylesheet, dispose);
};
connect = (ref, hash) => {
- const stylesCounter = this.stylesCounter.get(hash) ?? new Set();
- stylesCounter.add(ref);
- this.stylesCounter.set(hash, stylesCounter);
+ this.stylesCounter.set(hash, (this.stylesCounter.get(hash) ?? 0) + 1);
+ if (!this.finalizationRegistry) {
+ return;
+ }
+ const token = {};
+ const tokensByHash = this.finalizerTokens.get(ref) ?? new Map();
+ const tokens = tokensByHash.get(hash) ?? [];
+ tokens.push(token);
+ tokensByHash.set(hash, tokens);
+ this.finalizerTokens.set(ref, tokensByHash);
+ this.finalizationRegistry.register(ref, {
+ hash,
+ generation: this.cleanupGeneration
+ }, token);
};
remove = (ref, hash) => {
- const stylesCounter = this.stylesCounter.get(hash) ?? new Set();
- stylesCounter.delete(ref);
- if (stylesCounter.size === 0) {
- // Move this to the end of the event loop so the element is removed from the DOM
- return Promise.resolve().then(() => {
- // Check if element is still in the DOM
- if (document.querySelector(`.${hash}`)) {
- return false;
- }
- this.css.remove(hash);
- this.stylesCache.delete(hash);
- return true;
- });
+ const token = this.finalizerTokens.get(ref)?.get(hash)?.pop();
+ if (token) {
+ this.finalizationRegistry?.unregister(token);
+ }
+ return this.decrementAndMaybeCleanup(hash);
+ };
+ decrementAndMaybeCleanup = hash => {
+ const next = (this.stylesCounter.get(hash) ?? 0) - 1;
+ if (next > 0) {
+ this.stylesCounter.set(hash, next);
+ return Promise.resolve(false);
}
- return Promise.resolve(false);
+ this.stylesCounter.delete(hash);
+ // Move this to the end of the event loop so the element is removed from the DOM
+ return Promise.resolve().then(() => {
+ // Check if element is still in the DOM
+ if ((this.stylesCounter.get(hash) ?? 0) > 0) {
+ return false;
+ }
+ if (document.querySelector(`.${hash}`)) {
+ return false;
+ }
+ this.css.remove(hash);
+ this.stylesCache.delete(hash);
+ return true;
+ });
};
add = (value, forChild) => {
const generatedHash = generateHash(value);
@@ -87,7 +120,10 @@ export class UnistylesRegistry {
this.css.add(hash, value);
};
reset = () => {
+ this.cleanupGeneration += 1;
+ this.disposeListenersMap.forEach(dispose => dispose());
this.css.reset();
+ this.stylesheets.clear();
this.stylesCache.clear();
this.dependenciesMap.clear();
this.disposeListenersMap.clear();
diff --git a/node_modules/react-native-unistyles/src/web/registry.ts b/node_modules/react-native-unistyles/src/web/registry.ts
index 39e0d9d..a21ba95 100644
--- a/node_modules/react-native-unistyles/src/web/registry.ts
+++ b/node_modules/react-native-unistyles/src/web/registry.ts
@@ -9,7 +9,24 @@ import { error, extractUnistyleDependencies, generateHash } from './utils'
export class UnistylesRegistry {
private readonly stylesheets = new Map<StyleSheetWithSuperPowers<StyleSheet>, StyleSheet>()
private readonly stylesCache = new Set<string>()
- private readonly stylesCounter = new Map<string, Set<HTMLElement>>()
+ // Use counter instead of Set<HTMLElement> to avoid retaining detached DOM nodes
+ // FR is a fallback when remove() is missed
+ private readonly stylesCounter = new Map<string, number>()
+ // Bumped on reset() so stale FR callbacks are ignored
+ private cleanupGeneration = 0
+ // Per-registration unregister token, so remove() cancels only its own registration
+ private readonly finalizerTokens = new WeakMap<HTMLElement, Map<string, Array<object>>>()
+ // FR isn't available on every runtime - fall back to counter-only cleanup
+ private readonly finalizationRegistry =
+ typeof FinalizationRegistry === 'undefined'
+ ? undefined
+ : new FinalizationRegistry<{ hash: string; generation: number }>(({ hash, generation }) => {
+ if (generation !== this.cleanupGeneration) {
+ return
+ }
+
+ this.decrementAndMaybeCleanup(hash)
+ })
private readonly disposeListenersMap = new Map<object, VoidFunction>()
private readonly dependenciesMap = new Map<StyleSheetWithSuperPowers<StyleSheet>, Set<UnistyleDependency>>()
readonly css: CSSState
@@ -78,33 +95,61 @@ export class UnistylesRegistry {
}
connect = (ref: HTMLElement, hash: string) => {
- const stylesCounter = this.stylesCounter.get(hash) ?? new Set()
+ this.stylesCounter.set(hash, (this.stylesCounter.get(hash) ?? 0) + 1)
- stylesCounter.add(ref)
- this.stylesCounter.set(hash, stylesCounter)
+ if (!this.finalizationRegistry) {
+ return
+ }
+
+ const token = {}
+ const tokensByHash = this.finalizerTokens.get(ref) ?? new Map<string, Array<object>>()
+ const tokens = tokensByHash.get(hash) ?? []
+
+ tokens.push(token)
+ tokensByHash.set(hash, tokens)
+ this.finalizerTokens.set(ref, tokensByHash)
+ this.finalizationRegistry.register(ref, { hash, generation: this.cleanupGeneration }, token)
}
remove = (ref: HTMLElement, hash: string) => {
- const stylesCounter = this.stylesCounter.get(hash) ?? new Set()
+ const token = this.finalizerTokens.get(ref)?.get(hash)?.pop()
- stylesCounter.delete(ref)
+ if (token) {
+ this.finalizationRegistry?.unregister(token)
+ }
- if (stylesCounter.size === 0) {
- // Move this to the end of the event loop so the element is removed from the DOM
- return Promise.resolve().then(() => {
- // Check if element is still in the DOM
- if (document.querySelector(`.${hash}`)) {
- return false
- }
+ return this.decrementAndMaybeCleanup(hash)
+ }
+
+ private decrementAndMaybeCleanup = (hash: string): Promise<boolean> => {
+ const next = (this.stylesCounter.get(hash) ?? 0) - 1
- this.css.remove(hash)
- this.stylesCache.delete(hash)
+ if (next > 0) {
+ this.stylesCounter.set(hash, next)
- return true
- })
+ return Promise.resolve(false)
}
- return Promise.resolve(false)
+ // Drop the empty bucket from the Map
+ this.stylesCounter.delete(hash)
+
+ // Move this to the end of the event loop so the element is removed from the DOM
+ return Promise.resolve().then(() => {
+ // New connect raced in during the microtask
+ if ((this.stylesCounter.get(hash) ?? 0) > 0) {
+ return false
+ }
+
+ // Check if element is still in the DOM
+ if (document.querySelector(`.${hash}`)) {
+ return false
+ }
+
+ this.css.remove(hash)
+ this.stylesCache.delete(hash)
+
+ return true
+ })
}
add = (value: UnistylesValues, forChild?: boolean) => {
@@ -126,7 +171,11 @@ export class UnistylesRegistry {
}
reset = () => {
+ // Invalidate pending FR callbacks from this generation
+ this.cleanupGeneration += 1
+ this.disposeListenersMap.forEach((dispose) => dispose())
this.css.reset()
+ this.stylesheets.clear()
this.stylesCache.clear()
this.dependenciesMap.clear()
this.disposeListenersMap.clear()
diff --git a/node_modules/react-native-unistyles/android/build.gradle b/node_modules/react-native-unistyles/android/build.gradle
index 195954b..c4ac28c 100644
--- a/node_modules/react-native-unistyles/android/build.gradle
+++ b/node_modules/react-native-unistyles/android/build.gradle
@@ -38,6 +38,7 @@ if (isNewArchitectureEnabled()) {
android {
compileSdkVersion safeExtGet('compileSdkVersion', 35)
+ ndkVersion safeExtGet('ndkVersion', '27.1.12297006')
namespace "com.unistyles"
defaultConfig {
diff --git a/node_modules/react-native-unistyles/src/core/withUnistyles/withUnistyles.tsx b/node_modules/react-native-unistyles/src/core/withUnistyles/withUnistyles.tsx
--- a/node_modules/react-native-unistyles/src/core/withUnistyles/withUnistyles.tsx
+++ b/node_modules/react-native-unistyles/src/core/withUnistyles/withUnistyles.tsx
@@ -28,13 +28,14 @@
return forwardRef<GenericComponentRef<TComponent>, PropsWithUnistyles>((props, ref) => {
const narrowedProps = props as PropsWithUnistyles & UnistyleStyles
+ const { uniProps, ...componentProps } = narrowedProps
const styleClassNames = getClassName(narrowedProps.style, true)
const contentContainerStyleClassNames = getClassName(narrowedProps.contentContainerStyle)
const { proxifiedRuntime, proxifiedTheme } = useProxifiedUnistyles()
const { key: mappingsKey, ...mappingsProps } = mappings ? mappings(proxifiedTheme, proxifiedRuntime) : {}
- const { key: uniPropsKey, ...unistyleProps } = narrowedProps.uniProps
- ? narrowedProps.uniProps(proxifiedTheme, proxifiedRuntime)
+ const { key: uniPropsKey, ...unistyleProps } = uniProps
+ ? uniProps(proxifiedTheme, proxifiedRuntime)
: {}
const emptyStyles = narrowedProps.style
@@ -46,7 +47,7 @@
: undefined
const combinedProps = {
- ...deepMergeObjects(mappingsProps, unistyleProps, props),
+ ...deepMergeObjects(mappingsProps, unistyleProps, componentProps),
...(narrowedProps.style
? {
// Override default component styles with undefined values to reset them
diff --git a/node_modules/react-native-unistyles/src/core/withUnistyles/withUnistyles.native.tsx b/node_modules/react-native-unistyles/src/core/withUnistyles/withUnistyles.native.tsx
--- a/node_modules/react-native-unistyles/src/core/withUnistyles/withUnistyles.native.tsx
+++ b/node_modules/react-native-unistyles/src/core/withUnistyles/withUnistyles.native.tsx
@@ -63,6 +63,7 @@
return forwardRef<GenericComponentRef<TComponent>, PropsWithUnistyles>((props, ref) => {
const narrowedProps = props as PropsWithUnistyles & UnistyleStyles
+ const { uniProps, ...componentProps } = narrowedProps
const NativeComponent = Component as ComponentType
// @ts-ignore we don't know the type of the component
@@ -89,15 +90,15 @@
}, [narrowedProps.style, narrowedProps.contentContainerStyle])
const { key: mappingsKey, ...mappingsProps } = mappings ? mappings(proxifiedTheme, proxifiedRuntime) : {}
- const { key: uniPropsKey, ...unistyleProps } = narrowedProps.uniProps
- ? narrowedProps.uniProps(proxifiedTheme, proxifiedRuntime)
+ const { key: uniPropsKey, ...unistyleProps } = uniProps
+ ? uniProps(proxifiedTheme, proxifiedRuntime)
: {}
const styleSecrets = getSecrets(narrowedProps.style)
const contentContainerStyleSecrets = getSecrets(narrowedProps.contentContainerStyle)
const finalProps = {
- ...deepMergeObjects(mappingsProps, unistyleProps, props),
+ ...deepMergeObjects(mappingsProps, unistyleProps, componentProps),
...(narrowedProps.style
? {
style: styleSecrets.styles,
diff --git a/node_modules/react-native-unistyles/lib/module/core/withUnistyles/withUnistyles.js b/node_modules/react-native-unistyles/lib/module/core/withUnistyles/withUnistyles.js
--- a/node_modules/react-native-unistyles/lib/module/core/withUnistyles/withUnistyles.js
+++ b/node_modules/react-native-unistyles/lib/module/core/withUnistyles/withUnistyles.js
@@ -13,6 +13,7 @@
export const withUnistyles = (Component, mappings) => {
return /*#__PURE__*/forwardRef((props, ref) => {
const narrowedProps = props;
+ const { uniProps, ...componentProps } = narrowedProps;
const styleClassNames = getClassName(narrowedProps.style, true);
const contentContainerStyleClassNames = getClassName(narrowedProps.contentContainerStyle);
const {
@@ -26,10 +27,10 @@
const {
key: uniPropsKey,
...unistyleProps
- } = narrowedProps.uniProps ? narrowedProps.uniProps(proxifiedTheme, proxifiedRuntime) : {};
+ } = uniProps ? uniProps(proxifiedTheme, proxifiedRuntime) : {};
const emptyStyles = narrowedProps.style ? Object.fromEntries(Object.entries(Object.getOwnPropertyDescriptors(narrowedProps.style)).filter(([key]) => !key.startsWith('unistyles') && !key.startsWith('_')).map(([key]) => [key, undefined])) : undefined;
const combinedProps = {
- ...deepMergeObjects(mappingsProps, unistyleProps, props),
+ ...deepMergeObjects(mappingsProps, unistyleProps, componentProps),
...(narrowedProps.style ? {
// Override default component styles with undefined values to reset them
style: emptyStyles
diff --git a/node_modules/react-native-unistyles/lib/module/core/withUnistyles/withUnistyles.native.js b/node_modules/react-native-unistyles/lib/module/core/withUnistyles/withUnistyles.native.js
--- a/node_modules/react-native-unistyles/lib/module/core/withUnistyles/withUnistyles.native.js
+++ b/node_modules/react-native-unistyles/lib/module/core/withUnistyles/withUnistyles.native.js
@@ -27,6 +27,7 @@
};
return /*#__PURE__*/forwardRef((props, ref) => {
const narrowedProps = props;
+ const { uniProps, ...componentProps } = narrowedProps;
const NativeComponent = Component;
// @ts-ignore we don't know the type of the component
@@ -57,11 +58,11 @@
const {
key: uniPropsKey,
...unistyleProps
- } = narrowedProps.uniProps ? narrowedProps.uniProps(proxifiedTheme, proxifiedRuntime) : {};
+ } = uniProps ? uniProps(proxifiedTheme, proxifiedRuntime) : {};
const styleSecrets = getSecrets(narrowedProps.style);
const contentContainerStyleSecrets = getSecrets(narrowedProps.contentContainerStyle);
const finalProps = {
- ...deepMergeObjects(mappingsProps, unistyleProps, props),
+ ...deepMergeObjects(mappingsProps, unistyleProps, componentProps),
...(narrowedProps.style ? {
style: styleSecrets.styles
} : {}),
diff --git a/node_modules/react-native-unistyles/lib/commonjs/core/withUnistyles/withUnistyles.js b/node_modules/react-native-unistyles/lib/commonjs/core/withUnistyles/withUnistyles.js
--- a/node_modules/react-native-unistyles/lib/commonjs/core/withUnistyles/withUnistyles.js
+++ b/node_modules/react-native-unistyles/lib/commonjs/core/withUnistyles/withUnistyles.js
@@ -18,6 +18,7 @@
const withUnistyles = (Component, mappings) => {
return /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
const narrowedProps = props;
+ const { uniProps, ...componentProps } = narrowedProps;
const styleClassNames = (0, _getClassname.getClassName)(narrowedProps.style, true);
const contentContainerStyleClassNames = (0, _getClassname.getClassName)(narrowedProps.contentContainerStyle);
const {
@@ -31,10 +32,10 @@
const {
key: uniPropsKey,
...unistyleProps
- } = narrowedProps.uniProps ? narrowedProps.uniProps(proxifiedTheme, proxifiedRuntime) : {};
+ } = uniProps ? uniProps(proxifiedTheme, proxifiedRuntime) : {};
const emptyStyles = narrowedProps.style ? Object.fromEntries(Object.entries(Object.getOwnPropertyDescriptors(narrowedProps.style)).filter(([key]) => !key.startsWith('unistyles') && !key.startsWith('_')).map(([key]) => [key, undefined])) : undefined;
const combinedProps = {
- ...(0, _utils.deepMergeObjects)(mappingsProps, unistyleProps, props),
+ ...(0, _utils.deepMergeObjects)(mappingsProps, unistyleProps, componentProps),
...(narrowedProps.style ? {
// Override default component styles with undefined values to reset them
style: emptyStyles
diff --git a/node_modules/react-native-unistyles/lib/commonjs/core/withUnistyles/withUnistyles.native.js b/node_modules/react-native-unistyles/lib/commonjs/core/withUnistyles/withUnistyles.native.js
--- a/node_modules/react-native-unistyles/lib/commonjs/core/withUnistyles/withUnistyles.native.js
+++ b/node_modules/react-native-unistyles/lib/commonjs/core/withUnistyles/withUnistyles.native.js
@@ -32,6 +32,7 @@
};
return /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
const narrowedProps = props;
+ const { uniProps, ...componentProps } = narrowedProps;
const NativeComponent = Component;
// @ts-ignore we don't know the type of the component
@@ -62,11 +63,11 @@
const {
key: uniPropsKey,
...unistyleProps
- } = narrowedProps.uniProps ? narrowedProps.uniProps(proxifiedTheme, proxifiedRuntime) : {};
+ } = uniProps ? uniProps(proxifiedTheme, proxifiedRuntime) : {};
const styleSecrets = getSecrets(narrowedProps.style);
const contentContainerStyleSecrets = getSecrets(narrowedProps.contentContainerStyle);
const finalProps = {
- ...(0, _utils.deepMergeObjects)(mappingsProps, unistyleProps, props),
+ ...(0, _utils.deepMergeObjects)(mappingsProps, unistyleProps, componentProps),
...(narrowedProps.style ? {
style: styleSecrets.styles
} : {}),
diff --git a/node_modules/react-native-unistyles/lib/commonjs/web/runtime.js b/node_modules/react-native-unistyles/lib/commonjs/web/runtime.js
index 305fa49..5957aa5 100644
--- a/node_modules/react-native-unistyles/lib/commonjs/web/runtime.js
+++ b/node_modules/react-native-unistyles/lib/commonjs/web/runtime.js
@@ -35,10 +35,17 @@ class UnistylesRuntime {
return this.darkMedia;
}
get colorScheme() {
+ // Read the scheme through fresh lists, never through lightMedia/darkMedia. Chromium defers
+ // MediaQueryList change events while the document is hidden and drops the pending event
+ // of any list whose `matches` was read before the document became visible again, which
+ // would silence the adaptive-theme listeners registered on those two lists.
+ if ((0, _utils.isServer)()) {
+ return _types.ColorScheme.Unspecified;
+ }
switch (true) {
- case this.getLightMedia()?.matches:
+ case window.matchMedia('(prefers-color-scheme: light)').matches:
return _types.ColorScheme.Light;
- case this.getDarkMedia()?.matches:
+ case window.matchMedia('(prefers-color-scheme: dark)').matches:
return _types.ColorScheme.Dark;
default:
return _types.ColorScheme.Unspecified;
diff --git a/node_modules/react-native-unistyles/lib/module/web/runtime.js b/node_modules/react-native-unistyles/lib/module/web/runtime.js
index 7f13a06..c487bee 100644
--- a/node_modules/react-native-unistyles/lib/module/web/runtime.js
+++ b/node_modules/react-native-unistyles/lib/module/web/runtime.js
@@ -31,10 +31,17 @@ export class UnistylesRuntime {
return this.darkMedia;
}
get colorScheme() {
+ // Read the scheme through fresh lists, never through lightMedia/darkMedia. Chromium defers
+ // MediaQueryList change events while the document is hidden and drops the pending event
+ // of any list whose `matches` was read before the document became visible again, which
+ // would silence the adaptive-theme listeners registered on those two lists.
+ if (isServer()) {
+ return ColorScheme.Unspecified;
+ }
switch (true) {
- case this.getLightMedia()?.matches:
+ case window.matchMedia('(prefers-color-scheme: light)').matches:
return ColorScheme.Light;
- case this.getDarkMedia()?.matches:
+ case window.matchMedia('(prefers-color-scheme: dark)').matches:
return ColorScheme.Dark;
default:
return ColorScheme.Unspecified;
diff --git a/node_modules/react-native-unistyles/src/web/runtime.ts b/node_modules/react-native-unistyles/src/web/runtime.ts
index a16dac0..6519858 100644
--- a/node_modules/react-native-unistyles/src/web/runtime.ts
+++ b/node_modules/react-native-unistyles/src/web/runtime.ts
@@ -41,8 +41,16 @@ export class UnistylesRuntime {
get colorScheme() {
+ // Read the scheme through fresh lists, never through lightMedia/darkMedia. Chromium defers
+ // MediaQueryList change events while the document is hidden and drops the pending event
+ // of any list whose `matches` was read before the document became visible again, which
+ // would silence the adaptive-theme listeners registered on those two lists.
+ if (isServer()) {
+ return ColorScheme.Unspecified
+ }
+
switch (true) {
- case this.getLightMedia()?.matches:
+ case window.matchMedia('(prefers-color-scheme: light)').matches:
return ColorScheme.Light
- case this.getDarkMedia()?.matches:
+ case window.matchMedia('(prefers-color-scheme: dark)').matches:
return ColorScheme.Dark
default:
return ColorScheme.Unspecified