Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -2080,11 +2080,11 @@
"Go": "Go",
"Error processing audio message": "Error processing audio message",
"React": "React",
"Edit": "Edit",
"Reply in thread": "Reply in thread",
"Can't create a thread from an event with an existing relation": "Can't create a thread from an event with an existing relation",
"Beta feature": "Beta feature",
"Beta feature. Click to learn more.": "Beta feature. Click to learn more.",
"Edit": "Edit",
"Reply": "Reply",
"Collapse quotes": "Collapse quotes",
"Expand quotes": "Expand quotes",
Expand Down