Merge branch 'develop' into psg-863/dm-learn-more-rename
This commit is contained in:
commit
31c0988220
31 changed files with 486 additions and 150 deletions
4
.github/workflows/cypress.yaml
vendored
4
.github/workflows/cypress.yaml
vendored
|
@ -79,8 +79,8 @@ jobs:
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
# Run 3 instances in Parallel
|
# Run 4 instances in Parallel
|
||||||
runner: [1, 2, 3]
|
runner: [1, 2, 3, 4]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -64,6 +64,21 @@ describe("Composer", () => {
|
||||||
cy.contains('.mx_EventTile_body strong', 'bold message');
|
cy.contains('.mx_EventTile_body strong', 'bold message');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("should allow user to input emoji via graphical picker", () => {
|
||||||
|
cy.getComposer(false).within(() => {
|
||||||
|
cy.get('[aria-label="Emoji"]').click();
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get('[data-testid="mx_EmojiPicker"]').within(() => {
|
||||||
|
cy.contains(".mx_EmojiPicker_item", "😇").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.get(".mx_ContextualMenu_background").click(); // Close emoji picker
|
||||||
|
cy.get('div[contenteditable=true]').type("{enter}"); // Send message
|
||||||
|
|
||||||
|
cy.contains(".mx_EventTile_body", "😇");
|
||||||
|
});
|
||||||
|
|
||||||
describe("when Ctrl+Enter is required to send", () => {
|
describe("when Ctrl+Enter is required to send", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.setSettingValue("MessageComposerInput.ctrlEnterToSend", null, SettingLevel.ACCOUNT, true);
|
cy.setSettingValue("MessageComposerInput.ctrlEnterToSend", null, SettingLevel.ACCOUNT, true);
|
||||||
|
|
|
@ -77,7 +77,7 @@ async function proxyStart(synapse: SynapseInstance): Promise<ProxyInstance> {
|
||||||
const port = await getFreePort();
|
const port = await getFreePort();
|
||||||
console.log(new Date(), "starting proxy container...");
|
console.log(new Date(), "starting proxy container...");
|
||||||
const containerId = await dockerRun({
|
const containerId = await dockerRun({
|
||||||
image: "ghcr.io/matrix-org/sliding-sync-proxy:v0.4.0",
|
image: "ghcr.io/matrix-org/sliding-sync-proxy:v0.6.0",
|
||||||
containerName: "react-sdk-cypress-sliding-sync-proxy",
|
containerName: "react-sdk-cypress-sliding-sync-proxy",
|
||||||
params: [
|
params: [
|
||||||
"--rm",
|
"--rm",
|
||||||
|
|
|
@ -374,6 +374,4 @@
|
||||||
@import "./voice-broadcast/atoms/_PlaybackControlButton.pcss";
|
@import "./voice-broadcast/atoms/_PlaybackControlButton.pcss";
|
||||||
@import "./voice-broadcast/atoms/_VoiceBroadcastControl.pcss";
|
@import "./voice-broadcast/atoms/_VoiceBroadcastControl.pcss";
|
||||||
@import "./voice-broadcast/atoms/_VoiceBroadcastHeader.pcss";
|
@import "./voice-broadcast/atoms/_VoiceBroadcastHeader.pcss";
|
||||||
@import "./voice-broadcast/molecules/_VoiceBroadcastPlaybackBody.pcss";
|
@import "./voice-broadcast/molecules/_VoiceBroadcastBody.pcss";
|
||||||
@import "./voice-broadcast/molecules/_VoiceBroadcastRecordingBody.pcss";
|
|
||||||
@import "./voice-broadcast/molecules/_VoiceBroadcastRecordingPip.pcss";
|
|
||||||
|
|
|
@ -14,22 +14,26 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.mx_VoiceBroadcastRecordingPip {
|
.mx_VoiceBroadcastBody {
|
||||||
background-color: $system;
|
background-color: $quinary-content;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 8px 0 #0000004a;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: $spacing-12;
|
padding: $spacing-12;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_VoiceBroadcastRecordingPip_divider {
|
.mx_VoiceBroadcastBody--pip {
|
||||||
|
background-color: $system;
|
||||||
|
box-shadow: 0 2px 8px 0 #0000004a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_VoiceBroadcastBody_divider {
|
||||||
background-color: $quinary-content;
|
background-color: $quinary-content;
|
||||||
border: 0;
|
border: 0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
margin: $spacing-12 0;
|
margin: $spacing-12 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_VoiceBroadcastRecordingPip_controls {
|
.mx_VoiceBroadcastBody_controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
}
|
}
|
|
@ -1,27 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.mx_VoiceBroadcastPlaybackBody {
|
|
||||||
background-color: $quinary-content;
|
|
||||||
border-radius: 8px;
|
|
||||||
display: inline-block;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_VoiceBroadcastPlaybackBody_controls {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2022 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
.mx_VoiceBroadcastRecordingBody {
|
|
||||||
align-items: flex-start;
|
|
||||||
background-color: $quinary-content;
|
|
||||||
border-radius: 8px;
|
|
||||||
display: inline-flex;
|
|
||||||
gap: $spacing-8;
|
|
||||||
padding: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_VoiceBroadcastRecordingBody_title {
|
|
||||||
font-size: $font-12px;
|
|
||||||
font-weight: $font-semi-bold;
|
|
||||||
}
|
|
|
@ -63,6 +63,15 @@ const DEFAULT_ROOM_SUBSCRIPTION_INFO = {
|
||||||
required_state: [
|
required_state: [
|
||||||
["*", "*"], // all events
|
["*", "*"], // all events
|
||||||
],
|
],
|
||||||
|
include_old_rooms: {
|
||||||
|
timeline_limit: 0,
|
||||||
|
required_state: [ // state needed to handle space navigation and tombstone chains
|
||||||
|
[EventType.RoomCreate, ""],
|
||||||
|
[EventType.RoomTombstone, ""],
|
||||||
|
[EventType.SpaceChild, "*"],
|
||||||
|
[EventType.SpaceParent, "*"],
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PartialSlidingSyncRequest = {
|
export type PartialSlidingSyncRequest = {
|
||||||
|
@ -121,6 +130,16 @@ export class SlidingSyncManager {
|
||||||
[EventType.SpaceParent, "*"], // all space parents
|
[EventType.SpaceParent, "*"], // all space parents
|
||||||
[EventType.RoomMember, this.client.getUserId()!], // lets the client calculate that we are in fact in the room
|
[EventType.RoomMember, this.client.getUserId()!], // lets the client calculate that we are in fact in the room
|
||||||
],
|
],
|
||||||
|
include_old_rooms: {
|
||||||
|
timeline_limit: 0,
|
||||||
|
required_state: [
|
||||||
|
[EventType.RoomCreate, ""],
|
||||||
|
[EventType.RoomTombstone, ""], // lets JS SDK hide rooms which are dead
|
||||||
|
[EventType.SpaceChild, "*"], // all space children
|
||||||
|
[EventType.SpaceParent, "*"], // all space parents
|
||||||
|
[EventType.RoomMember, this.client.getUserId()!], // lets the client calculate that we are in fact in the room
|
||||||
|
],
|
||||||
|
},
|
||||||
filters: {
|
filters: {
|
||||||
room_types: ["m.space"],
|
room_types: ["m.space"],
|
||||||
},
|
},
|
||||||
|
@ -176,7 +195,7 @@ export class SlidingSyncManager {
|
||||||
list = {
|
list = {
|
||||||
ranges: [[0, 20]],
|
ranges: [[0, 20]],
|
||||||
sort: [
|
sort: [
|
||||||
"by_highlight_count", "by_notification_count", "by_recency",
|
"by_notification_level", "by_recency",
|
||||||
],
|
],
|
||||||
timeline_limit: 1, // most recent message display: though this seems to only be needed for favourites?
|
timeline_limit: 1, // most recent message display: though this seems to only be needed for favourites?
|
||||||
required_state: [
|
required_state: [
|
||||||
|
@ -187,6 +206,16 @@ export class SlidingSyncManager {
|
||||||
[EventType.RoomCreate, ""], // for isSpaceRoom checks
|
[EventType.RoomCreate, ""], // for isSpaceRoom checks
|
||||||
[EventType.RoomMember, this.client.getUserId()], // lets the client calculate that we are in fact in the room
|
[EventType.RoomMember, this.client.getUserId()], // lets the client calculate that we are in fact in the room
|
||||||
],
|
],
|
||||||
|
include_old_rooms: {
|
||||||
|
timeline_limit: 0,
|
||||||
|
required_state: [
|
||||||
|
[EventType.RoomCreate, ""],
|
||||||
|
[EventType.RoomTombstone, ""], // lets JS SDK hide rooms which are dead
|
||||||
|
[EventType.SpaceChild, "*"], // all space children
|
||||||
|
[EventType.SpaceParent, "*"], // all space parents
|
||||||
|
[EventType.RoomMember, this.client.getUserId()!], // lets the client calculate that we are in fact in the room
|
||||||
|
],
|
||||||
|
},
|
||||||
};
|
};
|
||||||
list = Object.assign(list, updateArgs);
|
list = Object.assign(list, updateArgs);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -570,8 +570,7 @@ export default class RoomSublist extends React.Component<IProps, IState> {
|
||||||
const slidingList = SlidingSyncManager.instance.slidingSync.getList(slidingSyncIndex);
|
const slidingList = SlidingSyncManager.instance.slidingSync.getList(slidingSyncIndex);
|
||||||
isAlphabetical = slidingList.sort[0] === "by_name";
|
isAlphabetical = slidingList.sort[0] === "by_name";
|
||||||
isUnreadFirst = (
|
isUnreadFirst = (
|
||||||
slidingList.sort[0] === "by_highlight_count" ||
|
slidingList.sort[0] === "by_notification_level"
|
||||||
slidingList.sort[0] === "by_notification_count"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,6 @@ export const useSlidingSyncRoomSearch = () => {
|
||||||
ranges: [[0, limit]],
|
ranges: [[0, limit]],
|
||||||
filters: {
|
filters: {
|
||||||
room_name_like: term,
|
room_name_like: term,
|
||||||
is_tombstoned: false,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const rooms = [];
|
const rooms = [];
|
||||||
|
|
|
@ -24,7 +24,7 @@ import SettingsStore from "../../settings/SettingsStore";
|
||||||
import { DefaultTagID, OrderedDefaultTagIDs, RoomUpdateCause, TagID } from "./models";
|
import { DefaultTagID, OrderedDefaultTagIDs, RoomUpdateCause, TagID } from "./models";
|
||||||
import { IListOrderingMap, ITagMap, ITagSortingMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models";
|
import { IListOrderingMap, ITagMap, ITagSortingMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models";
|
||||||
import { ActionPayload } from "../../dispatcher/payloads";
|
import { ActionPayload } from "../../dispatcher/payloads";
|
||||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
import defaultDispatcher, { MatrixDispatcher } from "../../dispatcher/dispatcher";
|
||||||
import { readReceiptChangeIsFor } from "../../utils/read-receipts";
|
import { readReceiptChangeIsFor } from "../../utils/read-receipts";
|
||||||
import { FILTER_CHANGED, IFilterCondition } from "./filters/IFilterCondition";
|
import { FILTER_CHANGED, IFilterCondition } from "./filters/IFilterCondition";
|
||||||
import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm";
|
import { Algorithm, LIST_UPDATED_EVENT } from "./algorithms/Algorithm";
|
||||||
|
@ -65,8 +65,8 @@ export class RoomListStoreClass extends AsyncStoreWithClient<IState> implements
|
||||||
this.emit(LISTS_UPDATE_EVENT);
|
this.emit(LISTS_UPDATE_EVENT);
|
||||||
});
|
});
|
||||||
|
|
||||||
constructor() {
|
constructor(dis: MatrixDispatcher) {
|
||||||
super(defaultDispatcher);
|
super(dis);
|
||||||
this.setMaxListeners(20); // RoomList + LeftPanel + 8xRoomSubList + spares
|
this.setMaxListeners(20); // RoomList + LeftPanel + 8xRoomSubList + spares
|
||||||
this.algorithm.start();
|
this.algorithm.start();
|
||||||
}
|
}
|
||||||
|
@ -613,11 +613,11 @@ export default class RoomListStore {
|
||||||
if (!RoomListStore.internalInstance) {
|
if (!RoomListStore.internalInstance) {
|
||||||
if (SettingsStore.getValue("feature_sliding_sync")) {
|
if (SettingsStore.getValue("feature_sliding_sync")) {
|
||||||
logger.info("using SlidingRoomListStoreClass");
|
logger.info("using SlidingRoomListStoreClass");
|
||||||
const instance = new SlidingRoomListStoreClass();
|
const instance = new SlidingRoomListStoreClass(defaultDispatcher, SdkContextClass.instance);
|
||||||
instance.start();
|
instance.start();
|
||||||
RoomListStore.internalInstance = instance;
|
RoomListStore.internalInstance = instance;
|
||||||
} else {
|
} else {
|
||||||
const instance = new RoomListStoreClass();
|
const instance = new RoomListStoreClass(defaultDispatcher);
|
||||||
instance.start();
|
instance.start();
|
||||||
RoomListStore.internalInstance = instance;
|
RoomListStore.internalInstance = instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,12 +21,10 @@ import { MSC3575Filter, SlidingSyncEvent } from "matrix-js-sdk/src/sliding-sync"
|
||||||
import { RoomUpdateCause, TagID, OrderedDefaultTagIDs, DefaultTagID } from "./models";
|
import { RoomUpdateCause, TagID, OrderedDefaultTagIDs, DefaultTagID } from "./models";
|
||||||
import { ITagMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models";
|
import { ITagMap, ListAlgorithm, SortAlgorithm } from "./algorithms/models";
|
||||||
import { ActionPayload } from "../../dispatcher/payloads";
|
import { ActionPayload } from "../../dispatcher/payloads";
|
||||||
import defaultDispatcher from "../../dispatcher/dispatcher";
|
import { MatrixDispatcher } from "../../dispatcher/dispatcher";
|
||||||
import { IFilterCondition } from "./filters/IFilterCondition";
|
import { IFilterCondition } from "./filters/IFilterCondition";
|
||||||
import { AsyncStoreWithClient } from "../AsyncStoreWithClient";
|
import { AsyncStoreWithClient } from "../AsyncStoreWithClient";
|
||||||
import { RoomListStore as Interface, RoomListStoreEvent } from "./Interface";
|
import { RoomListStore as Interface, RoomListStoreEvent } from "./Interface";
|
||||||
import { SlidingSyncManager } from "../../SlidingSyncManager";
|
|
||||||
import SpaceStore from "../spaces/SpaceStore";
|
|
||||||
import { MetaSpace, SpaceKey, UPDATE_SELECTED_SPACE } from "../spaces";
|
import { MetaSpace, SpaceKey, UPDATE_SELECTED_SPACE } from "../spaces";
|
||||||
import { LISTS_LOADING_EVENT } from "./RoomListStore";
|
import { LISTS_LOADING_EVENT } from "./RoomListStore";
|
||||||
import { UPDATE_EVENT } from "../AsyncStore";
|
import { UPDATE_EVENT } from "../AsyncStore";
|
||||||
|
@ -38,7 +36,7 @@ interface IState {
|
||||||
|
|
||||||
export const SlidingSyncSortToFilter: Record<SortAlgorithm, string[]> = {
|
export const SlidingSyncSortToFilter: Record<SortAlgorithm, string[]> = {
|
||||||
[SortAlgorithm.Alphabetic]: ["by_name", "by_recency"],
|
[SortAlgorithm.Alphabetic]: ["by_name", "by_recency"],
|
||||||
[SortAlgorithm.Recent]: ["by_highlight_count", "by_notification_count", "by_recency"],
|
[SortAlgorithm.Recent]: ["by_notification_level", "by_recency"],
|
||||||
[SortAlgorithm.Manual]: ["by_recency"],
|
[SortAlgorithm.Manual]: ["by_recency"],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,21 +46,18 @@ const filterConditions: Record<TagID, MSC3575Filter> = {
|
||||||
},
|
},
|
||||||
[DefaultTagID.Favourite]: {
|
[DefaultTagID.Favourite]: {
|
||||||
tags: ["m.favourite"],
|
tags: ["m.favourite"],
|
||||||
is_tombstoned: false,
|
|
||||||
},
|
},
|
||||||
// TODO https://github.com/vector-im/element-web/issues/23207
|
// TODO https://github.com/vector-im/element-web/issues/23207
|
||||||
// DefaultTagID.SavedItems,
|
// DefaultTagID.SavedItems,
|
||||||
[DefaultTagID.DM]: {
|
[DefaultTagID.DM]: {
|
||||||
is_dm: true,
|
is_dm: true,
|
||||||
is_invite: false,
|
is_invite: false,
|
||||||
is_tombstoned: false,
|
|
||||||
// If a DM has a Favourite & Low Prio tag then it'll be shown in those lists instead
|
// If a DM has a Favourite & Low Prio tag then it'll be shown in those lists instead
|
||||||
not_tags: ["m.favourite", "m.lowpriority"],
|
not_tags: ["m.favourite", "m.lowpriority"],
|
||||||
},
|
},
|
||||||
[DefaultTagID.Untagged]: {
|
[DefaultTagID.Untagged]: {
|
||||||
is_dm: false,
|
is_dm: false,
|
||||||
is_invite: false,
|
is_invite: false,
|
||||||
is_tombstoned: false,
|
|
||||||
not_room_types: ["m.space"],
|
not_room_types: ["m.space"],
|
||||||
not_tags: ["m.favourite", "m.lowpriority"],
|
not_tags: ["m.favourite", "m.lowpriority"],
|
||||||
// spaces filter added dynamically
|
// spaces filter added dynamically
|
||||||
|
@ -71,7 +66,6 @@ const filterConditions: Record<TagID, MSC3575Filter> = {
|
||||||
tags: ["m.lowpriority"],
|
tags: ["m.lowpriority"],
|
||||||
// If a room has both Favourite & Low Prio tags then it'll be shown under Favourites
|
// If a room has both Favourite & Low Prio tags then it'll be shown under Favourites
|
||||||
not_tags: ["m.favourite"],
|
not_tags: ["m.favourite"],
|
||||||
is_tombstoned: false,
|
|
||||||
},
|
},
|
||||||
// TODO https://github.com/vector-im/element-web/issues/23207
|
// TODO https://github.com/vector-im/element-web/issues/23207
|
||||||
// DefaultTagID.ServerNotice,
|
// DefaultTagID.ServerNotice,
|
||||||
|
@ -87,25 +81,25 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
private counts: Record<TagID, number> = {};
|
private counts: Record<TagID, number> = {};
|
||||||
private stickyRoomId: string | null;
|
private stickyRoomId: string | null;
|
||||||
|
|
||||||
public constructor() {
|
public constructor(dis: MatrixDispatcher, private readonly context: SdkContextClass) {
|
||||||
super(defaultDispatcher);
|
super(dis);
|
||||||
this.setMaxListeners(20); // RoomList + LeftPanel + 8xRoomSubList + spares
|
this.setMaxListeners(20); // RoomList + LeftPanel + 8xRoomSubList + spares
|
||||||
}
|
}
|
||||||
|
|
||||||
public async setTagSorting(tagId: TagID, sort: SortAlgorithm) {
|
public async setTagSorting(tagId: TagID, sort: SortAlgorithm) {
|
||||||
logger.info("SlidingRoomListStore.setTagSorting ", tagId, sort);
|
logger.info("SlidingRoomListStore.setTagSorting ", tagId, sort);
|
||||||
this.tagIdToSortAlgo[tagId] = sort;
|
this.tagIdToSortAlgo[tagId] = sort;
|
||||||
const slidingSyncIndex = SlidingSyncManager.instance.getOrAllocateListIndex(tagId);
|
const slidingSyncIndex = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
|
||||||
switch (sort) {
|
switch (sort) {
|
||||||
case SortAlgorithm.Alphabetic:
|
case SortAlgorithm.Alphabetic:
|
||||||
await SlidingSyncManager.instance.ensureListRegistered(
|
await this.context.slidingSyncManager.ensureListRegistered(
|
||||||
slidingSyncIndex, {
|
slidingSyncIndex, {
|
||||||
sort: SlidingSyncSortToFilter[SortAlgorithm.Alphabetic],
|
sort: SlidingSyncSortToFilter[SortAlgorithm.Alphabetic],
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case SortAlgorithm.Recent:
|
case SortAlgorithm.Recent:
|
||||||
await SlidingSyncManager.instance.ensureListRegistered(
|
await this.context.slidingSyncManager.ensureListRegistered(
|
||||||
slidingSyncIndex, {
|
slidingSyncIndex, {
|
||||||
sort: SlidingSyncSortToFilter[SortAlgorithm.Recent],
|
sort: SlidingSyncSortToFilter[SortAlgorithm.Recent],
|
||||||
},
|
},
|
||||||
|
@ -174,10 +168,13 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
// check all lists for each tag we know about and see if the room is there
|
// check all lists for each tag we know about and see if the room is there
|
||||||
const tags: TagID[] = [];
|
const tags: TagID[] = [];
|
||||||
for (const tagId in this.tagIdToSortAlgo) {
|
for (const tagId in this.tagIdToSortAlgo) {
|
||||||
const index = SlidingSyncManager.instance.getOrAllocateListIndex(tagId);
|
const index = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
|
||||||
const { roomIndexToRoomId } = SlidingSyncManager.instance.slidingSync.getListData(index);
|
const listData = this.context.slidingSyncManager.slidingSync.getListData(index);
|
||||||
for (const roomIndex in roomIndexToRoomId) {
|
if (!listData) {
|
||||||
const roomId = roomIndexToRoomId[roomIndex];
|
continue;
|
||||||
|
}
|
||||||
|
for (const roomIndex in listData.roomIndexToRoomId) {
|
||||||
|
const roomId = listData.roomIndexToRoomId[roomIndex];
|
||||||
if (roomId === room.roomId) {
|
if (roomId === room.roomId) {
|
||||||
tags.push(tagId);
|
tags.push(tagId);
|
||||||
break;
|
break;
|
||||||
|
@ -207,7 +204,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
|
|
||||||
// this room will not move due to it being viewed: it is sticky. This can be null to indicate
|
// this room will not move due to it being viewed: it is sticky. This can be null to indicate
|
||||||
// no sticky room if you aren't viewing a room.
|
// no sticky room if you aren't viewing a room.
|
||||||
this.stickyRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
this.stickyRoomId = this.context.roomViewStore.getRoomId();
|
||||||
let stickyRoomNewIndex = -1;
|
let stickyRoomNewIndex = -1;
|
||||||
const stickyRoomOldIndex = (tagMap[tagId] || []).findIndex((room) => {
|
const stickyRoomOldIndex = (tagMap[tagId] || []).findIndex((room) => {
|
||||||
return room.roomId === this.stickyRoomId;
|
return room.roomId === this.stickyRoomId;
|
||||||
|
@ -264,7 +261,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
}
|
}
|
||||||
|
|
||||||
private onSlidingSyncListUpdate(listIndex: number, joinCount: number, roomIndexToRoomId: Record<number, string>) {
|
private onSlidingSyncListUpdate(listIndex: number, joinCount: number, roomIndexToRoomId: Record<number, string>) {
|
||||||
const tagId = SlidingSyncManager.instance.listIdForIndex(listIndex);
|
const tagId = this.context.slidingSyncManager.listIdForIndex(listIndex);
|
||||||
this.counts[tagId]= joinCount;
|
this.counts[tagId]= joinCount;
|
||||||
this.refreshOrderedLists(tagId, roomIndexToRoomId);
|
this.refreshOrderedLists(tagId, roomIndexToRoomId);
|
||||||
// let the UI update
|
// let the UI update
|
||||||
|
@ -273,7 +270,7 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
|
|
||||||
private onRoomViewStoreUpdated() {
|
private onRoomViewStoreUpdated() {
|
||||||
// we only care about this to know when the user has clicked on a room to set the stickiness value
|
// we only care about this to know when the user has clicked on a room to set the stickiness value
|
||||||
if (SdkContextClass.instance.roomViewStore.getRoomId() === this.stickyRoomId) {
|
if (this.context.roomViewStore.getRoomId() === this.stickyRoomId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,14 +293,17 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
if (room) {
|
if (room) {
|
||||||
// resort it based on the slidingSync view of the list. This may cause this old sticky
|
// resort it based on the slidingSync view of the list. This may cause this old sticky
|
||||||
// room to cease to exist.
|
// room to cease to exist.
|
||||||
const index = SlidingSyncManager.instance.getOrAllocateListIndex(tagId);
|
const index = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
|
||||||
const { roomIndexToRoomId } = SlidingSyncManager.instance.slidingSync.getListData(index);
|
const listData = this.context.slidingSyncManager.slidingSync.getListData(index);
|
||||||
this.refreshOrderedLists(tagId, roomIndexToRoomId);
|
if (!listData) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.refreshOrderedLists(tagId, listData.roomIndexToRoomId);
|
||||||
hasUpdatedAnyList = true;
|
hasUpdatedAnyList = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// in the event we didn't call refreshOrderedLists, it helps to still remember the sticky room ID.
|
// in the event we didn't call refreshOrderedLists, it helps to still remember the sticky room ID.
|
||||||
this.stickyRoomId = SdkContextClass.instance.roomViewStore.getRoomId();
|
this.stickyRoomId = this.context.roomViewStore.getRoomId();
|
||||||
|
|
||||||
if (hasUpdatedAnyList) {
|
if (hasUpdatedAnyList) {
|
||||||
this.emit(LISTS_UPDATE_EVENT);
|
this.emit(LISTS_UPDATE_EVENT);
|
||||||
|
@ -313,11 +313,11 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
protected async onReady(): Promise<any> {
|
protected async onReady(): Promise<any> {
|
||||||
logger.info("SlidingRoomListStore.onReady");
|
logger.info("SlidingRoomListStore.onReady");
|
||||||
// permanent listeners: never get destroyed. Could be an issue if we want to test this in isolation.
|
// permanent listeners: never get destroyed. Could be an issue if we want to test this in isolation.
|
||||||
SlidingSyncManager.instance.slidingSync.on(SlidingSyncEvent.List, this.onSlidingSyncListUpdate.bind(this));
|
this.context.slidingSyncManager.slidingSync.on(SlidingSyncEvent.List, this.onSlidingSyncListUpdate.bind(this));
|
||||||
SdkContextClass.instance.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdated.bind(this));
|
this.context.roomViewStore.addListener(UPDATE_EVENT, this.onRoomViewStoreUpdated.bind(this));
|
||||||
SpaceStore.instance.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated.bind(this));
|
this.context.spaceStore.on(UPDATE_SELECTED_SPACE, this.onSelectedSpaceUpdated.bind(this));
|
||||||
if (SpaceStore.instance.activeSpace) {
|
if (this.context.spaceStore.activeSpace) {
|
||||||
this.onSelectedSpaceUpdated(SpaceStore.instance.activeSpace, false);
|
this.onSelectedSpaceUpdated(this.context.spaceStore.activeSpace, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// sliding sync has an initial response for spaces. Now request all the lists.
|
// sliding sync has an initial response for spaces. Now request all the lists.
|
||||||
|
@ -332,8 +332,8 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
const sort = SortAlgorithm.Recent; // default to recency sort, TODO: read from config
|
const sort = SortAlgorithm.Recent; // default to recency sort, TODO: read from config
|
||||||
this.tagIdToSortAlgo[tagId] = sort;
|
this.tagIdToSortAlgo[tagId] = sort;
|
||||||
this.emit(LISTS_LOADING_EVENT, tagId, true);
|
this.emit(LISTS_LOADING_EVENT, tagId, true);
|
||||||
const index = SlidingSyncManager.instance.getOrAllocateListIndex(tagId);
|
const index = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
|
||||||
SlidingSyncManager.instance.ensureListRegistered(index, {
|
this.context.slidingSyncManager.ensureListRegistered(index, {
|
||||||
filters: filter,
|
filters: filter,
|
||||||
sort: SlidingSyncSortToFilter[sort],
|
sort: SlidingSyncSortToFilter[sort],
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
@ -350,9 +350,18 @@ export class SlidingRoomListStoreClass extends AsyncStoreWithClient<IState> impl
|
||||||
const oldSpace = filters.spaces?.[0];
|
const oldSpace = filters.spaces?.[0];
|
||||||
filters.spaces = (activeSpace && activeSpace != MetaSpace.Home) ? [activeSpace] : undefined;
|
filters.spaces = (activeSpace && activeSpace != MetaSpace.Home) ? [activeSpace] : undefined;
|
||||||
if (oldSpace !== activeSpace) {
|
if (oldSpace !== activeSpace) {
|
||||||
|
// include subspaces in this list
|
||||||
|
this.context.spaceStore.traverseSpace(activeSpace, (roomId: string) => {
|
||||||
|
if (roomId === activeSpace) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filters.spaces.push(roomId); // add subspace
|
||||||
|
}, false);
|
||||||
|
|
||||||
this.emit(LISTS_LOADING_EVENT, tagId, true);
|
this.emit(LISTS_LOADING_EVENT, tagId, true);
|
||||||
SlidingSyncManager.instance.ensureListRegistered(
|
const index = this.context.slidingSyncManager.getOrAllocateListIndex(tagId);
|
||||||
SlidingSyncManager.instance.getOrAllocateListIndex(tagId),
|
this.context.slidingSyncManager.ensureListRegistered(
|
||||||
|
index,
|
||||||
{
|
{
|
||||||
filters: filters,
|
filters: filters,
|
||||||
},
|
},
|
||||||
|
|
|
@ -74,14 +74,14 @@ export const VoiceBroadcastPlaybackBody: React.FC<VoiceBroadcastPlaybackBodyProp
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_VoiceBroadcastPlaybackBody">
|
<div className="mx_VoiceBroadcastBody">
|
||||||
<VoiceBroadcastHeader
|
<VoiceBroadcastHeader
|
||||||
live={live}
|
live={live}
|
||||||
sender={sender}
|
sender={sender}
|
||||||
room={room}
|
room={room}
|
||||||
showBroadcast={true}
|
showBroadcast={true}
|
||||||
/>
|
/>
|
||||||
<div className="mx_VoiceBroadcastPlaybackBody_controls">
|
<div className="mx_VoiceBroadcastBody_controls">
|
||||||
{ control }
|
{ control }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,7 +27,7 @@ export const VoiceBroadcastRecordingBody: React.FC<VoiceBroadcastRecordingBodyPr
|
||||||
} = useVoiceBroadcastRecording(recording);
|
} = useVoiceBroadcastRecording(recording);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mx_VoiceBroadcastRecordingBody">
|
<div className="mx_VoiceBroadcastBody">
|
||||||
<VoiceBroadcastHeader
|
<VoiceBroadcastHeader
|
||||||
live={live}
|
live={live}
|
||||||
sender={sender}
|
sender={sender}
|
||||||
|
|
|
@ -52,15 +52,15 @@ export const VoiceBroadcastRecordingPip: React.FC<VoiceBroadcastRecordingPipProp
|
||||||
: <VoiceBroadcastControl onClick={toggleRecording} icon={PauseIcon} label={_t("pause voice broadcast")} />;
|
: <VoiceBroadcastControl onClick={toggleRecording} icon={PauseIcon} label={_t("pause voice broadcast")} />;
|
||||||
|
|
||||||
return <div
|
return <div
|
||||||
className="mx_VoiceBroadcastRecordingPip"
|
className="mx_VoiceBroadcastBody mx_VoiceBroadcastBody--pip"
|
||||||
>
|
>
|
||||||
<VoiceBroadcastHeader
|
<VoiceBroadcastHeader
|
||||||
live={live}
|
live={live}
|
||||||
sender={sender}
|
sender={sender}
|
||||||
room={room}
|
room={room}
|
||||||
/>
|
/>
|
||||||
<hr className="mx_VoiceBroadcastRecordingPip_divider" />
|
<hr className="mx_VoiceBroadcastBody_divider" />
|
||||||
<div className="mx_VoiceBroadcastRecordingPip_controls">
|
<div className="mx_VoiceBroadcastBody_controls">
|
||||||
{ toggleControl }
|
{ toggleControl }
|
||||||
<VoiceBroadcastControl
|
<VoiceBroadcastControl
|
||||||
icon={StopIcon}
|
icon={StopIcon}
|
||||||
|
|
|
@ -68,7 +68,7 @@ export const useVoiceBroadcastRecording = (recording: VoiceBroadcastRecording) =
|
||||||
const live = [
|
const live = [
|
||||||
VoiceBroadcastInfoState.Started,
|
VoiceBroadcastInfoState.Started,
|
||||||
VoiceBroadcastInfoState.Paused,
|
VoiceBroadcastInfoState.Paused,
|
||||||
VoiceBroadcastInfoState.Running,
|
VoiceBroadcastInfoState.Resumed,
|
||||||
].includes(recordingState);
|
].includes(recordingState);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -49,7 +49,7 @@ export const VoiceBroadcastChunkEventType = "io.element.voice_broadcast_chunk";
|
||||||
export enum VoiceBroadcastInfoState {
|
export enum VoiceBroadcastInfoState {
|
||||||
Started = "started",
|
Started = "started",
|
||||||
Paused = "paused",
|
Paused = "paused",
|
||||||
Running = "running",
|
Resumed = "resumed",
|
||||||
Stopped = "stopped",
|
Stopped = "stopped",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,15 +105,15 @@ export class VoiceBroadcastRecording
|
||||||
public async resume(): Promise<void> {
|
public async resume(): Promise<void> {
|
||||||
if (this.state !== VoiceBroadcastInfoState.Paused) return;
|
if (this.state !== VoiceBroadcastInfoState.Paused) return;
|
||||||
|
|
||||||
this.setState(VoiceBroadcastInfoState.Running);
|
this.setState(VoiceBroadcastInfoState.Resumed);
|
||||||
await this.getRecorder().start();
|
await this.getRecorder().start();
|
||||||
await this.sendInfoStateEvent(VoiceBroadcastInfoState.Running);
|
await this.sendInfoStateEvent(VoiceBroadcastInfoState.Resumed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toggle = async (): Promise<void> => {
|
public toggle = async (): Promise<void> => {
|
||||||
if (this.getState() === VoiceBroadcastInfoState.Paused) return this.resume();
|
if (this.getState() === VoiceBroadcastInfoState.Paused) return this.resume();
|
||||||
|
|
||||||
if ([VoiceBroadcastInfoState.Started, VoiceBroadcastInfoState.Running].includes(this.getState())) {
|
if ([VoiceBroadcastInfoState.Started, VoiceBroadcastInfoState.Resumed].includes(this.getState())) {
|
||||||
return this.pause();
|
return this.pause();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
319
test/stores/room-list/SlidingRoomListStore-test.ts
Normal file
319
test/stores/room-list/SlidingRoomListStore-test.ts
Normal file
|
@ -0,0 +1,319 @@
|
||||||
|
/*
|
||||||
|
Copyright 2022 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
import { mocked } from 'jest-mock';
|
||||||
|
import { SlidingSync, SlidingSyncEvent } from 'matrix-js-sdk/src/sliding-sync';
|
||||||
|
import { Room } from 'matrix-js-sdk/src/matrix';
|
||||||
|
|
||||||
|
import {
|
||||||
|
LISTS_UPDATE_EVENT,
|
||||||
|
SlidingRoomListStoreClass,
|
||||||
|
SlidingSyncSortToFilter,
|
||||||
|
} from "../../../src/stores/room-list/SlidingRoomListStore";
|
||||||
|
import { SpaceStoreClass } from "../../../src/stores/spaces/SpaceStore";
|
||||||
|
import { MockEventEmitter, stubClient, untilEmission } from "../../test-utils";
|
||||||
|
import { TestSdkContext } from '../../TestSdkContext';
|
||||||
|
import { SlidingSyncManager } from '../../../src/SlidingSyncManager';
|
||||||
|
import { RoomViewStore } from '../../../src/stores/RoomViewStore';
|
||||||
|
import { MatrixDispatcher } from '../../../src/dispatcher/dispatcher';
|
||||||
|
import { SortAlgorithm } from '../../../src/stores/room-list/algorithms/models';
|
||||||
|
import { DefaultTagID, TagID } from '../../../src/stores/room-list/models';
|
||||||
|
import { UPDATE_SELECTED_SPACE } from '../../../src/stores/spaces';
|
||||||
|
import { LISTS_LOADING_EVENT } from '../../../src/stores/room-list/RoomListStore';
|
||||||
|
import { UPDATE_EVENT } from '../../../src/stores/AsyncStore';
|
||||||
|
|
||||||
|
jest.mock('../../../src/SlidingSyncManager');
|
||||||
|
const MockSlidingSyncManager = <jest.Mock<SlidingSyncManager>><unknown>SlidingSyncManager;
|
||||||
|
|
||||||
|
describe("SlidingRoomListStore", () => {
|
||||||
|
let store: SlidingRoomListStoreClass;
|
||||||
|
let context: TestSdkContext;
|
||||||
|
let dis: MatrixDispatcher;
|
||||||
|
let activeSpace: string;
|
||||||
|
let tagIdToIndex = {};
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
context = new TestSdkContext();
|
||||||
|
context.client = stubClient();
|
||||||
|
context._SpaceStore = new MockEventEmitter<SpaceStoreClass>({
|
||||||
|
traverseSpace: jest.fn(),
|
||||||
|
get activeSpace() {
|
||||||
|
return activeSpace;
|
||||||
|
},
|
||||||
|
}) as SpaceStoreClass;
|
||||||
|
context._SlidingSyncManager = new MockSlidingSyncManager();
|
||||||
|
context._SlidingSyncManager.slidingSync = mocked(new MockEventEmitter({
|
||||||
|
getListData: jest.fn(),
|
||||||
|
}) as unknown as SlidingSync);
|
||||||
|
context._RoomViewStore = mocked(new MockEventEmitter({
|
||||||
|
getRoomId: jest.fn(),
|
||||||
|
}) as unknown as RoomViewStore);
|
||||||
|
|
||||||
|
// mock implementations to allow the store to map tag IDs to sliding sync list indexes and vice versa
|
||||||
|
let index = 0;
|
||||||
|
tagIdToIndex = {};
|
||||||
|
mocked(context._SlidingSyncManager.getOrAllocateListIndex).mockImplementation((listId: string): number => {
|
||||||
|
if (tagIdToIndex[listId] != null) {
|
||||||
|
return tagIdToIndex[listId];
|
||||||
|
}
|
||||||
|
tagIdToIndex[listId] = index;
|
||||||
|
index++;
|
||||||
|
return index;
|
||||||
|
});
|
||||||
|
mocked(context.slidingSyncManager.listIdForIndex).mockImplementation((i) => {
|
||||||
|
for (const tagId in tagIdToIndex) {
|
||||||
|
const j = tagIdToIndex[tagId];
|
||||||
|
if (i === j) {
|
||||||
|
return tagId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
mocked(context._SlidingSyncManager.ensureListRegistered).mockResolvedValue({
|
||||||
|
ranges: [[0, 10]],
|
||||||
|
});
|
||||||
|
|
||||||
|
dis = new MatrixDispatcher();
|
||||||
|
store = new SlidingRoomListStoreClass(dis, context);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("spaces", () => {
|
||||||
|
it("alters 'filters.spaces' on the DefaultTagID.Untagged list when the selected space changes", async () => {
|
||||||
|
await store.start(); // call onReady
|
||||||
|
const spaceRoomId = "!foo:bar";
|
||||||
|
|
||||||
|
const p = untilEmission(store, LISTS_LOADING_EVENT, (listName, isLoading) => {
|
||||||
|
return listName === DefaultTagID.Untagged && !isLoading;
|
||||||
|
});
|
||||||
|
|
||||||
|
// change the active space
|
||||||
|
activeSpace = spaceRoomId;
|
||||||
|
context._SpaceStore.emit(UPDATE_SELECTED_SPACE, spaceRoomId, false);
|
||||||
|
await p;
|
||||||
|
|
||||||
|
expect(context._SlidingSyncManager.ensureListRegistered).toHaveBeenCalledWith(
|
||||||
|
tagIdToIndex[DefaultTagID.Untagged],
|
||||||
|
{
|
||||||
|
filters: expect.objectContaining({
|
||||||
|
spaces: [spaceRoomId],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("alters 'filters.spaces' on the DefaultTagID.Untagged list if it loads with an active space", async () => {
|
||||||
|
// change the active space before we are ready
|
||||||
|
const spaceRoomId = "!foo2:bar";
|
||||||
|
activeSpace = spaceRoomId;
|
||||||
|
const p = untilEmission(store, LISTS_LOADING_EVENT, (listName, isLoading) => {
|
||||||
|
return listName === DefaultTagID.Untagged && !isLoading;
|
||||||
|
});
|
||||||
|
await store.start(); // call onReady
|
||||||
|
await p;
|
||||||
|
expect(context._SlidingSyncManager.ensureListRegistered).toHaveBeenCalledWith(
|
||||||
|
tagIdToIndex[DefaultTagID.Untagged],
|
||||||
|
expect.objectContaining({
|
||||||
|
filters: expect.objectContaining({
|
||||||
|
spaces: [spaceRoomId],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("includes subspaces in 'filters.spaces' when the selected space has subspaces", async () => {
|
||||||
|
await store.start(); // call onReady
|
||||||
|
const spaceRoomId = "!foo:bar";
|
||||||
|
const subSpace1 = "!ss1:bar";
|
||||||
|
const subSpace2 = "!ss2:bar";
|
||||||
|
|
||||||
|
const p = untilEmission(store, LISTS_LOADING_EVENT, (listName, isLoading) => {
|
||||||
|
return listName === DefaultTagID.Untagged && !isLoading;
|
||||||
|
});
|
||||||
|
|
||||||
|
mocked(context._SpaceStore.traverseSpace).mockImplementation(
|
||||||
|
(spaceId: string, fn: (roomId: string) => void) => {
|
||||||
|
if (spaceId === spaceRoomId) {
|
||||||
|
fn(subSpace1);
|
||||||
|
fn(subSpace2);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// change the active space
|
||||||
|
activeSpace = spaceRoomId;
|
||||||
|
context._SpaceStore.emit(UPDATE_SELECTED_SPACE, spaceRoomId, false);
|
||||||
|
await p;
|
||||||
|
|
||||||
|
expect(context._SlidingSyncManager.ensureListRegistered).toHaveBeenCalledWith(
|
||||||
|
tagIdToIndex[DefaultTagID.Untagged],
|
||||||
|
{
|
||||||
|
filters: expect.objectContaining({
|
||||||
|
spaces: [spaceRoomId, subSpace1, subSpace2],
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("setTagSorting alters the 'sort' option in the list", async () => {
|
||||||
|
mocked(context._SlidingSyncManager.getOrAllocateListIndex).mockReturnValue(0);
|
||||||
|
const tagId: TagID = "foo";
|
||||||
|
await store.setTagSorting(tagId, SortAlgorithm.Alphabetic);
|
||||||
|
expect(context._SlidingSyncManager.ensureListRegistered).toBeCalledWith(0, {
|
||||||
|
sort: SlidingSyncSortToFilter[SortAlgorithm.Alphabetic],
|
||||||
|
});
|
||||||
|
expect(store.getTagSorting(tagId)).toEqual(SortAlgorithm.Alphabetic);
|
||||||
|
|
||||||
|
await store.setTagSorting(tagId, SortAlgorithm.Recent);
|
||||||
|
expect(context._SlidingSyncManager.ensureListRegistered).toBeCalledWith(0, {
|
||||||
|
sort: SlidingSyncSortToFilter[SortAlgorithm.Recent],
|
||||||
|
});
|
||||||
|
expect(store.getTagSorting(tagId)).toEqual(SortAlgorithm.Recent);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("getTagsForRoom gets the tags for the room", async () => {
|
||||||
|
await store.start();
|
||||||
|
const untaggedIndex = context._SlidingSyncManager.getOrAllocateListIndex(DefaultTagID.Untagged);
|
||||||
|
const favIndex = context._SlidingSyncManager.getOrAllocateListIndex(DefaultTagID.Favourite);
|
||||||
|
const roomA = "!a:localhost";
|
||||||
|
const roomB = "!b:localhost";
|
||||||
|
const indexToListData = {
|
||||||
|
[untaggedIndex]: {
|
||||||
|
joinedCount: 10,
|
||||||
|
roomIndexToRoomId: {
|
||||||
|
0: roomA,
|
||||||
|
1: roomB,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[favIndex]: {
|
||||||
|
joinedCount: 2,
|
||||||
|
roomIndexToRoomId: {
|
||||||
|
0: roomB,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
mocked(context._SlidingSyncManager.slidingSync.getListData).mockImplementation((i: number) => {
|
||||||
|
return indexToListData[i] || null;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(store.getTagsForRoom(new Room(roomA, context.client, context.client.getUserId()))).toEqual(
|
||||||
|
[DefaultTagID.Untagged],
|
||||||
|
);
|
||||||
|
expect(store.getTagsForRoom(new Room(roomB, context.client, context.client.getUserId()))).toEqual(
|
||||||
|
[DefaultTagID.Favourite, DefaultTagID.Untagged],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("emits LISTS_UPDATE_EVENT when slidingSync lists update", async () => {
|
||||||
|
await store.start();
|
||||||
|
const roomA = "!a:localhost";
|
||||||
|
const roomB = "!b:localhost";
|
||||||
|
const roomC = "!c:localhost";
|
||||||
|
const tagId = DefaultTagID.Favourite;
|
||||||
|
const listIndex = context.slidingSyncManager.getOrAllocateListIndex(tagId);
|
||||||
|
const joinCount = 10;
|
||||||
|
const roomIndexToRoomId = { // mixed to ensure we sort
|
||||||
|
1: roomB,
|
||||||
|
2: roomC,
|
||||||
|
0: roomA,
|
||||||
|
};
|
||||||
|
const rooms = [
|
||||||
|
new Room(roomA, context.client, context.client.getUserId()),
|
||||||
|
new Room(roomB, context.client, context.client.getUserId()),
|
||||||
|
new Room(roomC, context.client, context.client.getUserId()),
|
||||||
|
];
|
||||||
|
mocked(context.client.getRoom).mockImplementation((roomId: string) => {
|
||||||
|
switch (roomId) {
|
||||||
|
case roomA:
|
||||||
|
return rooms[0];
|
||||||
|
case roomB:
|
||||||
|
return rooms[1];
|
||||||
|
case roomC:
|
||||||
|
return rooms[2];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
const p = untilEmission(store, LISTS_UPDATE_EVENT);
|
||||||
|
context.slidingSyncManager.slidingSync.emit(SlidingSyncEvent.List, listIndex, joinCount, roomIndexToRoomId);
|
||||||
|
await p;
|
||||||
|
expect(store.getCount(tagId)).toEqual(joinCount);
|
||||||
|
expect(store.orderedLists[tagId]).toEqual(rooms);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets the sticky room on the basis of the viewed room in RoomViewStore", async () => {
|
||||||
|
await store.start();
|
||||||
|
// seed the store with 3 rooms
|
||||||
|
const roomIdA = "!a:localhost";
|
||||||
|
const roomIdB = "!b:localhost";
|
||||||
|
const roomIdC = "!c:localhost";
|
||||||
|
const tagId = DefaultTagID.Favourite;
|
||||||
|
const listIndex = context.slidingSyncManager.getOrAllocateListIndex(tagId);
|
||||||
|
const joinCount = 10;
|
||||||
|
const roomIndexToRoomId = { // mixed to ensure we sort
|
||||||
|
1: roomIdB,
|
||||||
|
2: roomIdC,
|
||||||
|
0: roomIdA,
|
||||||
|
};
|
||||||
|
const roomA = new Room(roomIdA, context.client, context.client.getUserId());
|
||||||
|
const roomB = new Room(roomIdB, context.client, context.client.getUserId());
|
||||||
|
const roomC = new Room(roomIdC, context.client, context.client.getUserId());
|
||||||
|
mocked(context.client.getRoom).mockImplementation((roomId: string) => {
|
||||||
|
switch (roomId) {
|
||||||
|
case roomIdA:
|
||||||
|
return roomA;
|
||||||
|
case roomIdB:
|
||||||
|
return roomB;
|
||||||
|
case roomIdC:
|
||||||
|
return roomC;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
mocked(context._SlidingSyncManager.slidingSync.getListData).mockImplementation((i: number) => {
|
||||||
|
if (i !== listIndex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
roomIndexToRoomId: roomIndexToRoomId,
|
||||||
|
joinedCount: joinCount,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
let p = untilEmission(store, LISTS_UPDATE_EVENT);
|
||||||
|
context.slidingSyncManager.slidingSync.emit(SlidingSyncEvent.List, listIndex, joinCount, roomIndexToRoomId);
|
||||||
|
await p;
|
||||||
|
expect(store.orderedLists[tagId]).toEqual([roomA, roomB, roomC]);
|
||||||
|
|
||||||
|
// make roomB sticky and inform the store
|
||||||
|
mocked(context.roomViewStore.getRoomId).mockReturnValue(roomIdB);
|
||||||
|
context.roomViewStore.emit(UPDATE_EVENT);
|
||||||
|
|
||||||
|
// bump room C to the top, room B should not move from i=1 despite the list update saying to
|
||||||
|
roomIndexToRoomId[0] = roomIdC;
|
||||||
|
roomIndexToRoomId[1] = roomIdA;
|
||||||
|
roomIndexToRoomId[2] = roomIdB;
|
||||||
|
p = untilEmission(store, LISTS_UPDATE_EVENT);
|
||||||
|
context.slidingSyncManager.slidingSync.emit(SlidingSyncEvent.List, listIndex, joinCount, roomIndexToRoomId);
|
||||||
|
await p;
|
||||||
|
|
||||||
|
// check that B didn't move and that A was put below B
|
||||||
|
expect(store.orderedLists[tagId]).toEqual([roomC, roomB, roomA]);
|
||||||
|
|
||||||
|
// make room C sticky: rooms should move as a result, without needing an additional list update
|
||||||
|
mocked(context.roomViewStore.getRoomId).mockReturnValue(roomIdC);
|
||||||
|
p = untilEmission(store, LISTS_UPDATE_EVENT);
|
||||||
|
context.roomViewStore.emit(UPDATE_EVENT);
|
||||||
|
await p;
|
||||||
|
expect(store.orderedLists[tagId].map((r) => r.roomId)).toEqual([roomC, roomA, roomB].map((r) => r.roomId));
|
||||||
|
});
|
||||||
|
});
|
|
@ -21,6 +21,26 @@ import { MatrixClient, User } from "matrix-js-sdk/src/matrix";
|
||||||
|
|
||||||
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
import { MatrixClientPeg } from "../../src/MatrixClientPeg";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mocked generic class with a real EventEmitter.
|
||||||
|
* Useful for mocks which need event emitters.
|
||||||
|
*/
|
||||||
|
export class MockEventEmitter<T> extends EventEmitter {
|
||||||
|
/**
|
||||||
|
* Construct a new event emitter with additional properties/functions. The event emitter functions
|
||||||
|
* like .emit and .on will be real.
|
||||||
|
* @param mockProperties An object with the mock property or function implementations. 'getters'
|
||||||
|
* are correctly cloned to this event emitter.
|
||||||
|
*/
|
||||||
|
constructor(mockProperties: Partial<Record<MethodKeysOf<T>|PropertyKeysOf<T>, unknown>> = {}) {
|
||||||
|
super();
|
||||||
|
// We must use defineProperties and not assign as the former clones getters correctly,
|
||||||
|
// whereas the latter invokes the getter and sets the return value permanently on the
|
||||||
|
// destination object.
|
||||||
|
Object.defineProperties(this, Object.getOwnPropertyDescriptors(mockProperties));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mock client with real event emitter
|
* Mock client with real event emitter
|
||||||
* useful for testing code that listens
|
* useful for testing code that listens
|
||||||
|
|
|
@ -50,7 +50,7 @@ describe("VoiceBroadcastRecordingBody", () => {
|
||||||
room: roomId,
|
room: roomId,
|
||||||
user: userId,
|
user: userId,
|
||||||
});
|
});
|
||||||
recording = new VoiceBroadcastRecording(infoEvent, client, VoiceBroadcastInfoState.Running);
|
recording = new VoiceBroadcastRecording(infoEvent, client, VoiceBroadcastInfoState.Resumed);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when rendering a live broadcast", () => {
|
describe("when rendering a live broadcast", () => {
|
||||||
|
|
|
@ -118,7 +118,7 @@ describe("VoiceBroadcastRecordingPip", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should resume the recording", () => {
|
it("should resume the recording", () => {
|
||||||
expect(recording.getState()).toBe(VoiceBroadcastInfoState.Running);
|
expect(recording.getState()).toBe(VoiceBroadcastInfoState.Resumed);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
exports[`VoiceBroadcastPlaybackBody when rendering a 0 broadcast should render as expected 1`] = `
|
exports[`VoiceBroadcastPlaybackBody when rendering a 0 broadcast should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastPlaybackBody"
|
class="mx_VoiceBroadcastBody"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastHeader"
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
@ -51,7 +51,7 @@ exports[`VoiceBroadcastPlaybackBody when rendering a 0 broadcast should render a
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastPlaybackBody_controls"
|
class="mx_VoiceBroadcastBody_controls"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-label="resume voice broadcast"
|
aria-label="resume voice broadcast"
|
||||||
|
@ -71,7 +71,7 @@ exports[`VoiceBroadcastPlaybackBody when rendering a 0 broadcast should render a
|
||||||
exports[`VoiceBroadcastPlaybackBody when rendering a 1 broadcast should render as expected 1`] = `
|
exports[`VoiceBroadcastPlaybackBody when rendering a 1 broadcast should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastPlaybackBody"
|
class="mx_VoiceBroadcastBody"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastHeader"
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
@ -119,7 +119,7 @@ exports[`VoiceBroadcastPlaybackBody when rendering a 1 broadcast should render a
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastPlaybackBody_controls"
|
class="mx_VoiceBroadcastBody_controls"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-label="pause voice broadcast"
|
aria-label="pause voice broadcast"
|
||||||
|
@ -139,7 +139,7 @@ exports[`VoiceBroadcastPlaybackBody when rendering a 1 broadcast should render a
|
||||||
exports[`VoiceBroadcastPlaybackBody when rendering a buffering voice broadcast should render as expected 1`] = `
|
exports[`VoiceBroadcastPlaybackBody when rendering a buffering voice broadcast should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastPlaybackBody"
|
class="mx_VoiceBroadcastBody"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastHeader"
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
@ -187,7 +187,7 @@ exports[`VoiceBroadcastPlaybackBody when rendering a buffering voice broadcast s
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastPlaybackBody_controls"
|
class="mx_VoiceBroadcastBody_controls"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_Spinner"
|
class="mx_Spinner"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
exports[`VoiceBroadcastRecordingBody when rendering a live broadcast should render the expected HTML 1`] = `
|
exports[`VoiceBroadcastRecordingBody when rendering a live broadcast should render the expected HTML 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastRecordingBody"
|
class="mx_VoiceBroadcastBody"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastHeader"
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
exports[`VoiceBroadcastRecordingPip when rendering a paused recording should render as expected 1`] = `
|
exports[`VoiceBroadcastRecordingPip when rendering a paused recording should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastRecordingPip"
|
class="mx_VoiceBroadcastBody mx_VoiceBroadcastBody--pip"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastHeader"
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
@ -43,10 +43,10 @@ exports[`VoiceBroadcastRecordingPip when rendering a paused recording should ren
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr
|
<hr
|
||||||
class="mx_VoiceBroadcastRecordingPip_divider"
|
class="mx_VoiceBroadcastBody_divider"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastRecordingPip_controls"
|
class="mx_VoiceBroadcastBody_controls"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-label="resume voice broadcast"
|
aria-label="resume voice broadcast"
|
||||||
|
@ -76,7 +76,7 @@ exports[`VoiceBroadcastRecordingPip when rendering a paused recording should ren
|
||||||
exports[`VoiceBroadcastRecordingPip when rendering a started recording should render as expected 1`] = `
|
exports[`VoiceBroadcastRecordingPip when rendering a started recording should render as expected 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastRecordingPip"
|
class="mx_VoiceBroadcastBody mx_VoiceBroadcastBody--pip"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastHeader"
|
class="mx_VoiceBroadcastHeader"
|
||||||
|
@ -116,10 +116,10 @@ exports[`VoiceBroadcastRecordingPip when rendering a started recording should re
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr
|
<hr
|
||||||
class="mx_VoiceBroadcastRecordingPip_divider"
|
class="mx_VoiceBroadcastBody_divider"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="mx_VoiceBroadcastRecordingPip_controls"
|
class="mx_VoiceBroadcastBody_controls"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
aria-label="pause voice broadcast"
|
aria-label="pause voice broadcast"
|
||||||
|
|
|
@ -190,9 +190,9 @@ describe("VoiceBroadcastPlayback", () => {
|
||||||
onStateChanged = jest.fn();
|
onStateChanged = jest.fn();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when there is a running broadcast without chunks yet", () => {
|
describe(`when there is a ${VoiceBroadcastInfoState.Resumed} broadcast without chunks yet`, () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
infoEvent = mkInfoEvent(VoiceBroadcastInfoState.Running);
|
infoEvent = mkInfoEvent(VoiceBroadcastInfoState.Resumed);
|
||||||
playback = mkPlayback();
|
playback = mkPlayback();
|
||||||
setUpChunkEvents([]);
|
setUpChunkEvents([]);
|
||||||
});
|
});
|
||||||
|
@ -236,9 +236,9 @@ describe("VoiceBroadcastPlayback", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("when there is a running voice broadcast with some chunks", () => {
|
describe(`when there is a ${VoiceBroadcastInfoState.Resumed} voice broadcast with some chunks`, () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
infoEvent = mkInfoEvent(VoiceBroadcastInfoState.Running);
|
infoEvent = mkInfoEvent(VoiceBroadcastInfoState.Resumed);
|
||||||
playback = mkPlayback();
|
playback = mkPlayback();
|
||||||
setUpChunkEvents([chunk2Event, chunk0Event, chunk1Event]);
|
setUpChunkEvents([chunk2Event, chunk0Event, chunk1Event]);
|
||||||
});
|
});
|
||||||
|
|
|
@ -423,15 +423,15 @@ describe("VoiceBroadcastRecording", () => {
|
||||||
await action();
|
await action();
|
||||||
});
|
});
|
||||||
|
|
||||||
itShouldBeInState(VoiceBroadcastInfoState.Running);
|
itShouldBeInState(VoiceBroadcastInfoState.Resumed);
|
||||||
itShouldSendAnInfoEvent(VoiceBroadcastInfoState.Running);
|
itShouldSendAnInfoEvent(VoiceBroadcastInfoState.Resumed);
|
||||||
|
|
||||||
it("should start the recorder", () => {
|
it("should start the recorder", () => {
|
||||||
expect(mocked(voiceBroadcastRecorder.start)).toHaveBeenCalled();
|
expect(mocked(voiceBroadcastRecorder.start)).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should emit a running state changed event", () => {
|
it(`should emit a ${VoiceBroadcastInfoState.Resumed} state changed event`, () => {
|
||||||
expect(onStateChanged).toHaveBeenCalledWith(VoiceBroadcastInfoState.Running);
|
expect(onStateChanged).toHaveBeenCalledWith(VoiceBroadcastInfoState.Resumed);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -121,7 +121,7 @@ describe("hasRoomLiveVoiceBroadcast", () => {
|
||||||
// all there are kind of live states
|
// all there are kind of live states
|
||||||
VoiceBroadcastInfoState.Started,
|
VoiceBroadcastInfoState.Started,
|
||||||
VoiceBroadcastInfoState.Paused,
|
VoiceBroadcastInfoState.Paused,
|
||||||
VoiceBroadcastInfoState.Running,
|
VoiceBroadcastInfoState.Resumed,
|
||||||
])("when there is a live broadcast (%s) from the current user", (state: VoiceBroadcastInfoState) => {
|
])("when there is a live broadcast (%s) from the current user", (state: VoiceBroadcastInfoState) => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
addVoiceBroadcastInfoEvent(state, client.getUserId());
|
addVoiceBroadcastInfoEvent(state, client.getUserId());
|
||||||
|
@ -132,7 +132,7 @@ describe("hasRoomLiveVoiceBroadcast", () => {
|
||||||
|
|
||||||
describe("when there was a live broadcast, that has been stopped", () => {
|
describe("when there was a live broadcast, that has been stopped", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
addVoiceBroadcastInfoEvent(VoiceBroadcastInfoState.Running, client.getUserId());
|
addVoiceBroadcastInfoEvent(VoiceBroadcastInfoState.Resumed, client.getUserId());
|
||||||
addVoiceBroadcastInfoEvent(VoiceBroadcastInfoState.Stopped, client.getUserId());
|
addVoiceBroadcastInfoEvent(VoiceBroadcastInfoState.Stopped, client.getUserId());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ describe("hasRoomLiveVoiceBroadcast", () => {
|
||||||
|
|
||||||
describe("when there is a live broadcast from another user", () => {
|
describe("when there is a live broadcast from another user", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
addVoiceBroadcastInfoEvent(VoiceBroadcastInfoState.Running, otherUserId);
|
addVoiceBroadcastInfoEvent(VoiceBroadcastInfoState.Resumed, otherUserId);
|
||||||
});
|
});
|
||||||
|
|
||||||
itShouldReturnTrueFalse();
|
itShouldReturnTrueFalse();
|
||||||
|
|
|
@ -40,7 +40,7 @@ const testCases = [
|
||||||
[
|
[
|
||||||
"@user1:example.com",
|
"@user1:example.com",
|
||||||
"@user1:example.com",
|
"@user1:example.com",
|
||||||
VoiceBroadcastInfoState.Running,
|
VoiceBroadcastInfoState.Resumed,
|
||||||
true,
|
true,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
|
@ -128,7 +128,7 @@ describe("shouldDisplayAsVoiceBroadcastTile", () => {
|
||||||
describe.each(
|
describe.each(
|
||||||
[
|
[
|
||||||
VoiceBroadcastInfoState.Paused,
|
VoiceBroadcastInfoState.Paused,
|
||||||
VoiceBroadcastInfoState.Running,
|
VoiceBroadcastInfoState.Resumed,
|
||||||
VoiceBroadcastInfoState.Stopped,
|
VoiceBroadcastInfoState.Stopped,
|
||||||
],
|
],
|
||||||
)("when a voice broadcast info event in state %s occurs", (state: VoiceBroadcastInfoState) => {
|
)("when a voice broadcast info event in state %s occurs", (state: VoiceBroadcastInfoState) => {
|
||||||
|
|
|
@ -161,7 +161,7 @@ describe("startNewVoiceBroadcastRecording", () => {
|
||||||
room.currentState.setStateEvents([
|
room.currentState.setStateEvents([
|
||||||
mkVoiceBroadcastInfoStateEvent(
|
mkVoiceBroadcastInfoStateEvent(
|
||||||
roomId,
|
roomId,
|
||||||
VoiceBroadcastInfoState.Running,
|
VoiceBroadcastInfoState.Resumed,
|
||||||
client.getUserId(),
|
client.getUserId(),
|
||||||
client.getDeviceId(),
|
client.getDeviceId(),
|
||||||
),
|
),
|
||||||
|
@ -184,7 +184,7 @@ describe("startNewVoiceBroadcastRecording", () => {
|
||||||
room.currentState.setStateEvents([
|
room.currentState.setStateEvents([
|
||||||
mkVoiceBroadcastInfoStateEvent(
|
mkVoiceBroadcastInfoStateEvent(
|
||||||
roomId,
|
roomId,
|
||||||
VoiceBroadcastInfoState.Running,
|
VoiceBroadcastInfoState.Resumed,
|
||||||
otherUserId,
|
otherUserId,
|
||||||
"ASD123",
|
"ASD123",
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in a new issue