mirror of
https://github.com/tulir/gomuks.git
synced 2025-04-20 10:33:41 -05:00
web/timeline: auto-load history until screen is full
This commit is contained in:
parent
05f64edeaf
commit
83a4df9375
4 changed files with 27 additions and 7 deletions
|
@ -274,9 +274,8 @@ export default class Client {
|
|||
const room = this.store.rooms.get(roomID)
|
||||
if (!room) {
|
||||
throw new Error("Room not found")
|
||||
}
|
||||
if (room.paginating) {
|
||||
return
|
||||
} else if (room.paginating) {
|
||||
throw new Error("Already paginating")
|
||||
}
|
||||
room.paginating = true
|
||||
try {
|
||||
|
@ -288,6 +287,7 @@ export default class Client {
|
|||
if (room.timeline[0]?.timeline_rowid !== oldestRowID) {
|
||||
throw new Error("Timeline changed while loading history")
|
||||
}
|
||||
room.hasMoreHistory = resp.has_more
|
||||
room.applyPagination(resp.events)
|
||||
} finally {
|
||||
room.paginating = false
|
||||
|
|
|
@ -112,6 +112,7 @@ export class RoomStateStore {
|
|||
paginating = false
|
||||
paginationRequestedForRow = -1
|
||||
readUpToRow = -1
|
||||
hasMoreHistory = true
|
||||
|
||||
constructor(meta: DBRoom, private parent: StateStore) {
|
||||
this.roomID = meta.room_id
|
||||
|
@ -467,6 +468,7 @@ export class RoomStateStore {
|
|||
this.#membersCache = null
|
||||
this.#autocompleteMembersCache = null
|
||||
this.paginationRequestedForRow = -1
|
||||
this.hasMoreHistory = true
|
||||
this.timeline = []
|
||||
this.notifyTimelineSubscribers()
|
||||
const eventsToKeepList = this.eventsByRowID.values()
|
||||
|
|
|
@ -5,4 +5,15 @@ div.timeline-view {
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
> div.timeline-beginning {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
|
||||
> button {
|
||||
display: flex;
|
||||
padding: .5rem 1rem;
|
||||
gap: .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
import { use, useCallback, useEffect, useLayoutEffect, useRef } from "react"
|
||||
import { use, useCallback, useEffect, useLayoutEffect, useRef, useState } from "react"
|
||||
import { ScaleLoader } from "react-spinners"
|
||||
import { useRoomTimeline } from "@/api/statestore"
|
||||
import { MemDBEvent } from "@/api/types"
|
||||
import useFocus from "@/util/focus.ts"
|
||||
|
@ -27,14 +28,18 @@ const TimelineView = () => {
|
|||
const room = roomCtx.store
|
||||
const timeline = useRoomTimeline(room)
|
||||
const client = use(ClientContext)!
|
||||
const [isLoadingHistory, setLoadingHistory] = useState(false)
|
||||
const loadHistory = useCallback(() => {
|
||||
setLoadingHistory(true)
|
||||
client.loadMoreHistory(room.roomID)
|
||||
.catch(err => console.error("Failed to load history", err))
|
||||
.finally(() => setLoadingHistory(false))
|
||||
}, [client, room])
|
||||
const bottomRef = roomCtx.timelineBottomRef
|
||||
const topRef = useRef<HTMLDivElement>(null)
|
||||
const timelineViewRef = useRef<HTMLDivElement>(null)
|
||||
const prevOldestTimelineRow = useRef(0)
|
||||
const oldestTimelineRow = timeline[0]?.timeline_rowid
|
||||
const oldScrollHeight = useRef(0)
|
||||
const focused = useFocus()
|
||||
|
||||
|
@ -93,7 +98,7 @@ const TimelineView = () => {
|
|||
}, [focused, client, roomCtx, room, timeline])
|
||||
useEffect(() => {
|
||||
const topElem = topRef.current
|
||||
if (!topElem) {
|
||||
if (!topElem || !room.hasMoreHistory) {
|
||||
return
|
||||
}
|
||||
const observer = new IntersectionObserver(entries => {
|
||||
|
@ -108,12 +113,14 @@ const TimelineView = () => {
|
|||
})
|
||||
observer.observe(topElem)
|
||||
return () => observer.unobserve(topElem)
|
||||
}, [room, loadHistory])
|
||||
}, [room, room.hasMoreHistory, loadHistory, oldestTimelineRow])
|
||||
|
||||
let prevEvt: MemDBEvent | null = null
|
||||
return <div className="timeline-view" onScroll={handleScroll} ref={timelineViewRef}>
|
||||
<div className="timeline-beginning">
|
||||
<button onClick={loadHistory}>Load history</button>
|
||||
{room.hasMoreHistory ? <button onClick={loadHistory} disabled={isLoadingHistory}>
|
||||
{isLoadingHistory ? <><ScaleLoader /> Loading history...</> : "Load more history"}
|
||||
</button> : "No more history available in this room"}
|
||||
</div>
|
||||
<div className="timeline-list">
|
||||
<div className="timeline-top-ref" ref={topRef}/>
|
||||
|
|
Loading…
Add table
Reference in a new issue