/* * Copyright (C) 2022 StApps * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ import {Component, OnInit} from '@angular/core'; import {IonRefresher} from '@ionic/angular'; import { SCMessage, SCSearchFilter, SCSearchValueFilter, SCSetting, } from '@openstapps/core'; import {SettingsProvider} from '../../settings/settings.provider'; import { newsFilterSettingsCategory, newsFilterSettingsFieldsMapping, NewsFilterSettingsNames, } from '../news-filter-settings'; import {NewsProvider} from '../news.provider'; import {SplashScreen} from '@capacitor/splash-screen'; /** * News page component */ @Component({ selector: 'stapps-news-page', templateUrl: 'news-page.html', styleUrls: ['news-page.scss'], }) export class NewsPageComponent implements OnInit { /** * Thing counter to start query the next page from */ from = 0; /** * News (messages) to show */ news: SCMessage[] = []; /** * Minimum page size of queries */ minPageSize = 10; /** * Page size of queries */ pageSize = 10; /** * Element size in px */ elementSize = [300, 300]; /** * Relevant settings */ settings: SCSetting[]; /** * Active filters */ filters: SCSearchFilter[]; constructor( private newsProvider: NewsProvider, private settingsProvider: SettingsProvider, ) {} /** * Fetch news from the backend */ async fetchNews() { this.from = this.pageSize; this.news = await this.newsProvider.getList(this.pageSize, 0, [ ...this.filters, ]); await SplashScreen.hide(); } /** * Loads more news */ async loadMore( infiniteScrollElement?: HTMLIonInfiniteScrollElement, more = this.pageSize, ): Promise { const from = this.from; this.from += more; const fetchedNews = await this.newsProvider.getList(this.pageSize, from, [ ...this.filters, ]); this.news = [...this.news, ...fetchedNews]; await infiniteScrollElement?.complete(); } calcPageSize(entry: ResizeObserverEntry) { this.pageSize = Math.max( this.minPageSize, Math.floor(entry.contentRect.width / this.elementSize[0]) * Math.ceil(entry.contentRect.height / this.elementSize[1] + 0.25), ); if (!this.from || this.from === 0) return; const more = Math.max(0, this.pageSize - this.from); if (more !== 0) { void this.loadMore(undefined, Math.max(more, this.minPageSize)); } } /** * Initialize the local variables on component initialization */ async ngOnInit() { // Helper method to provide the relevant settings const getNewsSettings = async (settingNames: NewsFilterSettingsNames[]) => { const settings = []; for (const settingName of settingNames) { settings.push( await this.settingsProvider.getSetting( newsFilterSettingsCategory, settingName, ), ); } return settings; }; this.settings = await getNewsSettings( Object.keys(newsFilterSettingsFieldsMapping) as NewsFilterSettingsNames[], ); } /** * Updates the shown list * * @param refresher Refresher component that triggers the update */ async refresh(refresher: IonRefresher) { try { await this.fetchNews(); } catch { this.news = []; } finally { await refresher.complete(); } } /** * Executed when filters have been changed * * @param filters Current filters to be used */ toggleFilter(filters: SCSearchValueFilter[]) { this.filters = filters; void this.fetchNews(); } }