diff --git a/src/PageTypes.ts b/src/PageTypes.ts index fb0424f6e055..28e9178f6e24 100644 --- a/src/PageTypes.ts +++ b/src/PageTypes.ts @@ -21,6 +21,7 @@ enum PageType { RoomView = "room_view", UserView = "user_view", LegacyGroupView = "legacy_group_view", + FavouriteMessagesView = "favourite_messages_view" } export default PageType; diff --git a/src/components/structures/FavouriteMessagesView.tsx b/src/components/structures/FavouriteMessagesView.tsx new file mode 100644 index 000000000000..851f543c9b8a --- /dev/null +++ b/src/components/structures/FavouriteMessagesView.tsx @@ -0,0 +1,91 @@ +/* +Copyright 2015, 2016 OpenMarket Ltd +Copyright 2017 Vector Creations Ltd +Copyright 2018, 2019 New Vector Ltd +Copyright 2019 - 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 { MatrixClient, MatrixEvent } from 'matrix-js-sdk/src/matrix'; +import React, { useContext, useRef } from 'react'; + +import MatrixClientContext from '../../contexts/MatrixClientContext'; +import { _t } from '../../languageHandler'; +import { RoomViewStore } from '../../stores/RoomViewStore'; +import FavouriteMessageTile from '../views/rooms/FavouriteMessageTile'; +import ScrollPanel from './ScrollPanel'; + +function getFavouriteMessagesTiles(cli: MatrixClient, favouriteMessageEvents) { + const ret = []; + let lastRoomId: string; + + for (let i = (favouriteMessageEvents?.length || 0) - 1; i >= 0; i--) { + const timeline = [] as MatrixEvent[]; + const resultObj = favouriteMessageEvents[i]; + const roomId = resultObj.roomId; + const room = cli.getRoom(roomId); + const mxEvent = room.findEventById(resultObj.eventId); + timeline.push(mxEvent); + + if (roomId !== lastRoomId) { + ret.push(
  • +

    { _t("Room") }: { room.name }

    +
  • ); + lastRoomId = roomId; + } + + const resultLink = "#/room/"+roomId+"/"+mxEvent.getId(); + + ret.push( + , + ); + } + return ret; +} + +let favouriteMessagesPanel; + +const FavouriteMessagesView = () => { + const favouriteMessageEvents= JSON.parse( + localStorage?.getItem("io_element_favouriteMessages") ?? "[]") as any[]; + + const favouriteMessagesPanelRef = useRef(); + const isFavMessagesBtnClicked = RoomViewStore.instance.getFavouriteStatus(); + const cli = useContext(MatrixClientContext); + + if (isFavMessagesBtnClicked) { + if (favouriteMessageEvents?.length === 0) { + favouriteMessagesPanel = (

    { _t("No Saved Messages") }

    ); + } else { + favouriteMessagesPanel = ( + + { getFavouriteMessagesTiles(cli, favouriteMessageEvents) } + + ); + } + } + return ( + <> { favouriteMessagesPanel } + ); +}; + +export default FavouriteMessagesView; diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index bd120529a90c..d039ca69c59a 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -371,6 +371,7 @@ export default class LeftPanel extends React.Component { onResize={this.refreshStickyHeaders} onListCollapse={this.refreshStickyHeaders} ref={this.roomListRef} + pageType={this.props.pageType} />; const containerClasses = classNames({ diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index d4737c2fca2b..97c67e43123a 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -71,6 +71,7 @@ import LegacyGroupView from "./LegacyGroupView"; import { IConfigOptions } from "../../IConfigOptions"; import LeftPanelLiveShareWarning from '../views/beacon/LeftPanelLiveShareWarning'; import { UserOnboardingPage } from '../views/user-onboarding/UserOnboardingPage'; +import FavouriteMessagesView from './FavouriteMessagesView'; // We need to fetch each pinned message individually (if we don't already have it) // so each pinned message may trigger a request. Limit the number per room for sanity. @@ -645,6 +646,10 @@ class LoggedInView extends React.Component { case PageTypes.LegacyGroupView: pageElement = ; break; + + case PageTypes.FavouriteMessagesView: + pageElement = ; + break; } const wrapperClasses = classNames({ diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 8c173a363019..841e2b739e9e 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -803,6 +803,9 @@ export default class MatrixChat extends React.PureComponent { hideAnalyticsToast(); SettingsStore.setValue("pseudonymousAnalyticsOptIn", null, SettingLevel.ACCOUNT, true); break; + case Action.ViewFavouriteMessages: + this.viewFavouriteMessages(); + break; case Action.PseudonymousAnalyticsReject: hideAnalyticsToast(); SettingsStore.setValue("pseudonymousAnalyticsOptIn", null, SettingLevel.ACCOUNT, false); @@ -1007,6 +1010,11 @@ export default class MatrixChat extends React.PureComponent { this.themeWatcher.recheck(); } + private viewFavouriteMessages() { + this.setPage(PageType.FavouriteMessagesView); + this.notifyNewScreen('favourite_messages'); + } + private viewUser(userId: string, subAction: string) { // Wait for the first sync so that `getRoom` gives us a room object if it's // in the sync response @@ -1704,6 +1712,10 @@ export default class MatrixChat extends React.PureComponent { dis.dispatch({ action: Action.ViewHomePage, }); + } else if (screen === 'favourite_messages') { + dis.dispatch({ + action: Action.ViewFavouriteMessages, + }); } else if (screen === 'start') { this.showScreen('home'); dis.dispatch({ diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index e9c8bb4d8249..b555f315a73b 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -119,7 +119,6 @@ import { isLocalRoom } from '../../utils/localRoom/isLocalRoom'; import { ShowThreadPayload } from "../../dispatcher/payloads/ShowThreadPayload"; import { RoomStatusBarUnsentMessages } from './RoomStatusBarUnsentMessages'; import { LargeLoader } from './LargeLoader'; -import FavouriteMessageTile from '../views/rooms/FavouriteMessageTile'; const DEBUG = false; let debuglog = function(msg: string) {}; @@ -374,7 +373,6 @@ export class RoomView extends React.Component { private roomView = createRef(); private searchResultsPanel = createRef(); private messagePanel: TimelinePanel; - private favouriteMessagesPanel = createRef(); private roomViewBody = createRef(); static contextType = MatrixClientContext; @@ -565,7 +563,6 @@ export class RoomView extends React.Component { wasContextSwitch: RoomViewStore.instance.getWasContextSwitch(), initialEventId: null, // default to clearing this, will get set later in the method if needed showRightPanel: RightPanelStore.instance.isOpenForRoom(roomId), - isFavMessagesBtnClicked: RoomViewStore.instance.getFavouriteStatus(), }; const initialEventId = RoomViewStore.instance.getInitialEventId(); @@ -1576,51 +1573,6 @@ export class RoomView extends React.Component { }); } - private favouriteMessageEvents= JSON.parse( - localStorage?.getItem("io_element_favouriteMessages") ?? "[]") as any[]; - - private getFavouriteMessagesTiles() { - const ret = []; - let lastRoomId: string; - - const onHeightChanged = () => { - const scrollPanel = this.searchResultsPanel.current; - if (scrollPanel) { - scrollPanel.checkScroll(); - } - }; - - for (let i = (this.favouriteMessageEvents?.length || 0) - 1; i >= 0; i--) { - const timeline = [] as MatrixEvent[]; - const resultObj = this.favouriteMessageEvents[i]; - const roomId = resultObj.roomId; - const room = this.context.getRoom(roomId); - const mxEvent = room.findEventById(resultObj.eventId); - timeline.push(mxEvent); - - if (roomId !== lastRoomId) { - ret.push(
  • -

    { _t("Room") }: { room.name }

    -
  • ); - lastRoomId = roomId; - } - - const resultLink = "#/room/"+roomId+"/"+mxEvent.getId(); - - ret.push( - , - ); - } - return ret; - } - private getSearchResultTiles() { // XXX: todo: merge overlapping results somehow? // XXX: why doesn't searching on name work? @@ -2281,9 +2233,7 @@ export class RoomView extends React.Component { // if we have search results, we keep the messagepanel (so that it preserves its // scroll state), but hide it. let searchResultsPanel; - let favouriteMessagesPanel; let hideMessagePanel = false; - const isFavMessagesBtnClicked = RoomViewStore.instance.getFavouriteStatus(); if (this.state.searchResults) { // show searching spinner @@ -2307,24 +2257,6 @@ export class RoomView extends React.Component { hideMessagePanel = true; } - if (isFavMessagesBtnClicked) { - if (this.favouriteMessageEvents?.length === 0) { - favouriteMessagesPanel = (

    { _t("No Saved Messages") }

    ); - } else { - favouriteMessagesPanel = ( - -
  • - { this.getFavouriteMessagesTiles() } - - ); - } - hideMessagePanel = true; - } - let highlightedEventId = null; if (this.state.isInitialEventHighlighted) { highlightedEventId = this.state.initialEventId; @@ -2414,11 +2346,10 @@ export class RoomView extends React.Component { { jumpToBottom } { messagePanel } { searchResultsPanel } - { favouriteMessagesPanel } { statusBarArea } { previewBar } - { !isFavMessagesBtnClicked && messageComposer } + { messageComposer } ; break; case MainSplitContentType.MaximisedWidget: @@ -2496,7 +2427,7 @@ export class RoomView extends React.Component { appsShown={this.state.showApps} onCallPlaced={onCallPlaced} excludedRightPanelPhaseButtons={excludedRightPanelPhaseButtons} - showButtons={!isFavMessagesBtnClicked && !this.viewsLocalRoom} + showButtons={!this.viewsLocalRoom} enableRoomOptionsMenu={!this.viewsLocalRoom} /> diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index 6f49409b137f..b609207b257d 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -31,6 +31,7 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { useEventEmitterState } from "../../../hooks/useEventEmitter"; import { _t, _td } from "../../../languageHandler"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import PageType from "../../../PageTypes"; import PosthogTrackers from "../../../PosthogTrackers"; import SettingsStore from "../../../settings/SettingsStore"; import { UIComponent } from "../../../settings/UIFeature"; @@ -72,6 +73,7 @@ interface IProps { resizeNotifier: ResizeNotifier; isMinimized: boolean; activeSpace: SpaceKey; + pageType: PageType; } interface IState { @@ -457,8 +459,6 @@ export default class RoomList extends React.PureComponent { metricsViaKeyboard: true, }); } - // RoomViewStore.instance.setFavouriteStatus(false); - // console.log(RoomViewStore.instance.getFavouriteStatus()); } else if (payload.action === Action.PstnSupportUpdated) { this.updateLists(); } @@ -522,7 +522,6 @@ export default class RoomList extends React.PureComponent { this.props.onResize(); }); } - RoomViewStore.instance.setFavouriteStatus(false); }; private renderSuggestedRooms(): ReactComponentElement[] { @@ -576,23 +575,15 @@ export default class RoomList extends React.PureComponent { resizeMethod="crop" />); - // const opts = { createOpts: { - // name: "Favourites", - // } }; - - // const callFavRoomMethod = async () => { - // const favouriteRoomId = await createRoom(opts); - // console.log("FAVOURITE FAKE ROOMID", favouriteRoomId); - // }; - const onFavouriteClicked = () => { RoomViewStore.instance.setFavouriteStatus(true); + defaultDispatcher.dispatch({ action: Action.ViewFavouriteMessages }); }; return [ { } public setFavouriteStatus = (val: boolean) => { - dis.dispatch({ action: "view_favourite_messages", val }); + dis.dispatch({ action: Action.ViewFavouriteMessages, val }); }; public getFavouriteStatus = () => this.state.isFavouriteClicked; @@ -191,8 +191,10 @@ export class RoomViewStore extends Store { wasContextSwitch: false, }); break; - case "view_favourite_messages": + case Action.ViewFavouriteMessages: this.setState({ + roomId: null, + roomAlias: null, isFavouriteClicked: payload.val, }); break;