티스토리 수익 글 보기

티스토리 수익 글 보기

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)