@@ -16,7 +16,7 @@ See the License for the specific language governing permissions and
1616limitations under the License.
1717*/
1818
19- import React , { ReactElement , useEffect } from 'react' ;
19+ import React , { ReactElement , useContext , useEffect } from 'react' ;
2020import { EventStatus , MatrixEvent , MatrixEventEvent } from 'matrix-js-sdk/src/models/event' ;
2121import classNames from 'classnames' ;
2222import { MsgType , RelationType } from 'matrix-js-sdk/src/@types/event' ;
@@ -45,6 +45,7 @@ import { Key } from "../../../Keyboard";
4545import { ALTERNATE_KEY_NAME } from "../../../accessibility/KeyboardShortcuts" ;
4646import { UserTab } from '../dialogs/UserTab' ;
4747import { Action } from '../../../dispatcher/actions' ;
48+ import SdkConfig from "../../../SdkConfig" ;
4849
4950interface IOptionsButtonProps {
5051 mxEvent : MatrixEvent ;
@@ -154,6 +155,76 @@ const ReactButton: React.FC<IReactButtonProps> = ({ mxEvent, reactions, onFocusC
154155 </ React . Fragment > ;
155156} ;
156157
158+ interface IReplyInThreadButton {
159+ mxEvent : MatrixEvent ;
160+ }
161+
162+ const ReplyInThreadButton = ( { mxEvent } : IReplyInThreadButton ) => {
163+ const context = useContext ( CardContext ) ;
164+
165+ const relationType = mxEvent ?. getRelation ( ) ?. rel_type ;
166+ const hasARelation = ! ! relationType && relationType !== RelationType . Thread ;
167+ const firstTimeSeeingThreads = localStorage . getItem ( "mx_seen_feature_thread" ) === null &&
168+ ! SettingsStore . getValue ( "feature_thread" ) ;
169+
170+ const onClick = ( ) : void => {
171+ if ( localStorage . getItem ( "mx_seen_feature_thread" ) === null ) {
172+ localStorage . setItem ( "mx_seen_feature_thread" , "true" ) ;
173+ }
174+
175+ if ( ! SettingsStore . getValue ( "feature_thread" ) ) {
176+ dis . dispatch ( {
177+ action : Action . ViewUserSettings ,
178+ initialTabId : UserTab . Labs ,
179+ } ) ;
180+ } else if ( mxEvent . isThreadRelation ) {
181+ showThread ( {
182+ rootEvent : mxEvent . getThread ( ) . rootEvent ,
183+ initialEvent : mxEvent ,
184+ scroll_into_view : true ,
185+ highlighted : true ,
186+ push : context . isCard ,
187+ } ) ;
188+ } else {
189+ showThread ( {
190+ rootEvent : mxEvent ,
191+ push : context . isCard ,
192+ } ) ;
193+ }
194+ } ;
195+
196+ return < RovingAccessibleTooltipButton
197+ className = "mx_MessageActionBar_maskButton mx_MessageActionBar_threadButton"
198+
199+ disabled = { hasARelation }
200+ tooltip = { < >
201+ < div className = "mx_Tooltip_title" >
202+ { ! hasARelation
203+ ? _t ( "Reply in thread" )
204+ : _t ( "Can't create a thread from an event with an existing relation" ) }
205+ </ div >
206+ { ! hasARelation && (
207+ < div className = "mx_Tooltip_sub" >
208+ { SettingsStore . getValue ( "feature_thread" )
209+ ? _t ( "Beta feature" )
210+ : _t ( "Beta feature. Click to learn more." )
211+ }
212+ </ div >
213+ ) }
214+ </ > }
215+
216+ title = { ! hasARelation
217+ ? _t ( "Reply in thread" )
218+ : _t ( "Can't create a thread from an event with an existing relation" ) }
219+
220+ onClick = { onClick }
221+ >
222+ { firstTimeSeeingThreads && (
223+ < div className = "mx_Indicator" />
224+ ) }
225+ </ RovingAccessibleTooltipButton > ;
226+ } ;
227+
157228interface IMessageActionBarProps {
158229 mxEvent : MatrixEvent ;
159230 reactions ?: Relations ;
@@ -222,32 +293,6 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
222293 } ) ;
223294 } ;
224295
225- private onThreadClick = ( isCard : boolean ) : void => {
226- if ( localStorage . getItem ( "mx_seen_feature_thread" ) === null ) {
227- localStorage . setItem ( "mx_seen_feature_thread" , "true" ) ;
228- }
229-
230- if ( ! SettingsStore . getValue ( "feature_thread" ) ) {
231- dis . dispatch ( {
232- action : Action . ViewUserSettings ,
233- initialTabId : UserTab . Labs ,
234- } ) ;
235- } else if ( this . props . mxEvent . isThreadRelation ) {
236- showThread ( {
237- rootEvent : this . props . mxEvent . getThread ( ) . rootEvent ,
238- initialEvent : this . props . mxEvent ,
239- scroll_into_view : true ,
240- highlighted : true ,
241- push : isCard ,
242- } ) ;
243- } else {
244- showThread ( {
245- rootEvent : this . props . mxEvent ,
246- push : isCard ,
247- } ) ;
248- }
249- } ;
250-
251296 private onEditClick = ( ) : void => {
252297 editEvent ( this . props . mxEvent , this . context . timelineRenderingType , this . props . getRelationsForEvent ) ;
253298 } ;
@@ -257,6 +302,15 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
257302 ] ;
258303
259304 private get showReplyInThreadAction ( ) : boolean {
305+ if ( ! SettingsStore . getBetaInfo ( "feature_thread" ) &&
306+ ! SettingsStore . getValue ( "feature_thread" ) &&
307+ ! SdkConfig . get ( "show_labs_settings" )
308+ ) {
309+ // Hide the beta prompt if there is no UI to enable it,
310+ // e.g if config.json disables it and doesn't enable show labs flags
311+ return false ;
312+ }
313+
260314 const inNotThreadTimeline = this . context . timelineRenderingType !== TimelineRenderingType . Thread ;
261315
262316 const isAllowedMessageType = ! this . forbiddenThreadHeadMsgType . includes (
@@ -319,44 +373,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
319373 key = "cancel"
320374 /> ;
321375
322- const relationType = this . props . mxEvent ?. getRelation ( ) ?. rel_type ;
323- const hasARelation = ! ! relationType && relationType !== RelationType . Thread ;
324- const firstTimeSeeingThreads = localStorage . getItem ( "mx_seen_feature_thread" ) === null &&
325- ! SettingsStore . getValue ( "feature_thread" ) ;
326- const threadTooltipButton = < CardContext . Consumer key = "thread" >
327- { context =>
328- < RovingAccessibleTooltipButton
329- className = "mx_MessageActionBar_maskButton mx_MessageActionBar_threadButton"
330-
331- disabled = { hasARelation }
332- tooltip = { < >
333- < div className = "mx_Tooltip_title" >
334- { ! hasARelation
335- ? _t ( "Reply in thread" )
336- : _t ( "Can't create a thread from an event with an existing relation" ) }
337- </ div >
338- { ! hasARelation && (
339- < div className = "mx_Tooltip_sub" >
340- { SettingsStore . getValue ( "feature_thread" )
341- ? _t ( "Beta feature" )
342- : _t ( "Beta feature. Click to learn more." )
343- }
344- </ div >
345- ) }
346- </ > }
347-
348- title = { ! hasARelation
349- ? _t ( "Reply in thread" )
350- : _t ( "Can't create a thread from an event with an existing relation" ) }
351-
352- onClick = { this . onThreadClick . bind ( null , context . isCard ) }
353- >
354- { firstTimeSeeingThreads && (
355- < div className = "mx_Indicator" />
356- ) }
357- </ RovingAccessibleTooltipButton >
358- }
359- </ CardContext . Consumer > ;
376+ const threadTooltipButton = < ReplyInThreadButton mxEvent = { this . props . mxEvent } /> ;
360377
361378 // We show a different toolbar for failed events, so detect that first.
362379 const mxEvent = this . props . mxEvent ;
0 commit comments