import { Component, ViewChild } from "@angular/core"; import { IonicPage, NavController, NavParams, InfiniteScroll, Content, LoadingController } from "ionic-angular"; import { TwitterApiProvider } from "../../providers/twitter-api/twitter-api"; import { P2pStorageIpfsProvider } from "../../providers/p2p-storage-ipfs/p2p-storage-ipfs"; import { P2pDatabaseGunProvider } from "../../providers/p2p-database-gun/p2p-database-gun"; /** * Generated class for the ProfilePage page. * * See https://ionicframework.com/docs/components/#navigation for more info on * Ionic pages and navigation. */ @IonicPage() @Component({ selector: "page-profile", templateUrl: "profile.html" }) export class ProfilePage { user: any = []; tweets: any[]; oldestLoadedTweetId; enableRefresh: boolean = true; enableInfiniteScroll: boolean = true; @ViewChild(Content) content: Content; constructor( public navCtrl: NavController, private loadingCtrl: LoadingController, public navParams: NavParams, private twitter: TwitterApiProvider, private ipfs: P2pStorageIpfsProvider, private gun: P2pDatabaseGunProvider ) {} ionViewDidLoad() { // Show loading indicator const loading = this.loadingCtrl.create(); loading.present(); // Read user id const userId = this.navParams.get("userId"); // Fetch user details from Twitter this.twitter.fetchUser(userId).then(res => (this.user = res)); // Load user's timeline from Twitter and P2P this.loadTimeline(userId).then(res => { if (res.length > 0) { // Store tweets this.tweets = res; // Save oldest tweet's id for next load more this.oldestLoadedTweetId = res .filter(tweet => !tweet.private_tweet) .reduce((acc, cur) => (acc.id < cur.id ? acc : cur))["id"]; } // Hide loading indicator loading.dismiss(); }); } doRefresh(refresher) { this.loadTimeline(this.user.id).then(res => { if (res.length > 0) { // Replace tweets this.tweets = res; // Save oldest tweet's id for next load more this.oldestLoadedTweetId = res .filter(tweet => !tweet.private_tweet) .reduce((acc, cur) => (acc.id < cur.id ? acc : cur))["id"]; } // Hide loading icon refresher.complete(); }); } loadMore(infiniteScroll: InfiniteScroll) { if (this.enableInfiniteScroll) { this.loadTimeline(this.user.id, this.oldestLoadedTweetId).then(res => { if (res.length > 0) { // Append loaded tweets this.tweets = this.tweets.concat(res); // Save oldest tweet's id for next load more this.oldestLoadedTweetId = res .filter(tweet => !tweet.private_tweet) .reduce((acc, cur) => (acc.id < cur.id ? acc : cur))["id"]; } // Hide loading icon infiniteScroll.complete(); }); } else { // Hide loading icon infiniteScroll.complete(); } } private async loadTimeline(userId, oldestLoadedTweetId?) { // Fetch tweets from Twitter const tweets = oldestLoadedTweetId == null ? await this.twitter.fetchUserTimeline(userId) : await this.twitter.fetchUserTimelineSince( userId, oldestLoadedTweetId ); // Determine end of time interval to look for private tweets let intervalEnd: Date; if (tweets.length < 20) { // End of timeline is reached this.enableInfiniteScroll = false; intervalEnd = new Date("2018-04-01T00:00:00"); } else { const lastTweetTimestamp = tweets[tweets.length - 1].created_at; intervalEnd = new Date(lastTweetTimestamp); } // Fetch private tweet hashs from P2P DB for corresponding interval const privateTweetHashs: string[] = await this.gun.fetchPrivateTweetHashsForUserInInterval( userId, new Date(), intervalEnd ); if (privateTweetHashs.length) { // Load private tweets from P2P storage let privateTweets = await this.ipfs.fetchTweets(privateTweetHashs); // Add user object to private tweets privateTweets = await Promise.all( privateTweets.map(async tweet => await this.addUserToTweet(tweet)) ); // Combine and sort tweets return tweets .concat(privateTweets) .sort((a, b) => this.sortByDateAsc(a, b)); } else { return tweets; } } private sortByDateAsc(a, b) { const dateA = new Date(a.created_at); const dateB = new Date(b.created_at); if (dateA > dateB) { return -1; } else if (dateA < dateB) { return 1; } else { return 0; } } private async addUserToTweet(tweet) { tweet.user = await this.twitter.fetchUser(tweet.user_id); return tweet; } onScroll(event) { this.enableRefresh = event.scrollTop === 0; } }