infiniteScroll.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // @license http://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
  2. // SPDX-License-Identifier: AGPL-3.0-only
  3. function insertBeforeLast(node, elem) {
  4. node.insertBefore(elem, node.childNodes[node.childNodes.length - 2]);
  5. }
  6. function getLoadMore(doc) {
  7. return doc.querySelector('.show-more:not(.timeline-item)');
  8. }
  9. function isDuplicate(item, itemClass) {
  10. const tweet = item.querySelector(".tweet-link");
  11. if (tweet == null) return false;
  12. const href = tweet.getAttribute("href");
  13. return document.querySelector(itemClass + " .tweet-link[href='" + href + "']") != null;
  14. }
  15. window.onload = function() {
  16. const url = window.location.pathname;
  17. const isTweet = url.indexOf("/status/") !== -1;
  18. const containerClass = isTweet ? ".replies" : ".timeline";
  19. const itemClass = containerClass + ' > div:not(.top-ref)';
  20. var html = document.querySelector("html");
  21. var container = document.querySelector(containerClass);
  22. var loading = false;
  23. window.addEventListener('scroll', function() {
  24. if (loading) return;
  25. if (html.scrollTop + html.clientHeight >= html.scrollHeight - 3000) {
  26. loading = true;
  27. var loadMore = getLoadMore(document);
  28. if (loadMore == null) return;
  29. loadMore.children[0].text = "Loading...";
  30. var url = new URL(loadMore.children[0].href);
  31. url.searchParams.append('scroll', 'true');
  32. fetch(url.toString()).then(function (response) {
  33. return response.text();
  34. }).then(function (html) {
  35. var parser = new DOMParser();
  36. var doc = parser.parseFromString(html, 'text/html');
  37. loadMore.remove();
  38. for (var item of doc.querySelectorAll(itemClass)) {
  39. if (item.className == "timeline-item show-more") continue;
  40. if (isDuplicate(item, itemClass)) continue;
  41. if (isTweet) container.appendChild(item);
  42. else insertBeforeLast(container, item);
  43. }
  44. loading = false;
  45. const newLoadMore = getLoadMore(doc);
  46. if (newLoadMore == null) return;
  47. if (isTweet) container.appendChild(newLoadMore);
  48. else insertBeforeLast(container, newLoadMore);
  49. }).catch(function (err) {
  50. console.warn('Something went wrong.', err);
  51. loading = true;
  52. });
  53. }
  54. });
  55. };
  56. // @license-end