FilePanel: Implement pagination requesting using the EventIndex.
							parent
							
								
									7fb3645e94
								
							
						
					
					
						commit
						49c1dbe421
					
				| 
						 | 
				
			
			@ -71,6 +71,20 @@ const FilePanel = createReactClass({
 | 
			
		|||
        return timelineSet;
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onPaginationRequest(timelineWindow, direction, limit) {
 | 
			
		||||
        const client = MatrixClientPeg.get();
 | 
			
		||||
        const eventIndex = EventIndexPeg.get();
 | 
			
		||||
        const roomId = this.props.roomId;
 | 
			
		||||
 | 
			
		||||
        const room = client.getRoom(roomId);
 | 
			
		||||
 | 
			
		||||
        if (client.isRoomEncrypted(roomId) && eventIndex !== null) {
 | 
			
		||||
            return eventIndex.paginateTimelineWindow(room, timelineWindow, direction, limit);
 | 
			
		||||
        } else {
 | 
			
		||||
            return timelineWindow.paginate(direction, limit);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    async updateTimelineSet(roomId: string) {
 | 
			
		||||
        const client = MatrixClientPeg.get();
 | 
			
		||||
        const room = client.getRoom(roomId);
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +99,8 @@ const FilePanel = createReactClass({
 | 
			
		|||
                timelineSet = await this.fetchFileEventsServer(room)
 | 
			
		||||
 | 
			
		||||
                if (client.isRoomEncrypted(roomId) && eventIndex !== null) {
 | 
			
		||||
                    await eventIndex.populateFileTimeline(room, timelineSet);
 | 
			
		||||
                    const timeline = timelineSet.getLiveTimeline();
 | 
			
		||||
                    await eventIndex.populateFileTimeline(timelineSet, timeline, room, 1);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.setState({ timelineSet: timelineSet });
 | 
			
		||||
| 
						 | 
				
			
			@ -128,6 +143,7 @@ const FilePanel = createReactClass({
 | 
			
		|||
                        manageReadMarkers={false}
 | 
			
		||||
                        timelineSet={this.state.timelineSet}
 | 
			
		||||
                        showUrlPreview = {false}
 | 
			
		||||
                        onPaginationRequest={this.onPaginationRequest}
 | 
			
		||||
                        tileShape="file_grid"
 | 
			
		||||
                        resizeNotifier={this.props.resizeNotifier}
 | 
			
		||||
                        empty={_t('There are no visible files in this room')}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,6 +94,10 @@ const TimelinePanel = createReactClass({
 | 
			
		|||
        // callback which is called when the read-up-to mark is updated.
 | 
			
		||||
        onReadMarkerUpdated: PropTypes.func,
 | 
			
		||||
 | 
			
		||||
        // callback which is called when we wish to paginate the timeline
 | 
			
		||||
        // window.
 | 
			
		||||
        onPaginationRequest: PropTypes.func,
 | 
			
		||||
 | 
			
		||||
        // maximum number of events to show in a timeline
 | 
			
		||||
        timelineCap: PropTypes.number,
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -338,6 +342,14 @@ const TimelinePanel = createReactClass({
 | 
			
		|||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onPaginationRequest(timelineWindow, direction, size) {
 | 
			
		||||
        if (this.props.onPaginationRequest) {
 | 
			
		||||
            return this.props.onPaginationRequest(timelineWindow, direction, size);
 | 
			
		||||
        } else {
 | 
			
		||||
            return timelineWindow.paginate(direction, size);
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    // set off a pagination request.
 | 
			
		||||
    onMessageListFillRequest: function(backwards) {
 | 
			
		||||
        if (!this._shouldPaginate()) return Promise.resolve(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -360,7 +372,7 @@ const TimelinePanel = createReactClass({
 | 
			
		|||
        debuglog("TimelinePanel: Initiating paginate; backwards:"+backwards);
 | 
			
		||||
        this.setState({[paginatingKey]: true});
 | 
			
		||||
 | 
			
		||||
        return this._timelineWindow.paginate(dir, PAGINATE_SIZE).then((r) => {
 | 
			
		||||
        return this.onPaginationRequest(this._timelineWindow, dir, PAGINATE_SIZE).then((r) => {
 | 
			
		||||
            if (this.unmounted) { return; }
 | 
			
		||||
 | 
			
		||||
            debuglog("TimelinePanel: paginate complete backwards:"+backwards+"; success:"+r);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -418,17 +418,29 @@ export default class EventIndex {
 | 
			
		|||
        return indexManager.searchEventIndex(searchArgs);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async populateFileTimeline(room, timelineSet) {
 | 
			
		||||
    async loadFileEvents(room, limit = 10, fromEvent = null, direction = EventTimeline.BACKWARDS) {
 | 
			
		||||
        const client = MatrixClientPeg.get();
 | 
			
		||||
        const indexManager = PlatformPeg.get().getEventIndexingManager();
 | 
			
		||||
 | 
			
		||||
        let loadArgs = {
 | 
			
		||||
            roomId: room.roomId,
 | 
			
		||||
            limit: limit
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (fromEvent) {
 | 
			
		||||
            loadArgs.fromEvent = fromEvent;
 | 
			
		||||
            loadArgs.direction = direction;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let events
 | 
			
		||||
 | 
			
		||||
        // Get our events from the event index.
 | 
			
		||||
        const events = await indexManager.loadFileEvents(
 | 
			
		||||
            {
 | 
			
		||||
                roomId: room.roomId,
 | 
			
		||||
                limit: 10
 | 
			
		||||
            }
 | 
			
		||||
        );
 | 
			
		||||
        try {
 | 
			
		||||
            events = await indexManager.loadFileEvents(loadArgs);
 | 
			
		||||
        } catch (e) {
 | 
			
		||||
            console.log("EventIndex: Error getting file events", e);
 | 
			
		||||
            return []
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        let eventMapper = client.getEventMapper();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -468,15 +480,82 @@ export default class EventIndex {
 | 
			
		|||
            return matrixEvent;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        return matrixEvents;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async populateFileTimeline(timelineSet, timeline, room, limit = 10,
 | 
			
		||||
                               fromEvent = null, direction = EventTimeline.BACKWARDS) {
 | 
			
		||||
        let matrixEvents = await this.loadFileEvents(room, limit, fromEvent, direction);
 | 
			
		||||
 | 
			
		||||
        // Add the events to the live timeline of the file panel.
 | 
			
		||||
        matrixEvents.forEach(e => {
 | 
			
		||||
            if (!timelineSet.eventIdToTimeline(e.getId())) {
 | 
			
		||||
                const liveTimeline = timelineSet.getLiveTimeline();
 | 
			
		||||
                timelineSet.addEventToTimeline(e, liveTimeline, true)
 | 
			
		||||
                timelineSet.addEventToTimeline(e, timeline,
 | 
			
		||||
                                               direction == EventTimeline.BACKWARDS)
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Set the pagination token to the oldest event that we retrieved.
 | 
			
		||||
        timelineSet.getLiveTimeline().setPaginationToken("", EventTimeline.BACKWARDS);
 | 
			
		||||
        if (matrixEvents.length > 0) {
 | 
			
		||||
            timeline.setPaginationToken(matrixEvents[matrixEvents.length - 1].getId(),
 | 
			
		||||
                                        EventTimeline.BACKWARDS);
 | 
			
		||||
            return true;
 | 
			
		||||
        } else {
 | 
			
		||||
            timeline.setPaginationToken("", EventTimeline.BACKWARDS);
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    paginateTimelineWindow(room, timelineWindow, direction, limit) {
 | 
			
		||||
        let tl;
 | 
			
		||||
 | 
			
		||||
        // TODO this is from the js-sdk, this should probably be exposed to
 | 
			
		||||
        // us through the js-sdk.
 | 
			
		||||
        const moveWindowCap = (titmelineWindow, timeline, direction, limit) => {
 | 
			
		||||
            var count = (direction == EventTimeline.BACKWARDS) ?
 | 
			
		||||
            timeline.retreat(limit) : timeline.advance(limit);
 | 
			
		||||
 | 
			
		||||
            if (count) {
 | 
			
		||||
                timelineWindow._eventCount += count;
 | 
			
		||||
                var excess = timelineWindow._eventCount - timelineWindow._windowLimit;
 | 
			
		||||
 | 
			
		||||
                if (excess > 0) {
 | 
			
		||||
                    timelineWindow.unpaginate(3, direction != EventTimeline.BACKWARDS);
 | 
			
		||||
                }
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        // TODO these private fields should be somehow exposed in the js-sdk.
 | 
			
		||||
        if (direction == EventTimeline.BACKWARDS) tl = timelineWindow._start;
 | 
			
		||||
        else if (direction == EventTimeline.FORWARDS) tl = timelineWindow._end;
 | 
			
		||||
 | 
			
		||||
        if (!tl) return Promise.resolve(false);
 | 
			
		||||
        if (tl.pendingPaginate) return tl.pendingPaginate;
 | 
			
		||||
 | 
			
		||||
        if (moveWindowCap(timelineWindow, tl, direction, limit)) {
 | 
			
		||||
            return Promise.resolve(true);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const paginationMethod = async (timelineWindow, timeline, room, direction, limit) => {
 | 
			
		||||
            const timelineSet = timelineWindow._timelineSet;
 | 
			
		||||
            const token = timeline.timeline.getPaginationToken(direction);
 | 
			
		||||
 | 
			
		||||
            const ret = await this.populateFileTimeline(timelineSet, timeline.timeline,
 | 
			
		||||
                                                        room, limit, token, direction);
 | 
			
		||||
 | 
			
		||||
            moveWindowCap(timelineWindow, timeline, direction, limit)
 | 
			
		||||
            timeline.pendingPaginate = null;
 | 
			
		||||
 | 
			
		||||
            return ret;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const paginationPromise = paginationMethod(timelineWindow, tl, room,
 | 
			
		||||
                                                   direction, limit);
 | 
			
		||||
        tl.pendingPaginate = paginationPromise;
 | 
			
		||||
 | 
			
		||||
        return paginationPromise;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue