html and css updates

This commit is contained in:
Zed 2020-06-01 02:22:22 +02:00
parent 762d00b21d
commit 2950c0de35
14 changed files with 246 additions and 224 deletions

View File

@ -42,7 +42,8 @@
img {
display: block;
width: calc(100% - 8px);
box-sizing: border-box;
width: 100%;
height: 100%;
margin: 0;
border: 4px solid var(--darker_grey);

View File

@ -14,9 +14,10 @@
}
&-header-mobile {
padding: 5px 12px 0;
display: none;
width: calc(100% - 24px);
box-sizing: border-box;
padding: 5px 12px 0;
width: 100%;
float: unset;
color: var(--accent);
justify-content: space-between;

View File

@ -13,18 +13,28 @@
}
.timeline-header {
width: 100%;
background-color: var(--bg_panel);
text-align: center;
padding: 8px;
display: block;
font-weight: bold;
margin-bottom: 5px;
box-sizing: border-box;
button {
float: unset;
}
}
.timeline-banner img {
width: 100%;
}
.timeline-description {
font-weight: normal;
}
.tab {
align-items: center;
display: flex;

View File

@ -76,7 +76,7 @@
left: 0;
bottom: 0;
right: 0;
background-color: var(--fg_color);
background-color: var(--bg_overlays);
img {
width: 100%;

View File

@ -13,7 +13,7 @@
.still-image {
width: 100%;
display: block;
display: flex;
}
}
@ -67,17 +67,17 @@
display: inline-block;
}
.single-image {
display: inline-block;
width: 100%;
max-height: 600px;
// .single-image {
// display: inline-block;
// width: 100%;
// max-height: 600px;
.attachments {
width: unset;
max-height: unset;
display: inherit;
}
}
// .attachments {
// width: unset;
// max-height: unset;
// display: inherit;
// }
// }
.overlay-circle {
border-radius: 50%;

View File

@ -5,10 +5,10 @@
border: solid 1px var(--dark_grey);
border-radius: 10px;
background-color: var(--bg_elements);
overflow: auto;
padding: 6px;
position: relative;
overflow: hidden;
pointer-events: all;
position: relative;
width: 100%;
&:hover {
border-color: var(--grey);
@ -17,91 +17,73 @@
&.unavailable:hover {
border-color: var(--dark_grey);
}
.tweet-name-row {
padding: 6px 6px 0px 6px;
}
.quote-text {
overflow: hidden;
white-space: pre-wrap;
word-wrap: break-word;
padding: 3px 6px 6px 6px;
}
.show-thread {
padding: 0px 6px 3px 6px;
margin-top: -3px;
}
.replying-to {
padding: 0px 6px;
margin: unset;
}
}
.unavailable-quote {
padding: 6px;
padding: 12px;
}
.quote-link {
height: 100%;
width: 100%;
height: 100%;
left: 0;
top: 0;
position: absolute;
}
.quote .quote-link {
z-index: 1;
}
.quote-text {
overflow: hidden;
white-space: pre-wrap;
word-wrap: break-word;
}
.quote-media-container {
max-height: 300px;
display: flex;
flex-direction: column;
align-items: center;
overflow: hidden;
max-height: 102px;
width: 102px;
float: left;
margin-right: 7px;
border-radius: 7px;
position: relative;
}
.quote-media {
display: flex;
justify-content: center;
pointer-events: none;
.card {
margin: unset;
}
img {
.media-gif {
width: 100%;
height: 100%;
align-self: center;
}
}
.quote-badge {
left: 0;
bottom: 0;
position: absolute;
z-index: 1;
align-self: flex-end;
}
.quote-badge-text {
margin: 4px;
background: $shadow;
border-radius: 4px;
color: #fffffff0;
padding: 1px 3px;
font-size: 12px;
font-weight: bold;
}
.quote-sensitive {
background: var(--darker_grey);
width: 102px;
height: 102px;
border-radius: 12px;
display: flex;
justify-content: center;
align-items: center;
}
.quote-sensitive-icon {
font-size: 40px;
color: var(--grey);
}
@media(max-width: 600px) {
.quote-media-container {
width: 70px;
max-height: 70px;
}
.attachments {
border-radius: 0;
}
.gallery-gif .attachment {
display: flex;
justify-content: center;
background-color: var(--bg_color);
video {
height: unset;
width: unset;
}
}
.gallery-video, .gallery-gif {
max-height: 300px;
}
.still-image img {
max-height: 250px
}
}

View File

@ -2,7 +2,7 @@ import strformat
import karax/[karaxdsl, vdom]
import renderutils
import ".."/[types]
import ".."/[types, utils]
proc renderListTabs*(query: Query; path: string): VNode =
buildHtml(ul(class="tab")):
@ -11,10 +11,18 @@ proc renderListTabs*(query: Query; path: string): VNode =
li(class=query.getTabClass(userList)):
a(href=(path & "/members")): text "Members"
proc renderList*(body: VNode; query: Query; name, list: string): VNode =
proc renderList*(body: VNode; query: Query; list: List): VNode =
buildHtml(tdiv(class="timeline-container")):
tdiv(class="timeline-header"):
text &"\"{list}\" by @{name}"
if list.banner.len > 0:
tdiv(class="timeline-banner"):
a(href=getPicUrl(list.banner), target="_blank"):
genImg(list.banner)
renderListTabs(query, &"/{name}/lists/{list}")
tdiv(class="timeline-header"):
text &"\"{list.name}\" by @{list.username}"
tdiv(class="timeline-description"):
text list.description
renderListTabs(query, &"/{list.username}/lists/{list.name}")
body

View File

@ -58,14 +58,15 @@ proc renderProfileCard*(profile: Profile; prefs: Prefs): VNode =
renderStat(profile.likes, "likes")
proc renderPhotoRail(profile: Profile; photoRail: PhotoRail): VNode =
let count = insertSep($profile.media, ',')
buildHtml(tdiv(class="photo-rail-card")):
tdiv(class="photo-rail-header"):
a(href=(&"/{profile.username}/media")):
icon "picture", $profile.media & " Photos and videos"
icon "picture", count & " Photos and videos"
input(id="photo-rail-grid-toggle", `type`="checkbox")
label(`for`="photo-rail-grid-toggle", class="photo-rail-header-mobile"):
icon "picture", $profile.media & " Photos and videos"
icon "picture", count & " Photos and videos"
icon "down"
tdiv(class="photo-rail-grid"):
@ -73,7 +74,7 @@ proc renderPhotoRail(profile: Profile; photoRail: PhotoRail): VNode =
if i == 16: break
a(href=(&"/{profile.username}/status/{photo.tweetId}#m"),
style={backgroundColor: photo.color}):
genImg(photo.url & ":thumb")
genImg(photo.url & (if "format" in photo.url: "" else: ":thumb"))
proc renderBanner(profile: Profile): VNode =
buildHtml():
@ -89,7 +90,7 @@ proc renderProtected(username: string): VNode =
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;
proc renderProfile*(profile: Profile; timeline: var Timeline;
photoRail: PhotoRail; prefs: Prefs; path: string): VNode =
timeline.query.fromUser = @[profile.username]
buildHtml(tdiv(class="profile-tabs")):

View File

@ -1,7 +1,6 @@
import strutils, xmltree
import strutils
import karax/[karaxdsl, vdom, vstyles]
import ../types, ../utils
import ".."/[types, utils]
proc icon*(icon: string; text=""; title=""; class=""; href=""): VNode =
var c = "icon-" & icon

View File

@ -82,24 +82,24 @@
<width>128</width>
<height>128</height>
</image>
#if timeline != nil:
# if timeline.content.len > 0:
${renderRssTweets(timeline.content, prefs, hostname)}
#end if
</channel>
</rss>
#end proc
#
#proc renderListRss*(tweets: seq[Tweet]; name, list, hostname: string): string =
#proc renderListRss*(tweets: seq[Tweet]; list: List; hostname: string): string =
#let prefs = Prefs(replaceTwitter: hostname, replaceYouTube: "invidio.us")
#let link = &"https://{hostname}/{name}/lists/{list}"
#let link = &"https://{hostname}/{list.username}/lists/{list.name}"
#result = ""
<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
<channel>
<atom:link href="${link}" rel="self" type="application/rss+xml" />
<title>${list} / @${name}</title>
<title>${list.name} / @${list.username}</title>
<link>${link}</link>
<description>Twitter feed for: ${list} by @${name}. Generated by ${hostname}</description>
<description>Twitter feed for: ${list.name} by @${list.username}. Generated by ${hostname}</description>
<language>en-us</language>
<ttl>40</ttl>
${renderRssTweets(tweets, prefs, hostname)}

View File

@ -1,8 +1,8 @@
import strutils, strformat, sequtils, unicode, tables
import karax/[karaxdsl, vdom, vstyles]
import karax/[karaxdsl, vdom]
import renderutils, timeline
import ".."/[types, formatters, query]
import ".."/[types, query]
let toggles = {
"nativeretweets": "Retweets",
@ -93,13 +93,15 @@ proc renderTweetSearch*(results: Result[Tweet]; prefs: Prefs; path: string): VNo
if query.fromUser.len > 1:
tdiv(class="timeline-header"):
text query.fromUser.join(" | ")
if query.fromUser.len > 0:
renderProfileTabs(query, query.fromUser.join(","))
if query.fromUser.len == 0 or query.kind == tweets:
tdiv(class="timeline-header"):
renderSearchPanel(query)
if query.fromUser.len > 0:
renderProfileTabs(query, query.fromUser.join(","))
else:
if query.fromUser.len == 0:
renderSearchTabs(query)
renderTimelineTweets(results, prefs, path)

View File

@ -1,3 +1,4 @@
import uri
import karax/[karaxdsl, vdom]
import ".."/[types, formatters]
@ -13,7 +14,7 @@ proc renderMoreReplies(thread: Chain): VNode =
let reply = if thread.more == 1: "reply" else: "replies"
let link = getLink(thread.content[^1])
buildHtml(tdiv(class="timeline-item more-replies")):
if link.len > 0:
if thread.content[^1].available:
a(class="more-replies-text", href=link):
text $num & "more " & reply
else:
@ -32,41 +33,45 @@ proc renderReplyThread(thread: Chain; prefs: Prefs; path: string): VNode =
proc renderReplies*(replies: Result[Chain]; prefs: Prefs; path: string): VNode =
buildHtml(tdiv(class="replies", id="r")):
for thread in replies.content:
if thread == nil: continue
if thread.content.len == 0: continue
renderReplyThread(thread, prefs, path)
if replies.hasMore:
renderMore(Query(), replies.minId, focus="#r")
if replies.bottom.len > 0:
renderMore(Query(), encodeUrl(replies.bottom), focus="#r")
proc renderConversation*(conversation: Conversation; prefs: Prefs; path: string): VNode =
let hasAfter = conversation.after != nil
let showReplies = not prefs.hideReplies
proc renderConversation*(conv: Conversation; prefs: Prefs; path: string): VNode =
let hasAfter = conv.after.content.len > 0
let threadId = conv.tweet.threadId
buildHtml(tdiv(class="conversation")):
tdiv(class="main-thread"):
if conversation.before != nil:
if conv.before.content.len > 0:
tdiv(class="before-tweet thread-line"):
if conversation.before.more == -1:
renderEarlier(conversation.before)
for i, tweet in conversation.before.content:
let first = conv.before.content[0]
if threadId != first.id and (first.replyId > 0 or not first.available):
renderEarlier(conv.before)
for i, tweet in conv.before.content:
renderTweet(tweet, prefs, path, index=i)
tdiv(class="main-tweet", id="m"):
let afterClass = if hasAfter: "thread thread-line" else: ""
renderTweet(conversation.tweet, prefs, path, class=afterClass,
mainTweet=true)
renderTweet(conv.tweet, prefs, path, class=afterClass, mainTweet=true)
if hasAfter:
tdiv(class="after-tweet thread-line"):
let total = conversation.after.content.high
let more = conversation.after.more
for i, tweet in conversation.after.content:
renderTweet(tweet, prefs, path, index=i, last=(i == total and more == 0))
let
total = conv.after.content.high
more = conv.after.more
for i, tweet in conv.after.content:
renderTweet(tweet, prefs, path, index=i,
last=(i == total and more == 0), afterTweet=true)
if more != 0:
renderMoreReplies(conversation.after)
renderMoreReplies(conv.after)
if conversation.replies != nil and showReplies:
if not conversation.replies.beginning:
renderNewer(Query(), getLink(conversation.tweet))
if conversation.replies.content.len > 0:
renderReplies(conversation.replies, prefs, path)
if not prefs.hideReplies:
if not conv.replies.beginning:
renderNewer(Query(), getLink(conv.tweet), focus="#r")
if conv.replies.content.len > 0 or conv.replies.bottom.len > 0:
renderReplies(conv.replies, prefs, path)
renderToTop(focus="#m")

View File

@ -10,16 +10,22 @@ proc getQuery(query: Query): string =
if result.len > 0:
result &= "&"
proc renderNewer*(query: Query; path: string): VNode =
let q = genQueryUrl(query)
let url = if q.len > 0: "?" & q else: ""
proc renderToTop*(focus="#"): VNode =
buildHtml(tdiv(class="top-ref")):
icon "down", href=focus
proc renderNewer*(query: Query; path: string; focus=""): VNode =
let
q = genQueryUrl(query)
url = if q.len > 0: "?" & q else: ""
p = if focus.len > 0: path.replace("#m", focus) else: path
buildHtml(tdiv(class="timeline-item show-more")):
a(href=(path & url)):
a(href=(p & url)):
text "Load newest"
proc renderMore*(query: Query; minId: string; focus=""): VNode =
proc renderMore*(query: Query; cursor: string; focus=""): VNode =
buildHtml(tdiv(class="show-more")):
a(href=(&"?{getQuery(query)}max_position={minId}{focus}")):
a(href=(&"?{getQuery(query)}cursor={encodeUrl(cursor)}{focus}")):
text "Load more"
proc renderNoMore(): VNode =
@ -32,10 +38,6 @@ proc renderNoneFound(): VNode =
h2(class="timeline-none"):
text "No items found"
proc renderToTop(): VNode =
buildHtml(tdiv(class="top-ref")):
icon "down", href="#"
proc renderThread(thread: seq[Tweet]; prefs: Prefs; path: string): VNode =
buildHtml(tdiv(class="thread-line")):
let sortedThread = thread.sortedByIt(it.id)
@ -43,10 +45,16 @@ proc renderThread(thread: seq[Tweet]; prefs: Prefs; path: string): VNode =
let show = i == thread.high and sortedThread[0].id != tweet.threadId
let header = if tweet.pinned or tweet.retweet.isSome: "with-header " else: ""
renderTweet(tweet, prefs, path, class=(header & "thread"),
index=i, total=thread.high, showThread=show)
index=i, last=(i == thread.high), showThread=show)
proc threadFilter(it: Tweet; thread: int64): bool =
it.retweet.isNone and it.reply.len == 0 and it.threadId == thread
proc threadFilter(tweets: openArray[Tweet]; threads: openArray[int64]; it: Tweet): seq[Tweet] =
result = @[it]
if it.retweet.isSome or it.replyId in threads: return
for t in tweets:
if t.id == result[0].replyId:
result.insert t
elif t.replyId == result[0].id:
result.add t
proc renderUser(user: Profile; prefs: Prefs): VNode =
buildHtml(tdiv(class="timeline-item")):
@ -72,8 +80,8 @@ proc renderTimelineUsers*(results: Result[Profile]; prefs: Prefs; path=""): VNod
if results.content.len > 0:
for user in results.content:
renderUser(user, prefs)
if results.minId != "0":
renderMore(results.query, results.minId)
if results.bottom.len > 0:
renderMore(results.query, results.bottom)
renderToTop()
elif results.beginning:
renderNoneFound()
@ -86,24 +94,31 @@ proc renderTimelineTweets*(results: Result[Tweet]; prefs: Prefs; path: string):
renderNewer(results.query, parseUri(path).path)
if results.content.len == 0:
renderNoneFound()
if not results.beginning:
renderNoMore()
else:
renderNoneFound()
else:
var threads: seq[int64]
var retweets: seq[int64]
var
threads: seq[int64]
retweets: seq[int64]
for tweet in results.content:
if tweet.threadId in threads or tweet.id in retweets: continue
if tweet.pinned and prefs.hidePins: continue
let thread = results.content.filterIt(threadFilter(it, tweet.threadId))
let rt = if tweet.retweet.isSome: get(tweet.retweet).id else: 0
if tweet.id in threads or rt in retweets or
tweet.pinned and prefs.hidePins: continue
let thread = results.content.threadFilter(threads, tweet)
if thread.len < 2:
if tweet.retweet.isSome:
retweets &= tweet.id
renderTweet(tweet, prefs, path, showThread=tweet.hasThread)
var hasThread = tweet.hasThread
if rt != 0:
retweets &= rt
hasThread = get(tweet.retweet).hasThread
renderTweet(tweet, prefs, path, showThread=hasThread)
else:
renderThread(thread, prefs, path)
threads &= tweet.threadId
threads &= thread.mapIt(it.id)
if results.hasMore or results.query.kind != posts:
renderMore(results.query, results.minId)
else:
renderNoMore()
renderMore(results.query, results.bottom)
renderToTop()

View File

@ -4,11 +4,11 @@ import karax/[karaxdsl, vdom, vstyles]
import renderutils
import ".."/[types, utils, formatters]
proc renderHeader(tweet: Tweet): VNode =
proc renderHeader(tweet: Tweet; retweet=""): VNode =
buildHtml(tdiv):
if tweet.retweet.isSome:
if retweet.len > 0:
tdiv(class="retweet-header"):
span: icon "retweet", get(tweet.retweet).by & " retweeted"
span: icon "retweet", retweet & " retweeted"
if tweet.pinned:
tdiv(class="pinned"):
@ -24,31 +24,24 @@ proc renderHeader(tweet: Tweet): VNode =
linkUser(tweet.profile, class="username")
span(class="tweet-date"):
a(href=getLink(tweet), title=tweet.getTime()):
text tweet.shortTime
a(href=getLink(tweet), title=tweet.getTime):
text tweet.getShortTime
proc renderAlbum(tweet: Tweet): VNode =
let
groups = if tweet.photos.len < 3: @[tweet.photos]
else: tweet.photos.distribute(2)
if groups.len == 1 and groups[0].len == 1:
buildHtml(tdiv(class="single-image")):
tdiv(class="attachments gallery-row"):
a(href=getPicUrl(groups[0][0] & "?name=orig"), class="still-image",
target="_blank"):
genImg(groups[0][0])
else:
buildHtml(tdiv(class="attachments")):
for i, photos in groups:
let margin = if i > 0: ".25em" else: ""
let flex = if photos.len > 1 or groups.len > 1: "flex" else: "block"
tdiv(class="gallery-row", style={marginTop: margin}):
for photo in photos:
tdiv(class="attachment image"):
a(href=getPicUrl(photo & "?name=orig"), class="still-image",
target="_blank", style={display: flex}):
genImg(photo)
buildHtml(tdiv(class="attachments")):
for i, photos in groups:
let margin = if i > 0: ".25em" else: ""
tdiv(class="gallery-row", style={marginTop: margin}):
for photo in photos:
tdiv(class="attachment image"):
var url = photo
if "=orig" notin url: url &= "?name=orig"
a(href=getPicUrl(url), class="still-image", target="_blank"):
genImg(photo)
proc isPlaybackEnabled(prefs: Prefs; video: Video): bool =
case video.playbackType
@ -88,7 +81,8 @@ proc renderVideo*(video: Video; prefs: Prefs; path: string): VNode =
elif not prefs.isPlaybackEnabled(video):
renderVideoDisabled(video, path)
else:
let source = getVidUrl(video.url)
let vid = video.variants.filterIt(it.videoType == video.playbackType)
let source = getVidUrl(vid[0].url)
case video.playbackType
of mp4:
if prefs.muteVideos:
@ -138,7 +132,7 @@ proc renderPoll(poll: Poll): VNode =
proc renderCardImage(card: Card): VNode =
buildHtml(tdiv(class="card-image-container")):
tdiv(class="card-image"):
img(src=getPicUrl(get(card.image)))
img(src=getPicUrl(card.image), alt="")
if card.kind == player:
tdiv(class="card-overlay"):
tdiv(class="overlay-circle"):
@ -151,9 +145,8 @@ proc renderCardContent(card: Card): VNode =
span(class="card-destination"): text card.dest
proc renderCard(card: Card; prefs: Prefs; path: string): VNode =
const largeCards = {summaryLarge, liveEvent, promoWebsite,
promoVideo, promoVideoConvo}
let large = if card.kind in largeCards: " large" else: ""
const smallCards = {player, summary}
let large = if card.kind notin smallCards: " large" else: ""
let url = replaceUrl(card.url, prefs)
buildHtml(tdiv(class=("card" & large))):
@ -164,7 +157,7 @@ proc renderCard(card: Card; prefs: Prefs; path: string): VNode =
renderCardContent(card)
else:
a(class="card-container", href=url):
if card.image.isSome:
if card.image.len > 0:
renderCardImage(card)
tdiv(class="card-content-container"):
renderCardContent(card)
@ -184,13 +177,6 @@ proc renderReply(tweet: Tweet): VNode =
if i > 0: text " "
a(href=("/" & u)): text "@" & u
proc renderReply(quote: Quote): VNode =
buildHtml(tdiv(class="replying-to")):
text "Replying to "
for i, u in quote.reply:
if i > 0: text " "
a(href=("/" & u)): text "@" & u
proc renderAttribution(profile: Profile): VNode =
let avatarUrl = getPicUrl(profile.getUserpic("_200x200"))
buildHtml(a(class="attribution", href=("/" & profile.username))):
@ -206,19 +192,17 @@ proc renderMediaTags(tags: seq[Profile]): VNode =
if i < tags.high:
text ", "
proc renderQuoteMedia(quote: Quote): VNode =
proc renderQuoteMedia(quote: Tweet; prefs: Prefs; path: string): VNode =
buildHtml(tdiv(class="quote-media-container")):
if quote.thumb.len > 0:
tdiv(class="quote-media"):
genImg(quote.thumb)
if quote.badge.len > 0:
tdiv(class="quote-badge"):
tdiv(class="quote-badge-text"): text quote.badge
elif quote.sensitive:
tdiv(class="quote-sensitive"):
icon "attention", class="quote-sensitive-icon"
if quote.photos.len > 0:
renderAlbum(quote)
# genImg(quote.photos[0])
elif quote.video.isSome:
renderVideo(quote.video.get(), prefs, path)
elif quote.gif.isSome:
renderGif(quote.gif.get(), prefs)
proc renderQuote(quote: Quote; prefs: Prefs): VNode =
proc renderQuote(quote: Tweet; prefs: Prefs; path: string): VNode =
if not quote.available:
return buildHtml(tdiv(class="quote unavailable")):
tdiv(class="unavailable-quote"):
@ -227,26 +211,32 @@ proc renderQuote(quote: Quote; prefs: Prefs): VNode =
else:
text "This tweet is unavailable"
buildHtml(tdiv(class="quote")):
buildHtml(tdiv(class="quote quote-big")):
a(class="quote-link", href=getLink(quote))
if quote.thumb.len > 0 or quote.sensitive:
renderQuoteMedia(quote)
tdiv(class="tweet-name-row"):
tdiv(class="fullname-and-username"):
linkUser(quote.profile, class="fullname")
linkUser(quote.profile, class="username")
tdiv(class="fullname-and-username"):
linkUser(quote.profile, class="fullname")
linkUser(quote.profile, class="username")
span(class="tweet-date"):
a(href=getLink(quote), title=quote.getTime):
text quote.getShortTime
if quote.reply.len > 0:
renderReply(quote)
tdiv(class="quote-text"):
verbatim replaceUrl(quote.text, prefs)
if quote.text.len > 0:
tdiv(class="quote-text"):
verbatim replaceUrl(quote.text, prefs)
if quote.hasThread:
a(class="show-thread", href=getLink(quote)):
text "Show this thread"
if quote.photos.len > 0 or quote.video.isSome or quote.gif.isSome:
renderQuoteMedia(quote, prefs, path)
proc renderLocation*(tweet: Tweet): string =
let (place, url) = tweet.getLocation()
if place.len == 0: return
@ -258,11 +248,10 @@ proc renderLocation*(tweet: Tweet): string =
text place
return $node
proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
index=0; total=(-1); last=false; showThread=false;
mainTweet=false): VNode =
proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class=""; index=0;
last=false; showThread=false; mainTweet=false; afterTweet=false): VNode =
var divClass = class
if index == total or last:
if index == -1 or last:
divClass = "thread-last " & class
if not tweet.available:
@ -273,15 +262,22 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
else:
text "This tweet is unavailable"
let fullTweet = tweet
var retweet: string
var tweet = fullTweet
if tweet.retweet.isSome:
tweet = tweet.retweet.get
retweet = fullTweet.profile.fullname
buildHtml(tdiv(class=("timeline-item " & divClass))):
if not mainTweet:
a(class="tweet-link", href=getLink(tweet))
tdiv(class="tweet-body"):
var views = ""
renderHeader(tweet)
renderHeader(tweet, retweet)
if index == 0 and tweet.reply.len > 0 and
if not afterTweet and index == 0 and tweet.reply.len > 0 and
(tweet.reply.len > 1 or tweet.reply[0] != tweet.profile.username):
renderReply(tweet)
@ -293,7 +289,8 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
if tweet.card.isSome:
renderCard(tweet.card.get(), prefs, path)
elif tweet.photos.len > 0:
if tweet.photos.len > 0:
renderAlbum(tweet)
elif tweet.video.isSome:
renderVideo(tweet.video.get(), prefs, path)
@ -301,11 +298,12 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class="";
elif tweet.gif.isSome:
renderGif(tweet.gif.get(), prefs)
views = "GIF"
elif tweet.poll.isSome:
if tweet.poll.isSome:
renderPoll(tweet.poll.get())
if tweet.quote.isSome:
renderQuote(tweet.quote.get(), prefs)
renderQuote(tweet.quote.get(), prefs, path)
if mainTweet:
p(class="tweet-published"): text getTweetTime(tweet)