Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit 42d6afd

Browse files
authored
Merge pull request #6497 from matrix-org/t3chguy/fix/18093
2 parents 7c9df71 + 3c436c9 commit 42d6afd

File tree

23 files changed

+948
-540
lines changed

23 files changed

+948
-540
lines changed

res/css/structures/_SpacePanel.scss

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ $activeBorderColor: $secondary-fg-color;
297297
.mx_SpaceButton:hover,
298298
.mx_SpaceButton:focus-within,
299299
.mx_SpaceButton_hasMenuOpen {
300-
&:not(.mx_SpaceButton_home):not(.mx_SpaceButton_invite) {
300+
&:not(.mx_SpaceButton_invite) {
301301
// Hide the badge container on hover because it'll be a menu button
302302
.mx_SpacePanel_badgeContainer {
303303
width: 0;
@@ -368,6 +368,14 @@ $activeBorderColor: $secondary-fg-color;
368368
.mx_SpacePanel_iconExplore::before {
369369
mask-image: url('$(res)/img/element-icons/roomlist/browse.svg');
370370
}
371+
372+
.mx_SpacePanel_noIcon {
373+
display: none;
374+
375+
& + .mx_IconizedContextMenu_label {
376+
padding-left: 5px !important; // override default iconized label style to align with header
377+
}
378+
}
371379
}
372380

373381

res/css/views/context_menus/_IconizedContextMenu.scss

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,17 @@ limitations under the License.
149149
}
150150
}
151151

152-
.mx_IconizedContextMenu_checked {
152+
.mx_IconizedContextMenu_checked,
153+
.mx_IconizedContextMenu_unchecked {
153154
margin-left: 16px;
154155
margin-right: -5px;
156+
}
155157

156-
&::before {
157-
mask-image: url('$(res)/img/element-icons/roomlist/checkmark.svg');
158-
}
158+
.mx_IconizedContextMenu_checked::before {
159+
mask-image: url('$(res)/img/element-icons/roomlist/checkmark.svg');
160+
}
161+
162+
.mx_IconizedContextMenu_unchecked::before {
163+
content: unset;
159164
}
160165
}

res/css/views/settings/tabs/_SettingsTab.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ limitations under the License.
7272
padding-right: 10px;
7373
}
7474

75+
.mx_SettingsTab_section .mx_SettingsFlag .mx_SettingsFlag_microcopy {
76+
margin-top: 4px;
77+
font-size: $font-12px;
78+
line-height: $font-15px;
79+
color: $secondary-fg-color;
80+
}
81+
7582
.mx_SettingsTab_section .mx_SettingsFlag .mx_ToggleSwitch {
7683
float: right;
7784
}

src/components/structures/ContextMenu.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
1616
limitations under the License.
1717
*/
1818

19-
import React, { CSSProperties, RefObject, useRef, useState } from "react";
19+
import React, { CSSProperties, RefObject, SyntheticEvent, useRef, useState } from "react";
2020
import ReactDOM from "react-dom";
2121
import classNames from "classnames";
2222

@@ -471,10 +471,14 @@ type ContextMenuTuple<T> = [boolean, RefObject<T>, () => void, () => void, (val:
471471
export const useContextMenu = <T extends any = HTMLElement>(): ContextMenuTuple<T> => {
472472
const button = useRef<T>(null);
473473
const [isOpen, setIsOpen] = useState(false);
474-
const open = () => {
474+
const open = (ev?: SyntheticEvent) => {
475+
ev?.preventDefault();
476+
ev?.stopPropagation();
475477
setIsOpen(true);
476478
};
477-
const close = () => {
479+
const close = (ev?: SyntheticEvent) => {
480+
ev?.preventDefault();
481+
ev?.stopPropagation();
478482
setIsOpen(false);
479483
};
480484

src/components/views/context_menus/IconizedContextMenu.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ export const IconizedContextMenuCheckbox: React.FC<ICheckboxProps> = ({
8686
>
8787
<span className={classNames("mx_IconizedContextMenu_icon", iconClassName)} />
8888
<span className="mx_IconizedContextMenu_label">{ label }</span>
89-
{ active && <span className="mx_IconizedContextMenu_icon mx_IconizedContextMenu_checked" /> }
89+
<span className={classNames("mx_IconizedContextMenu_icon", {
90+
mx_IconizedContextMenu_checked: active,
91+
mx_IconizedContextMenu_unchecked: !active,
92+
})} />
9093
</MenuItemCheckbox>;
9194
};
9295

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/*
2+
Copyright 2021 The Matrix.org Foundation C.I.C.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import React, { useContext } from "react";
18+
import { Room } from "matrix-js-sdk/src/models/room";
19+
import { EventType } from "matrix-js-sdk/src/@types/event";
20+
21+
import {
22+
IProps as IContextMenuProps,
23+
} from "../../structures/ContextMenu";
24+
import IconizedContextMenu, { IconizedContextMenuOption, IconizedContextMenuOptionList } from "./IconizedContextMenu";
25+
import { _t } from "../../../languageHandler";
26+
import {
27+
leaveSpace,
28+
shouldShowSpaceSettings,
29+
showAddExistingRooms,
30+
showCreateNewRoom,
31+
showCreateNewSubspace,
32+
showSpaceInvite,
33+
showSpaceSettings,
34+
} from "../../../utils/space";
35+
import MatrixClientContext from "../../../contexts/MatrixClientContext";
36+
import { ButtonEvent } from "../elements/AccessibleButton";
37+
import defaultDispatcher from "../../../dispatcher/dispatcher";
38+
import RoomViewStore from "../../../stores/RoomViewStore";
39+
import { SetRightPanelPhasePayload } from "../../../dispatcher/payloads/SetRightPanelPhasePayload";
40+
import { Action } from "../../../dispatcher/actions";
41+
import { RightPanelPhases } from "../../../stores/RightPanelStorePhases";
42+
import { BetaPill } from "../beta/BetaCard";
43+
44+
interface IProps extends IContextMenuProps {
45+
space: Room;
46+
}
47+
48+
const SpaceContextMenu = ({ space, onFinished, ...props }: IProps) => {
49+
const cli = useContext(MatrixClientContext);
50+
const userId = cli.getUserId();
51+
52+
let inviteOption;
53+
if (space.getJoinRule() === "public" || space.canInvite(userId)) {
54+
const onInviteClick = (ev: ButtonEvent) => {
55+
ev.preventDefault();
56+
ev.stopPropagation();
57+
58+
showSpaceInvite(space);
59+
onFinished();
60+
};
61+
62+
inviteOption = (
63+
<IconizedContextMenuOption
64+
className="mx_SpacePanel_contextMenu_inviteButton"
65+
iconClassName="mx_SpacePanel_iconInvite"
66+
label={_t("Invite people")}
67+
onClick={onInviteClick}
68+
/>
69+
);
70+
}
71+
72+
let settingsOption;
73+
let leaveSection;
74+
if (shouldShowSpaceSettings(space)) {
75+
const onSettingsClick = (ev: ButtonEvent) => {
76+
ev.preventDefault();
77+
ev.stopPropagation();
78+
79+
showSpaceSettings(space);
80+
onFinished();
81+
};
82+
83+
settingsOption = (
84+
<IconizedContextMenuOption
85+
iconClassName="mx_SpacePanel_iconSettings"
86+
label={_t("Settings")}
87+
onClick={onSettingsClick}
88+
/>
89+
);
90+
} else {
91+
const onLeaveClick = (ev: ButtonEvent) => {
92+
ev.preventDefault();
93+
ev.stopPropagation();
94+
95+
leaveSpace(space);
96+
onFinished();
97+
};
98+
99+
leaveSection = <IconizedContextMenuOptionList red first>
100+
<IconizedContextMenuOption
101+
iconClassName="mx_SpacePanel_iconLeave"
102+
label={_t("Leave space")}
103+
onClick={onLeaveClick}
104+
/>
105+
</IconizedContextMenuOptionList>;
106+
}
107+
108+
const canAddRooms = space.currentState.maySendStateEvent(EventType.SpaceChild, userId);
109+
110+
let newRoomSection;
111+
if (space.currentState.maySendStateEvent(EventType.SpaceChild, userId)) {
112+
const onNewRoomClick = (ev: ButtonEvent) => {
113+
ev.preventDefault();
114+
ev.stopPropagation();
115+
116+
showCreateNewRoom(space);
117+
onFinished();
118+
};
119+
120+
const onAddExistingRoomClick = (ev: ButtonEvent) => {
121+
ev.preventDefault();
122+
ev.stopPropagation();
123+
124+
showAddExistingRooms(space);
125+
onFinished();
126+
};
127+
128+
const onNewSubspaceClick = (ev: ButtonEvent) => {
129+
ev.preventDefault();
130+
ev.stopPropagation();
131+
132+
showCreateNewSubspace(space);
133+
onFinished();
134+
};
135+
136+
newRoomSection = <IconizedContextMenuOptionList first>
137+
<IconizedContextMenuOption
138+
iconClassName="mx_SpacePanel_iconPlus"
139+
label={_t("Create new room")}
140+
onClick={onNewRoomClick}
141+
/>
142+
<IconizedContextMenuOption
143+
iconClassName="mx_SpacePanel_iconHash"
144+
label={_t("Add existing room")}
145+
onClick={onAddExistingRoomClick}
146+
/>
147+
<IconizedContextMenuOption
148+
iconClassName="mx_SpacePanel_iconPlus"
149+
label={_t("Add space")}
150+
onClick={onNewSubspaceClick}
151+
>
152+
<BetaPill />
153+
</IconizedContextMenuOption>
154+
</IconizedContextMenuOptionList>;
155+
}
156+
157+
const onMembersClick = (ev: ButtonEvent) => {
158+
ev.preventDefault();
159+
ev.stopPropagation();
160+
161+
if (!RoomViewStore.getRoomId()) {
162+
defaultDispatcher.dispatch({
163+
action: "view_room",
164+
room_id: space.roomId,
165+
}, true);
166+
}
167+
168+
defaultDispatcher.dispatch<SetRightPanelPhasePayload>({
169+
action: Action.SetRightPanelPhase,
170+
phase: RightPanelPhases.SpaceMemberList,
171+
refireParams: { space: space },
172+
});
173+
onFinished();
174+
};
175+
176+
const onExploreRoomsClick = (ev: ButtonEvent) => {
177+
ev.preventDefault();
178+
ev.stopPropagation();
179+
180+
defaultDispatcher.dispatch({
181+
action: "view_room",
182+
room_id: space.roomId,
183+
});
184+
onFinished();
185+
};
186+
187+
return <IconizedContextMenu
188+
{...props}
189+
onFinished={onFinished}
190+
className="mx_SpacePanel_contextMenu"
191+
compact
192+
>
193+
<div className="mx_SpacePanel_contextMenu_header">
194+
{ space.name }
195+
</div>
196+
<IconizedContextMenuOptionList first>
197+
{ inviteOption }
198+
<IconizedContextMenuOption
199+
iconClassName="mx_SpacePanel_iconMembers"
200+
label={_t("Members")}
201+
onClick={onMembersClick}
202+
/>
203+
{ settingsOption }
204+
<IconizedContextMenuOption
205+
iconClassName="mx_SpacePanel_iconExplore"
206+
label={canAddRooms ? _t("Manage & explore rooms") : _t("Explore rooms")}
207+
onClick={onExploreRoomsClick}
208+
/>
209+
</IconizedContextMenuOptionList>
210+
{ newRoomSection }
211+
{ leaveSection }
212+
</IconizedContextMenu>;
213+
};
214+
215+
export default SpaceContextMenu;
216+

src/components/views/settings/tabs/user/PreferencesUserSettingsTab.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { replaceableComponent } from "../../../../../utils/replaceableComponent"
2626
import SettingsFlag from '../../../elements/SettingsFlag';
2727
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
2828
import AccessibleButton from "../../../elements/AccessibleButton";
29+
import SpaceStore from "../../../../../stores/SpaceStore";
2930

3031
interface IState {
3132
autoLaunch: boolean;
@@ -47,6 +48,10 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
4748
'breadcrumbs',
4849
];
4950

51+
static SPACES_SETTINGS = [
52+
"Spaces.allRoomsInHome",
53+
];
54+
5055
static KEYBINDINGS_SETTINGS = [
5156
'ctrlFForSearch',
5257
];
@@ -231,6 +236,11 @@ export default class PreferencesUserSettingsTab extends React.Component<{}, ISta
231236
{ this.renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS) }
232237
</div>
233238

239+
{ SpaceStore.spacesEnabled && <div className="mx_SettingsTab_section">
240+
<span className="mx_SettingsTab_subheading">{ _t("Spaces") }</span>
241+
{ this.renderGroup(PreferencesUserSettingsTab.SPACES_SETTINGS) }
242+
</div> }
243+
234244
<div className="mx_SettingsTab_section">
235245
<span className="mx_SettingsTab_subheading">{ _t("Keyboard shortcuts") }</span>
236246
<AccessibleButton className="mx_SettingsFlag" onClick={KeyboardShortcuts.toggleDialog}>

0 commit comments

Comments
 (0)