status.nim 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # SPDX-License-Identifier: AGPL-3.0-only
  2. import sequtils
  3. import karax/[karaxdsl, vdom]
  4. import ".."/[types, formatters]
  5. import tweet, timeline
  6. proc renderEarlier(thread: Chain): VNode =
  7. buildHtml(tdiv(class="timeline-item more-replies earlier-replies")):
  8. a(class="more-replies-text", href=getLink(thread.content[0])):
  9. text "earlier replies"
  10. proc renderMoreReplies(thread: Chain): VNode =
  11. let link = getLink(thread.content[^1])
  12. buildHtml(tdiv(class="timeline-item more-replies")):
  13. if thread.content[^1].available:
  14. a(class="more-replies-text", href=link):
  15. text "more replies"
  16. else:
  17. a(class="more-replies-text"):
  18. text "more replies"
  19. proc renderReplyThread(thread: Chain; prefs: Prefs; path: string): VNode =
  20. buildHtml(tdiv(class="reply thread thread-line")):
  21. for i, tweet in thread.content:
  22. let last = (i == thread.content.high and not thread.hasMore)
  23. renderTweet(tweet, prefs, path, index=i, last=last)
  24. if thread.hasMore:
  25. renderMoreReplies(thread)
  26. proc renderReplySort(sort: RankingMode): VNode =
  27. buildHtml(tdiv(class="reply-sort")):
  28. span(class="reply-sort-label"): text "Sort replies:"
  29. for mode in RankingMode:
  30. let
  31. cls = if mode == sort: "reply-sort-option active"
  32. else: "reply-sort-option"
  33. label = case mode
  34. of Relevance: "Relevant"
  35. of Recency: "Recent"
  36. of Likes: "Liked"
  37. a(class=cls, href=("?sort=" & $mode & "#r")):
  38. text label
  39. proc renderReplies*(replies: Result[Chain]; prefs: Prefs; path: string;
  40. tweet: Tweet = nil; sort = Relevance): VNode =
  41. buildHtml(tdiv(class="replies", id="r")):
  42. var hasReplies = false
  43. var replyCount = 0
  44. for thread in replies.content:
  45. if thread.content.len == 0 or thread.related: continue
  46. hasReplies = true
  47. replyCount += thread.content.len
  48. renderReplyThread(thread, prefs, path)
  49. if hasReplies and replies.bottom.len > 0:
  50. if tweet == nil or not replies.beginning or replyCount < tweet.stats.replies:
  51. let extra = if sort == Relevance: "" else: "sort=" & $sort & "&"
  52. renderMore(Query(), replies.bottom, focus="#r", extra=extra)
  53. proc renderRelated(replies: Result[Chain]; prefs: Prefs; path: string): VNode =
  54. buildHtml(tdiv(class="related-tweets")):
  55. tdiv(class="related-header"):
  56. text "Related tweets"
  57. for thread in replies.content:
  58. if thread.content.len == 0 or not thread.related: continue
  59. renderReplyThread(thread, prefs, path)
  60. proc renderConversation*(conv: Conversation; prefs: Prefs; path: string;
  61. sort = Relevance): VNode =
  62. let hasAfter = conv.after.content.len > 0
  63. let threadId = conv.tweet.threadId
  64. buildHtml(tdiv(class="conversation")):
  65. tdiv(class="main-thread"):
  66. if conv.before.content.len > 0:
  67. tdiv(class="before-tweet thread-line"):
  68. let first = conv.before.content[0]
  69. if threadId != first.id and (first.replyId > 0 or not first.available):
  70. renderEarlier(conv.before)
  71. for i, tweet in conv.before.content:
  72. renderTweet(tweet, prefs, path, index=i)
  73. tdiv(class="main-tweet", id="m"):
  74. let afterClass = if hasAfter: "thread thread-line" else: ""
  75. renderTweet(conv.tweet, prefs, path, class=afterClass, mainTweet=true)
  76. if hasAfter:
  77. tdiv(class="after-tweet thread-line"):
  78. let
  79. total = conv.after.content.high
  80. hasMore = conv.after.hasMore
  81. for i, tweet in conv.after.content:
  82. renderTweet(tweet, prefs, path, index=i,
  83. last=(i == total and not hasMore), afterTweet=true)
  84. if hasMore:
  85. renderMoreReplies(conv.after)
  86. if not prefs.hideReplies:
  87. if not conv.replies.beginning:
  88. renderNewer(Query(), getLink(conv.tweet), focus="#r")
  89. if conv.replies.content.len > 0 or conv.replies.bottom.len > 0:
  90. renderReplySort(sort)
  91. renderReplies(conv.replies, prefs, path, conv.tweet, sort)
  92. if not prefs.hideRelated:
  93. if conv.replies.content.anyIt(it.related and it.content.len > 0):
  94. renderRelated(conv.replies, prefs, path)
  95. renderToTop(focus="#m")
  96. proc renderEditHistory*(edits: EditHistory; prefs: Prefs; path: string): VNode =
  97. buildHtml(tdiv(class="edit-history")):
  98. tdiv(class="latest-edit"):
  99. tdiv(class="edit-history-header"):
  100. text "Latest post"
  101. renderTweet(edits.latest, prefs, path)
  102. tdiv(class="previous-edits"):
  103. tdiv(class="edit-history-header"):
  104. text "Version history"
  105. for tweet in edits.history:
  106. tdiv(class="tweet-edit"):
  107. renderTweet(tweet, prefs, path)