Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: implement random sort and dynamic timeline sorting via dropdown #13

Merged
merged 10 commits into from
Jun 5, 2024
Merged
32 changes: 21 additions & 11 deletions db.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,13 @@ export class ActivityPubDB extends EventTarget {
}
}

async getTotalNotesCount () {
const tx = this.db.transaction(NOTES_STORE, 'readonly')
const store = tx.objectStore(NOTES_STORE)
const totalNotes = await store.count()
return totalNotes
}

async getActivity (url) {
try {
return this.db.get(ACTIVITIES_STORE, url)
Expand Down Expand Up @@ -255,20 +262,23 @@ export class ActivityPubDB extends EventTarget {
const store = tx.objectStore(NOTES_STORE)
const totalNotes = await store.count()

RangerMauve marked this conversation as resolved.
Show resolved Hide resolved
for (let i = 0; i < limit; i++) {
if (totalNotes === 0) return // Early exit if no notes are present

let cursor = await store.openCursor()
const uniqueIndexes = new Set()

while (uniqueIndexes.size < limit && uniqueIndexes.size < totalNotes) {
const randomSkip = Math.floor(Math.random() * totalNotes)
let cursor = await store.openCursor()
if (cursor) {
if (randomSkip > 0) { // Only advance if randomSkip is greater than 0
if (!uniqueIndexes.has(randomSkip)) {
uniqueIndexes.add(randomSkip)
if (randomSkip > 0) {
// Move the cursor to the randomSkip position if not already there
await cursor.advance(randomSkip)
if (cursor) {
yield cursor.value
cursor = await cursor.continue()
}
} else {
// If randomSkip is 0, yield the first item directly
}
if (cursor) {
RangerMauve marked this conversation as resolved.
Show resolved Hide resolved
yield cursor.value
cursor = await cursor.continue() // Continue to the next for proper iteration
// After yielding, reset the cursor to the start for the next random pick
cursor = await store.openCursor()
}
}
}
Expand Down
48 changes: 24 additions & 24 deletions timeline.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ class ReaderTimeline extends HTMLElement {
limit = 32
hasMoreItems = true
sort = 'latest'
totalNotesCount = 0
loadedNotesCount = 0
loadMoreBtn = null
randomNotes = [] // Cache for random notes
randomIndex = 0 // Current index in the random notes cache

constructor () {
super()
Expand All @@ -24,7 +24,7 @@ class ReaderTimeline extends HTMLElement {
this.loadMoreBtn.addEventListener('click', () => this.loadMore())
}

connectedCallback () {
async connectedCallback () {
this.initializeSortOrder()
this.initializeDefaultFollowedActors().then(() => this.initTimeline())
}
Expand Down Expand Up @@ -52,8 +52,8 @@ class ReaderTimeline extends HTMLElement {

async resetTimeline () {
this.skip = 0
this.randomIndex = 0
this.randomNotes = []
this.totalNotesCount = await db.getTotalNotesCount()
this.loadedNotesCount = 0
this.hasMoreItems = true
while (this.firstChild) {
this.removeChild(this.firstChild)
Expand All @@ -78,35 +78,35 @@ class ReaderTimeline extends HTMLElement {
}

async initTimeline () {
this.loadMore() // Start loading notes immediately

if (!hasLoaded) {
hasLoaded = true
const followedActors = await db.getFollowedActors()
await Promise.all(followedActors.map(({ url }) => db.ingestActor(url)))
// Ingest actors in the background without waiting for them
Promise.all(followedActors.map(({ url }) => db.ingestActor(url)))
.then(() => console.log('All followed actors have been ingested'))
.catch(error => console.error('Error ingesting followed actors:', error))
}
this.loadMore()
}

async loadMore () {
this.loadMoreBtnWrapper.remove()
let count = 0

if (this.sort === 'random' && this.randomNotes.length === 0) {
const allNotes = []
for await (const note of db.searchNotesRandom(this.limit)) {
allNotes.push(note)
}
this.randomNotes = allNotes.sort(() => Math.random() - 0.5)
}

const notesToShow = this.sort === 'random'
? this.randomNotes.slice(this.randomIndex, this.randomIndex + this.limit)
: await this.fetchSortedNotes()

for (const note of notesToShow) {
if (note) {
if (this.sort === 'random') {
for await (const note of db.searchNotesRandom({ limit: this.limit })) {
this.appendNoteElement(note)
count++
}
} else {
const notesToShow = await this.fetchSortedNotes()
for (const note of notesToShow) {
if (note) {
this.appendNoteElement(note)
count++
}
}
}

this.updateIndexes(count)
Expand All @@ -124,10 +124,10 @@ class ReaderTimeline extends HTMLElement {

updateIndexes (count) {
RangerMauve marked this conversation as resolved.
Show resolved Hide resolved
if (this.sort === 'random') {
this.randomIndex += this.limit
this.hasMoreItems = this.randomIndex < this.randomNotes.length
this.loadedNotesCount += count
this.hasMoreItems = this.loadedNotesCount < this.totalNotesCount
} else {
this.skip += this.limit
this.skip += count
this.hasMoreItems = count === this.limit
}
}
Expand Down
Loading