profile.ts 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. import { Component, ViewChild } from "@angular/core";
  2. import {
  3. IonicPage,
  4. NavController,
  5. NavParams,
  6. InfiniteScroll,
  7. Content
  8. } from "ionic-angular";
  9. import { TwitterApiProvider } from "../../providers/twitter-api/twitter-api";
  10. import { P2pStorageIpfsProvider } from "../../providers/p2p-storage-ipfs/p2p-storage-ipfs";
  11. import { P2pDatabaseGunProvider } from "../../providers/p2p-database-gun/p2p-database-gun";
  12. /**
  13. * Generated class for the ProfilePage page.
  14. *
  15. * See https://ionicframework.com/docs/components/#navigation for more info on
  16. * Ionic pages and navigation.
  17. */
  18. @IonicPage()
  19. @Component({
  20. selector: "page-profile",
  21. templateUrl: "profile.html"
  22. })
  23. export class ProfilePage {
  24. user: any = [];
  25. tweets: any[];
  26. oldestLoadedTweetId;
  27. enableRefresh: boolean = true;
  28. enableInfiniteScroll: boolean = true;
  29. @ViewChild(Content)
  30. content: Content;
  31. constructor(
  32. public navCtrl: NavController,
  33. public navParams: NavParams,
  34. private twitter: TwitterApiProvider,
  35. private ipfs: P2pStorageIpfsProvider,
  36. private gun: P2pDatabaseGunProvider
  37. ) {}
  38. ionViewDidLoad() {
  39. const userId = this.navParams.get("userId");
  40. this.twitter.fetchUser(userId).then(res => (this.user = res));
  41. this.loadTimeline(userId, null).then(res => {
  42. if (res.length > 0) {
  43. // Save tweets
  44. this.tweets = res;
  45. // Save oldest tweet's id for next load more
  46. this.oldestLoadedTweetId = res
  47. .filter(tweet => !tweet.private_tweet)
  48. .reduce((acc, cur) => (acc.id < cur.id ? acc : cur))["id"];
  49. }
  50. });
  51. }
  52. doRefresh(refresher) {
  53. this.loadTimeline(this.user.id, null).then(res => {
  54. if (res.length > 0) {
  55. // Replace tweets
  56. this.tweets = res;
  57. // Save oldest tweet's id for next load more
  58. this.oldestLoadedTweetId = res
  59. .filter(tweet => !tweet.private_tweet)
  60. .reduce((acc, cur) => (acc.id < cur.id ? acc : cur))["id"];
  61. }
  62. // Hide loading icon
  63. refresher.complete();
  64. });
  65. }
  66. loadMore(infiniteScroll: InfiniteScroll) {
  67. this.loadTimeline(this.user.id, this.oldestLoadedTweetId).then(res => {
  68. if (res.length > 0) {
  69. // Append loaded tweets
  70. this.tweets = this.tweets.concat(res);
  71. // Save oldest tweet's id for next load more
  72. this.oldestLoadedTweetId = res
  73. .filter(tweet => !tweet.private_tweet)
  74. .reduce((acc, cur) => (acc.id < cur.id ? acc : cur))["id"];
  75. }
  76. // Hide loading icon
  77. infiniteScroll.complete();
  78. });
  79. }
  80. private async loadTimeline(userId, oldestLoadedTweetId) {
  81. // Fetch tweets from Twitter
  82. const tweets =
  83. oldestLoadedTweetId == null
  84. ? await this.twitter.fetchUserTimeline(userId)
  85. : await this.twitter.fetchUserTimelineSince(
  86. userId,
  87. oldestLoadedTweetId
  88. );
  89. // Determine end of time interval to look for private tweets
  90. let intervalEnd;
  91. if (tweets.length < 20) {
  92. // End of timeline is reached
  93. this.enableInfiniteScroll = false;
  94. intervalEnd = new Date("2018-04-01T00:00:00");
  95. } else {
  96. const lastTweetTimestamp = tweets[tweets.length - 1].created_at;
  97. intervalEnd = new Date(lastTweetTimestamp);
  98. }
  99. // Fetch private tweet hashs from P2P DB for corresponding interval
  100. const privateTweetHashs: string[] = await this.gun.fetchPrivateTweetHashsForUserInInterval(
  101. userId,
  102. new Date(),
  103. intervalEnd
  104. );
  105. // Load private tweets from P2P storage
  106. let privateTweets = await this.ipfs.fetchTweets(privateTweetHashs);
  107. // Add user object to private tweets
  108. privateTweets = await Promise.all(
  109. privateTweets.map(async tweet => await this.addUserToTweet(tweet))
  110. );
  111. // Combine and sort tweets
  112. return tweets
  113. .concat(privateTweets)
  114. .sort((a, b) => this.sortByDateAsc(a, b));
  115. }
  116. private sortByDateAsc(a, b) {
  117. const dateA = new Date(a.created_at);
  118. const dateB = new Date(b.created_at);
  119. if (dateA > dateB) {
  120. return -1;
  121. } else if (dateA < dateB) {
  122. return 1;
  123. } else {
  124. return 0;
  125. }
  126. }
  127. private async addUserToTweet(tweet) {
  128. tweet.user = await this.twitter.fetchUser(tweet.user_id);
  129. return tweet;
  130. }
  131. onScroll(event) {
  132. this.enableRefresh = event.scrollTop === 0;
  133. }
  134. }