diff --git a/res/css/views/messages/_MessageActionBar.pcss b/res/css/views/messages/_MessageActionBar.pcss index 04ef242f93..040442b8af 100644 --- a/res/css/views/messages/_MessageActionBar.pcss +++ b/res/css/views/messages/_MessageActionBar.pcss @@ -21,7 +21,6 @@ limitations under the License. --MessageActionBar-item-hover-background: $panel-actions; --MessageActionBar-item-hover-borderRadius: 6px; --MessageActionBar-item-hover-zIndex: 1; - --MessageActionBar-star-button-color: #ffa534; position: absolute; visibility: hidden; @@ -118,10 +117,6 @@ limitations under the License. color: $primary-content; } - &.mx_MessageActionBar_favouriteButton_fillstar { - color: var(--MessageActionBar-star-button-color); - } - &.mx_MessageActionBar_downloadButton { --MessageActionBar-icon-size: 14px; diff --git a/src/components/views/messages/MessageActionBar.tsx b/src/components/views/messages/MessageActionBar.tsx index a0b730b65f..e792a47221 100644 --- a/src/components/views/messages/MessageActionBar.tsx +++ b/src/components/views/messages/MessageActionBar.tsx @@ -28,7 +28,6 @@ import { Icon as EmojiIcon } from "../../../../res/img/element-icons/room/messag import { Icon as ResendIcon } from "../../../../res/img/element-icons/retry.svg"; import { Icon as ThreadIcon } from "../../../../res/img/element-icons/message/thread.svg"; import { Icon as TrashcanIcon } from "../../../../res/img/element-icons/trashcan.svg"; -import { Icon as StarIcon } from "../../../../res/img/element-icons/room/message-bar/star.svg"; import { Icon as ReplyIcon } from "../../../../res/img/element-icons/room/message-bar/reply.svg"; import { Icon as ExpandMessageIcon } from "../../../../res/img/element-icons/expand-message.svg"; import { Icon as CollapseMessageIcon } from "../../../../res/img/element-icons/collapse-message.svg"; @@ -45,7 +44,6 @@ import Resend from "../../../Resend"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import { MediaEventHelper } from "../../../utils/MediaEventHelper"; import DownloadActionButton from "./DownloadActionButton"; -import SettingsStore from "../../../settings/SettingsStore"; import { RoomPermalinkCreator } from "../../../utils/permalinks/Permalinks"; import ReplyChain from "../elements/ReplyChain"; import ReactionPicker from "../emojipicker/ReactionPicker"; @@ -55,7 +53,6 @@ import { Key } from "../../../Keyboard"; import { ALTERNATE_KEY_NAME } from "../../../accessibility/KeyboardShortcuts"; import { Action } from "../../../dispatcher/actions"; import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload"; -import useFavouriteMessages from "../../../hooks/useFavouriteMessages"; import { GetRelationsForEvent } from "../rooms/EventTile"; import { VoiceBroadcastInfoEventType } from "../../../voice-broadcast/types"; import { ButtonEvent } from "../elements/AccessibleButton"; @@ -254,42 +251,6 @@ const ReplyInThreadButton: React.FC = ({ mxEvent }) => { ); }; -interface IFavouriteButtonProp { - mxEvent: MatrixEvent; -} - -const FavouriteButton: React.FC = ({ mxEvent }) => { - const { isFavourite, toggleFavourite } = useFavouriteMessages(); - - const eventId = mxEvent.getId()!; - const classes = classNames("mx_MessageActionBar_iconButton mx_MessageActionBar_favouriteButton", { - mx_MessageActionBar_favouriteButton_fillstar: isFavourite(eventId), - }); - - const onClick = useCallback( - (e: ButtonEvent) => { - // Don't open the regular browser or our context menu on right-click - e.preventDefault(); - e.stopPropagation(); - - toggleFavourite(eventId); - }, - [toggleFavourite, eventId], - ); - - return ( - - - - ); -}; - interface IMessageActionBarProps { mxEvent: MatrixEvent; reactions?: Relations | null | undefined; @@ -518,9 +479,6 @@ export default class MessageActionBar extends React.PureComponent, ); } - if (SettingsStore.getValue("feature_favourite_messages")) { - toolbarOpts.splice(-1, 0, ); - } // XXX: Assuming that the underlying tile will be a media event if it is eligible media. if (MediaEventHelper.isEligible(this.props.mxEvent)) { diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 8c0d797df6..0d905ccdd2 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -78,7 +78,6 @@ interface IState { sublists: ITagMap; currentRoomId?: string; suggestedRooms: ISuggestedRoom[]; - feature_favourite_messages: boolean; } export const TAG_ORDER: TagID[] = [ @@ -443,7 +442,6 @@ const TAG_AESTHETICS: TagAestheticsMap = { export default class RoomList extends React.PureComponent { private dispatcherRef?: string; private treeRef = createRef(); - private favouriteMessageWatcher?: string; public static contextType = MatrixClientContext; public context!: React.ContextType; @@ -454,7 +452,6 @@ export default class RoomList extends React.PureComponent { this.state = { sublists: {}, suggestedRooms: SpaceStore.instance.suggestedRooms, - feature_favourite_messages: SettingsStore.getValue("feature_favourite_messages"), }; } @@ -463,20 +460,12 @@ export default class RoomList extends React.PureComponent { SdkContextClass.instance.roomViewStore.on(UPDATE_EVENT, this.onRoomViewStoreUpdate); SpaceStore.instance.on(UPDATE_SUGGESTED_ROOMS, this.updateSuggestedRooms); RoomListStore.instance.on(LISTS_UPDATE_EVENT, this.updateLists); - this.favouriteMessageWatcher = SettingsStore.watchSetting( - "feature_favourite_messages", - null, - (...[, , , value]) => { - this.setState({ feature_favourite_messages: value }); - }, - ); this.updateLists(); // trigger the first update } public componentWillUnmount(): void { SpaceStore.instance.off(UPDATE_SUGGESTED_ROOMS, this.updateSuggestedRooms); RoomListStore.instance.off(LISTS_UPDATE_EVENT, this.updateLists); - if (this.favouriteMessageWatcher) SettingsStore.unwatchSetting(this.favouriteMessageWatcher); if (this.dispatcherRef) defaultDispatcher.unregister(this.dispatcherRef); SdkContextClass.instance.roomViewStore.off(UPDATE_EVENT, this.onRoomViewStoreUpdate); } @@ -607,29 +596,6 @@ export default class RoomList extends React.PureComponent { ); }); } - private renderFavoriteMessagesList(): ReactComponentElement[] { - const avatar = ( - - ); - - return [ - ""} - key="favMessagesTile_key" - />, - ]; - } private renderSublists(): React.ReactElement[] { // show a skeleton UI if the user is in no rooms and they are not filtering and have no suggested rooms @@ -641,8 +607,6 @@ export default class RoomList extends React.PureComponent { let extraTiles: ReactComponentElement[] | undefined; if (orderedTagId === DefaultTagID.Suggested) { extraTiles = this.renderSuggestedRooms(); - } else if (this.state.feature_favourite_messages && orderedTagId === DefaultTagID.SavedItems) { - extraTiles = this.renderFavoriteMessagesList(); } const aesthetics = TAG_AESTHETICS[orderedTagId]; diff --git a/src/hooks/useFavouriteMessages.ts b/src/hooks/useFavouriteMessages.ts deleted file mode 100644 index fe5b23dc9e..0000000000 --- a/src/hooks/useFavouriteMessages.ts +++ /dev/null @@ -1,43 +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. -*/ - -import { useState } from "react"; - -const favouriteMessageIds = JSON.parse(localStorage?.getItem("io_element_favouriteMessages") ?? "[]") as string[]; - -export default function useFavouriteMessages(): { - toggleFavourite: (eventId: string) => void; - isFavourite: (eventId: string) => boolean; -} { - const [, setX] = useState(); - - //checks if an id already exist - const isFavourite = (eventId: string): boolean => favouriteMessageIds.includes(eventId); - - const toggleFavourite = (eventId: string): void => { - isFavourite(eventId) - ? favouriteMessageIds.splice(favouriteMessageIds.indexOf(eventId), 1) - : favouriteMessageIds.push(eventId); - - //update the local storage - localStorage.setItem("io_element_favouriteMessages", JSON.stringify(favouriteMessageIds)); - - // This forces a re-render to account for changes in appearance in real-time when the favourite button is toggled - setX([]); - }; - - return { isFavourite, toggleFavourite }; -} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 4b5c15f333..a7b25faaa8 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -985,11 +985,10 @@ "Temporary implementation. Locations persist in room history.": "Temporary implementation. Locations persist in room history.", "Dynamic room predecessors": "Dynamic room predecessors", "Enable MSC3946 (to support late-arriving room archives)": "Enable MSC3946 (to support late-arriving room archives)", - "Favourite Messages": "Favourite Messages", - "Under active development.": "Under active development.", "Force 15s voice broadcast chunk length": "Force 15s voice broadcast chunk length", "Enable new native OIDC flows (Under active development)": "Enable new native OIDC flows (Under active development)", "Rust cryptography implementation": "Rust cryptography implementation", + "Under active development.": "Under active development.", "Font size": "Font size", "Use custom size": "Use custom size", "Enable Emoji suggestions while typing": "Enable Emoji suggestions while typing", @@ -2390,7 +2389,6 @@ "React": "React", "Reply in thread": "Reply in thread", "Can't create a thread from an event with an existing relation": "Can't create a thread from an event with an existing relation", - "Favourite": "Favourite", "Edit": "Edit", "Reply": "Reply", "Collapse quotes": "Collapse quotes", @@ -3246,6 +3244,7 @@ "Copy link": "Copy link", "Forget": "Forget", "Favourited": "Favourited", + "Favourite": "Favourite", "Mentions only": "Mentions only", "Copy room link": "Copy room link", "Low Priority": "Low Priority", diff --git a/src/settings/Settings.tsx b/src/settings/Settings.tsx index 6f24491c57..5ff31b602f 100644 --- a/src/settings/Settings.tsx +++ b/src/settings/Settings.tsx @@ -426,14 +426,6 @@ export const SETTINGS: { [setting: string]: ISetting } = { shouldWarn: true, default: false, }, - "feature_favourite_messages": { - isFeature: true, - labsGroup: LabGroup.Messaging, - supportedLevels: LEVELS_FEATURE, - displayName: _td("Favourite Messages"), - description: _td("Under active development."), - default: false, - }, [Features.VoiceBroadcast]: { isFeature: true, labsGroup: LabGroup.Messaging, diff --git a/test/components/views/messages/MessageActionBar-test.tsx b/test/components/views/messages/MessageActionBar-test.tsx index da475a58de..634be112db 100644 --- a/test/components/views/messages/MessageActionBar-test.tsx +++ b/test/components/views/messages/MessageActionBar-test.tsx @@ -433,88 +433,7 @@ describe("", () => { }); }); - describe("favourite button", () => { - //for multiple event usecase - const favButton = (evt: MatrixEvent) => { - return getComponent({ mxEvent: evt }).getByTestId(evt.getId()!); - }; - - describe("when favourite_messages feature is enabled", () => { - beforeEach(() => { - jest.spyOn(SettingsStore, "getValue").mockImplementation( - (setting) => setting === "feature_favourite_messages", - ); - localStorageMock.clear(); - }); - - it("renders favourite button on own actionable event", () => { - const { queryByLabelText } = getComponent({ mxEvent: alicesMessageEvent }); - expect(queryByLabelText("Favourite")).toBeTruthy(); - }); - - it("renders favourite button on other actionable events", () => { - const { queryByLabelText } = getComponent({ mxEvent: bobsMessageEvent }); - expect(queryByLabelText("Favourite")).toBeTruthy(); - }); - - it("does not render Favourite button on non-actionable event", () => { - //redacted event is not actionable - const { queryByLabelText } = getComponent({ mxEvent: redactedEvent }); - expect(queryByLabelText("Favourite")).toBeFalsy(); - }); - - it("remembers favourited state of multiple events, and handles the localStorage of the events accordingly", () => { - const alicesAction = favButton(alicesMessageEvent); - const bobsAction = favButton(bobsMessageEvent); - - //default state before being clicked - expect(alicesAction.classList).not.toContain("mx_MessageActionBar_favouriteButton_fillstar"); - expect(bobsAction.classList).not.toContain("mx_MessageActionBar_favouriteButton_fillstar"); - expect(localStorageMock.getItem("io_element_favouriteMessages")).toBeNull(); - - //if only alice's event is fired - fireEvent.click(alicesAction); - - expect(alicesAction.classList).toContain("mx_MessageActionBar_favouriteButton_fillstar"); - expect(bobsAction.classList).not.toContain("mx_MessageActionBar_favouriteButton_fillstar"); - expect(localStorageMock.setItem).toHaveBeenCalledWith( - "io_element_favouriteMessages", - '["$alices_message"]', - ); - - //when bob's event is fired,both should be styled and stored in localStorage - fireEvent.click(bobsAction); - - expect(alicesAction.classList).toContain("mx_MessageActionBar_favouriteButton_fillstar"); - expect(bobsAction.classList).toContain("mx_MessageActionBar_favouriteButton_fillstar"); - expect(localStorageMock.setItem).toHaveBeenCalledWith( - "io_element_favouriteMessages", - '["$alices_message","$bobs_message"]', - ); - - //finally, at this point the localStorage should contain the two eventids - expect(localStorageMock.getItem("io_element_favouriteMessages")).toEqual( - '["$alices_message","$bobs_message"]', - ); - - //if decided to unfavourite bob's event by clicking again - fireEvent.click(bobsAction); - expect(bobsAction.classList).not.toContain("mx_MessageActionBar_favouriteButton_fillstar"); - expect(alicesAction.classList).toContain("mx_MessageActionBar_favouriteButton_fillstar"); - expect(localStorageMock.getItem("io_element_favouriteMessages")).toEqual('["$alices_message"]'); - }); - }); - - describe("when favourite_messages feature is disabled", () => { - it("does not render", () => { - jest.spyOn(SettingsStore, "getValue").mockReturnValue(false); - const { queryByLabelText } = getComponent({ mxEvent: alicesMessageEvent }); - expect(queryByLabelText("Favourite")).toBeFalsy(); - }); - }); - }); - - it.each([["React"], ["Reply"], ["Reply in thread"], ["Favourite"], ["Edit"]])( + it.each([["React"], ["Reply"], ["Reply in thread"], ["Edit"]])( "does not show context menu when right-clicking", (buttonLabel: string) => { // For favourite button