From ebe19168c26fb43c20738004836a3b858e203d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 10:39:45 +0200 Subject: [PATCH 01/17] Add allowClose to payload MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/dispatcher/payloads/SetRightPanelPhasePayload.ts | 5 +++++ src/stores/RightPanelStore.ts | 3 ++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/dispatcher/payloads/SetRightPanelPhasePayload.ts b/src/dispatcher/payloads/SetRightPanelPhasePayload.ts index a4dcb8cfe1..ea997e4ed1 100644 --- a/src/dispatcher/payloads/SetRightPanelPhasePayload.ts +++ b/src/dispatcher/payloads/SetRightPanelPhasePayload.ts @@ -27,6 +27,11 @@ export interface SetRightPanelPhasePayload extends ActionPayload { phase: RightPanelPhases; refireParams?: SetRightPanelPhaseRefireParams; + + /** + * By default SetRightPanelPhase can close the panel, this allows overriding that behaviour + */ + allowClose?: boolean; } export interface SetRightPanelPhaseRefireParams { diff --git a/src/stores/RightPanelStore.ts b/src/stores/RightPanelStore.ts index c539fcdb40..2bad0572b1 100644 --- a/src/stores/RightPanelStore.ts +++ b/src/stores/RightPanelStore.ts @@ -161,6 +161,7 @@ export default class RightPanelStore extends Store { case Action.SetRightPanelPhase: { let targetPhase = payload.phase; let refireParams = payload.refireParams; + const allowClose = payload.allowClose ?? true; // redirect to EncryptionPanel if there is an ongoing verification request if (targetPhase === RightPanelPhases.RoomMemberInfo && payload.refireParams) { const {member} = payload.refireParams; @@ -192,7 +193,7 @@ export default class RightPanelStore extends Store { }); } } else { - if (targetPhase === this.state.lastRoomPhase && !refireParams) { + if (targetPhase === this.state.lastRoomPhase && !refireParams && allowClose) { this.setState({ showRoomPanel: !this.state.showRoomPanel, previousPhase: null, From 8d47ea63c2aeb2e31798d10dfd7d430da878fa8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 10:40:30 +0200 Subject: [PATCH 02/17] Make pinned message text clickable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- res/css/views/messages/_TextualEvent.scss | 5 ++++ src/{TextForEvent.ts => TextForEvent.tsx} | 34 ++++++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) rename src/{TextForEvent.ts => TextForEvent.tsx} (96%) diff --git a/res/css/views/messages/_TextualEvent.scss b/res/css/views/messages/_TextualEvent.scss index be7565b3c5..e87fed90de 100644 --- a/res/css/views/messages/_TextualEvent.scss +++ b/res/css/views/messages/_TextualEvent.scss @@ -17,4 +17,9 @@ limitations under the License. .mx_TextualEvent { opacity: 0.5; overflow-y: hidden; + + a { + color: $accent-color; + cursor: pointer; + } } diff --git a/src/TextForEvent.ts b/src/TextForEvent.tsx similarity index 96% rename from src/TextForEvent.ts rename to src/TextForEvent.tsx index 649c53664e..ee9bd53250 100644 --- a/src/TextForEvent.ts +++ b/src/TextForEvent.tsx @@ -13,6 +13,8 @@ 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 React from 'react'; import {MatrixClientPeg} from './MatrixClientPeg'; import { _t } from './languageHandler'; import * as Roles from './Roles'; @@ -20,6 +22,10 @@ import {isValid3pidInvite} from "./RoomInvite"; import SettingsStore from "./settings/SettingsStore"; import {ALL_RULE_TYPES, ROOM_RULE_TYPES, SERVER_RULE_TYPES, USER_RULE_TYPES} from "./mjolnir/BanList"; import {WIDGET_LAYOUT_EVENT_TYPE} from "./stores/widgets/WidgetLayoutStore"; +import { RightPanelPhases } from './stores/RightPanelStorePhases'; +import { Action } from './dispatcher/actions'; +import defaultDispatcher from './dispatcher/dispatcher'; +import { SetRightPanelPhasePayload } from './dispatcher/payloads/SetRightPanelPhasePayload'; // These functions are frequently used just to check whether an event has // any text to display at all. For this reason they return deferred values @@ -466,9 +472,29 @@ function textForPowerEvent(event): () => string | null { }); } -function textForPinnedEvent(event): () => string | null { +function textForPinnedEvent(event): () => JSX.Element | null { + if (!SettingsStore.getValue("feature_pinning")) return null; + const senderName = event.sender ? event.sender.name : event.getSender(); - return () => _t("%(senderName)s changed the pinned messages for the room.", {senderName}); + const onPinnedMessagesClick = () => { + defaultDispatcher.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.PinnedMessages, + allowClose: false, + }); + } + + return () => ( + + { + _t( + "%(senderName)s changed the pinned messages for the room.", + { senderName }, + { "a": (sub) => { sub } }, + ) + } + + ); } function textForWidgetEvent(event): () => string | null { @@ -594,7 +620,7 @@ function textForMjolnirEvent(event): () => string | null { } interface IHandlers { - [type: string]: (ev: any) => (() => string | null); + [type: string]: (ev: any) => (() => string | JSX.Element | null); } const handlers: IHandlers = { @@ -635,7 +661,7 @@ export function hasText(ev): boolean { return Boolean(handler?.(ev)); } -export function textForEvent(ev): string { +export function textForEvent(ev): string | JSX.Element { const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()]; return handler?.(ev)?.() || ''; } From 7eb36426926f3310de0ede9f65e7e6a0782205a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 10:40:35 +0200 Subject: [PATCH 03/17] i18n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/i18n/strings/en_EN.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 7751c2eb32..c092c2b592 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -558,7 +558,7 @@ "%(senderName)s made future room history visible to unknown (%(visibility)s).": "%(senderName)s made future room history visible to unknown (%(visibility)s).", "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s changed the power level of %(powerLevelDiffText)s.", "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s", - "%(senderName)s changed the pinned messages for the room.": "%(senderName)s changed the pinned messages for the room.", + "%(senderName)s changed the pinned messages for the room.": "%(senderName)s changed the pinned messages for the room.", "%(widgetName)s widget modified by %(senderName)s": "%(widgetName)s widget modified by %(senderName)s", "%(widgetName)s widget added by %(senderName)s": "%(widgetName)s widget added by %(senderName)s", "%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s widget removed by %(senderName)s", From a8b2c6d36b490b2a0453954dde8b5f37f8b7e10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 12:24:42 +0200 Subject: [PATCH 04/17] Type event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/TextForEvent.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index ee9bd53250..b7e9deda8d 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -26,6 +26,7 @@ import { RightPanelPhases } from './stores/RightPanelStorePhases'; import { Action } from './dispatcher/actions'; import defaultDispatcher from './dispatcher/dispatcher'; import { SetRightPanelPhasePayload } from './dispatcher/payloads/SetRightPanelPhasePayload'; +import { MatrixEvent } from "matrix-js-sdk/src/models/event"; // These functions are frequently used just to check whether an event has // any text to display at all. For this reason they return deferred values @@ -472,7 +473,7 @@ function textForPowerEvent(event): () => string | null { }); } -function textForPinnedEvent(event): () => JSX.Element | null { +function textForPinnedEvent(event: MatrixEvent): () => JSX.Element | null { if (!SettingsStore.getValue("feature_pinning")) return null; const senderName = event.sender ? event.sender.name : event.getSender(); From 6333d4aa364717715df59823093dd74e10df9d86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 14:02:06 +0200 Subject: [PATCH 05/17] Iterate PR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/TextForEvent.tsx | 53 +++++++++++-------- src/components/views/messages/TextualEvent.js | 2 +- src/i18n/strings/en_EN.json | 1 + 3 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index b7e9deda8d..50bdae8ca9 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -473,29 +473,36 @@ function textForPowerEvent(event): () => string | null { }); } -function textForPinnedEvent(event: MatrixEvent): () => JSX.Element | null { +function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null { if (!SettingsStore.getValue("feature_pinning")) return null; - const senderName = event.sender ? event.sender.name : event.getSender(); - const onPinnedMessagesClick = () => { - defaultDispatcher.dispatch({ - action: Action.SetRightPanelPhase, - phase: RightPanelPhases.PinnedMessages, - allowClose: false, - }); - } - return () => ( - - { - _t( - "%(senderName)s changed the pinned messages for the room.", - { senderName }, - { "a": (sub) => { sub } }, - ) - } - - ); + if (allowJSX) { + const onPinnedMessagesClick = () => { + defaultDispatcher.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.PinnedMessages, + allowClose: false, + }); + } + + return () => ( + + { + _t( + "%(senderName)s changed the pinned messages for the room.", + { senderName }, + { "a": (sub) => { sub } }, + ) + } + + ); + } else { + return () => _t( + "%(senderName)s changed the pinned messages for the room.", + { senderName }, + ); + } } function textForWidgetEvent(event): () => string | null { @@ -621,7 +628,7 @@ function textForMjolnirEvent(event): () => string | null { } interface IHandlers { - [type: string]: (ev: any) => (() => string | JSX.Element | null); + [type: string]: (ev: MatrixEvent, allowJSX?: boolean) => (() => string | JSX.Element | null); } const handlers: IHandlers = { @@ -662,7 +669,7 @@ export function hasText(ev): boolean { return Boolean(handler?.(ev)); } -export function textForEvent(ev): string | JSX.Element { +export function textForEvent(ev: MatrixEvent, allowJSX = false): string | JSX.Element { const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()]; - return handler?.(ev)?.() || ''; + return handler?.(ev, allowJSX)?.() || ''; } diff --git a/src/components/views/messages/TextualEvent.js b/src/components/views/messages/TextualEvent.js index a020cc6c52..25da18da0d 100644 --- a/src/components/views/messages/TextualEvent.js +++ b/src/components/views/messages/TextualEvent.js @@ -28,7 +28,7 @@ export default class TextualEvent extends React.Component { }; render() { - const text = TextForEvent.textForEvent(this.props.mxEvent); + const text = TextForEvent.textForEvent(this.props.mxEvent, true); if (text == null || text.length === 0) return null; return (
{ text }
diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index c092c2b592..73bf948778 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -559,6 +559,7 @@ "%(senderName)s changed the power level of %(powerLevelDiffText)s.": "%(senderName)s changed the power level of %(powerLevelDiffText)s.", "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s": "%(userId)s from %(fromPowerLevel)s to %(toPowerLevel)s", "%(senderName)s changed the pinned messages for the room.": "%(senderName)s changed the pinned messages for the room.", + "%(senderName)s changed the pinned messages for the room.": "%(senderName)s changed the pinned messages for the room.", "%(widgetName)s widget modified by %(senderName)s": "%(widgetName)s widget modified by %(senderName)s", "%(widgetName)s widget added by %(senderName)s": "%(widgetName)s widget added by %(senderName)s", "%(widgetName)s widget removed by %(senderName)s": "%(widgetName)s widget removed by %(senderName)s", From 0542c69b66686b3c28eba20861a013230b579dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 14:13:27 +0200 Subject: [PATCH 06/17] Fix types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/Notifier.ts | 2 +- src/TextForEvent.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Notifier.ts b/src/Notifier.ts index 4f55046e72..2afc7d9901 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -68,7 +68,7 @@ export const Notifier = { // or not pendingEncryptedEventIds: [], - notificationMessageForEvent: function(ev: MatrixEvent) { + notificationMessageForEvent: function(ev: MatrixEvent): string { if (typehandlers.hasOwnProperty(ev.getContent().msgtype)) { return typehandlers[ev.getContent().msgtype](ev); } diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index 50bdae8ca9..4c2c264439 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -669,6 +669,7 @@ export function hasText(ev): boolean { return Boolean(handler?.(ev)); } +export function textForEvent(ev: MatrixEvent): string export function textForEvent(ev: MatrixEvent, allowJSX = false): string | JSX.Element { const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()]; return handler?.(ev, allowJSX)?.() || ''; From e436e28f01dcbc4bdc7290d99f0394b7a64e5eb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 14:31:04 +0200 Subject: [PATCH 07/17] Make TS happy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/TextForEvent.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index 4c2c264439..10c787bcb6 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -669,7 +669,8 @@ export function hasText(ev): boolean { return Boolean(handler?.(ev)); } -export function textForEvent(ev: MatrixEvent): string +export function textForEvent(ev: MatrixEvent): string; +export function textForEvent(ev: MatrixEvent, allowJSX: true): string | JSX.Element; export function textForEvent(ev: MatrixEvent, allowJSX = false): string | JSX.Element { const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()]; return handler?.(ev, allowJSX)?.() || ''; From cc1f68296e84885a18a48828bbe7fc277744c53e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 16:58:56 +0200 Subject: [PATCH 08/17] Iterate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/TextForEvent.tsx | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index 10c787bcb6..4721e13cec 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -473,19 +473,19 @@ function textForPowerEvent(event): () => string | null { }); } +const onPinnedMessagesClick = (): void => { + defaultDispatcher.dispatch({ + action: Action.SetRightPanelPhase, + phase: RightPanelPhases.PinnedMessages, + allowClose: false, + }); +} + function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string | JSX.Element | null { if (!SettingsStore.getValue("feature_pinning")) return null; const senderName = event.sender ? event.sender.name : event.getSender(); if (allowJSX) { - const onPinnedMessagesClick = () => { - defaultDispatcher.dispatch({ - action: Action.SetRightPanelPhase, - phase: RightPanelPhases.PinnedMessages, - allowClose: false, - }); - } - return () => ( { @@ -498,10 +498,7 @@ function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string ); } else { - return () => _t( - "%(senderName)s changed the pinned messages for the room.", - { senderName }, - ); + return () => _t("%(senderName)s changed the pinned messages for the room.", { senderName }); } } From e282c4aa54cf15d160ab2da00493d7e4309e3ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 17:23:42 +0200 Subject: [PATCH 09/17] Simplifie code Co-authored-by: Michael Telatynski <7t3chguy@googlemail.com> --- src/TextForEvent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index 038c69ac15..ea669d4050 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -510,9 +510,9 @@ function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string } ); - } else { - return () => _t("%(senderName)s changed the pinned messages for the room.", { senderName }); } + + return () => _t("%(senderName)s changed the pinned messages for the room.", { senderName }); } function textForWidgetEvent(event): () => string | null { From ff11244de82c8459399d94bb300ba1bb53a167f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=A0imon=20Brandner?= Date: Thu, 24 Jun 2021 17:27:53 +0200 Subject: [PATCH 10/17] Trailing spaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Šimon Brandner --- src/TextForEvent.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TextForEvent.tsx b/src/TextForEvent.tsx index ea669d4050..def0ac2cb8 100644 --- a/src/TextForEvent.tsx +++ b/src/TextForEvent.tsx @@ -511,7 +511,7 @@ function textForPinnedEvent(event: MatrixEvent, allowJSX: boolean): () => string ); } - + return () => _t("%(senderName)s changed the pinned messages for the room.", { senderName }); } From 2b9e2e2e851db76e7570bf074c8ba31d72aa51d9 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 25 Jun 2021 10:41:13 +0100 Subject: [PATCH 11/17] Fix private space creation setting an alias anyway --- src/components/views/spaces/SpaceCreateMenu.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/components/views/spaces/SpaceCreateMenu.tsx b/src/components/views/spaces/SpaceCreateMenu.tsx index 2d096e1b9f..0a92bd2dbf 100644 --- a/src/components/views/spaces/SpaceCreateMenu.tsx +++ b/src/components/views/spaces/SpaceCreateMenu.tsx @@ -129,7 +129,9 @@ const SpaceCreateMenu = ({ onFinished }) => { events_default: 100, ...Visibility.Public ? { invite: 0 } : {}, }, - room_alias_name: alias ? alias.substr(1, alias.indexOf(":") - 1) : undefined, + room_alias_name: visibility === Visibility.Public && alias + ? alias.substr(1, alias.indexOf(":") - 1) + : undefined, topic, }, spinner: false, From 5facee56b0789fc343fe54a0e9d3b3e6f67cfaa3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 25 Jun 2021 10:41:45 +0100 Subject: [PATCH 12/17] Fix space settings using join rule private instead of invite --- .../views/settings/tabs/room/SecurityRoomSettingsTab.tsx | 3 +++ src/components/views/spaces/SpaceSettingsVisibilityTab.tsx | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx index bb7e194253..16c620ad84 100644 --- a/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx +++ b/src/components/views/settings/tabs/room/SecurityRoomSettingsTab.tsx @@ -33,6 +33,9 @@ export enum JoinRule { Public = "public", Knock = "knock", Invite = "invite", + /** + * @deprecated Reserved. Should not be used. + */ Private = "private", } diff --git a/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx b/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx index 263823603b..f27b73a511 100644 --- a/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx +++ b/src/components/views/spaces/SpaceSettingsVisibilityTab.tsx @@ -62,9 +62,9 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space }: IProps) => { const userId = cli.getUserId(); const [visibility, setVisibility] = useLocalEcho( - () => space.getJoinRule() === JoinRule.Private ? SpaceVisibility.Private : SpaceVisibility.Unlisted, + () => space.getJoinRule() === JoinRule.Invite ? SpaceVisibility.Private : SpaceVisibility.Unlisted, visibility => cli.sendStateEvent(space.roomId, EventType.RoomJoinRules, { - join_rule: visibility === SpaceVisibility.Unlisted ? JoinRule.Public : JoinRule.Private, + join_rule: visibility === SpaceVisibility.Unlisted ? JoinRule.Public : JoinRule.Invite, }, ""), () => setError(_t("Failed to update the visibility of this space")), ); From 1c8e24023ef32320dbb9f64c6ed62d04928e27a8 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 25 Jun 2021 11:00:27 +0100 Subject: [PATCH 13/17] Fix space preview for when user cannot join the space --- src/components/structures/SpaceRoomView.tsx | 90 ++++++++++++--------- 1 file changed, 53 insertions(+), 37 deletions(-) diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index aad770888b..a91c47b067 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -14,58 +14,60 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, {RefObject, useContext, useRef, useState} from "react"; -import {EventType} from "matrix-js-sdk/src/@types/event"; -import {Room} from "matrix-js-sdk/src/models/room"; -import {EventSubscription} from "fbemitter"; +import React, { RefObject, useContext, useRef, useState } from "react"; +import { EventType } from "matrix-js-sdk/src/@types/event"; +import { Preset } from "matrix-js-sdk/src/@types/partials"; +import { Room } from "matrix-js-sdk/src/models/room"; +import { EventSubscription } from "fbemitter"; import MatrixClientContext from "../../contexts/MatrixClientContext"; import RoomAvatar from "../views/avatars/RoomAvatar"; -import {_t} from "../../languageHandler"; +import { _t } from "../../languageHandler"; import AccessibleButton from "../views/elements/AccessibleButton"; import RoomName from "../views/elements/RoomName"; import RoomTopic from "../views/elements/RoomTopic"; import InlineSpinner from "../views/elements/InlineSpinner"; -import {inviteMultipleToRoom, showRoomInviteDialog} from "../../RoomInvite"; -import {useRoomMembers} from "../../hooks/useRoomMembers"; -import createRoom, {IOpts} from "../../createRoom"; +import { inviteMultipleToRoom, showRoomInviteDialog } from "../../RoomInvite"; +import { useRoomMembers } from "../../hooks/useRoomMembers"; +import createRoom, { IOpts } from "../../createRoom"; import Field from "../views/elements/Field"; -import {useEventEmitter} from "../../hooks/useEventEmitter"; +import { useEventEmitter } from "../../hooks/useEventEmitter"; import withValidation from "../views/elements/Validation"; import * as Email from "../../email"; import defaultDispatcher from "../../dispatcher/dispatcher"; -import {Action} from "../../dispatcher/actions"; +import dis from "../../dispatcher/dispatcher"; +import { Action } from "../../dispatcher/actions"; import ResizeNotifier from "../../utils/ResizeNotifier" import MainSplit from './MainSplit'; import ErrorBoundary from "../views/elements/ErrorBoundary"; -import {ActionPayload} from "../../dispatcher/payloads"; +import { ActionPayload } from "../../dispatcher/payloads"; import RightPanel from "./RightPanel"; import RightPanelStore from "../../stores/RightPanelStore"; -import {RightPanelPhases} from "../../stores/RightPanelStorePhases"; -import {SetRightPanelPhasePayload} from "../../dispatcher/payloads/SetRightPanelPhasePayload"; -import {useStateArray} from "../../hooks/useStateArray"; +import { RightPanelPhases } from "../../stores/RightPanelStorePhases"; +import { SetRightPanelPhasePayload } from "../../dispatcher/payloads/SetRightPanelPhasePayload"; +import { useStateArray } from "../../hooks/useStateArray"; import SpacePublicShare from "../views/spaces/SpacePublicShare"; -import {showAddExistingRooms, showCreateNewRoom, shouldShowSpaceSettings, showSpaceSettings} from "../../utils/space"; -import {showRoom, SpaceHierarchy} from "./SpaceRoomDirectory"; +import { shouldShowSpaceSettings, showAddExistingRooms, showCreateNewRoom, showSpaceSettings } from "../../utils/space"; +import { showRoom, SpaceHierarchy } from "./SpaceRoomDirectory"; import MemberAvatar from "../views/avatars/MemberAvatar"; -import {useStateToggle} from "../../hooks/useStateToggle"; +import { useStateToggle } from "../../hooks/useStateToggle"; import SpaceStore from "../../stores/SpaceStore"; import FacePile from "../views/elements/FacePile"; -import {AddExistingToSpace} from "../views/dialogs/AddExistingToSpaceDialog"; -import {ChevronFace, ContextMenuButton, useContextMenu} from "./ContextMenu"; +import { AddExistingToSpace } from "../views/dialogs/AddExistingToSpaceDialog"; +import { ChevronFace, ContextMenuButton, useContextMenu } from "./ContextMenu"; import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList, } from "../views/context_menus/IconizedContextMenu"; import AccessibleTooltipButton from "../views/elements/AccessibleTooltipButton"; -import {BetaPill} from "../views/beta/BetaCard"; +import { BetaPill } from "../views/beta/BetaCard"; import { UserTab } from "../views/dialogs/UserSettingsDialog"; import SettingsStore from "../../settings/SettingsStore"; -import dis from "../../dispatcher/dispatcher"; import Modal from "../../Modal"; import BetaFeedbackDialog from "../views/dialogs/BetaFeedbackDialog"; import SdkConfig from "../../SdkConfig"; -import { Preset } from "matrix-js-sdk/src/@types/partials"; +import { EffectiveMembership, getEffectiveMembership } from "../../utils/membership"; +import { JoinRule } from "../views/settings/tabs/room/SecurityRoomSettingsTab"; interface IProps { space: Room; @@ -178,6 +180,9 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => const spacesEnabled = SettingsStore.getValue("feature_spaces"); + const cannotJoin = getEffectiveMembership(myMembership) === EffectiveMembership.Leave + && space.getJoinRule() !== JoinRule.Public; + let inviterSection; let joinButtons; if (myMembership === "join") { @@ -244,7 +249,7 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => setBusy(true); onJoinButtonClicked(); }} - disabled={!spacesEnabled} + disabled={!spacesEnabled || cannotJoin} > { _t("Join") } @@ -255,6 +260,30 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => joinButtons = ; } + let footer; + if (!spacesEnabled) { + footer =
+ { myMembership === "join" + ? _t("To view %(spaceName)s, turn on the Spaces beta", { + spaceName: space.name, + }, { + a: sub => { sub }, + }) + : _t("To join %(spaceName)s, turn on the Spaces beta", { + spaceName: space.name, + }, { + a: sub => { sub }, + }) + } +
; + } else if (cannotJoin) { + footer =
+ { _t("To view %(spaceName)s, you need an invite", { + spaceName: space.name, + }) } +
; + } + return
{ inviterSection } @@ -274,20 +303,7 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }) =>
{ joinButtons }
- { !spacesEnabled &&
- { myMembership === "join" - ? _t("To view %(spaceName)s, turn on the Spaces beta", { - spaceName: space.name, - }, { - a: sub => { sub }, - }) - : _t("To join %(spaceName)s, turn on the Spaces beta", { - spaceName: space.name, - }, { - a: sub => { sub }, - }) - } -
} + { footer }
; }; From a8649ca0915b873991077f92f61dfde8852eab00 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 25 Jun 2021 11:02:33 +0100 Subject: [PATCH 14/17] i18n --- src/i18n/strings/en_EN.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index bc62868a0f..d87781ea14 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2767,6 +2767,7 @@ " invites you": " invites you", "To view %(spaceName)s, turn on the Spaces beta": "To view %(spaceName)s, turn on the Spaces beta", "To join %(spaceName)s, turn on the Spaces beta": "To join %(spaceName)s, turn on the Spaces beta", + "To view %(spaceName)s, you need an invite": "To view %(spaceName)s, you need an invite", "Welcome to ": "Welcome to ", "Random": "Random", "Support": "Support", From 620e14eb4bc0c530181ea60ba5eb9797fc783462 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 25 Jun 2021 11:10:37 +0100 Subject: [PATCH 15/17] Fix space avatar management layout being broken --- res/css/views/spaces/_SpaceBasicSettings.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/spaces/_SpaceBasicSettings.scss b/res/css/views/spaces/_SpaceBasicSettings.scss index 68e8723f11..c73e0715dd 100644 --- a/res/css/views/spaces/_SpaceBasicSettings.scss +++ b/res/css/views/spaces/_SpaceBasicSettings.scss @@ -73,7 +73,7 @@ limitations under the License. } } - .mx_AccessibleButton { + .mx_AccessibleButton_hasKind { padding: 8px 22px; margin-left: auto; display: block; From a8e2c1bc2a9a8f4ab7850ca540ac6162c3e740fc Mon Sep 17 00:00:00 2001 From: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com> Date: Fri, 25 Jun 2021 11:45:15 +0100 Subject: [PATCH 16/17] Move the dial pad button next to Explore button from Create Room context menu (#6237) This commit moves the dial pad from a context menu to sit right by the explore button, in line with the designs in the linked issue. The dial pad button is only shown when PSTN support is detected. --- res/css/structures/_LeftPanel.scss | 29 +++++++++++++ res/img/element-icons/call/dialpad.svg | 3 ++ src/components/structures/LeftPanel.tsx | 25 ++++++++++- src/components/views/rooms/RoomList.tsx | 57 ++----------------------- src/i18n/strings/en_EN.json | 3 +- 5 files changed, 60 insertions(+), 57 deletions(-) create mode 100644 res/img/element-icons/call/dialpad.svg diff --git a/res/css/structures/_LeftPanel.scss b/res/css/structures/_LeftPanel.scss index c7dd678c07..f254ca3226 100644 --- a/res/css/structures/_LeftPanel.scss +++ b/res/css/structures/_LeftPanel.scss @@ -111,6 +111,29 @@ $roomListCollapsedWidth: 68px; } } + .mx_LeftPanel_dialPadButton { + width: 32px; + height: 32px; + border-radius: 8px; + background-color: $roomlist-button-bg-color; + position: relative; + margin-left: 8px; + + &::before { + content: ''; + position: absolute; + top: 8px; + left: 8px; + width: 16px; + height: 16px; + mask-image: url('$(res)/img/element-icons/call/dialpad.svg'); + mask-position: center; + mask-size: contain; + mask-repeat: no-repeat; + background: $secondary-fg-color; + } + } + .mx_LeftPanel_exploreButton { width: 32px; height: 32px; @@ -185,6 +208,12 @@ $roomListCollapsedWidth: 68px; flex-direction: column; justify-content: center; + .mx_LeftPanel_dialPadButton { + margin-left: 0; + margin-top: 8px; + background-color: transparent; + } + .mx_LeftPanel_exploreButton { margin-left: 0; margin-top: 8px; diff --git a/res/img/element-icons/call/dialpad.svg b/res/img/element-icons/call/dialpad.svg new file mode 100644 index 0000000000..a97e80aa0b --- /dev/null +++ b/res/img/element-icons/call/dialpad.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index af22db1350..dec4e4c13e 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -24,6 +24,7 @@ import CustomRoomTagPanel from "./CustomRoomTagPanel"; import dis from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; import RoomList from "../views/rooms/RoomList"; +import CallHandler from "../../CallHandler"; import { HEADER_HEIGHT } from "../views/rooms/RoomSublist"; import { Action } from "../../dispatcher/actions"; import UserMenu from "./UserMenu"; @@ -124,6 +125,10 @@ export default class LeftPanel extends React.Component { this.setState({ activeSpace }); }; + private onDialPad = () => { + dis.fire(Action.OpenDialPad); + } + private onExplore = () => { dis.fire(Action.ViewRoomDirectory); }; @@ -397,7 +402,20 @@ export default class LeftPanel extends React.Component { } } - private renderSearchExplore(): React.ReactNode { + private renderSearchDialExplore(): React.ReactNode { + let dialPadButton = null; + + // If we have dialer support, show a button to bring up the dial pad + // to start a new call + if (CallHandler.sharedInstance().getSupportsPstnProtocol()) { + dialPadButton = + ; + } + return (
{ onKeyDown={this.onKeyDown} onSelectRoom={this.selectRoom} /> + + {dialPadButton} + { {leftLeftPanel}