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

Commit 5815e70

Browse files
TAC: Release Announcement (#12380)
* WIP * Store the release announcements in the account settings * Update TAC release announcement description * Fix settings content comparison * Add logging in case of failure * Watch settings changes * I add release announcement settings to disable it * Disable release announcement in e2e test * Add release announcement in e2e test * Add tests for ReleaseAnnouncementStore.ts * Update compound-web to `3.3.0` * Update TAC tests * Update Labs tests * Nits * Add test for ReleaseAnnouncement.tsx * Update `@vector-im/compound-web` * Add playwright snapshot * Delete false playwright screenshot * Wait for EW to be displayed after reload * Add screenshot * Clean util file * Renaming and comments fixing * Use second store instead of looking in the store. --------- Co-authored-by: R Midhun Suresh <[email protected]>
1 parent 156f2fa commit 5815e70

File tree

18 files changed

+805
-45
lines changed

18 files changed

+805
-45
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
"@sentry/browser": "^7.0.0",
7777
"@testing-library/react-hooks": "^8.0.1",
7878
"@vector-im/compound-design-tokens": "^1.2.0",
79-
"@vector-im/compound-web": "^3.1.1",
79+
"@vector-im/compound-web": "^3.3.1",
8080
"@zxcvbn-ts/core": "^3.0.4",
8181
"@zxcvbn-ts/language-common": "^3.0.4",
8282
"@zxcvbn-ts/language-en": "^3.0.2",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
*
3+
* Copyright 2024 The Matrix.org Foundation C.I.C.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
* /
17+
*/
18+
19+
import { Page } from "@playwright/test";
20+
21+
import { test as base, expect } from "../../element-web-test";
22+
23+
/**
24+
* Set up for release announcement tests.
25+
*/
26+
export const test = base.extend<{
27+
util: Helpers;
28+
}>({
29+
displayName: "Alice",
30+
botCreateOpts: { displayName: "Other User" },
31+
32+
util: async ({ page, app, bot }, use) => {
33+
await use(new Helpers(page));
34+
},
35+
});
36+
37+
export class Helpers {
38+
constructor(private page: Page) {}
39+
40+
/**
41+
* Get the release announcement with the given name.
42+
* @param name
43+
* @private
44+
*/
45+
private getReleaseAnnouncement(name: string) {
46+
return this.page.getByRole("dialog", { name });
47+
}
48+
49+
/**
50+
* Assert that the release announcement with the given name is visible.
51+
* @param name
52+
*/
53+
async assertReleaseAnnouncementIsVisible(name: string) {
54+
await expect(this.getReleaseAnnouncement(name)).toBeVisible();
55+
await expect(this.page).toMatchScreenshot(`release-announcement-${name}.png`);
56+
}
57+
58+
/**
59+
* Assert that the release announcement with the given name is not visible.
60+
* @param name
61+
*/
62+
assertReleaseAnnouncementIsNotVisible(name: string) {
63+
return expect(this.getReleaseAnnouncement(name)).not.toBeVisible();
64+
}
65+
66+
/**
67+
* Mark the release announcement with the given name as read.
68+
* If the release announcement is not visible, this will throw an error.
69+
* @param name
70+
*/
71+
async markReleaseAnnouncementAsRead(name: string) {
72+
const dialog = this.getReleaseAnnouncement(name);
73+
await dialog.getByRole("button", { name: "Ok" }).click();
74+
}
75+
}
76+
77+
export { expect };
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
*
3+
* Copyright 2024 The Matrix.org Foundation C.I.C.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
* /
17+
*/
18+
19+
import { test, expect } from "./";
20+
21+
test.describe("Release announcement", () => {
22+
test.use({
23+
config: {
24+
features: {
25+
feature_release_announcement: true,
26+
},
27+
},
28+
labsFlags: ["threadsActivityCentre"],
29+
});
30+
31+
test("should display the release announcement process", async ({ page, app, util }) => {
32+
// The TAC release announcement should be displayed
33+
await util.assertReleaseAnnouncementIsVisible("Threads Activity Centre");
34+
// Hide the release announcement
35+
await util.markReleaseAnnouncementAsRead("Threads Activity Centre");
36+
await util.assertReleaseAnnouncementIsNotVisible("Threads Activity Centre");
37+
38+
await page.reload();
39+
// Wait for EW to load
40+
await expect(page.getByRole("navigation", { name: "Spaces" })).toBeVisible();
41+
// Check that once the release announcement has been marked as viewed, it does not appear again
42+
await util.assertReleaseAnnouncementIsNotVisible("Threads Activity Centre");
43+
});
44+
});

playwright/element-web-test.ts

+5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ const CONFIG_JSON: Partial<IConfigOptions> = {
5252

5353
// the location tests want a map style url.
5454
map_style_url: "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx",
55+
56+
features: {
57+
// We don't want to go through the feature announcement during the e2e test
58+
feature_release_announcement: false,
59+
},
5560
};
5661

5762
export type TestOptions = {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
*
3+
* Copyright 2024 The Matrix.org Foundation C.I.C.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
* /
17+
*/
18+
19+
import React, { ComponentProps, JSX, PropsWithChildren } from "react";
20+
import { ReleaseAnnouncement as ReleaseAnnouncementCompound } from "@vector-im/compound-web";
21+
22+
import { ReleaseAnnouncementStore, Feature } from "../../stores/ReleaseAnnouncementStore";
23+
import { useIsReleaseAnnouncementOpen } from "../../hooks/useIsReleaseAnnouncementOpen";
24+
25+
interface ReleaseAnnouncementProps
26+
extends Omit<ComponentProps<typeof ReleaseAnnouncementCompound>, "open" | "onClick"> {
27+
feature: Feature;
28+
}
29+
30+
/**
31+
* Display a release announcement component around the children
32+
* Wrapper gluing the release announcement compound and the ReleaseAnnouncementStore
33+
* @param feature - the feature to announce, should be listed in {@link Feature}
34+
* @param children
35+
* @param props
36+
* @constructor
37+
*/
38+
export function ReleaseAnnouncement({
39+
feature,
40+
children,
41+
...props
42+
}: PropsWithChildren<ReleaseAnnouncementProps>): JSX.Element {
43+
const enabled = useIsReleaseAnnouncementOpen(feature);
44+
45+
return (
46+
<ReleaseAnnouncementCompound
47+
open={enabled}
48+
onClick={() => ReleaseAnnouncementStore.instance.nextReleaseAnnouncement()}
49+
{...props}
50+
>
51+
{children}
52+
</ReleaseAnnouncementCompound>
53+
);
54+
}

src/components/views/spaces/threads-activity-centre/ThreadsActivityCentre.tsx

+47-30
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import { NotificationLevel } from "../../../../stores/notifications/Notification
3434
import PosthogTrackers from "../../../../PosthogTrackers";
3535
import { getKeyBindingsManager } from "../../../../KeyBindingsManager";
3636
import { KeyBindingAction } from "../../../../accessibility/KeyboardShortcuts";
37+
import { ReleaseAnnouncement } from "../../../structures/ReleaseAnnouncement";
38+
import { useIsReleaseAnnouncementOpen } from "../../../../hooks/useIsReleaseAnnouncementOpen";
3739

3840
interface ThreadsActivityCentreProps {
3941
/**
@@ -49,6 +51,7 @@ interface ThreadsActivityCentreProps {
4951
export function ThreadsActivityCentre({ displayButtonLabel }: ThreadsActivityCentreProps): JSX.Element {
5052
const [open, setOpen] = useState(false);
5153
const roomsAndNotifications = useUnreadThreadRooms(open);
54+
const isReleaseAnnouncementOpen = useIsReleaseAnnouncementOpen("threadsActivityCentre");
5255

5356
return (
5457
<div
@@ -65,41 +68,55 @@ export function ThreadsActivityCentre({ displayButtonLabel }: ThreadsActivityCen
6568
}
6669
}}
6770
>
68-
<Menu
69-
align="end"
70-
open={open}
71-
onOpenChange={(newOpen) => {
72-
// Track only when the Threads Activity Centre is opened
73-
if (newOpen) PosthogTrackers.trackInteraction("WebThreadsActivityCentreButton");
74-
75-
setOpen(newOpen);
76-
}}
77-
side="right"
78-
title={_t("threads_activity_centre|header")}
79-
trigger={
71+
{isReleaseAnnouncementOpen ? (
72+
<ReleaseAnnouncement
73+
feature="threadsActivityCentre"
74+
header={_t("threads_activity_centre|release_announcement_header")}
75+
description={_t("threads_activity_centre|release_announcement_description")}
76+
closeLabel={_t("action|ok")}
77+
>
8078
<ThreadsActivityCentreButton
8179
displayLabel={displayButtonLabel}
8280
notificationLevel={roomsAndNotifications.greatestNotificationLevel}
8381
/>
84-
}
85-
>
86-
{/* Make the content of the pop-up scrollable */}
87-
<div className="mx_ThreadsActivityCentre_rows">
88-
{roomsAndNotifications.rooms.map(({ room, notificationLevel }) => (
89-
<ThreadsActivityCentreRow
90-
key={room.roomId}
91-
room={room}
92-
notificationLevel={notificationLevel}
93-
onClick={() => setOpen(false)}
82+
</ReleaseAnnouncement>
83+
) : (
84+
<Menu
85+
align="end"
86+
open={open}
87+
onOpenChange={(newOpen) => {
88+
// Track only when the Threads Activity Centre is opened
89+
if (newOpen) PosthogTrackers.trackInteraction("WebThreadsActivityCentreButton");
90+
91+
setOpen(newOpen);
92+
}}
93+
side="right"
94+
title={_t("threads_activity_centre|header")}
95+
trigger={
96+
<ThreadsActivityCentreButton
97+
displayLabel={displayButtonLabel}
98+
notificationLevel={roomsAndNotifications.greatestNotificationLevel}
9499
/>
95-
))}
96-
{roomsAndNotifications.rooms.length === 0 && (
97-
<div className="mx_ThreadsActivityCentre_emptyCaption">
98-
{_t("threads_activity_centre|no_rooms_with_unreads_threads")}
99-
</div>
100-
)}
101-
</div>
102-
</Menu>
100+
}
101+
>
102+
{/* Make the content of the pop-up scrollable */}
103+
<div className="mx_ThreadsActivityCentre_rows">
104+
{roomsAndNotifications.rooms.map(({ room, notificationLevel }) => (
105+
<ThreadsActivityCentreRow
106+
key={room.roomId}
107+
room={room}
108+
notificationLevel={notificationLevel}
109+
onClick={() => setOpen(false)}
110+
/>
111+
))}
112+
{roomsAndNotifications.rooms.length === 0 && (
113+
<div className="mx_ThreadsActivityCentre_emptyCaption">
114+
{_t("threads_activity_centre|no_rooms_with_unreads_threads")}
115+
</div>
116+
)}
117+
</div>
118+
</Menu>
119+
)}
103120
</div>
104121
);
105122
}
+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
*
3+
* Copyright 2024 The Matrix.org Foundation C.I.C.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
* /
17+
*/
18+
19+
import { useTypedEventEmitterState } from "./useEventEmitter";
20+
import { Feature, ReleaseAnnouncementStore } from "../stores/ReleaseAnnouncementStore";
21+
22+
/**
23+
* Return true if the release announcement of the given feature is enabled
24+
* @param feature
25+
*/
26+
export function useIsReleaseAnnouncementOpen(feature: Feature): boolean {
27+
return useTypedEventEmitterState(
28+
ReleaseAnnouncementStore.instance,
29+
"releaseAnnouncementChanged",
30+
() => ReleaseAnnouncementStore.instance.getReleaseAnnouncement() === feature,
31+
);
32+
}

src/i18n/strings/en_EN.json

+5-1
Original file line numberDiff line numberDiff line change
@@ -1417,6 +1417,7 @@
14171417
"group_spaces": "Spaces",
14181418
"group_themes": "Themes",
14191419
"group_threads": "Threads",
1420+
"group_ui": "User interface",
14201421
"group_voip": "Voice & Video",
14211422
"group_widgets": "Widgets",
14221423
"hidebold": "Hide notification dot (only display counters badges)",
@@ -1440,6 +1441,7 @@
14401441
"oidc_native_flow": "OIDC native authentication",
14411442
"oidc_native_flow_description": "⚠ WARNING: Experimental. Use OIDC native authentication when supported by the server.",
14421443
"pinning": "Message Pinning",
1444+
"release_announcement": "Release announcement",
14431445
"render_reaction_images": "Render custom images in reactions",
14441446
"render_reaction_images_description": "Sometimes referred to as \"custom emojis\".",
14451447
"report_to_moderators": "Report to moderators",
@@ -3161,7 +3163,9 @@
31613163
},
31623164
"threads_activity_centre": {
31633165
"header": "Threads activity",
3164-
"no_rooms_with_unreads_threads": "You don't have rooms with unread threads yet."
3166+
"no_rooms_with_unreads_threads": "You don't have rooms with unread threads yet.",
3167+
"release_announcement_description": "Threads notifications have moved, find them here from now on.",
3168+
"release_announcement_header": "Threads Activity Centre"
31653169
},
31663170
"time": {
31673171
"about_day_ago": "about a day ago",

0 commit comments

Comments
 (0)