1
0
mirror of https://github.com/matrix-org/matrix-react-sdk.git synced 2025-07-28 15:22:05 +03:00

Pop out of Threads Activity Centre (#12136)

* Add `Thread Activity centre` labs flag

* Rename translation string

* WIP Thread Activity Centre

* Update supportedLevels

* css lint

* i18n lint

* Fix labs subsection test

* Update Threads Activity Centre label

* Rename Thread Activity Centre to Threads Activity Centre

* Use compound `MenuItem` instead of custom button

* Color thread icon when hovered

* Make the pop-up scrollable and add a max height

* Remove Math.random in key

* Remove unused class

* Change add comments on `mx_ThreadsActivityRows` and `mx_ThreadsActivityRow`

* Make threads activity centre labs flag split out unread counts

Just shows notif & unread counts for main thread if the TAC is enabled.

* Fix tests

* Simpler fix

* Open thread panel when thread clicke in Threads Activity Centre

Hopefully this is a sensible enough way. The panel will stay open of
course (ie. if you go to a different room & come back), but that's the
nature of the right panel.

* Dynamic state of room

* Add doc

* Use the StatelessNotificationBadge component in ThreadsActivityCentre

and re-use the existing NotificationLevel

* Remove unused style

* Add room sorting

* Fix `ThreadsActivityRow` props doc

* Pass in & cache the status of the TAC labs flag

* Pass includeThreads as setting to doesRoomHaveUnreadMessages too

* Fix tests

* Add analytics to the TAC (#12179)

* Update TAC label (#12186)

* Add `IndicatorIcon` to the TAC button (#12182)

Add `IndicatorIcon` to the TAC button

* Threads don't have activity if the room is muted

This makes it match the computation in determineUnreadState.
Ideally this logic should all be in one place.

* Re-use doesRoomHaveUnreadThreads for useRoomThreadNotifications

This incorporates the logic of not showing unread dots if the room
is muted

* Add TAC description in labs (#12197)

* Fox position & size of dot on the tac button

IndicatorIcon doesn't like having the size of its icon adjusted and
we probably shouldn't do it anyway: better to specify to the component
what size we want it.

* TAC: Utils tests (#12200)

* Add tests for `doesRoomHaveUnreadThreads`
* Add tests for `getThreadNotificationLevel`

* Add test for the ThreadsActivityCentre component

* Add snapshot test

* Fix narrow hover background on TAC button

Make the button 32x32 (and the inner icon 24x24)

* Add caption for empty TAC

* s/tac/threads_activity_centre/

* Fix i18n & add tests

* Add playwright tests for the TAC (#12227)

* Fox comments

---------

Co-authored-by: David Baker <dbkr@users.noreply.github.com>
This commit is contained in:
Florian Duros
2024-02-07 14:49:40 +01:00
committed by GitHub
parent 3052025dd0
commit a4987060b7
24 changed files with 1455 additions and 14 deletions

View File

@ -23,6 +23,7 @@ import { makeBeaconEvent, mkEvent, stubClient } from "./test-utils";
import { makeThreadEvents, mkThread, populateThread } from "./test-utils/threads";
import {
doesRoomHaveUnreadMessages,
doesRoomHaveUnreadThreads,
doesRoomOrThreadHaveUnreadMessages,
eventTriggersUnreadCount,
} from "../src/Unread";
@ -533,4 +534,112 @@ describe("Unread", () => {
});
});
});
describe("doesRoomHaveUnreadThreads()", () => {
let room: Room;
const roomId = "!abc:server.org";
const myId = client.getSafeUserId();
beforeAll(() => {
client.supportsThreads = () => true;
});
beforeEach(async () => {
room = new Room(roomId, client, myId);
jest.spyOn(logger, "warn");
// Don't care about the code path of hidden events.
mocked(haveRendererForEvent).mockClear().mockReturnValue(true);
});
it("returns false when no threads", () => {
expect(doesRoomHaveUnreadThreads(room)).toBe(false);
// Add event to the room
const event = mkEvent({
event: true,
type: "m.room.message",
user: aliceId,
room: roomId,
content: {},
});
room.addLiveEvents([event]);
// It still returns false
expect(doesRoomHaveUnreadThreads(room)).toBe(false);
});
it("return true when we don't have any receipt for the thread", async () => {
await populateThread({
room,
client,
authorId: myId,
participantUserIds: [aliceId],
});
// There is no receipt for the thread, it should be unread
expect(doesRoomHaveUnreadThreads(room)).toBe(true);
});
it("return false when we have a receipt for the thread", async () => {
const { events, rootEvent } = await populateThread({
room,
client,
authorId: myId,
participantUserIds: [aliceId],
});
// Mark the thread as read.
const receipt = new MatrixEvent({
type: "m.receipt",
room_id: "!foo:bar",
content: {
[events[events.length - 1].getId()!]: {
[ReceiptType.Read]: {
[myId]: { ts: 1, thread_id: rootEvent.getId()! },
},
},
},
});
room.addReceipt(receipt);
// There is a receipt for the thread, it should be read
expect(doesRoomHaveUnreadThreads(room)).toBe(false);
});
it("return true when only of the threads has a receipt", async () => {
// Create a first thread
await populateThread({
room,
client,
authorId: myId,
participantUserIds: [aliceId],
});
// Create a second thread
const { events, rootEvent } = await populateThread({
room,
client,
authorId: myId,
participantUserIds: [aliceId],
});
// Mark the thread as read.
const receipt = new MatrixEvent({
type: "m.receipt",
room_id: "!foo:bar",
content: {
[events[events.length - 1].getId()!]: {
[ReceiptType.Read]: {
[myId]: { ts: 1, thread_id: rootEvent.getId()! },
},
},
},
});
room.addReceipt(receipt);
// The first thread doesn't have a receipt, it should be unread
expect(doesRoomHaveUnreadThreads(room)).toBe(true);
});
});
});