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

Ask to refresh timeline when historical messages are imported (MSC2716) #8354

Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
66ea757
Ask to refresh timeline when historical messages are imported (MSC2716)
MadLittleMods Apr 13, 2022
6dba3df
Back to false after getting screenshot
MadLittleMods Apr 13, 2022
12b0115
Fix lints
MadLittleMods Apr 13, 2022
eb5e899
Fix room not showing refresh timeline banner if not switched to the r…
MadLittleMods Apr 13, 2022
a50e011
Fix type lints
MadLittleMods Apr 13, 2022
ed910bb
Remove parenthesis change
MadLittleMods Apr 14, 2022
8d61226
Raw refreshLiveTimeline usage that seems to work
MadLittleMods Apr 16, 2022
d8f94ed
Clean up raw commit
MadLittleMods Apr 18, 2022
c43d309
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods Apr 19, 2022
623960b
Clean up event usage
MadLittleMods Apr 19, 2022
d9001ce
Remove unreadable image descriptions
MadLittleMods Apr 19, 2022
b4c81e1
Fix up lints
MadLittleMods Apr 19, 2022
361675e
Add tests for RoomStatusBar
MadLittleMods Apr 19, 2022
bf8555f
Fix lints
MadLittleMods Apr 19, 2022
886b676
Fix lints
MadLittleMods Apr 19, 2022
65cacbb
Match case of other room events
MadLittleMods Apr 20, 2022
cef6d3c
Add types and fix up mis-type
MadLittleMods Apr 20, 2022
f571107
Fix snapshots with using string value case
MadLittleMods Apr 20, 2022
a926252
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods May 19, 2022
c2895ff
WIP: Cypress tests
MadLittleMods May 20, 2022
f580947
Register virtual users
MadLittleMods May 21, 2022
4c53f34
All assertions
MadLittleMods May 21, 2022
ee10ae2
Best practice Cypress test selectors
MadLittleMods May 21, 2022
2bdb165
Don't assert text that could change
MadLittleMods May 21, 2022
64e7e28
Send live events sequentially to avoid them all having the same depth
MadLittleMods May 21, 2022
6dbe331
Better self describing message
MadLittleMods May 24, 2022
18adde8
Use function scoped to the tests where it is only used
MadLittleMods May 24, 2022
a661bf6
WIP: Test to make sure racing sync that resolve before /context finis…
MadLittleMods May 24, 2022
ae5338d
The racey sync test does pass, not sure if testing the right thing
MadLittleMods May 24, 2022
f9a525c
Better comments and state of things
MadLittleMods May 24, 2022
b45be5b
More robust to failurse and user feedback
MadLittleMods May 25, 2022
c14cc18
All Cypress tests passing
MadLittleMods May 25, 2022
5286641
Some test cleanup
MadLittleMods May 25, 2022
9ae6483
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods May 25, 2022
7848501
Fix some lints
MadLittleMods May 25, 2022
47ecf3b
Remove unused import
MadLittleMods May 25, 2022
2ef47f9
Fix unexpected 'this' lints
MadLittleMods May 26, 2022
e9861c7
Smaller padding
MadLittleMods May 26, 2022
54268ba
Better comment
MadLittleMods May 26, 2022
3defe30
Update snapshots
MadLittleMods May 26, 2022
8461a96
Add test for refreshing the timeline multiple times
MadLittleMods May 26, 2022
4af71c2
Add context into intercepted request error so it's more obvious why y…
MadLittleMods May 26, 2022
0dae43e
Fill in comment doc
MadLittleMods May 26, 2022
e75d92a
Update spapshots after removing last marker processed from js-sdk
MadLittleMods May 26, 2022
b7eb441
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods May 27, 2022
7eb0576
Add comments describing why mxSettingsStore is useful
MadLittleMods May 27, 2022
8ed948d
Fix being able to reference Preset
MadLittleMods May 27, 2022
75fc3d4
Save the file
MadLittleMods May 27, 2022
1f4d3b5
Comment out so typescript doesn't go as crazy. Still need to solve th…
MadLittleMods May 27, 2022
17d3203
Remove debug logging
MadLittleMods May 27, 2022
0c5c0b5
Add comment doc to test functions
MadLittleMods May 27, 2022
641d37c
Add snapshot tests for error states
MadLittleMods May 27, 2022
daa0ca7
Fix lints
MadLittleMods May 27, 2022
6c7df4e
Use correct public_baseurl (COPYME template is wrong)
MadLittleMods May 28, 2022
0fac6b2
Only getBot should respond to invites by joining the room
MadLittleMods May 28, 2022
fc0d474
Use spacing variables
MadLittleMods May 28, 2022
0c89bcb
Type unintitialized variable
MadLittleMods May 28, 2022
2008696
Fix minor spacing typo in comments
MadLittleMods Jun 1, 2022
34ebd08
Make sure sentences are properly spaced apart
MadLittleMods Jun 1, 2022
df0522c
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods Jul 11, 2022
b9c86ca
Some type cleanup
MadLittleMods Jul 11, 2022
9d7eec3
Update from Modal.createTrackedDialog to Modal.createDialog
MadLittleMods Jul 11, 2022
32952e3
Update snapshots with Matrix client changes
MadLittleMods Jul 11, 2022
7b5ee36
Fix markerEventId typo
MadLittleMods Jul 12, 2022
0e923b7
Fix eventIdWhileRefrshingTimeline typo
MadLittleMods Jul 12, 2022
c9270d8
Add test when we fail to refresh and latest event is a threaded message
MadLittleMods Jul 13, 2022
b44f6a1
Remove the test only
MadLittleMods Jul 13, 2022
ac998bd
Use fire-forget pattern
MadLittleMods Jul 19, 2022
50da54e
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods Aug 29, 2022
bbc060f
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods Nov 4, 2022
c6e91a1
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods Nov 7, 2022
8c78dd5
Make test more robust
MadLittleMods Nov 8, 2022
3d259de
Fix joinRoom duplication
MadLittleMods Nov 8, 2022
e64e59b
Fix duplicate command
MadLittleMods Nov 8, 2022
1ff2c78
Fix some lints
MadLittleMods Nov 8, 2022
ef58f45
Migrate away from enzyme
MadLittleMods Nov 8, 2022
012d27f
Fix more strict errors
MadLittleMods Nov 8, 2022
d2e300b
Update i18n
MadLittleMods Nov 8, 2022
eb815cc
Workaround lint
MadLittleMods Nov 8, 2022
b9cd0a6
More strict lints
MadLittleMods Nov 8, 2022
43f90f6
Use supported room version
MadLittleMods Nov 8, 2022
131af45
Fix lints
MadLittleMods Nov 8, 2022
280ddb5
Fix `Error: TypeError: (0 , _jestMock.mocked)(...).mockReturnValue is…
MadLittleMods Nov 8, 2022
1726830
Update snapshots with small change and lots of quote escaping differe…
MadLittleMods Nov 8, 2022
939a6ef
Merge branch 'develop' into madlittlemods/refresh-timeline-when-we-se…
MadLittleMods Nov 28, 2022
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
6 changes: 6 additions & 0 deletions res/css/structures/_RoomStatusBar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ limitations under the License.
mask-image: url('$(res)/img/element-icons/retry.svg');
}
}

&.mx_RoomStatusBar_refreshTimelineBtn {
&::before {
mask-image: url('$(res)/img/element-icons/retry.svg');
}
}
}

.mx_InlineSpinner {
Expand Down
4 changes: 3 additions & 1 deletion src/components/structures/FilePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ class FilePanel extends React.Component<IProps, IState> {
}

if (!this.state.timelineSet.eventIdToTimeline(ev.getId())) {
this.state.timelineSet.addEventToTimeline(ev, timeline, false);
this.state.timelineSet.addEventToTimeline(ev, timeline, {
toStartOfTimeline: false,
});
}
}

Expand Down
77 changes: 72 additions & 5 deletions src/components/structures/RoomStatusBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ limitations under the License.
import React from 'react';
import { EventStatus, MatrixEvent } from "matrix-js-sdk/src/models/event";
import { SyncState, ISyncStateData } from "matrix-js-sdk/src/sync";
import { Room } from "matrix-js-sdk/src/models/room";
import { Room, RoomEvent } from "matrix-js-sdk/src/models/room";

import { _t, _td } from '../../languageHandler';
import Resend from '../../Resend';
Expand Down Expand Up @@ -79,6 +79,7 @@ interface IState {
syncStateData: ISyncStateData;
unsentMessages: MatrixEvent[];
isResending: boolean;
timelineNeedsRefresh: boolean;
}

export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
Expand All @@ -93,19 +94,30 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
syncStateData: this.context.getSyncStateData(),
unsentMessages: getUnsentMessages(this.props.room),
isResending: false,
timelineNeedsRefresh: this.props.room.getTimelineNeedsRefresh(),
};
}

public componentDidMount(): void {
const client = this.context;
client.on("sync", this.onSyncStateChange);
client.on("Room.localEchoUpdated", this.onRoomLocalEchoUpdated);
this.props.room.on(RoomEvent.historyImportedWithinTimeline, this.onRoomHistoryImportedWithinTimeline);
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved

this.checkSize();
}

public componentDidUpdate(): void {
public componentDidUpdate(prevProps): void {
MadLittleMods marked this conversation as resolved.
Show resolved Hide resolved
this.checkSize();

// When the room changes, setup the new listener
if (prevProps.room !== this.props.room) {
prevProps.room.removeListener(
"Room.historyImportedWithinTimeline",
this.onRoomHistoryImportedWithinTimeline,
);
this.props.room.on(RoomEvent.historyImportedWithinTimeline, this.onRoomHistoryImportedWithinTimeline);
}
}

public componentWillUnmount(): void {
Expand All @@ -116,6 +128,11 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
client.removeListener("sync", this.onSyncStateChange);
client.removeListener("Room.localEchoUpdated", this.onRoomLocalEchoUpdated);
}

this.props.room.removeListener(
RoomEvent.historyImportedWithinTimeline,
this.onRoomHistoryImportedWithinTimeline,
);
}

private onSyncStateChange = (state: SyncState, prevState: SyncState, data: ISyncStateData): void => {
Expand All @@ -142,6 +159,15 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
dis.fire(Action.FocusSendMessageComposer);
};

private onRefreshTimelineClick = (): void => {
// Empty out the current timeline and re-request it
this.props.room.refreshLiveTimeline();

this.setState({
timelineNeedsRefresh: false,
});
};
t3chguy marked this conversation as resolved.
Show resolved Hide resolved

private onRoomLocalEchoUpdated = (ev: MatrixEvent, room: Room) => {
if (room.roomId !== this.props.room.roomId) return;
const messages = getUnsentMessages(this.props.room);
Expand All @@ -151,6 +177,14 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
});
};

private onRoomHistoryImportedWithinTimeline = (markerEv: MatrixEvent, room: Room) => {
if (room.roomId !== this.props.room.roomId) return;

this.setState({
timelineNeedsRefresh: room.getTimelineNeedsRefresh(),
});
};

// Check whether current size is greater than 0, if yes call props.onVisible
private checkSize(): void {
if (this.getSize()) {
Expand All @@ -166,7 +200,11 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
private getSize(): number {
if (this.shouldShowConnectionError()) {
return STATUS_BAR_EXPANDED;
} else if (this.state.unsentMessages.length > 0 || this.state.isResending) {
} else if (
this.state.unsentMessages.length > 0 ||
this.state.isResending ||
this.state.timelineNeedsRefresh
) {
return STATUS_BAR_EXPANDED_LARGE;
}
return STATUS_BAR_HIDDEN;
Expand Down Expand Up @@ -286,8 +324,7 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
src={require("../../../res/img/feather-customised/warning-triangle.svg").default}
width="24"
height="24"
title="/!\ "
alt="/!\ " />
alt="" />
<div>
<div className="mx_RoomStatusBar_connectionLostBar_title">
{ _t('Connectivity to the server has been lost.') }
Expand All @@ -306,6 +343,36 @@ export default class RoomStatusBar extends React.PureComponent<IProps, IState> {
return this.getUnsentMessageContent();
}

if (this.state.timelineNeedsRefresh) {
return (
<div className="mx_RoomStatusBar mx_RoomStatusBar_unsentMessages">
<div role="alert">
<div className="mx_RoomStatusBar_unsentBadge">
<img
src={require("../../../res/img/feather-customised/warning-triangle.svg").default}
width="24"
height="24"
alt="" />
</div>
<div>
<div className="mx_RoomStatusBar_unsentTitle">
{ _t("History import detected.") }
</div>
<div className="mx_RoomStatusBar_unsentDescription">
{ _t("History was just imported somewhere in the room. " +
"In order to see the historical messages, refresh your timeline.") }
</div>
</div>
<div className="mx_RoomStatusBar_unsentButtonBar">
<AccessibleButton onClick={this.onRefreshTimelineClick} className="mx_RoomStatusBar_refreshTimelineBtn">
{ _t("Refresh timeline") }
</AccessibleButton>
</div>
</div>
</div>
);
}

return null;
}
}
24 changes: 23 additions & 1 deletion src/components/structures/TimelinePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
const cli = MatrixClientPeg.get();
cli.on(RoomEvent.Timeline, this.onRoomTimeline);
cli.on(RoomEvent.TimelineReset, this.onRoomTimelineReset);
this.props.timelineSet.room.on(RoomEvent.TimelineRefresh, this.onRoomTimelineRefresh);
cli.on(RoomEvent.Redaction, this.onRoomRedaction);
if (SettingsStore.getValue("feature_msc3531_hide_messages_pending_moderation")) {
// Make sure that events are re-rendered when their visibility-pending-moderation changes.
Expand Down Expand Up @@ -338,6 +339,14 @@ class TimelinePanel extends React.Component<IProps, IState> {
}
}

public componentDidUpdate(prevProps): void {
// When the room changes, setup the new listener
if (prevProps.timelineSet.room !== this.props.timelineSet.room) {
prevProps.timelineSet.room.removeListener(RoomEvent.TimelineRefresh, this.onRoomTimelineRefresh);
this.props.timelineSet.room.on(RoomEvent.TimelineRefresh, this.onRoomTimelineRefresh);
}
}

componentWillUnmount() {
// set a boolean to say we've been unmounted, which any pending
// promises can use to throw away their results.
Expand Down Expand Up @@ -370,6 +379,8 @@ class TimelinePanel extends React.Component<IProps, IState> {
client.removeListener(MatrixEventEvent.VisibilityChange, this.onEventVisibilityChange);
client.removeListener(ClientEvent.Sync, this.onSync);
}

this.props.timelineSet.room.removeListener(RoomEvent.TimelineRefresh, this.onRoomTimelineRefresh);
}

private onMessageListUnfillRequest = (backwards: boolean, scrollToken: string): void => {
Expand Down Expand Up @@ -627,10 +638,21 @@ class TimelinePanel extends React.Component<IProps, IState> {
});
};

private onRoomTimelineRefresh = (room: Room, timelineSet: EventTimelineSet): void => {
debuglog(`onRoomTimelineRefresh skipping=${timelineSet !== this.props.timelineSet}`);
if (timelineSet !== this.props.timelineSet) return;

this.refreshTimeline();
};

private onRoomTimelineReset = (room: Room, timelineSet: EventTimelineSet): void => {
debuglog(
`onRoomTimelineReset skipping=${timelineSet !== this.props.timelineSet} ` +
`skippingBecauseAtBottom=${this.canResetTimeline()}`,
);
if (timelineSet !== this.props.timelineSet) return;

if (this.messagePanel.current && this.messagePanel.current.isAtBottom()) {
if (this.canResetTimeline()) {
Copy link
Contributor Author

@MadLittleMods MadLittleMods Apr 19, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a missed refactor. canResetTimeline by name seems applicable here and the logic appears pretty equivalent.

public canResetTimeline = () => {
if (!this.messagePanel) {
return true;
}
return this.messagePanel.canResetTimeline();
};

public canResetTimeline = () => this.messagePanel?.current.isAtBottom();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Split out to #10403

this.loadTimeline();
}
};
Expand Down
3 changes: 3 additions & 0 deletions src/i18n/strings/en_EN.json
Original file line number Diff line number Diff line change
Expand Up @@ -3058,6 +3058,9 @@
"You can select all or individual messages to retry or delete": "You can select all or individual messages to retry or delete",
"Connectivity to the server has been lost.": "Connectivity to the server has been lost.",
"Sent messages will be stored until your connection has returned.": "Sent messages will be stored until your connection has returned.",
"History import detected.": "History import detected.",
"History was just imported somewhere in the room. In order to see the historical messages, refresh your timeline.": "History was just imported somewhere in the room. In order to see the historical messages, refresh your timeline.",
"Refresh timeline": "Refresh timeline",
"You seem to be uploading files, are you sure you want to quit?": "You seem to be uploading files, are you sure you want to quit?",
"You seem to be in a call, are you sure you want to quit?": "You seem to be in a call, are you sure you want to quit?",
"Search failed": "Search failed",
Expand Down
4 changes: 3 additions & 1 deletion src/indexing/EventIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -808,7 +808,9 @@ export default class EventIndex extends EventEmitter {
// Add the events to the timeline of the file panel.
matrixEvents.forEach(e => {
if (!timelineSet.eventIdToTimeline(e.getId())) {
timelineSet.addEventToTimeline(e, timeline, direction == EventTimeline.BACKWARDS);
timelineSet.addEventToTimeline(e, timeline, {
toStartOfTimeline: direction == EventTimeline.BACKWARDS,
});
}
});

Expand Down
Loading