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

Commit f71144e

Browse files
committed
Delabs threads
1 parent dec72c7 commit f71144e

31 files changed

+51
-203
lines changed

cypress/e2e/polls/polls.spec.ts

-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,6 @@ describe("Polls", () => {
7979
};
8080

8181
beforeEach(() => {
82-
cy.enableLabsFeature("feature_thread");
8382
cy.window().then(win => {
8483
win.localStorage.setItem("mx_lhs_size", "0"); // Collapse left panel for these tests
8584
});

cypress/e2e/threads/threads.spec.ts

-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ describe("Threads", () => {
2828
let synapse: SynapseInstance;
2929

3030
beforeEach(() => {
31-
// Default threads to ON for this spec
32-
cy.enableLabsFeature("feature_thread");
3331
cy.window().then(win => {
3432
win.localStorage.setItem("mx_lhs_size", "0"); // Collapse left panel for these tests
3533
});

res/css/views/messages/_MessageActionBar.pcss

-8
Original file line numberDiff line numberDiff line change
@@ -114,14 +114,6 @@ limitations under the License.
114114
color: $primary-content;
115115
}
116116

117-
&.mx_MessageActionBar_threadButton {
118-
119-
.mx_Indicator {
120-
background: $links;
121-
animation-iteration-count: infinite;
122-
}
123-
}
124-
125117
&.mx_MessageActionBar_favouriteButton_fillstar {
126118
color: var(--MessageActionBar-star-button-color);
127119
}

res/img/betas/threads.png

-85 KB
Binary file not shown.

src/MatrixClientPeg.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ class MatrixClientPegClass implements IMatrixClientPeg {
236236
opts.pendingEventOrdering = PendingEventOrdering.Detached;
237237
opts.lazyLoadMembers = true;
238238
opts.clientWellKnownPollPeriod = 2 * 60 * 60; // 2 hours
239-
opts.experimentalThreadSupport = SettingsStore.getValue("feature_thread");
239+
opts.experimentalThreadSupport = true;
240240

241241
if (SettingsStore.getValue("feature_sliding_sync")) {
242242
const proxyUrl = SettingsStore.getValue("feature_sliding_sync_proxy_url");

src/Unread.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export function doesRoomHaveUnreadMessages(room: Room): boolean {
6666
// despite the name of the method :((
6767
const readUpToId = room.getEventReadUpTo(myUserId);
6868

69-
if (!SettingsStore.getValue("feature_thread")) {
69+
if (!SettingsStore.getValue("feature_threadstable")) {
7070
// as we don't send RRs for our own messages, make sure we special case that
7171
// if *we* sent the last message into the room, we consider it not unread!
7272
// Should fix: https://github.com/vector-im/element-web/issues/3263

src/components/structures/MessagePanel.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ export default class MessagePanel extends React.Component<IProps, IState> {
280280
// and we check this in a hot code path. This is also cached in our
281281
// RoomContext, however we still need a fallback for roomless MessagePanels.
282282
this._showHiddenEvents = SettingsStore.getValue("showHiddenEventsInTimeline");
283-
this.threadsEnabled = SettingsStore.getValue("feature_thread");
283+
this.threadsEnabled = SettingsStore.getValue("feature_threadstable");
284284

285285
this.showTypingNotificationsWatcherRef =
286286
SettingsStore.watchSetting("showTypingNotifications", null, this.onShowTypingNotificationsChange);

src/components/structures/RoomSearchView.tsx

+3-7
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import ResizeNotifier from "../../utils/ResizeNotifier";
3333
import MatrixClientContext from "../../contexts/MatrixClientContext";
3434
import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks";
3535
import RoomContext from "../../contexts/RoomContext";
36+
import SettingsStore from '../../settings/SettingsStore';
3637

3738
const DEBUG = false;
3839
let debuglog = function(msg: string) {};
@@ -100,7 +101,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(({
100101
return b.length - a.length;
101102
});
102103

103-
if (client.supportsExperimentalThreads()) {
104+
if (SettingsStore.getValue("feature_threadstable")) {
104105
// Process all thread roots returned in this batch of search results
105106
// XXX: This won't work for results coming from Seshat which won't include the bundled relationship
106107
for (const result of results.results) {
@@ -109,12 +110,7 @@ export const RoomSearchView = forwardRef<ScrollPanel, Props>(({
109110
.getServerAggregatedRelation<IThreadBundledRelationship>(THREAD_RELATION_TYPE.name);
110111
if (!bundledRelationship || event.getThread()) continue;
111112
const room = client.getRoom(event.getRoomId());
112-
const thread = room.findThreadForEvent(event);
113-
if (thread) {
114-
event.setThread(thread);
115-
} else {
116-
room.createThread(event.getId(), event, [], true);
117-
}
113+
room.createThread(event.getId(), event, [], true);
118114
}
119115
}
120116
}

src/components/structures/RoomView.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
11621162
CHAT_EFFECTS.forEach(effect => {
11631163
if (containsEmoji(ev.getContent(), effect.emojis) || ev.getContent().msgtype === effect.msgType) {
11641164
// For initial threads launch, chat effects are disabled see #19731
1165-
if (!SettingsStore.getValue("feature_thread") || !ev.isRelation(THREAD_RELATION_TYPE.name)) {
1165+
if (!SettingsStore.getValue("feature_threadstable") || !ev.isRelation(THREAD_RELATION_TYPE.name)) {
11661166
dis.dispatch({ action: `effects.${effect.command}` });
11671167
}
11681168
}

src/components/structures/ThreadPanel.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ const ThreadPanel: React.FC<IProps> = ({
224224

225225
const openFeedback = shouldShowFeedback() ? () => {
226226
Modal.createDialog(BetaFeedbackDialog, {
227-
featureId: "feature_thread",
227+
featureId: "feature_threadstable",
228228
});
229229
} : null;
230230

src/components/structures/TimelinePanel.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
16381638
is very tied to the main room timeline, we are forcing the timeline to
16391639
send read receipts for threaded events */
16401640
const isThreadTimeline = this.context.timelineRenderingType === TimelineRenderingType.Thread;
1641-
if (SettingsStore.getValue("feature_thread") && isThreadTimeline) {
1641+
if (SettingsStore.getValue("feature_threadstable") && isThreadTimeline) {
16421642
return 0;
16431643
}
16441644
const index = this.state.events.findIndex(ev => ev.getId() === evId);

src/components/views/context_menus/MessageContextMenu.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ const ReplyInThreadButton = ({ mxEvent, closeMenu }: IReplyInThreadButton) => {
7676
if (Boolean(relationType) && relationType !== RelationType.Thread) return null;
7777

7878
const onClick = (): void => {
79-
if (!localStorage.getItem("mx_seen_feature_thread")) {
80-
localStorage.setItem("mx_seen_feature_thread", "true");
79+
if (!localStorage.getItem("mx_seen_feature_threadstable")) {
80+
localStorage.setItem("mx_seen_feature_threadstable", "true");
8181
}
8282

83-
if (!SettingsStore.getValue("feature_thread")) {
83+
if (!SettingsStore.getValue("feature_threadstable")) {
8484
dis.dispatch({
8585
action: Action.ViewUserSettings,
8686
initialTabId: UserTab.Labs,
@@ -647,7 +647,7 @@ export default class MessageContextMenu extends React.Component<IProps, IState>
647647
rightClick &&
648648
contentActionable &&
649649
canSendMessages &&
650-
SettingsStore.getValue("feature_thread") &&
650+
SettingsStore.getValue("feature_threadstable") &&
651651
Thread.hasServerSideSupport &&
652652
timelineRenderingType !== TimelineRenderingType.Thread
653653
) {

src/components/views/messages/MessageActionBar.tsx

+5-27
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@ import { Key } from "../../../Keyboard";
5656
import { ALTERNATE_KEY_NAME } from "../../../accessibility/KeyboardShortcuts";
5757
import { UserTab } from '../dialogs/UserTab';
5858
import { Action } from '../../../dispatcher/actions';
59-
import SdkConfig from "../../../SdkConfig";
6059
import { ShowThreadPayload } from "../../../dispatcher/payloads/ShowThreadPayload";
6160
import useFavouriteMessages from '../../../hooks/useFavouriteMessages';
6261
import { GetRelationsForEvent } from '../rooms/EventTile';
@@ -190,8 +189,7 @@ const ReplyInThreadButton = ({ mxEvent }: IReplyInThreadButton) => {
190189

191190
const relationType = mxEvent?.getRelation()?.rel_type;
192191
const hasARelation = !!relationType && relationType !== RelationType.Thread;
193-
const firstTimeSeeingThreads = !localStorage.getItem("mx_seen_feature_thread");
194-
const threadsEnabled = SettingsStore.getValue("feature_thread");
192+
const threadsEnabled = SettingsStore.getValue("feature_threadstable");
195193

196194
if (!threadsEnabled && !Thread.hasServerSideSupport) {
197195
// hide the prompt if the user would only have degraded mode
@@ -203,11 +201,7 @@ const ReplyInThreadButton = ({ mxEvent }: IReplyInThreadButton) => {
203201
e.preventDefault();
204202
e.stopPropagation();
205203

206-
if (firstTimeSeeingThreads) {
207-
localStorage.setItem("mx_seen_feature_thread", "true");
208-
}
209-
210-
if (!SettingsStore.getValue("feature_thread")) {
204+
if (!SettingsStore.getValue("feature_threadstable")) {
211205
dis.dispatch({
212206
action: Action.ViewUserSettings,
213207
initialTabId: UserTab.Labs,
@@ -241,7 +235,7 @@ const ReplyInThreadButton = ({ mxEvent }: IReplyInThreadButton) => {
241235
</div>
242236
{ !hasARelation && (
243237
<div className="mx_Tooltip_sub">
244-
{ SettingsStore.getValue("feature_thread")
238+
{ SettingsStore.getValue("feature_threadstable")
245239
? _t("Beta feature")
246240
: _t("Beta feature. Click to learn more.")
247241
}
@@ -257,9 +251,6 @@ const ReplyInThreadButton = ({ mxEvent }: IReplyInThreadButton) => {
257251
onContextMenu={onClick}
258252
>
259253
<ThreadIcon />
260-
{ firstTimeSeeingThreads && !threadsEnabled && (
261-
<div className="mx_Indicator" />
262-
) }
263254
</RovingAccessibleTooltipButton>;
264255
};
265256

@@ -375,20 +366,6 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
375366
];
376367

377368
private get showReplyInThreadAction(): boolean {
378-
if (!SettingsStore.getValue("feature_thread") && !Thread.hasServerSideSupport) {
379-
// hide the prompt if the user would only have degraded mode
380-
return null;
381-
}
382-
383-
if (!SettingsStore.getBetaInfo("feature_thread") &&
384-
!SettingsStore.getValue("feature_thread") &&
385-
!SdkConfig.get("show_labs_settings")
386-
) {
387-
// Hide the beta prompt if there is no UI to enable it,
388-
// e.g if config.json disables it and doesn't enable show labs flags
389-
return false;
390-
}
391-
392369
const inNotThreadTimeline = this.context.timelineRenderingType !== TimelineRenderingType.Thread;
393370

394371
const isAllowedMessageType = (
@@ -398,6 +375,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
398375
* until cross-platform support
399376
* (PSF-1041)
400377
*/
378+
401379
!M_BEACON_INFO.matches(this.props.mxEvent.getType())
402380
);
403381

@@ -534,7 +512,7 @@ export default class MessageActionBar extends React.PureComponent<IMessageAction
534512
key="download"
535513
/>);
536514
}
537-
} else if (SettingsStore.getValue("feature_thread") &&
515+
} else if (SettingsStore.getValue("feature_threadstable") &&
538516
// Show thread icon even for deleted messages, but only within main timeline
539517
this.context.timelineRenderingType === TimelineRenderingType.Room &&
540518
this.props.mxEvent.getThread()

src/components/views/right_panel/RoomHeaderButtons.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ export default class RoomHeaderButtons extends HeaderButtons<IProps> {
292292
onClick={this.onTimelineCardClicked} />,
293293
);
294294
rightPanelPhaseButtons.set(RightPanelPhases.ThreadPanel,
295-
SettingsStore.getValue("feature_thread")
295+
SettingsStore.getValue("feature_threadstable")
296296
? <HeaderButton
297297
key={RightPanelPhases.ThreadPanel}
298298
name="threadsButton"

src/components/views/rooms/EventTile.tsx

+4-15
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
391391
}
392392
}
393393

394-
if (SettingsStore.getValue("feature_thread")) {
394+
if (SettingsStore.getValue("feature_threadstable")) {
395395
this.props.mxEvent.on(ThreadEvent.Update, this.updateThread);
396396

397397
if (this.thread && !this.supportsThreadNotifications) {
@@ -473,7 +473,7 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
473473
if (this.props.showReactions) {
474474
this.props.mxEvent.removeListener(MatrixEventEvent.RelationsCreated, this.onReactionsCreated);
475475
}
476-
if (SettingsStore.getValue("feature_thread")) {
476+
if (SettingsStore.getValue("feature_threadstable")) {
477477
this.props.mxEvent.off(ThreadEvent.Update, this.updateThread);
478478
}
479479
this.threadState?.off(NotificationStateEvents.Update, this.onThreadStateUpdate);
@@ -500,22 +500,11 @@ export class UnwrappedEventTile extends React.Component<EventTileProps, IState>
500500
};
501501

502502
private get thread(): Thread | null {
503-
if (!SettingsStore.getValue("feature_thread")) {
503+
if (!SettingsStore.getValue("feature_threadstable")) {
504504
return null;
505505
}
506506

507-
let thread = this.props.mxEvent.getThread();
508-
/**
509-
* Accessing the threads value through the room due to a race condition
510-
* that will be solved when there are proper backend support for threads
511-
* We currently have no reliable way to discover than an event is a thread
512-
* when we are at the sync stage
513-
*/
514-
if (!thread) {
515-
const room = MatrixClientPeg.get().getRoom(this.props.mxEvent.getRoomId());
516-
thread = room?.findThreadForEvent(this.props.mxEvent);
517-
}
518-
return thread ?? null;
507+
return this.props.mxEvent.getThread() ?? null;
519508
}
520509

521510
private renderThreadPanelSummary(): JSX.Element | null {

src/components/views/rooms/SearchResultTile.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export default class SearchResultTile extends React.Component<IProps> {
6767
const layout = SettingsStore.getValue("layout");
6868
const isTwelveHour = SettingsStore.getValue("showTwelveHourTimestamps");
6969
const alwaysShowTimestamps = SettingsStore.getValue("alwaysShowTimestamps");
70-
const threadsEnabled = SettingsStore.getValue("feature_thread");
70+
const threadsEnabled = SettingsStore.getValue("feature_threadstable");
7171

7272
const timeline = result.context.getTimeline();
7373
for (let j = 0; j < timeline.length; j++) {

src/components/views/rooms/SendMessageComposer.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ export class SendMessageComposer extends React.Component<ISendMessageComposerPro
432432
// For initial threads launch, chat effects are disabled
433433
// see #19731
434434
const isNotThread = this.props.relation?.rel_type !== THREAD_RELATION_TYPE.name;
435-
if (!SettingsStore.getValue("feature_thread") || isNotThread) {
435+
if (!SettingsStore.getValue("feature_threadstable") || isNotThread) {
436436
dis.dispatch({ action: `effects.${effect.command}` });
437437
}
438438
}

src/components/views/rooms/wysiwyg_composer/utils/message.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ export function sendMessage(
118118
// For initial threads launch, chat effects are disabled
119119
// see #19731
120120
const isNotThread = relation?.rel_type !== THREAD_RELATION_TYPE.name;
121-
if (!SettingsStore.getValue("feature_thread") || isNotThread) {
121+
if (!SettingsStore.getValue("feature_threadstable") || isNotThread) {
122122
dis.dispatch({ action: `effects.${effect.command}` });
123123
}
124124
}

src/i18n/strings/en_EN.json

+3-9
Original file line numberDiff line numberDiff line change
@@ -913,15 +913,7 @@
913913
"In rooms that support moderation, the “Report” button will let you report abuse to room moderators.": "In rooms that support moderation, the “Report” button will let you report abuse to room moderators.",
914914
"Render LaTeX maths in messages": "Render LaTeX maths in messages",
915915
"Message Pinning": "Message Pinning",
916-
"Threaded messaging": "Threaded messaging",
917-
"Keep discussions organised with threads.": "Keep discussions organised with threads.",
918-
"Threads help keep conversations on-topic and easy to track. <a>Learn more</a>.": "Threads help keep conversations on-topic and easy to track. <a>Learn more</a>.",
919-
"How can I start a thread?": "How can I start a thread?",
920-
"Use “%(replyInThread)s” when hovering over a message.": "Use “%(replyInThread)s” when hovering over a message.",
921-
"Reply in thread": "Reply in thread",
922-
"How can I leave the beta?": "How can I leave the beta?",
923-
"To leave, return to this page and use the “%(leaveTheBeta)s” button.": "To leave, return to this page and use the “%(leaveTheBeta)s” button.",
924-
"Leave the beta": "Leave the beta",
916+
"Threaded messages": "Threaded messages",
925917
"Rich text editor": "Rich text editor",
926918
"Use rich text instead of Markdown in the message composer. Plain text mode coming soon.": "Use rich text instead of Markdown in the message composer. Plain text mode coming soon.",
927919
"Render simple counters in room header": "Render simple counters in room header",
@@ -2320,6 +2312,7 @@
23202312
"Error processing audio message": "Error processing audio message",
23212313
"View live location": "View live location",
23222314
"React": "React",
2315+
"Reply in thread": "Reply in thread",
23232316
"Can't create a thread from an event with an existing relation": "Can't create a thread from an event with an existing relation",
23242317
"Beta feature": "Beta feature",
23252318
"Beta feature. Click to learn more.": "Beta feature. Click to learn more.",
@@ -3196,6 +3189,7 @@
31963189
"Beta": "Beta",
31973190
"Leaving the beta will reload %(brand)s.": "Leaving the beta will reload %(brand)s.",
31983191
"Joining the beta will reload %(brand)s.": "Joining the beta will reload %(brand)s.",
3192+
"Leave the beta": "Leave the beta",
31993193
"Join the beta": "Join the beta",
32003194
"Updated %(humanizedUpdateTime)s": "Updated %(humanizedUpdateTime)s",
32013195
"Live until %(expiryTime)s": "Live until %(expiryTime)s",

src/settings/Settings.tsx

+3-35
Original file line numberDiff line numberDiff line change
@@ -270,45 +270,13 @@ export const SETTINGS: {[setting: string]: ISetting} = {
270270
supportedLevels: LEVELS_FEATURE,
271271
default: false,
272272
},
273-
"feature_thread": {
273+
"feature_threadstable": {
274274
isFeature: true,
275275
labsGroup: LabGroup.Messaging,
276276
controller: new ThreadBetaController(),
277-
displayName: _td("Threaded messaging"),
277+
displayName: _td("Threaded messages"),
278278
supportedLevels: LEVELS_FEATURE,
279-
default: false,
280-
betaInfo: {
281-
title: _td("Threads"),
282-
caption: () => <>
283-
<p>{ _t("Keep discussions organised with threads.") }</p>
284-
<p>{ _t("Threads help keep conversations on-topic and easy to track. <a>Learn more</a>.", {}, {
285-
a: (sub) => <a href="https://element.io/help#threads" rel="noreferrer noopener" target="_blank">
286-
{ sub }
287-
</a>,
288-
}) }</p>
289-
</>,
290-
faq: () =>
291-
SdkConfig.get().bug_report_endpoint_url && <>
292-
<h4>{ _t("How can I start a thread?") }</h4>
293-
<p>
294-
{ _t("Use “%(replyInThread)s” when hovering over a message.", {
295-
replyInThread: _t("Reply in thread"),
296-
}) }
297-
</p>
298-
<h4>{ _t("How can I leave the beta?") }</h4>
299-
<p>
300-
{ _t("To leave, return to this page and use the “%(leaveTheBeta)s” button.", {
301-
leaveTheBeta: _t("Leave the beta"),
302-
}) }
303-
</p>
304-
</>,
305-
feedbackLabel: "thread-feedback",
306-
feedbackSubheading: _td("Thank you for trying the beta, " +
307-
"please go into as much detail as you can so we can improve it."),
308-
image: require("../../res/img/betas/threads.png"),
309-
requiresRefresh: true,
310-
},
311-
279+
default: true,
312280
},
313281
"feature_wysiwyg_composer": {
314282
isFeature: true,

0 commit comments

Comments
 (0)