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 expect(threadPanel).toBeVisible();
|
||||||
await threadPanel.evaluate(($panel) => {
|
await threadPanel.evaluate(($panel) => {
|
||||||
const $button = $panel.querySelector<HTMLElement>('[data-testid="base-card-back-button"]');
|
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
|
// If the Threads back button is present then click it - the
|
||||||
// threads button can open either threads list or thread panel
|
// threads button can open either threads list or thread panel
|
||||||
if ($button) {
|
if ($button && title !== "Threads") {
|
||||||
$button.click();
|
$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 { SdkContextClass } from "../../contexts/SDKContext";
|
||||||
import { MatrixClientPeg } from "../../MatrixClientPeg";
|
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
|
* 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
|
* 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 };
|
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 {
|
public setCard(card: IRightPanelCard, allowClose = true, roomId?: string): void {
|
||||||
const rId = roomId ?? this.viewedRoomId ?? "";
|
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 redirect = this.getVerificationRedirect(card);
|
||||||
const targetPhase = redirect?.phase ?? card.phase;
|
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
|
// Checks for wrong SetRightPanelPhase requests
|
||||||
if (!this.isPhaseValid(targetPhase, Boolean(rId))) return;
|
if (!this.isPhaseValid(targetPhase, Boolean(rId))) return;
|
||||||
@@ -155,7 +176,7 @@ export default class RightPanelStore extends ReadyWatchingStore {
|
|||||||
this.emitAndUpdateSettings();
|
this.emitAndUpdateSettings();
|
||||||
} else if (targetPhase !== this.currentCardForRoom(rId)?.phase || !this.byRoom[rId]) {
|
} else if (targetPhase !== this.currentCardForRoom(rId)?.phase || !this.byRoom[rId]) {
|
||||||
// Set right panel and initialize/erase history
|
// 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.byRoom[rId] = { history, isOpen: true };
|
||||||
this.emitAndUpdateSettings();
|
this.emitAndUpdateSettings();
|
||||||
} else {
|
} 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 {
|
private loadCacheFromSettings(): void {
|
||||||
if (this.viewedRoomId) {
|
if (this.viewedRoomId) {
|
||||||
const room = this.mxClient?.getRoom(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.isOpenForRoom("!1:example.org")).toEqual(true);
|
||||||
expect(store.currentCardForRoom("!1:example.org").phase).toEqual(RightPanelPhases.RoomSummary);
|
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");
|
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");
|
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