Skip to content

Commit f98fc5b

Browse files
committed
fix(android): let setDarkModeHandler and bar color setters replace values
Utils.android.setDarkModeHandler() kept the first handler it was given and ignored later ones, and setStatusBarColor() and setNavigationBarColor() never changed a color at all: they assigned with `??=` onto settings that always start with default colors. All three also stored the settings under the current activity rather than the one passed in, so refreshEdgeToEdge() on that activity lost them. The setters now replace the handler and the colors they are given, keep the colors they are not, and store the settings under the activity they were given.
1 parent 1a701b9 commit f98fc5b

2 files changed

Lines changed: 78 additions & 8 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2+
3+
import { Color } from '../color';
4+
import { setDarkModeHandler, setNavigationBarColor, setStatusBarColor, refreshEdgeToEdge } from './native-helper-for-android';
5+
6+
describe('Android edge-to-edge setters', () => {
7+
let globals: Record<string, any>;
8+
let enableEdgeToEdge: ReturnType<typeof vi.fn>;
9+
10+
class HandleDarkMode {
11+
constructor(readonly implementation: { onHandle(bar: number, resources: any): boolean }) {}
12+
}
13+
14+
beforeEach(() => {
15+
globals = { android: (global as any).android, org: (global as any).org, java: (global as any).java };
16+
enableEdgeToEdge = vi.fn();
17+
(global as any).android = { ...globals.android, view: { ...globals.android?.view, Window: class Window {} } };
18+
(global as any).org = { nativescript: { widgets: { Utils: { enableEdgeToEdge, HandleDarkMode } } } };
19+
(global as any).java = { lang: { Integer: { valueOf: (value: number) => value } } };
20+
});
21+
22+
afterEach(() => {
23+
Object.assign(global, globals);
24+
});
25+
26+
/** The dark mode handler last passed to the native enableEdgeToEdge, as a JS function. */
27+
function lastHandler(): (bar: number) => boolean {
28+
const args = enableEdgeToEdge.mock.calls.at(-1);
29+
const handler = args.at(-1);
30+
return handler instanceof HandleDarkMode ? (bar) => handler.implementation.onHandle(bar, null) : null;
31+
}
32+
33+
function lastColors(): number[] {
34+
return enableEdgeToEdge.mock.calls.at(-1).slice(1, 5);
35+
}
36+
37+
it('uses the latest dark mode handler', () => {
38+
const activity = {} as any;
39+
40+
setDarkModeHandler({ activity, handler: () => false });
41+
setDarkModeHandler({ activity, handler: () => true });
42+
expect(lastHandler()(0)).toBe(true);
43+
44+
refreshEdgeToEdge(activity);
45+
expect(lastHandler()(0)).toBe(true);
46+
});
47+
48+
it('keeps the settings of the activity it was given', () => {
49+
const activity = {} as any;
50+
51+
setStatusBarColor({ activity, lightColor: new Color('#ff0000') });
52+
setNavigationBarColor({ activity, darkColor: new Color('#0000ff') });
53+
refreshEdgeToEdge(activity);
54+
55+
const [statusBarLight, , , navigationBarDark] = lastColors();
56+
expect(statusBarLight).toBe(new Color('#ff0000').android);
57+
expect(navigationBarDark).toBe(new Color('#0000ff').android);
58+
});
59+
60+
it('replaces colors set before and keeps the ones not given', () => {
61+
const activity = {} as any;
62+
63+
setStatusBarColor({ activity, lightColor: new Color('#ff0000'), darkColor: new Color('#00ff00') });
64+
setStatusBarColor({ activity, lightColor: new Color('#0000ff') });
65+
66+
const [statusBarLight, statusBarDark] = lastColors();
67+
expect(statusBarLight).toBe(new Color('#0000ff').android);
68+
expect(statusBarDark).toBe(new Color('#00ff00').android);
69+
});
70+
});

‎packages/core/utils/native-helper-for-android.ts‎

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,9 @@ export function setStatusBarColor(options?: { activity?: androidx.appcompat.app.
344344
statusBarLight: DefaultStatusBarLight,
345345
statusBarDark: DefaultStatusBarDark,
346346
};
347-
existingColors.statusBarLight ??= statusBarLightColor;
348-
existingColors.statusBarDark ??= statusBarDarkColor;
349-
systemColors.set(getCurrentActivity(), existingColors);
347+
existingColors.statusBarLight = statusBarLightColor ?? existingColors.statusBarLight;
348+
existingColors.statusBarDark = statusBarDarkColor ?? existingColors.statusBarDark;
349+
systemColors.set(activity, existingColors);
350350

351351
setEnableEdgeToEdge(activity, existingColors);
352352
}
@@ -363,9 +363,9 @@ export function setNavigationBarColor(options?: { activity?: androidx.appcompat.
363363
statusBarLight: DefaultStatusBarLight,
364364
statusBarDark: DefaultStatusBarDark,
365365
};
366-
existingColors.navigationBarLight ??= navigationBarLightColor;
367-
existingColors.navigationBarDark ??= navigationBarDarkColor;
368-
systemColors.set(getCurrentActivity(), existingColors);
366+
existingColors.navigationBarLight = navigationBarLightColor ?? existingColors.navigationBarLight;
367+
existingColors.navigationBarDark = navigationBarDarkColor ?? existingColors.navigationBarDark;
368+
systemColors.set(activity, existingColors);
369369

370370
setEnableEdgeToEdge(activity, existingColors);
371371
}
@@ -382,9 +382,9 @@ export function setDarkModeHandler(options?: { activity?: androidx.appcompat.app
382382
statusBarDark: DefaultStatusBarDark,
383383
};
384384

385-
existingColors.handler ??= darkModeHandler;
385+
existingColors.handler = darkModeHandler;
386386

387-
systemColors.set(getCurrentActivity(), existingColors);
387+
systemColors.set(activity, existingColors);
388388

389389
setEnableEdgeToEdge(activity, existingColors);
390390
}

0 commit comments

Comments
 (0)