Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit fa7505e

Browse files
committed
Significantly reduce work of useUserOnboardingContext
1 parent aa9191b commit fa7505e

File tree

2 files changed

+68
-40
lines changed

2 files changed

+68
-40
lines changed

src/hooks/useUserOnboardingContext.ts

+62-30
Original file line numberDiff line numberDiff line change
@@ -15,54 +15,86 @@ limitations under the License.
1515
*/
1616

1717
import { logger } from "matrix-js-sdk/src/logger";
18-
import { ClientEvent, IMyDevice, Room } from "matrix-js-sdk/src/matrix";
19-
import { useCallback, useEffect, useState } from "react";
18+
import { ClientEvent } from "matrix-js-sdk/src/matrix";
19+
import { useCallback, useEffect, useRef, useState } from "react";
2020

2121
import { MatrixClientPeg } from "../MatrixClientPeg";
22+
import { Notifier } from "../Notifier";
2223
import DMRoomMap from "../utils/DMRoomMap";
23-
import { useEventEmitter } from "./useEventEmitter";
2424

2525
export interface UserOnboardingContext {
26-
avatar: string | null;
27-
myDevice: string;
28-
devices: IMyDevice[];
29-
dmRooms: {[userId: string]: Room};
26+
hasAvatar: boolean;
27+
hasDevices: boolean;
28+
hasDmRooms: boolean;
29+
hasNotificationsEnabled: boolean;
30+
}
31+
32+
const USER_ONBOARDING_CONTEXT_INTERVAL = 5000;
33+
34+
function useRefOf<T extends [], R>(value: (...values: T) => R): (...values: T) => R {
35+
const ref = useRef(value);
36+
ref.current = value;
37+
return useCallback(
38+
(...values: T) => ref.current(...values),
39+
[],
40+
);
3041
}
3142

3243
export function useUserOnboardingContext(): UserOnboardingContext | null {
3344
const [context, setContext] = useState<UserOnboardingContext | null>(null);
3445

3546
const cli = MatrixClientPeg.get();
36-
const handler = useCallback(async () => {
37-
try {
38-
const profile = await cli.getProfileInfo(cli.getUserId());
39-
40-
const myDevice = cli.getDeviceId();
41-
const devices = await cli.getDevices();
42-
43-
const dmRooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals() ?? {};
44-
setContext({
45-
avatar: profile?.avatar_url ?? null,
46-
myDevice,
47-
devices: devices.devices,
48-
dmRooms: dmRooms,
49-
});
50-
} catch (e) {
51-
logger.warn("Could not load context for user onboarding task list: ", e);
52-
setContext(null);
53-
}
54-
}, [cli]);
55-
56-
useEventEmitter(cli, ClientEvent.AccountData, handler);
47+
const handler = useRefOf(
48+
useCallback(async () => {
49+
try {
50+
let hasAvatar = context?.hasAvatar;
51+
if (!hasAvatar) {
52+
const profile = await cli.getProfileInfo(cli.getUserId());
53+
hasAvatar = Boolean(profile?.avatar_url);
54+
}
55+
56+
let hasDevices = context?.hasDevices;
57+
if (!hasDevices) {
58+
const myDevice = cli.getDeviceId();
59+
const devices = await cli.getDevices();
60+
hasDevices = Boolean(devices.devices.find(device => device.device_id !== myDevice));
61+
}
62+
63+
let hasDmRooms = context?.hasDmRooms;
64+
if (!hasDmRooms) {
65+
const dmRooms = DMRoomMap.shared().getUniqueRoomsWithIndividuals() ?? {};
66+
hasDmRooms = Boolean(Object.keys(dmRooms).length);
67+
}
68+
69+
let hasNotificationsEnabled = context?.hasNotificationsEnabled;
70+
if (!hasNotificationsEnabled) {
71+
hasNotificationsEnabled = Notifier.isPossible();
72+
}
73+
74+
if (hasAvatar !== context?.hasAvatar
75+
|| hasDevices !== context?.hasDevices
76+
|| hasDmRooms !== context?.hasDmRooms
77+
|| hasNotificationsEnabled !== context?.hasNotificationsEnabled) {
78+
setContext({ hasAvatar, hasDevices, hasDmRooms, hasNotificationsEnabled });
79+
}
80+
} catch (e) {
81+
logger.warn("Could not load context for user onboarding task list: ", e);
82+
setContext(null);
83+
}
84+
}, [context, cli]),
85+
);
86+
5787
useEffect(() => {
58-
const handle = setInterval(handler, 2000);
88+
cli.on(ClientEvent.AccountData, handler);
89+
const handle = setInterval(handler, USER_ONBOARDING_CONTEXT_INTERVAL);
5990
handler();
6091
return () => {
92+
cli.off(ClientEvent.AccountData, handler);
6193
if (handle) {
6294
clearInterval(handle);
6395
}
6496
};
65-
}, [handler]);
97+
}, [cli, handler]);
6698

6799
return context;
68100
}

src/hooks/useUserOnboardingTasks.ts

+6-10
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ interface InternalUserOnboardingTask extends UserOnboardingTask {
4646
completed: (ctx: UserOnboardingContext) => boolean;
4747
}
4848

49-
const hasOpenDMs = (ctx: UserOnboardingContext) => Boolean(Object.entries(ctx.dmRooms).length);
50-
5149
const onClickStartDm = (ev: ButtonEvent) => {
5250
PosthogTrackers.trackInteraction("WebUserOnboardingTaskSendDm", ev);
5351
defaultDispatcher.dispatch({ action: 'view_create_chat' });
@@ -64,7 +62,7 @@ const tasks: InternalUserOnboardingTask[] = [
6462
id: "find-friends",
6563
title: _t("Find and invite your friends"),
6664
description: _t("It’s what you’re here for, so lets get to it"),
67-
completed: hasOpenDMs,
65+
completed: (ctx: UserOnboardingContext) => ctx.hasDmRooms,
6866
relevant: [UseCase.PersonalMessaging, UseCase.Skip],
6967
action: {
7068
label: _t("Find friends"),
@@ -75,7 +73,7 @@ const tasks: InternalUserOnboardingTask[] = [
7573
id: "find-coworkers",
7674
title: _t("Find and invite your co-workers"),
7775
description: _t("Get stuff done by finding your teammates"),
78-
completed: hasOpenDMs,
76+
completed: (ctx: UserOnboardingContext) => ctx.hasDmRooms,
7977
relevant: [UseCase.WorkMessaging],
8078
action: {
8179
label: _t("Find people"),
@@ -86,7 +84,7 @@ const tasks: InternalUserOnboardingTask[] = [
8684
id: "find-community-members",
8785
title: _t("Find and invite your community members"),
8886
description: _t("Get stuff done by finding your teammates"),
89-
completed: hasOpenDMs,
87+
completed: (ctx: UserOnboardingContext) => ctx.hasDmRooms,
9088
relevant: [UseCase.CommunityMessaging],
9189
action: {
9290
label: _t("Find people"),
@@ -97,9 +95,7 @@ const tasks: InternalUserOnboardingTask[] = [
9795
id: "download-apps",
9896
title: _t("Download Element"),
9997
description: _t("Don’t miss a thing by taking Element with you"),
100-
completed: (ctx: UserOnboardingContext) => {
101-
return Boolean(ctx.devices.filter(it => it.device_id !== ctx.myDevice).length);
102-
},
98+
completed: (ctx: UserOnboardingContext) => ctx.hasDevices,
10399
action: {
104100
label: _t("Download apps"),
105101
onClick: (ev: ButtonEvent) => {
@@ -112,7 +108,7 @@ const tasks: InternalUserOnboardingTask[] = [
112108
id: "setup-profile",
113109
title: _t("Set up your profile"),
114110
description: _t("Make sure people know it’s really you"),
115-
completed: (info: UserOnboardingContext) => Boolean(info.avatar),
111+
completed: (ctx: UserOnboardingContext) => ctx.hasAvatar,
116112
action: {
117113
label: _t("Your profile"),
118114
onClick: (ev: ButtonEvent) => {
@@ -128,7 +124,7 @@ const tasks: InternalUserOnboardingTask[] = [
128124
id: "permission-notifications",
129125
title: _t("Turn on notifications"),
130126
description: _t("Don’t miss a reply or important message"),
131-
completed: () => Notifier.isPossible(),
127+
completed: (ctx: UserOnboardingContext) => ctx.hasNotificationsEnabled,
132128
action: {
133129
label: _t("Enable notifications"),
134130
onClick: (ev: ButtonEvent) => {

0 commit comments

Comments
 (0)