Skip to content

Commit

Permalink
Unlabs feature pinning
Browse files Browse the repository at this point in the history
  • Loading branch information
florianduros committed Sep 10, 2024
1 parent 24fe2f2 commit 7baaafd
Show file tree
Hide file tree
Showing 24 changed files with 170 additions and 104 deletions.
4 changes: 0 additions & 4 deletions playwright/e2e/pinned-messages/pinned-messages.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ import { test } from "./index";
import { expect } from "../../element-web-test";

test.describe("Pinned messages", () => {
test.use({
labsFlags: ["feature_pinning"],
});

test("should show the empty state when there are no pinned messages", async ({ page, app, room1, util }) => {
await util.goTo(room1);
await util.openRoomInfo();
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 0 additions & 1 deletion src/TextForEvent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,6 @@ const onPinnedMessagesClick = (): void => {
};

function textForPinnedEvent(event: MatrixEvent, client: MatrixClient, allowJSX: boolean): (() => Renderable) | null {
if (!SettingsStore.getValue("feature_pinning")) return null;
const senderName = getSenderName(event);
const roomId = event.getRoomId()!;

Expand Down
3 changes: 1 addition & 2 deletions src/components/structures/RightPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import RightPanelStore from "../../stores/right-panel/RightPanelStore";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import RoomSummaryCard from "../views/right_panel/RoomSummaryCard";
import WidgetCard from "../views/right_panel/WidgetCard";
import SettingsStore from "../../settings/SettingsStore";
import MemberList from "../views/rooms/MemberList";
import UserInfo from "../views/right_panel/UserInfo";
import ThirdPartyMemberInfo from "../views/rooms/ThirdPartyMemberInfo";
Expand Down Expand Up @@ -220,7 +219,7 @@ export default class RightPanel extends React.Component<Props, IState> {
break;

case RightPanelPhases.PinnedMessages:
if (!!this.props.room && SettingsStore.getValue("feature_pinning")) {
if (!!this.props.room) {
card = (
<PinnedMessagesCard
room={this.props.room}
Expand Down
10 changes: 3 additions & 7 deletions src/components/structures/RoomView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2408,13 +2408,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
</AuxPanel>
);

const isPinningEnabled = SettingsStore.getValue<boolean>("feature_pinning");
let pinnedMessageBanner;
if (isPinningEnabled) {
pinnedMessageBanner = (
<PinnedMessageBanner room={this.state.room} permalinkCreator={this.permalinkCreator} />
);
}
const pinnedMessageBanner = (
<PinnedMessageBanner room={this.state.room} permalinkCreator={this.permalinkCreator} />
);

let messageComposer;
const showComposer =
Expand Down
3 changes: 1 addition & 2 deletions src/components/structures/grouper/MainGrouper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import DateSeparator from "../../views/messages/DateSeparator";
import HistoryTile from "../../views/rooms/HistoryTile";
import EventListSummary from "../../views/elements/EventListSummary";
import { SeparatorKind } from "../../views/messages/TimelineSeparator";
import SettingsStore from "../../../settings/SettingsStore";

const groupedStateEvents = [
EventType.RoomMember,
Expand Down Expand Up @@ -91,7 +90,7 @@ export class MainGrouper extends BaseGrouper {
return;
}

if (ev.getType() === EventType.RoomPinnedEvents && !SettingsStore.getValue("feature_pinning")) {
if (ev.getType() === EventType.RoomPinnedEvents) {
// If pinned messages are disabled, don't show the summary
return;
}
Expand Down
6 changes: 2 additions & 4 deletions src/components/views/context_menus/RoomContextMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { EchoChamber } from "../../../stores/local-echo/EchoChamber";
import { RoomNotifState } from "../../../RoomNotifs";
import Modal from "../../../Modal";
import ExportDialog from "../dialogs/ExportDialog";
import { useFeatureEnabled } from "../../../hooks/useSettings";
import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePhases";
import { RoomSettingsTab } from "../dialogs/RoomSettingsDialog";
import { useEventEmitterState } from "../../../hooks/useEventEmitter";
Expand Down Expand Up @@ -261,11 +260,10 @@ const RoomContextMenu: React.FC<IProps> = ({ room, onFinished, ...props }) => {
);
}

const pinningEnabled = useFeatureEnabled("feature_pinning");
const pinCount = usePinnedEvents(pinningEnabled ? room : undefined)?.length;
const pinCount = usePinnedEvents(room).length;

let pinsOption: JSX.Element | undefined;
if (pinningEnabled && !isVideoRoom) {
if (!isVideoRoom) {
pinsOption = (
<IconizedContextMenuOption
onClick={(ev: ButtonEvent) => {
Expand Down
22 changes: 10 additions & 12 deletions src/components/views/right_panel/LegacyRoomHeaderButtons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import { RightPanelPhases } from "../../../stores/right-panel/RightPanelStorePha
import { ActionPayload } from "../../../dispatcher/payloads";
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
import { showThreadPanel } from "../../../dispatcher/dispatch-actions/threads";
import SettingsStore from "../../../settings/SettingsStore";
import {
RoomNotificationStateStore,
UPDATE_STATUS_INDICATOR,
Expand Down Expand Up @@ -245,17 +244,16 @@ export default class LegacyRoomHeaderButtons extends HeaderButtons<IProps> {

const rightPanelPhaseButtons: Map<RightPanelPhases, any> = new Map();

if (SettingsStore.getValue("feature_pinning")) {
rightPanelPhaseButtons.set(
RightPanelPhases.PinnedMessages,
<PinnedMessagesHeaderButton
key="pinnedMessagesButton"
room={this.props.room}
isHighlighted={this.isPhase(RightPanelPhases.PinnedMessages)}
onClick={this.onPinnedMessagesClicked}
/>,
);
}
rightPanelPhaseButtons.set(
RightPanelPhases.PinnedMessages,
<PinnedMessagesHeaderButton
key="pinnedMessagesButton"
room={this.props.room}
isHighlighted={this.isPhase(RightPanelPhases.PinnedMessages)}
onClick={this.onPinnedMessagesClicked}
/>,
);

rightPanelPhaseButtons.set(
RightPanelPhases.Timeline,
<TimelineCardHeaderButton
Expand Down
25 changes: 11 additions & 14 deletions src/components/views/right_panel/RoomSummaryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import { useEventEmitterState } from "../../../hooks/useEventEmitter";
import { E2EStatus } from "../../../utils/ShieldUtils";
import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks";
import RoomContext, { TimelineRenderingType } from "../../../contexts/RoomContext";
import { useFeatureEnabled } from "../../../hooks/useSettings";
import RoomName from "../elements/RoomName";
import ExportDialog from "../dialogs/ExportDialog";
import RightPanelStore from "../../../stores/right-panel/RightPanelStore";
Expand Down Expand Up @@ -314,8 +313,7 @@ const RoomSummaryCard: React.FC<IProps> = ({
</header>
);

const pinningEnabled = useFeatureEnabled("feature_pinning");
const pinCount = usePinnedEvents(pinningEnabled ? room : undefined)?.length;
const pinCount = usePinnedEvents(room).length;

const roomTags = useEventEmitterState(RoomListStore.instance, LISTS_UPDATE_EVENT, () =>
RoomListStore.instance.getTagsForRoom(room),
Expand Down Expand Up @@ -382,17 +380,16 @@ const RoomSummaryCard: React.FC<IProps> = ({

{!isVideoRoom && (
<>
{pinningEnabled && (
<MenuItem
Icon={PinIcon}
label={_t("right_panel|pinned_messages_button")}
onSelect={onRoomPinsClick}
>
<Text as="span" size="sm">
{pinCount}
</Text>
</MenuItem>
)}
<MenuItem
Icon={PinIcon}
label={_t("right_panel|pinned_messages_button")}
onSelect={onRoomPinsClick}
>
<Text as="span" size="sm">
{pinCount}
</Text>
</MenuItem>

<MenuItem Icon={FilesIcon} label={_t("right_panel|files_button")} onSelect={onRoomFilesClick} />
</>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -267,15 +267,13 @@ export default class RolesRoomSettingsTab extends React.Component<IProps> {
[EventType.RoomServerAcl]: _td("room_settings|permissions|m.room.server_acl"),
[EventType.Reaction]: _td("room_settings|permissions|m.reaction"),
[EventType.RoomRedaction]: _td("room_settings|permissions|m.room.redaction"),
[EventType.RoomPinnedEvents]: _td("room_settings|permissions|m.room.pinned_events"),

// TODO: Enable support for m.widget event type (https://github.com/vector-im/element-web/issues/13111)
"im.vector.modular.widgets": isSpaceRoom ? null : _td("room_settings|permissions|m.widget"),
[VoiceBroadcastInfoEventType]: _td("room_settings|permissions|io.element.voice_broadcast_info"),
};

if (SettingsStore.getValue("feature_pinning")) {
plEventsToLabels[EventType.RoomPinnedEvents] = _td("room_settings|permissions|m.room.pinned_events");
}
// MSC3401: Native Group VoIP signaling
if (SettingsStore.getValue("feature_group_calls")) {
plEventsToLabels[ElementCall.CALL_EVENT_TYPE.name] = _td("room_settings|permissions|m.call");
Expand Down
1 change: 0 additions & 1 deletion src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -1464,7 +1464,6 @@
"notifications": "Enable the notifications panel in the room header",
"oidc_native_flow": "OIDC native authentication",
"oidc_native_flow_description": "⚠ WARNING: Experimental. Use OIDC native authentication when supported by the server.",
"pinning": "Message Pinning",
"release_announcement": "Release announcement",
"render_reaction_images": "Render custom images in reactions",
"render_reaction_images_description": "Sometimes referred to as \"custom emojis\".",
Expand Down
8 changes: 0 additions & 8 deletions src/settings/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -274,14 +274,6 @@ export const SETTINGS: { [setting: string]: ISetting } = {
supportedLevelsAreOrdered: true,
default: false,
},
"feature_pinning": {
isFeature: true,
labsGroup: LabGroup.Messaging,
displayName: _td("labs|pinning"),
supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG_PRIORITISED,
supportedLevelsAreOrdered: true,
default: false,
},
"feature_wysiwyg_composer": {
isFeature: true,
labsGroup: LabGroup.Messaging,
Expand Down
2 changes: 0 additions & 2 deletions src/utils/PinningUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details.
import { MatrixEvent, EventType, M_POLL_START, MatrixClient, EventTimeline, Room } from "matrix-js-sdk/src/matrix";

import { isContentActionable } from "./EventUtils";
import SettingsStore from "../settings/SettingsStore";
import { ReadPinsEventId } from "../components/views/right_panel/types";

export default class PinningUtils {
Expand Down Expand Up @@ -70,7 +69,6 @@ export default class PinningUtils {
* @private
*/
private static canPinOrUnpin(matrixClient: MatrixClient, mxEvent: MatrixEvent): boolean {
if (!SettingsStore.getValue("feature_pinning")) return false;
if (!isContentActionable(mxEvent)) return false;

const room = matrixClient.getRoom(mxEvent.getRoomId());
Expand Down
5 changes: 0 additions & 5 deletions test/TextForEvent-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ describe("TextForEvent", () => {
});

describe("TextForPinnedEvent", () => {
beforeAll(() => {
// enable feature_pinning setting
(SettingsStore.getValue as jest.Mock).mockImplementation((feature) => feature === "feature_pinning");
});

it("mentions message when a single message was pinned, with no previously pinned messages", () => {
const event = mockPinnedEvent(["message-1"]);
const plainText = textForEvent(event, mockClient);
Expand Down
16 changes: 0 additions & 16 deletions test/components/views/context_menus/MessageContextMenu-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,22 +116,6 @@ describe("MessageContextMenu", () => {
expect(screen.queryByRole("menuitem", { name: "Pin" })).toBeFalsy();
});

it("does not show pin option when pinning feature is disabled", () => {
const eventContent = createMessageEventContent("hello");
const pinnableEvent = new MatrixEvent({
type: EventType.RoomMessage,
content: eventContent,
room_id: roomId,
});

// disable pinning feature
jest.spyOn(SettingsStore, "getValue").mockReturnValue(false);

createMenu(pinnableEvent, { rightClick: true }, {}, undefined, room);

expect(screen.queryByRole("menuitem", { name: "Pin" })).toBeFalsy();
});

it("shows pin option when pinning feature is enabled", () => {
const eventContent = createMessageEventContent("hello");
const pinnableEvent = new MatrixEvent({
Expand Down
12 changes: 3 additions & 9 deletions test/components/views/right_panel/RoomSummaryCard-test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,7 @@ describe("<RoomSummaryCard />", () => {
});

describe("pinning", () => {
it("renders pins options when pinning feature is enabled", () => {
mocked(settingsHooks.useFeatureEnabled).mockImplementation((feature) => feature === "feature_pinning");
it("renders pins options", () => {
const { getByText } = getComponent();

expect(getByText("Pinned messages")).toBeInTheDocument();
Expand Down Expand Up @@ -291,9 +290,7 @@ describe("<RoomSummaryCard />", () => {
describe("video rooms", () => {
it("does not render irrelevant options for element video room", () => {
jest.spyOn(room, "isElementVideoRoom").mockReturnValue(true);
mocked(settingsHooks.useFeatureEnabled).mockImplementation(
(feature) => feature === "feature_video_rooms" || feature === "feature_pinning",
);
mocked(settingsHooks.useFeatureEnabled).mockImplementation((feature) => feature === "feature_video_rooms");
const { queryByText } = getComponent();

// options not rendered
Expand All @@ -305,10 +302,7 @@ describe("<RoomSummaryCard />", () => {
it("does not render irrelevant options for element call room", () => {
jest.spyOn(room, "isCallRoom").mockReturnValue(true);
mocked(settingsHooks.useFeatureEnabled).mockImplementation(
(feature) =>
feature === "feature_element_call_video_rooms" ||
feature === "feature_video_rooms" ||
feature === "feature_pinning",
(feature) => feature === "feature_element_call_video_rooms" || feature === "feature_video_rooms",
);
const { queryByText } = getComponent();

Expand Down
Loading

0 comments on commit 7baaafd

Please sign in to comment.