-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtimeline.js
155 lines (125 loc) · 4.48 KB
/
timeline.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
import { db } from './dbInstance.js'
import { applyDefaults, initializeDefaultFollowedActors } from './defaults.js'
let hasLoaded = false
class ReaderTimeline extends HTMLElement {
skip = 0
limit = 32
hasMoreItems = true
sort = 'latest'
totalNotesCount = 0
loadedNotesCount = 0
loadMoreBtn = null
loadingText = null
constructor () {
super()
// Create the Load More button
this.loadMoreBtn = document.createElement('button')
this.loadMoreBtn.textContent = 'Load More...'
this.loadMoreBtn.className = 'load-more-btn'
this.loadMoreBtnWrapper = document.createElement('div')
this.loadMoreBtnWrapper.className = 'load-more-btn-container'
this.loadMoreBtnWrapper.appendChild(this.loadMoreBtn)
this.loadMoreBtn.addEventListener('click', () => this.loadMore())
// Create the loading text element
this.loadingText = document.createElement('div')
this.loadingText.textContent = 'Loading...'
this.loadingText.className = 'loading-text'
}
async connectedCallback () {
// Show the loading text when initializing
this.appendChild(this.loadingText)
await applyDefaults()
this.initializeSortOrder()
await initializeDefaultFollowedActors()
await this.initTimeline()
}
initializeSortOrder () {
const params = new URLSearchParams(window.location.search)
this.sort = params.get('sort') || 'latest'
const sortOrderSelect = document.getElementById('sortOrder')
if (sortOrderSelect) {
sortOrderSelect.value = this.sort
sortOrderSelect.addEventListener('change', (event) => {
this.sort = event.target.value
this.updateURL()
this.resetTimeline()
})
}
}
updateURL () {
const url = new URL(window.location)
url.searchParams.set('sort', this.sort)
window.history.pushState({}, '', url)
}
async resetTimeline () {
this.skip = 0
this.totalNotesCount = await db.getTotalNotesCount()
this.loadedNotesCount = 0
this.hasMoreItems = true
while (this.firstChild) {
this.removeChild(this.firstChild)
}
this.appendChild(this.loadingText) // Show loading text when resetting timeline
await this.loadMore()
}
async initTimeline () {
if (!hasLoaded) {
hasLoaded = true
const followedActors = await db.getFollowedActors()
// Ensure all followed actors are ingested before loading notes.
await Promise.all(followedActors.map(({ url }) => db.ingestActor(url)))
console.log('All followed actors have been ingested')
// Load the timeline notes after ingestion.
this.resetTimeline()
} else {
this.loadMore() // Start loading notes immediately if already loaded.
}
}
async loadMore () {
// Hide loadMore button when fetching new data
this.loadMoreBtnWrapper.remove()
// Show loading text while fetching new notes
this.appendChild(this.loadingText)
let notesProcessed = 0
let count = 0
const sortValue = this.sort === 'random' ? 0 : (this.sort === 'oldest' ? 1 : -1)
// Fetch notes and render them as they become available
for await (const note of db.searchNotes({ timeline: 'following' }, { skip: this.skip, limit: this.limit, sort: sortValue })) {
console.log('Loading note:', note)
// Exclude replies from appearing in the timeline
if (!note.inReplyTo) {
this.appendNoteElement(note)
count++
}
notesProcessed++
}
// Remove loading text once fetching is done
if (this.contains(this.loadingText)) {
this.removeChild(this.loadingText)
}
this.updateHasMore(count, notesProcessed, sortValue)
this.appendLoadMoreIfNeeded() // Ensure this is called even if no notes are found
}
updateHasMore (count, notesProcessed, sortValue) {
this.skip += notesProcessed
if (this.sort === 'random') {
// For random, we need to compare against the total number of notes
this.loadedNotesCount += count
this.hasMoreItems = this.loadedNotesCount < this.totalNotesCount
} else {
// For other sorts, check if the fetched notes are less than the limit
this.hasMoreItems = notesProcessed === this.limit
}
}
appendLoadMoreIfNeeded () {
if (this.hasMoreItems) {
this.appendChild(this.loadMoreBtnWrapper)
}
}
appendNoteElement (note) {
const activityElement = document.createElement('distributed-post')
activityElement.setAttribute('url', note.id)
this.appendChild(activityElement)
}
}
customElements.define('reader-timeline', ReaderTimeline)