Browse Source

Refactor tweet/timeline views

Zed 7 years ago
parent
commit
eeae28da0c

+ 1 - 1
src/sass/profile/_base.scss

@@ -47,7 +47,7 @@
     .profile-tabs {
         width: 100vw;
 
-        .timeline-tab {
+        .timeline-container {
             width: 100% !important;
         }
     }

+ 17 - 28
src/sass/timeline.scss

@@ -1,30 +1,19 @@
 @import '_variables';
 
-#posts {
-    background-color: $bg_panel;
+.timeline-container {
+    @include panel(100%, 600px);
 }
 
-.timeline-tab {
-    float: right;
-    padding: 0;
-    box-sizing: border-box;
-    display: inline-block;
-    font-size: 14px;
-    text-align: left;
-    vertical-align: top;
-}
-
-.multi-timeline {
-    max-width: 600px;
-    width: 100%;
-    margin: 0 auto;
+.timeline {
+    background-color: $bg_panel;
 
-    .timeline-tab {
-        width: 100%;
+    > div:not(:last-child) {
+        border-bottom: 1px solid $border_grey;
     }
+
 }
 
-.multi-header {
+.timeline-header {
     background-color: $bg_panel;
     text-align: center;
     padding: 10px;
@@ -72,10 +61,6 @@
     }
 }
 
-.timeline-tweet {
-    border-bottom: 1px solid $border_grey;
-}
-
 .timeline-footer {
     background-color: $bg_panel;
     padding: 6px 0;
@@ -119,11 +104,7 @@
     background-color: $bg_panel;
     text-align: center;
     padding: .75em 0;
-    display: block;
-
-    &.status-el {
-        border-bottom: 1px solid $border_grey;
-    }
+    display: block !important;
 
     a {
         background-color: $darkest_grey;
@@ -137,3 +118,11 @@
         }
     }
 }
+
+.timeline-item {
+    overflow-wrap: break-word;
+    border-left-width: 0;
+    min-width: 0;
+    padding: .75em;
+    display: flex;
+}

+ 6 - 15
src/sass/tweet/_base.scss

@@ -7,25 +7,17 @@
 @import 'poll';
 @import 'quote';
 
-.status-el {
-    overflow-wrap: break-word;
-    border-left-width: 0;
-    min-width: 0;
-    padding: .75em;
-    display: flex;
-
-    .status-content {
-        font-family: $font_3;
-        line-height: 1.4em;
-    }
-}
-
-.status-body {
+.tweet-body {
     flex: 1;
     min-width: 0;
     margin-left: 58px;
 }
 
+.tweet-content {
+    font-family: $font_3;
+    line-height: 1.4em;
+}
+
 .tweet-header {
     padding: 0;
     vertical-align: bottom;
@@ -79,7 +71,6 @@
         float: left;
         margin-top: 3px;
         margin-left: -58px;
-        position: absolute;
         width: 48px;
         height: 48px;
         border-radius: 50%;

+ 3 - 3
src/sass/tweet/thread.scss

@@ -10,7 +10,7 @@
     background-color: $bg_panel;
 }
 
-.main-tweet .status-content {
+.main-tweet .tweet-content {
     font-size: 20px;
 }
 
@@ -20,7 +20,7 @@
 }
 
 .thread-line {
-    .status-el::before {
+    .timeline-item::before {
         background: $accent_dark;
         content: '';
         position: relative;
@@ -53,7 +53,7 @@
     }
 }
 
-.thread-last .status-el::before {
+.timeline-item.thread-last::before {
     background: unset;
     min-width: unset;
     width: 0;

+ 12 - 8
src/views/profile.nim

@@ -75,6 +75,12 @@ proc renderBanner(profile: Profile): VNode =
       a(href=getPicUrl(profile.banner), target="_blank"):
         genImg(profile.banner)
 
+proc renderProtected(username: string): VNode =
+  buildHtml(tdiv(class="timeline-container timeline")):
+    tdiv(class="timeline-header timeline-protected"):
+      h2: text "This account's tweets are protected."
+      p: text &"Only confirmed followers have access to @{username}'s tweets."
+
 proc renderProfile*(profile: Profile; timeline: Timeline;
                     photoRail: seq[GalleryPhoto]; prefs: Prefs; path: string): VNode =
   buildHtml(tdiv(class="profile-tabs")):
@@ -88,11 +94,9 @@ proc renderProfile*(profile: Profile; timeline: Timeline;
       if photoRail.len > 0:
         renderPhotoRail(profile, photoRail)
 
-    tdiv(class="timeline-tab"):
-      renderTimeline(timeline, profile.username, profile.protected, prefs, path)
-
-proc renderMulti*(timeline: Timeline; usernames: string;
-                  prefs: Prefs; path: string): VNode =
-  buildHtml(tdiv(class="multi-timeline")):
-    tdiv(class="timeline-tab"):
-      renderTimeline(timeline, usernames, false, prefs, path, multi=true)
+    tdiv(class="timeline-container"):
+      if profile.protected:
+        renderProtected(profile.username)
+      else:
+        renderProfileTabs(timeline, profile.username)
+        renderTimelineTweets(timeline, prefs, path)

+ 1 - 1
src/views/status.nim

@@ -6,7 +6,7 @@ import tweet
 proc renderMoreReplies(thread: Thread): VNode =
   let num = if thread.more != -1: $thread.more & " " else: ""
   let reply = if thread.more == 1: "reply" else: "replies"
-  buildHtml(tdiv(class="status-el more-replies")):
+  buildHtml(tdiv(class="timeline-item more-replies")):
     a(class="more-replies-text", title="Not implemented yet"):
       text $num & "more " & reply
 

+ 41 - 53
src/views/timeline.nim

@@ -1,25 +1,29 @@
 import strutils, strformat, sequtils, algorithm, times
 import karax/[karaxdsl, vdom, vstyles]
 
-import ../types, ../search
+import ".."/[types, query, formatters]
 import tweet, renderutils
 
-proc getQuery(timeline: Timeline): string =
-  if timeline.query.isNone: "?"
-  else: genQueryUrl(get(timeline.query))
+proc getQuery(query: Option[Query]): string =
+  if query.isNone:
+    result = "?"
+  else:
+    result = genQueryUrl(get(query))
+    if result[^1] != '?':
+      result &= "&"
 
-proc getTabClass(timeline: Timeline; tab: string): string =
+proc getTabClass(results: Result; tab: string): string =
   var classes = @["tab-item"]
 
-  if timeline.query.isNone or get(timeline.query).kind == multi:
+  if results.query.isNone or get(results.query).kind == multi:
     if tab == "posts":
       classes.add "active"
-  elif $get(timeline.query).kind == tab:
+  elif $get(results.query).kind == tab:
     classes.add "active"
 
   return classes.join(" ")
 
-proc renderSearchTabs(timeline: Timeline; username: string): VNode =
+proc renderProfileTabs*(timeline: Timeline; username: string): VNode =
   let link = "/" & username
   buildHtml(ul(class="tab")):
     li(class=timeline.getTabClass("posts")):
@@ -29,33 +33,28 @@ proc renderSearchTabs(timeline: Timeline; username: string): VNode =
     li(class=timeline.getTabClass("media")):
       a(href=(link & "/media")): text "Media"
 
-proc renderNewer(timeline: Timeline; username: string): VNode =
-  buildHtml(tdiv(class="status-el show-more")):
-    a(href=("/" & username & getQuery(timeline).strip(chars={'?'}))):
-      text "Load newest tweets"
+proc renderNewer(query: Option[Query]): VNode =
+  buildHtml(tdiv(class="timeline-item show-more")):
+    a(href=(getQuery(query).strip(chars={'?', '&'}))):
+      text "Load newest"
 
-proc renderOlder(timeline: Timeline; username: string): VNode =
+proc renderOlder(query: Option[Query]; minId: string): VNode =
   buildHtml(tdiv(class="show-more")):
-    a(href=(&"/{username}{getQuery(timeline)}after={timeline.minId}")):
-      text "Load older tweets"
+    a(href=(&"{getQuery(query)}after={minId}")):
+      text "Load older"
 
 proc renderNoMore(): VNode =
   buildHtml(tdiv(class="timeline-footer")):
     h2(class="timeline-end"):
-      text "No more tweets."
+      text "No more items"
 
 proc renderNoneFound(): VNode =
   buildHtml(tdiv(class="timeline-header")):
     h2(class="timeline-none"):
-      text "No tweets found."
-
-proc renderProtected(username: string): VNode =
-  buildHtml(tdiv(class="timeline-header timeline-protected")):
-    h2: text "This account's tweets are protected."
-    p: text &"Only confirmed followers have access to @{username}'s tweets."
+      text "No items found"
 
 proc renderThread(thread: seq[Tweet]; prefs: Prefs; path: string): VNode =
-  buildHtml(tdiv(class="timeline-tweet thread-line")):
+  buildHtml(tdiv(class="thread-line")):
     for i, threadTweet in thread.sortedByIt(it.time):
       renderTweet(threadTweet, prefs, path, class="thread",
                   index=i, total=thread.high)
@@ -63,37 +62,26 @@ proc renderThread(thread: seq[Tweet]; prefs: Prefs; path: string): VNode =
 proc threadFilter(it: Tweet; tweetThread: string): bool =
   it.retweet.isNone and it.reply.len == 0 and it.threadId == tweetThread
 
-proc renderTweets(timeline: Timeline; prefs: Prefs; path: string): VNode =
-  buildHtml(tdiv(id="posts")):
-    var threads: seq[string]
-    for tweet in timeline.content:
-      if tweet.threadId in threads: continue
-      let thread = timeline.content.filterIt(threadFilter(it, tweet.threadId))
-      if thread.len < 2:
-        renderTweet(tweet, prefs, path, class="timeline-tweet")
-      else:
-        renderThread(thread, prefs, path)
-        threads &= tweet.threadId
-
-proc renderTimeline*(timeline: Timeline; username: string; protected: bool;
-                     prefs: Prefs; path: string; multi=false): VNode =
-  buildHtml(tdiv):
-    if multi:
-      tdiv(class="multi-header"):
-        text username.replace(",", " | ")
-
-    if not protected:
-      renderSearchTabs(timeline, username)
-      if not timeline.beginning:
-        renderNewer(timeline, username)
-
-    if protected:
-      renderProtected(username)
-    elif timeline.content.len == 0:
+
+proc renderTimelineTweets*(results: Result[Tweet]; prefs: Prefs; path: string): VNode =
+  buildHtml(tdiv(class="timeline")):
+    if not results.beginning:
+      renderNewer(results.query)
+
+    if results.content.len == 0:
       renderNoneFound()
     else:
-      renderTweets(timeline, prefs, path)
-      if timeline.hasMore or timeline.query.isSome:
-        renderOlder(timeline, username)
+      var threads: seq[string]
+      for tweet in results.content:
+        if tweet.threadId in threads: continue
+        let thread = results.content.filterIt(threadFilter(it, tweet.threadId))
+        if thread.len < 2:
+          renderTweet(tweet, prefs, path)
+        else:
+          renderThread(thread, prefs, path)
+          threads &= tweet.threadId
+
+      if results.hasMore or results.query.isSome:
+        renderOlder(results.query, results.minId)
       else:
         renderNoMore()

+ 33 - 34
src/views/tweet.nim

@@ -224,43 +224,42 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
 
   if not tweet.available:
     return buildHtml(tdiv(class=divClass)):
-      tdiv(class="status-el unavailable"):
+      tdiv(class="timeline-item unavailable"):
         tdiv(class="unavailable-box"):
           if tweet.tombstone.len > 0:
             text tweet.tombstone
           else:
             text "This tweet is unavailable"
 
-  buildHtml(tdiv(class=divClass)):
-    tdiv(class="status-el"):
-      tdiv(class="status-body"):
-        var views = ""
-        renderHeader(tweet)
-
-        if index == 0 and tweet.reply.len > 0:
-          renderReply(tweet)
-
-        tdiv(class="status-content media-body"):
-          verbatim linkifyText(tweet.text, prefs)
-
-        if tweet.quote.isSome:
-          renderQuote(tweet.quote.get(), prefs)
-
-        if tweet.card.isSome:
-          renderCard(tweet.card.get(), prefs, path)
-        elif tweet.photos.len > 0:
-          renderAlbum(tweet)
-        elif tweet.video.isSome:
-          renderVideo(tweet.video.get(), prefs, path)
-          views = tweet.video.get().views
-        elif tweet.gif.isSome:
-          renderGif(tweet.gif.get(), prefs)
-        elif tweet.poll.isSome:
-          renderPoll(tweet.poll.get())
-
-        if not prefs.hideTweetStats:
-          renderStats(tweet.stats, views)
-
-        if tweet.hasThread and "timeline" in class:
-          a(class="show-thread", href=getLink(tweet)):
-            text "Show this thread"
+  buildHtml(tdiv(class=("timeline-item " & divClass))):
+    tdiv(class="tweet-body"):
+      var views = ""
+      renderHeader(tweet)
+
+      if index == 0 and tweet.reply.len > 0:
+        renderReply(tweet)
+
+      tdiv(class="tweet-content media-body"):
+        verbatim linkifyText(tweet.text, prefs)
+
+      if tweet.quote.isSome:
+        renderQuote(tweet.quote.get(), prefs)
+
+      if tweet.card.isSome:
+        renderCard(tweet.card.get(), prefs, path)
+      elif tweet.photos.len > 0:
+        renderAlbum(tweet)
+      elif tweet.video.isSome:
+        renderVideo(tweet.video.get(), prefs, path)
+        views = tweet.video.get().views
+      elif tweet.gif.isSome:
+        renderGif(tweet.gif.get(), prefs)
+      elif tweet.poll.isSome:
+        renderPoll(tweet.poll.get())
+
+      if not prefs.hideTweetStats:
+        renderStats(tweet.stats, views)
+
+      if tweet.hasThread and "timeline" in class:
+        a(class="show-thread", href=getLink(tweet)):
+          text "Show this thread"