search.nim 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import strutils, strformat, sequtils, unicode, tables
  2. import karax/[karaxdsl, vdom, vstyles]
  3. import renderutils, timeline
  4. import ".."/[types, formatters, query]
  5. let toggles = {
  6. "nativeretweets": "Retweets",
  7. "media": "Media",
  8. "videos": "Videos",
  9. "news": "News",
  10. "verified": "Verified",
  11. "native_video": "Native videos",
  12. "replies": "Replies",
  13. "links": "Links",
  14. "images": "Images",
  15. "safe": "Safe",
  16. "quote": "Quotes",
  17. "pro_video": "Pro videos"
  18. }.toOrderedTable
  19. proc renderSearch*(): VNode =
  20. buildHtml(tdiv(class="panel-container")):
  21. tdiv(class="search-bar"):
  22. form(`method`="get", action="/search"):
  23. hiddenField("f", "users")
  24. input(`type`="text", name="q", autofocus="", placeholder="Enter username...")
  25. button(`type`="submit"): icon "search"
  26. proc renderProfileTabs*(query: Query; username: string): VNode =
  27. let link = "/" & username
  28. buildHtml(ul(class="tab")):
  29. li(class=query.getTabClass(posts)):
  30. a(href=link): text "Tweets"
  31. li(class=(query.getTabClass(replies) & " wide")):
  32. a(href=(link & "/with_replies")): text "Tweets & Replies"
  33. li(class=query.getTabClass(media)):
  34. a(href=(link & "/media")): text "Media"
  35. li(class=query.getTabClass(tweets)):
  36. a(href=(link & "/search")): text "Search"
  37. proc renderSearchTabs*(query: Query): VNode =
  38. var q = query
  39. buildHtml(ul(class="tab")):
  40. li(class=query.getTabClass(tweets)):
  41. q.kind = tweets
  42. a(href=("?" & genQueryUrl(q))): text "Tweets"
  43. li(class=query.getTabClass(users)):
  44. q.kind = users
  45. a(href=("?" & genQueryUrl(q))): text "Users"
  46. proc isPanelOpen(q: Query): bool =
  47. q.fromUser.len == 0 and (q.filters.len > 0 or q.excludes.len > 0 or
  48. @[q.near, q.until, q.since].anyIt(it.len > 0))
  49. proc renderSearchPanel*(query: Query): VNode =
  50. let user = query.fromUser.join(",")
  51. let action = if user.len > 0: &"/{user}/search" else: "/search"
  52. buildHtml(form(`method`="get", action=action, class="search-field")):
  53. hiddenField("f", "tweets")
  54. genInput("q", "", query.text, "Enter search...",
  55. class="pref-inline", autofocus=true)
  56. button(`type`="submit"): icon "search"
  57. if isPanelOpen(query):
  58. input(id="search-panel-toggle", `type`="checkbox", checked="")
  59. else:
  60. input(id="search-panel-toggle", `type`="checkbox")
  61. label(`for`="search-panel-toggle"):
  62. icon "down"
  63. tdiv(class="search-panel"):
  64. for f in @["filter", "exclude"]:
  65. span(class="search-title"): text capitalize(f)
  66. tdiv(class="search-toggles"):
  67. for k, v in toggles:
  68. let state =
  69. if f == "filter": k in query.filters
  70. else: k in query.excludes
  71. genCheckbox(&"{f[0]}-{k}", v, state)
  72. tdiv(class="search-row"):
  73. tdiv:
  74. span(class="search-title"): text "Time range"
  75. tdiv(class="date-range"):
  76. genDate("since", query.since)
  77. span(class="search-title"): text "-"
  78. genDate("until", query.until)
  79. tdiv:
  80. span(class="search-title"): text "Near"
  81. genInput("near", "", query.near, placeholder="Location...")
  82. proc renderTweetSearch*(results: Result[Tweet]; prefs: Prefs; path: string): VNode =
  83. let query = results.query
  84. buildHtml(tdiv(class="timeline-container")):
  85. if query.fromUser.len > 1:
  86. tdiv(class="timeline-header"):
  87. text query.fromUser.join(" | ")
  88. if query.fromUser.len == 0 or query.kind == tweets:
  89. tdiv(class="timeline-header"):
  90. renderSearchPanel(query)
  91. if query.fromUser.len > 0:
  92. renderProfileTabs(query, query.fromUser.join(","))
  93. else:
  94. renderSearchTabs(query)
  95. renderTimelineTweets(results, prefs, path)
  96. proc renderUserSearch*(results: Result[Profile]; prefs: Prefs): VNode =
  97. buildHtml(tdiv(class="timeline-container")):
  98. tdiv(class="timeline-header"):
  99. form(`method`="get", action="/search", class="search-field"):
  100. hiddenField("f", "users")
  101. genInput("q", "", results.query.text, "Enter username...",
  102. class="pref-inline", autofocus=true)
  103. button(`type`="submit"): icon "search"
  104. renderSearchTabs(results.query)
  105. renderTimelineUsers(results, prefs)