Always show back button in the right panel (#29128)
* Construct history on setCard So that back buttons are always shown in the right panel * Check card state to ensure operation is atomic * Fix tests * Fix lint * Remove null case * Fix broken test
This commit is contained in:
@@ -526,9 +526,10 @@ class Helpers {
|
||||
await expect(threadPanel).toBeVisible();
|
||||
await threadPanel.evaluate(($panel) => {
|
||||
const $button = $panel.querySelector<HTMLElement>('[data-testid="base-card-back-button"]');
|
||||
const title = $panel.querySelector<HTMLElement>(".mx_BaseCard_header_title")?.textContent;
|
||||
// If the Threads back button is present then click it - the
|
||||
// threads button can open either threads list or thread panel
|
||||
if ($button) {
|
||||
if ($button && title !== "Threads") {
|
||||
$button.click();
|
||||
}
|
||||
});
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
@@ -30,6 +30,23 @@ import { ActiveRoomChangedPayload } from "../../dispatcher/payloads/ActiveRoomCh
|
||||
import { SdkContextClass } from "../../contexts/SDKContext";
|
||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
||||
|
||||
/**
|
||||
* @see RightPanelStore#generateHistoryForPhase
|
||||
*/
|
||||
function getPhasesForPhase(phase: IRightPanelCard["phase"]): RightPanelPhases[] {
|
||||
switch (phase) {
|
||||
case RightPanelPhases.ThreadPanel:
|
||||
case RightPanelPhases.MemberList:
|
||||
case RightPanelPhases.PinnedMessages:
|
||||
return [RightPanelPhases.RoomSummary];
|
||||
case RightPanelPhases.MemberInfo:
|
||||
case RightPanelPhases.ThreePidMemberInfo:
|
||||
return [RightPanelPhases.RoomSummary, RightPanelPhases.MemberList];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class for tracking the state of the right panel between layouts and
|
||||
* sessions. This state includes a history for each room. Each history element
|
||||
@@ -134,16 +151,20 @@ export default class RightPanelStore extends ReadyWatchingStore {
|
||||
return { state: {}, phase: null };
|
||||
}
|
||||
|
||||
// Setters
|
||||
/**
|
||||
* This function behaves as following:
|
||||
* - If the same phase is sent along with a non-empty state, only the state is updated and history is retained.
|
||||
* - If the provided phase is different to the current phase:
|
||||
* - Existing history is thrown away.
|
||||
* - New card is added along with a different history, see {@link generateHistoryForPhase}
|
||||
*
|
||||
* If the right panel was set, this function also shows the right panel.
|
||||
*/
|
||||
public setCard(card: IRightPanelCard, allowClose = true, roomId?: string): void {
|
||||
const rId = roomId ?? this.viewedRoomId ?? "";
|
||||
// This function behaves as following:
|
||||
// Update state: if the same phase is send but with a state
|
||||
// Set right panel and erase history: if a "different to the current" phase is send (with or without a state)
|
||||
// If the right panel is set, this function also shows the right panel.
|
||||
const redirect = this.getVerificationRedirect(card);
|
||||
const targetPhase = redirect?.phase ?? card.phase;
|
||||
const cardState = redirect?.state ?? (Object.keys(card.state ?? {}).length === 0 ? null : card.state);
|
||||
const cardState = redirect?.state ?? (Object.keys(card.state ?? {}).length === 0 ? undefined : card.state);
|
||||
|
||||
// Checks for wrong SetRightPanelPhase requests
|
||||
if (!this.isPhaseValid(targetPhase, Boolean(rId))) return;
|
||||
@@ -155,7 +176,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
|
||||
this.emitAndUpdateSettings();
|
||||
} else if (targetPhase !== this.currentCardForRoom(rId)?.phase || !this.byRoom[rId]) {
|
||||
// Set right panel and initialize/erase history
|
||||
const history = [{ phase: targetPhase, state: cardState ?? {} }];
|
||||
const history = this.generateHistoryForPhase(targetPhase!, cardState ?? {});
|
||||
this.byRoom[rId] = { history, isOpen: true };
|
||||
this.emitAndUpdateSettings();
|
||||
} else {
|
||||
@@ -247,6 +268,31 @@ export default class RightPanelStore extends ReadyWatchingStore {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For a given phase, generates card history such that it looks
|
||||
* similar to how an user typically would reach said phase in the app.
|
||||
* eg: User would usually reach the memberlist via room-info panel, so
|
||||
* that history is added.
|
||||
*/
|
||||
private generateHistoryForPhase(
|
||||
phase: IRightPanelCard["phase"],
|
||||
cardState?: Partial<IRightPanelCardState>,
|
||||
): IRightPanelCard[] {
|
||||
const card = { phase, state: cardState };
|
||||
if (!this.isCardStateValid(card)) {
|
||||
/**
|
||||
* If the card we're adding is not valid, then we just return
|
||||
* an empty history.
|
||||
* This is to avoid a scenario where, for eg, you set a member info
|
||||
* card with invalid card state (no member) but the member list is
|
||||
* shown since the created history is valid except for the last card.
|
||||
*/
|
||||
return [];
|
||||
}
|
||||
const cards = getPhasesForPhase(phase).map((p) => ({ phase: p, state: {} }));
|
||||
return [...cards, card];
|
||||
}
|
||||
|
||||
private loadCacheFromSettings(): void {
|
||||
if (this.viewedRoomId) {
|
||||
const room = this.mxClient?.getRoom(this.viewedRoomId);
|
||||
|
||||
@@ -114,11 +114,14 @@ describe("RightPanelStore", () => {
|
||||
expect(store.isOpenForRoom("!1:example.org")).toEqual(true);
|
||||
expect(store.currentCardForRoom("!1:example.org").phase).toEqual(RightPanelPhases.RoomSummary);
|
||||
});
|
||||
it("overwrites history if changing the phase", async () => {
|
||||
it("history is generated for certain phases", async () => {
|
||||
await viewRoom("!1:example.org");
|
||||
store.setCard({ phase: RightPanelPhases.RoomSummary }, true, "!1:example.org");
|
||||
// Setting the memberlist card should also generate a history with room summary card
|
||||
store.setCard({ phase: RightPanelPhases.MemberList }, true, "!1:example.org");
|
||||
expect(store.roomPhaseHistory).toEqual([{ phase: RightPanelPhases.MemberList, state: {} }]);
|
||||
expect(store.roomPhaseHistory).toEqual([
|
||||
{ phase: RightPanelPhases.RoomSummary, state: {} },
|
||||
{ phase: RightPanelPhases.MemberList, state: {} },
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user