Selaa lähdekoodia

Fix search repeating when the end has been reached

Zed 6 kuukautta sitten
vanhempi
commit
2898efab6b
4 muutettua tiedostoa jossa 65 lisäystä ja 54 poistoa
  1. 57 52
      public/js/infiniteScroll.js
  2. 5 0
      src/api.nim
  3. 1 1
      src/routes/status.nim
  4. 2 1
      src/routes/timeline.nim

+ 57 - 52
public/js/infiniteScroll.js

@@ -1,77 +1,82 @@
 // @license http://www.gnu.org/licenses/agpl-3.0.html AGPL-3.0
 // SPDX-License-Identifier: AGPL-3.0-only
 function insertBeforeLast(node, elem) {
-    node.insertBefore(elem, node.childNodes[node.childNodes.length - 2]);
+  node.insertBefore(elem, node.childNodes[node.childNodes.length - 2]);
 }
 
 function getLoadMore(doc) {
-    return doc.querySelector(".show-more:not(.timeline-item)");
+  return doc.querySelector(".show-more:not(.timeline-item)");
 }
 
 function isDuplicate(item, itemClass) {
-    const tweet = item.querySelector(".tweet-link");
-    if (tweet == null) return false;
-    const href = tweet.getAttribute("href");
-    return document.querySelector(itemClass + " .tweet-link[href='" + href + "']") != null;
+  const tweet = item.querySelector(".tweet-link");
+  if (tweet == null) return false;
+  const href = tweet.getAttribute("href");
+  return (
+    document.querySelector(itemClass + " .tweet-link[href='" + href + "']") !=
+    null
+  );
 }
 
 window.onload = function () {
-    const url = window.location.pathname;
-    const isTweet = url.indexOf("/status/") !== -1;
-    const containerClass = isTweet ? ".replies" : ".timeline";
-    const itemClass = containerClass + " > div:not(.top-ref)";
+  const url = window.location.pathname;
+  const isTweet = url.indexOf("/status/") !== -1;
+  const containerClass = isTweet ? ".replies" : ".timeline";
+  const itemClass = containerClass + " > div:not(.top-ref)";
 
-    var html = document.querySelector("html");
-    var container = document.querySelector(containerClass);
-    var loading = false;
+  var html = document.querySelector("html");
+  var container = document.querySelector(containerClass);
+  var loading = false;
 
-    function handleScroll(failed) {
-        if (loading) return;
+  function handleScroll(failed) {
+    if (loading) return;
 
-        if (html.scrollTop + html.clientHeight >= html.scrollHeight - 3000) {
-            loading = true;
-            var loadMore = getLoadMore(document);
-            if (loadMore == null) return;
+    if (html.scrollTop + html.clientHeight >= html.scrollHeight - 3000) {
+      loading = true;
+      var loadMore = getLoadMore(document);
+      if (loadMore == null) return;
 
-            loadMore.children[0].text = "Loading...";
+      loadMore.children[0].text = "Loading...";
 
-            var url = new URL(loadMore.children[0].href);
-            url.searchParams.append("scroll", "true");
+      var url = new URL(loadMore.children[0].href);
+      url.searchParams.append("scroll", "true");
 
-            fetch(url.toString()).then(function (response) {
-                if (response.status === 404) throw "error";
+      fetch(url.toString())
+        .then(function (response) {
+          if (response.status > 299) throw "error";
+          return response.text();
+        })
+        .then(function (html) {
+          var parser = new DOMParser();
+          var doc = parser.parseFromString(html, "text/html");
+          loadMore.remove();
 
-                return response.text();
-            }).then(function (html) {
-                var parser = new DOMParser();
-                var doc = parser.parseFromString(html, "text/html");
-                loadMore.remove();
+          for (var item of doc.querySelectorAll(itemClass)) {
+            if (item.className == "timeline-item show-more") continue;
+            if (isDuplicate(item, itemClass)) continue;
+            if (isTweet) container.appendChild(item);
+            else insertBeforeLast(container, item);
+          }
 
-                for (var item of doc.querySelectorAll(itemClass)) {
-                    if (item.className == "timeline-item show-more") continue;
-                    if (isDuplicate(item, itemClass)) continue;
-                    if (isTweet) container.appendChild(item);
-                    else insertBeforeLast(container, item);
-                }
+          loading = false;
+          const newLoadMore = getLoadMore(doc);
+          if (newLoadMore == null) return;
+          if (isTweet) container.appendChild(newLoadMore);
+          else insertBeforeLast(container, newLoadMore);
+        })
+        .catch(function (err) {
+          console.warn("Something went wrong.", err);
+          if (failed > 3) {
+            loadMore.children[0].text = "Error";
+            return;
+          }
 
-                loading = false;
-                const newLoadMore = getLoadMore(doc);
-                if (newLoadMore == null) return;
-                if (isTweet) container.appendChild(newLoadMore);
-                else insertBeforeLast(container, newLoadMore);
-            }).catch(function (err) {
-                console.warn("Something went wrong.", err);
-                if (failed > 3) {
-                    loadMore.children[0].text = "Error";
-                    return;
-                }
-
-                loading = false;
-                handleScroll((failed || 0) + 1);
-            });
-        }
+          loading = false;
+          handleScroll((failed || 0) + 1);
+        });
     }
+  }
 
-    window.addEventListener("scroll", () => handleScroll());
+  window.addEventListener("scroll", () => handleScroll());
 };
 // @license-end

+ 5 - 0
src/api.nim

@@ -168,6 +168,11 @@ proc getGraphTweetSearch*(query: Query; after=""): Future[Timeline] {.async.} =
   result = parseGraphSearch[Tweets](js, after)
   result.query = query
 
+  # when no more items are available the API just returns the last page in
+  # full. this detects that and clears the page instead.
+  if after.len > 0 and after[0..<64] == result.bottom[0..<64]:
+    result.content.setLen(0)
+
 proc getGraphUserSearch*(query: Query; after=""): Future[Result[User]] {.async.} =
   if query.text.len == 0:
     return Result[User](query: query, beginning: true)

+ 1 - 1
src/routes/status.nim

@@ -27,7 +27,7 @@ proc createStatusRouter*(cfg: Config) =
       if @"scroll".len > 0:
         let replies = await getReplies(id, getCursor())
         if replies.content.len == 0:
-          resp Http404, ""
+          resp Http204
         resp $renderReplies(replies, prefs, getPath())
 
       let conv = await getTweet(id, getCursor())

+ 2 - 1
src/routes/timeline.nim

@@ -129,7 +129,8 @@ proc createTimelineRouter*(cfg: Config) =
       if @"scroll".len > 0:
         if query.fromUser.len != 1:
           var timeline = await getGraphTweetSearch(query, after)
-          if timeline.content.len == 0: resp Http404
+          if timeline.content.len == 0: 
+            resp Http204
           timeline.beginning = true
           resp $renderTweetSearch(timeline, prefs, getPath())
         else: