Merge pull request #6594 from matrix-org/t3chguy/fix/18088

This commit is contained in:
Michael Telatynski 2021-09-16 10:16:33 +01:00 committed by GitHub
commit bbc8e4da23
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 355 additions and 227 deletions

View file

@ -146,19 +146,13 @@ class GroupFilterPanel extends React.Component<IGroupFilterPanelProps, IGroupFil
mx_GroupFilterPanel_items_selected: itemsSelected,
});
let betaDot;
if (SettingsStore.getBetaInfo("feature_spaces") && !localStorage.getItem("mx_seenSpacesBeta")) {
betaDot = <div className="mx_BetaDot" />;
}
let createButton = (
<ActionButton
tooltip
label={_t("Communities")}
action="toggle_my_groups"
className="mx_TagTile mx_TagTile_plus">
{ betaDot }
</ActionButton>
className="mx_TagTile mx_TagTile_plus"
/>
);
if (SettingsStore.getValue("feature_communities_v2_prototypes")) {

View file

@ -0,0 +1,116 @@
/*
Copyright 2021 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 React, { useContext } from "react";
import MatrixClientContext from "../../contexts/MatrixClientContext";
import { _t } from "../../languageHandler";
import AccessibleButton from "../views/elements/AccessibleButton";
import ErrorBoundary from "../views/elements/ErrorBoundary";
import { IGroupSummary } from "../views/dialogs/CreateSpaceFromCommunityDialog";
import { useAsyncMemo } from "../../hooks/useAsyncMemo";
import Spinner from "../views/elements/Spinner";
import GroupAvatar from "../views/avatars/GroupAvatar";
import { linkifyElement } from "../../HtmlUtils";
import defaultDispatcher from "../../dispatcher/dispatcher";
import { Action } from "../../dispatcher/actions";
import { UserTab } from "../views/dialogs/UserSettingsDialog";
import MainSplit from './MainSplit';
interface IProps {
groupId: string;
}
const onSwapClick = () => {
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
initialTabId: UserTab.Preferences,
});
};
// XXX: temporary community migration component, reuses SpaceRoomView & SpacePreview classes for simplicity
const LegacyCommunityPreview = ({ groupId }: IProps) => {
const cli = useContext(MatrixClientContext);
const groupSummary = useAsyncMemo<IGroupSummary>(() => cli.getGroupSummary(groupId), [cli, groupId]);
if (!groupSummary) {
return <main className="mx_SpaceRoomView">
<MainSplit>
<div className="mx_SpaceRoomView_preview">
<Spinner />
</div>
</MainSplit>
</main>;
}
let visibilitySection: JSX.Element;
if (groupSummary.profile.is_public) {
visibilitySection = <span className="mx_SpaceRoomView_info_public">
{ _t("Public community") }
</span>;
} else {
visibilitySection = <span className="mx_SpaceRoomView_info_private">
{ _t("Private community") }
</span>;
}
return <main className="mx_SpaceRoomView">
<ErrorBoundary>
<MainSplit>
<div className="mx_SpaceRoomView_preview">
<GroupAvatar
groupId={groupId}
groupName={groupSummary.profile.name}
groupAvatarUrl={groupSummary.profile.avatar_url}
height={80}
width={80}
resizeMethod='crop'
/>
<h1 className="mx_SpaceRoomView_preview_name">
{ groupSummary.profile.name }
</h1>
<div className="mx_SpaceRoomView_info">
{ visibilitySection }
</div>
<div className="mx_SpaceRoomView_preview_topic" ref={e => e && linkifyElement(e)}>
{ groupSummary.profile.short_description }
</div>
<div className="mx_SpaceRoomView_preview_spaceBetaPrompt">
{ groupSummary.user?.membership === "join"
? _t("To view %(communityName)s, swap to communities in your <a>preferences</a>", {
communityName: groupSummary.profile.name,
}, {
a: sub => (
<AccessibleButton onClick={onSwapClick} kind="link">{ sub }</AccessibleButton>
),
})
: _t("To join %(communityName)s, swap to communities in your <a>preferences</a>", {
communityName: groupSummary.profile.name,
}, {
a: sub => (
<AccessibleButton onClick={onSwapClick} kind="link">{ sub }</AccessibleButton>
),
})
}
</div>
</div>
</MainSplit>
</ErrorBoundary>
</main>;
};
export default LegacyCommunityPreview;

View file

@ -69,6 +69,7 @@ import classNames from 'classnames';
import GroupFilterPanel from './GroupFilterPanel';
import CustomRoomTagPanel from './CustomRoomTagPanel';
import { mediaFromMxc } from "../../customisations/Media";
import LegacyCommunityPreview from "./LegacyCommunityPreview";
// 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.
@ -629,11 +630,15 @@ class LoggedInView extends React.Component<IProps, IState> {
pageElement = <UserView userId={this.props.currentUserId} resizeNotifier={this.props.resizeNotifier} />;
break;
case PageTypes.GroupView:
pageElement = <GroupView
groupId={this.props.currentGroupId}
isNew={this.props.currentGroupIsNew}
resizeNotifier={this.props.resizeNotifier}
/>;
if (SpaceStore.spacesEnabled) {
pageElement = <LegacyCommunityPreview groupId={this.props.currentGroupId} />;
} else {
pageElement = <GroupView
groupId={this.props.currentGroupId}
isNew={this.props.currentGroupIsNew}
resizeNotifier={this.props.resizeNotifier}
/>;
}
break;
}

View file

@ -1800,11 +1800,6 @@ export default class MatrixChat extends React.PureComponent<IProps, IState> {
subAction: params.action,
});
} else if (screen.indexOf('group/') === 0) {
if (SpaceStore.spacesEnabled) {
dis.dispatch({ action: "view_home_page" });
return;
}
const groupId = screen.substring(6);
// TODO: Check valid group ID

View file

@ -25,7 +25,6 @@ import AccessibleButton from '../views/elements/AccessibleButton';
import MatrixClientContext from "../../contexts/MatrixClientContext";
import AutoHideScrollbar from "./AutoHideScrollbar";
import { replaceableComponent } from "../../utils/replaceableComponent";
import BetaCard from "../views/beta/BetaCard";
@replaceableComponent("structures.MyGroups")
export default class MyGroups extends React.Component {
@ -138,7 +137,6 @@ export default class MyGroups extends React.Component {
</div>
</div>*/ }
</div>
<BetaCard featureId="feature_spaces" title={_t("Communities are changing to Spaces")} />
<div className="mx_MyGroups_content">
{ contentHeader }
{ content }

View file

@ -156,10 +156,10 @@ const SpaceInfo = ({ space }) => {
</div>;
};
const onBetaClick = () => {
const onPreferencesClick = () => {
defaultDispatcher.dispatch({
action: Action.ViewUserSettings,
initialTabId: UserTab.Labs,
initialTabId: UserTab.Preferences,
});
};
@ -286,15 +286,11 @@ const SpacePreview = ({ space, onJoinButtonClicked, onRejectButtonClicked }: ISp
if (!spacesEnabled) {
footer = <div className="mx_SpaceRoomView_preview_spaceBetaPrompt">
{ myMembership === "join"
? _t("To view %(spaceName)s, turn on the <a>Spaces beta</a>", {
spaceName: space.name,
}, {
a: sub => <AccessibleButton onClick={onBetaClick} kind="link">{ sub }</AccessibleButton>,
? _t("To view this Space, hide communities in your <a>preferences</a>", {}, {
a: sub => <AccessibleButton onClick={onPreferencesClick} kind="link">{ sub }</AccessibleButton>,
})
: _t("To join %(spaceName)s, turn on the <a>Spaces beta</a>", {
spaceName: space.name,
}, {
a: sub => <AccessibleButton onClick={onBetaClick} kind="link">{ sub }</AccessibleButton>,
: _t("To join this Space, hide communities in your <a>preferences</a>", {}, {
a: sub => <AccessibleButton onClick={onPreferencesClick} kind="link">{ sub }</AccessibleButton>,
})
}
</div>;
@ -731,7 +727,7 @@ const SpaceSetupPrivateInvite = ({ space, onFinished }) => {
</div>
<div className="mx_SpaceRoomView_inviteTeammates_betaDisclaimer">
<BetaPill onClick={onBetaClick} />
<BetaPill />
{ _t("<b>This is an experimental feature.</b> For now, " +
"new users receiving an invite will have to open the invite on <link/> to actually join.", {}, {
b: sub => <b>{ sub }</b>,

View file

@ -28,7 +28,6 @@ import { replaceableComponent } from "../../../../../utils/replaceableComponent"
import SettingsFlag from '../../../elements/SettingsFlag';
import * as KeyboardShortcuts from "../../../../../accessibility/KeyboardShortcuts";
import AccessibleButton from "../../../elements/AccessibleButton";
import SpaceStore from "../../../../../stores/SpaceStore";
import GroupAvatar from "../../../avatars/GroupAvatar";
import dis from "../../../../../dispatcher/dispatcher";
import GroupActions from "../../../../../actions/GroupActions";
@ -145,7 +144,7 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
];
static COMMUNITIES_SETTINGS = [
// TODO: part of delabsing move the toggle here - https://github.com/vector-im/element-web/issues/18088
"showCommunitiesInsteadOfSpaces",
];
static KEYBINDINGS_SETTINGS = [
@ -286,9 +285,17 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
SettingsStore.setValue("readMarkerOutOfViewThresholdMs", null, SettingLevel.DEVICE, e.target.value);
};
private renderGroup(settingIds: string[]): React.ReactNodeArray {
return settingIds.filter(SettingsStore.isEnabled).map(i => {
return <SettingsFlag key={i} name={i} level={SettingLevel.ACCOUNT} />;
private renderGroup(
settingIds: string[],
level = SettingLevel.ACCOUNT,
includeDisabled = false,
): React.ReactNodeArray {
if (!includeDisabled) {
settingIds = settingIds.filter(SettingsStore.isEnabled);
}
return settingIds.map(i => {
return <SettingsFlag key={i} name={i} level={level} />;
});
}
@ -334,10 +341,10 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
{ this.renderGroup(PreferencesUserSettingsTab.ROOM_LIST_SETTINGS) }
</div>
{ SpaceStore.spacesEnabled && <div className="mx_SettingsTab_section">
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{ _t("Spaces") }</span>
{ this.renderGroup(PreferencesUserSettingsTab.SPACES_SETTINGS) }
</div> }
{ this.renderGroup(PreferencesUserSettingsTab.SPACES_SETTINGS, SettingLevel.ACCOUNT, true) }
</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{ _t("Communities") }</span>
@ -349,7 +356,7 @@ export default class PreferencesUserSettingsTab extends React.Component<IProps,
<p>{ _t("If a community isn't shown you may not have permission to convert it.") }</p>
<CommunityMigrator onFinished={this.props.closeSettingsFn} />
</details>
{ this.renderGroup(PreferencesUserSettingsTab.COMMUNITIES_SETTINGS) }
{ this.renderGroup(PreferencesUserSettingsTab.COMMUNITIES_SETTINGS, SettingLevel.DEVICE) }
</div>
<div className="mx_SettingsTab_section">

View file

@ -117,9 +117,7 @@ export const SpaceFeedbackPrompt = ({ onClick }: { onClick?: () => void }) => {
"Your feedback will help inform the next versions."),
rageshakeLabel: "spaces-feedback",
rageshakeData: Object.fromEntries([
"feature_spaces.all_rooms",
"feature_spaces.space_member_dms",
"feature_spaces.space_dm_badges",
"Spaces.allRoomsInHome",
].map(k => [k, SettingsStore.getValue(k)])),
});
}}
@ -301,13 +299,13 @@ const SpaceCreateMenu = ({ onFinished }) => {
/>
<p>
{ _t("You can also create a Space from a <a>community</a>.", {}, {
{ _t("You can also make Spaces from <a>communities</a>.", {}, {
a: sub => <AccessibleButton kind="link" onClick={onCreateSpaceFromCommunityClick}>
{ sub }
</AccessibleButton>,
}) }
<br />
{ _t("To join an existing space you'll need an invite.") }
{ _t("To join a space you'll need an invite.") }
</p>
<SpaceFeedbackPrompt onClick={onFinished} />

View file

@ -151,12 +151,19 @@ const CreateSpaceButton = ({
}
const onNewClick = menuDisplayed ? closeMenu : () => {
// persist that the user has interacted with this, use it to dismiss the beta dot
localStorage.setItem("mx_seenSpaces", "1");
if (!isPanelCollapsed) setPanelCollapsed(true);
openMenu();
};
let betaDot: JSX.Element;
if (!localStorage.getItem("mx_seenSpaces") && !SpaceStore.instance.spacePanelSpaces.length) {
betaDot = <div className="mx_BetaDot" />;
}
return <li
className={classNames("mx_SpaceItem", {
className={classNames("mx_SpaceItem mx_SpaceItem_new", {
"collapsed": isPanelCollapsed,
})}
role="treeitem"
@ -169,6 +176,7 @@ const CreateSpaceButton = ({
onClick={onNewClick}
isNarrow={isPanelCollapsed}
/>
{ betaDot }
{ contextMenu }
</li>;