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

Hide the reply in thread button in deployments where beta is forcibly disabled #8294

Merged
merged 5 commits into from
Apr 12, 2022
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 82 additions & 65 deletions src/components/views/messages/MessageActionBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

import React, { ReactElement, useEffect } from 'react';
import React, { ReactElement, useContext, useEffect } from 'react';
import { EventStatus, MatrixEvent, MatrixEventEvent } from 'matrix-js-sdk/src/models/event';
import classNames from 'classnames';
import { MsgType, RelationType } from 'matrix-js-sdk/src/@types/event';
Expand Down Expand Up @@ -45,6 +45,7 @@ import { Key } from "../../../Keyboard";
import { ALTERNATE_KEY_NAME } from "../../../accessibility/KeyboardShortcuts";
import { UserTab } from '../dialogs/UserTab';
import { Action } from '../../../dispatcher/actions';
import SdkConfig from "../../../SdkConfig";

interface IOptionsButtonProps {
mxEvent: MatrixEvent;
Expand Down Expand Up @@ -154,6 +155,76 @@ const ReactButton: React.FC<IReactButtonProps> = ({ mxEvent, reactions, onFocusC
</React.Fragment>;
};

interface IReplyInThreadButton {
mxEvent: MatrixEvent;
}

const ReplyInThreadButton = ({ mxEvent }: IReplyInThreadButton) => {
const context = useContext(CardContext);

const relationType = mxEvent?.getRelation()?.rel_type;
const hasARelation = !!relationType && relationType !== RelationType.Thread;
const firstTimeSeeingThreads = localStorage.getItem("mx_seen_feature_thread") === null &&
!SettingsStore.getValue("feature_thread");

const onClick = (): void => {
if (localStorage.getItem("mx_seen_feature_thread") === null) {
localStorage.setItem("mx_seen_feature_thread", "true");
}

if (!SettingsStore.getValue("feature_thread")) {
dis.dispatch({
action: Action.ViewUserSettings,
initialTabId: UserTab.Labs,
});
} else if (mxEvent.isThreadRelation) {
showThread({
rootEvent: mxEvent.getThread().rootEvent,
initialEvent: mxEvent,
scroll_into_view: true,
highlighted: true,
push: context.isCard,
});
} else {
showThread({
rootEvent: mxEvent,
push: context.isCard,
});
}
};

return <RovingAccessibleTooltipButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_threadButton"

disabled={hasARelation}
tooltip={<>
<div className="mx_Tooltip_title">
{ !hasARelation
? _t("Reply in thread")
: _t("Can't create a thread from an event with an existing relation") }
</div>
{ !hasARelation && (
<div className="mx_Tooltip_sub">
{ SettingsStore.getValue("feature_thread")
? _t("Beta feature")
: _t("Beta feature. Click to learn more.")
}
</div>
) }
</>}

title={!hasARelation
? _t("Reply in thread")
: _t("Can't create a thread from an event with an existing relation")}

onClick={onClick}
>
{ firstTimeSeeingThreads && (
<div className="mx_Indicator" />
) }
</RovingAccessibleTooltipButton>;
};

interface IMessageActionBarProps {
mxEvent: MatrixEvent;
reactions?: Relations;
Expand Down Expand Up @@ -222,32 +293,6 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
});
};

private onThreadClick = (isCard: boolean): void => {
if (localStorage.getItem("mx_seen_feature_thread") === null) {
localStorage.setItem("mx_seen_feature_thread", "true");
}

if (!SettingsStore.getValue("feature_thread")) {
dis.dispatch({
action: Action.ViewUserSettings,
initialTabId: UserTab.Labs,
});
} else if (this.props.mxEvent.isThreadRelation) {
showThread({
rootEvent: this.props.mxEvent.getThread().rootEvent,
initialEvent: this.props.mxEvent,
scroll_into_view: true,
highlighted: true,
push: isCard,
});
} else {
showThread({
rootEvent: this.props.mxEvent,
push: isCard,
});
}
};

private onEditClick = (): void => {
editEvent(this.props.mxEvent, this.context.timelineRenderingType, this.props.getRelationsForEvent);
};
Expand All @@ -257,6 +302,15 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
];

private get showReplyInThreadAction(): boolean {
if (!SettingsStore.getBetaInfo("feature_thread") &&
!SettingsStore.getValue("feature_thread") &&
!SdkConfig.get("show_labs_settings")
) {
// Hide the beta prompt if there is no UI to enable it,
// e.g if config.json disables it and doesn't enable show labs flags
return false;
}

const inNotThreadTimeline = this.context.timelineRenderingType !== TimelineRenderingType.Thread;

const isAllowedMessageType = !this.forbiddenThreadHeadMsgType.includes(
Expand Down Expand Up @@ -319,44 +373,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
key="cancel"
/>;

const relationType = this.props.mxEvent?.getRelation()?.rel_type;
const hasARelation = !!relationType && relationType !== RelationType.Thread;
const firstTimeSeeingThreads = localStorage.getItem("mx_seen_feature_thread") === null &&
!SettingsStore.getValue("feature_thread");
const threadTooltipButton = <CardContext.Consumer key="thread">
{ context =>
<RovingAccessibleTooltipButton
className="mx_MessageActionBar_maskButton mx_MessageActionBar_threadButton"

disabled={hasARelation}
tooltip={<>
<div className="mx_Tooltip_title">
{ !hasARelation
? _t("Reply in thread")
: _t("Can't create a thread from an event with an existing relation") }
</div>
{ !hasARelation && (
<div className="mx_Tooltip_sub">
{ SettingsStore.getValue("feature_thread")
? _t("Beta feature")
: _t("Beta feature. Click to learn more.")
}
</div>
) }
</>}

title={!hasARelation
? _t("Reply in thread")
: _t("Can't create a thread from an event with an existing relation")}

onClick={this.onThreadClick.bind(null, context.isCard)}
>
{ firstTimeSeeingThreads && (
<div className="mx_Indicator" />
) }
</RovingAccessibleTooltipButton>
}
</CardContext.Consumer>;
const threadTooltipButton = <ReplyInThreadButton mxEvent={this.props.mxEvent} />;

// We show a different toolbar for failed events, so detect that first.
const mxEvent = this.props.mxEvent;
Expand Down