// @ts-check /* Imports */ /** @typedef {import("@libs/filterInputs").Filters} Filters */ /** @typedef {import("@typings/types").PluginList} PluginList */ /** @typedef {import("@typings/plugin").Plugin.PluginItem} PluginItem */ /** @typedef {import("@typings/plugin").Plugin.ChapterItem} ChapterItem */ /** @typedef {import("@typings/plugin").Plugin.NovelItem} NovelItem */ /** @typedef {import("@typings/plugin").Plugin.SourceNovel & {totalPages?: number}} SourceNovel */ /** @typedef {import("@typings/plugin").Plugin.SourcePage} SourcePage */ /** @typedef {import("@libs/filterInputs").FilterTypes} FilterTypes */ /** @typedef {import("@libs/filterInputs").FilterTypes.CheckboxGroup} CheckboxGroup */ /** * @template {FilterTypes} T * @typedef {import("@libs/filterInputs").ValueOfFilter} ValueOfFilter */ /** * @template {Filters} T * @typedef {import("@libs/filterInputs").FilterToValues} FilterToValues */ /** @typedef {{backgroundColor:string, textColor:string}} Theme */ /** @typedef {Theme[]} Themes */ /** @typedef {import("./accordion").AccordionBox} AccordionBox */ /// // #region DOM Queries const nav = $('nav'); /** @type {JQuery} */ const headerChanger = $('#headerChanger'); /** @type {JQuery} */ const popularNovels = $('#popularNovels'); /** @type {JQuery} */ const popularNovels_page_select = $('#popularNovels .page-select'); /** @type {JQuery} */ const popularNovels_fetch_btn = $('#popularNovels .fetch-btn'); /** @type {JQuery} */ const popularNovels_spinner = $('#popularNovels .spinner-border'); /** @type {JQuery} */ const popularNovels_novel_list = $('#popularNovels .novel-list'); /** @type {JQuery} */ const searchNovels = $('#searchNovels'); /** @type {JQuery} */ const seacrhNovels_novel_list = $('#searchNovels .novel-list'); /** @type {JQuery} */ const searchNovels_page_select = $('#searchNovels .page-select'); /** @type {JQuery} */ const searchNovels_fetch_btn = $('#searchNovels .fetch-btn'); /** @type {JQuery} */ const searchNovels_searchbar = $('#searchNovels .searchbar input'); /** @type {JQuery} */ const parseNovel = $('#parseNovel'); /** @type {JQuery} */ const parsePage = $('#parsePage'); /** @type {JQuery} */ const parseChapter = $('#parseChapter'); /** @type {JQuery} */ const fetchImage = $('#fetchImage'); /** @type {JQuery} */ const resolveUrl = $('#resolveUrl'); /** @type {JQuery}*/ const plugin_language_selection = $('#language'); /** @type {JQuery} */ const plugin_search = $('#plugin'); /** @type {JQuery} */ const plugin_search_results = $('#search-results'); /** @type {JQuery} */ const clear_plugin_search = $('#clear-search'); /** @type {JQuery} */ const previewSwitch = $('#raw-preview-switch'); /** @type {JQuery} */ const chapterViewer = $('#chapter-viewer'); /** @type {JQuery} */ const filtersModal = $('#filtersModal .modal-body'); /** @type {JQuery} */ const latestSwitch = $('#latest-switch'); // #endregion // #region pagination class NovelListPagination { constructor( /** @type {boolean} */ sL, /** @type {JQuery} */ sE, /** @type {JQuery} */ fC, /** @type {JQuery} */ nL, ) { /** @type {Record} */ this.pageStore = {}; this._showlatest = sL; this.lastFetchedPage = 0; this.currentPage = 0; this.canFetchMore = true; this.selectElement = sE; this.fetchContainer = fC; this.resetStoreOnFetch = true; this.novelList = nL; } get showLatest() { return this._showlatest; } set showLatest(val) { this._showlatest = val; this.reset(); } get fetchBtn() { return this.fetchContainer.children('button')[0]; } get numSelect() { return this.selectElement.children('select')[0]; } lockFetch(cause = 0) { this.canFetchMore = false; this.fetchBtn.disabled = true; if (cause === 1) this.fetchBtn.innerText = 'no more to fetch'; if (cause === 2) this.fetchBtn.innerText = 'fetching'; if (cause === 3) this.fetchBtn.innerText = 'error'; } unlockFetch() { this.canFetchMore = true; this.fetchBtn.disabled = false; this.fetchBtn.innerText = 'fetch'; } async fetchNovels( /** @type {(page:number, latest: boolean)=>Promise} */ fn, ) { this.error = undefined; if (this.resetStoreOnFetch) { this.resetStoreOnFetch = false; this.pageStore = {}; } try { this.lockFetch(2); const lfp = ++this.lastFetchedPage; console.log('fetching ', lfp, 'page'); const novels = await fn(lfp, this.showLatest); if (novels.length === 0) { this.lastFetchedPage--; this.lockFetch(1); if (this.lastFetchedPage === 0) { this.error = 'No novels found!'; this.render(); } return false; } this.loadNovels(lfp, novels); this.unlockFetch(); return true; } catch (e) { this.lastFetchedPage--; this.lockFetch(3); this.error = `${e}`; this.render(); return false; } } showNextPage() { console.log('lf', this.lastFetchedPage, 'cp', this.currentPage); if (this.lastFetchedPage > this.currentPage) { this.currentPage = this.lastFetchedPage; this.render(); } this.numSelect.value = `${this.currentPage}`; } arePagesTheSame( /** @type {NovelItem[]} */ p1, /** @type {NovelItem[]} */ p2, ) { if (p1.length !== p2.length) return false; let i = 0; for (const novel of p1) { if (novel.path !== p2[i].path) return false; i++; } return true; } loadNovels(/** @type {number} */ page, /** @type {NovelItem[]} */ list) { this.pageStore[page] = list; if (page - 1 > 0 && this.pageStore[page - 1]) { if ( this.arePagesTheSame(this.pageStore[page], this.pageStore[page - 1]) ) { if (this.numSelect.nextElementSibling) this.numSelect.nextElementSibling.innerHTML = "Pages are the same! It's possible that pagination is not implemented in the source!"; } } } reset() { this.hideSelectBox(); this.currentPage = 0; this.lastFetchedPage = 0; this.resetStoreOnFetch = true; this.error = undefined; if (this.numSelect.nextElementSibling) { this.numSelect.nextElementSibling.innerHTML = ''; } this.unlockFetch(); } setupSelectBox() { this.selectElement[0].style.display = 'inline'; this.numSelect.innerHTML = ''; for (let i = 1; i <= this.lastFetchedPage; i++) { const option = $('