| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- #? stdtmpl(subsChar = '$', metaChar = '#')
- #import xmltree, strutils, strformat, sequtils, times, uri
- #import ../types, ../formatters, ../utils
- #
- #proc renderHeading(tweet: Tweet): string =
- #if tweet.retweet.isSome:
- <div class="retweet">
- <span>🔄 ${get(tweet.retweet).by} retweeted</span>
- </div>
- #end if
- #if tweet.pinned:
- <div class="pinned">
- <span>📌 Pinned Tweet</span>
- </div>
- #end if
- <div class="media-heading">
- <div class="heading-name-row">
- <a class="tweet-avatar" href="/${tweet.profile.username}">
- ${genImg(tweet.profile.getUserpic("_bigger"), "avatar")}
- </a>
- <div class="fullname-and-username">
- ${linkUser(tweet.profile, class="fullname")}
- ${linkUser(tweet.profile, class="username")}
- </div>
- <span class="heading-right">
- <a href="${getLink(tweet)}" title="${tweet.getTime()}">${tweet.shortTime}</a>
- </span>
- </div>
- </div>
- #end proc
- #
- #proc renderMediaGroup(tweet: Tweet): string =
- #let groups = if tweet.photos.len > 2: tweet.photos.distribute(2) else: @[tweet.photos]
- #let class = if groups.len == 1 and groups[0].len == 1: "single-image" else: ""
- #var first = true
- <div class="attachments ${class}">
- #for photos in groups:
- #let margin = if not first: "margin-top: .25em;" else: ""
- #let flex = if photos.len > 1 or groups.len > 1: "display: flex;" else: ""
- <div class="gallery-row cover-fit" style="${margin}">
- #for photo in photos:
- <div class="attachment image">
- ##TODO: why doesn't this work?
- <a href=${getSigUrl(photo & "?name=orig", "pic")} target="_blank" class="image-attachment">
- <div class="still-image" style="${flex}">
- ${genImg(photo)}
- </div>
- </a>
- </div>
- #end for
- </div>
- #first = false
- #end for
- </div>
- #end proc
- #
- #proc renderVideo(video: Video): string =
- <div class="attachments">
- <div class="gallery-video">
- <div class="attachment video-container">
- #case video.playbackType
- #of mp4:
- <video poster=${video.thumb.getSigUrl("pic")} controls>
- <source src=${video.url.getSigUrl("video")} type="video/mp4">
- </video>
- #of m3u8, vmap:
- <video poster=${video.thumb.getSigUrl("pic")} autoplay muted loop></video>
- <div class="video-overlay">
- <p>Video playback not supported</p>
- </div>
- #end case
- </div>
- </div>
- </div>
- #end proc
- #
- #proc renderGif(gif: Gif): string =
- <div class="attachments media-gif">
- <div class="gallery-gif" style="max-height: unset;">
- <div class="attachment">
- <video class="gif" poster=${gif.thumb.getSigUrl("pic")} autoplay muted loop>
- <source src=${gif.url.getSigUrl("video")} type="video/mp4">
- </video>
- </div>
- </div>
- </div>
- #end proc
- #
- #proc renderPoll(poll: Poll): string =
- <div class="poll">
- #for i in 0 ..< poll.options.len:
- #let leader = if poll.leader == i: " leader" else: ""
- <div class="poll-meter${leader}">
- <span class="poll-choice-bar" style="width: ${poll.values[i]}%"></span>
- <span class="poll-choice-value">${poll.values[i]}%</span>
- <span class="poll-choice-option">${poll.options[i]}</span>
- </div>
- #end for
- <span class="poll-info">${poll.votes} votes • ${poll.status}</span>
- </div>
- #end proc
- #
- #proc renderStats(stats: TweetStats): string =
- <div class="tweet-stats">
- <span class="tweet-stat">💬 ${$stats.replies}</span>
- <span class="tweet-stat">🔄 ${$stats.retweets}</span>
- <span class="tweet-stat">👍 ${$stats.likes}</span>
- </div>
- #end proc
- #
- #proc renderShowThread(tweet: Tweet | Quote): string =
- <a href="${getLink(tweet)}">Show this thread</a>
- #end proc
- #
- #proc renderReply(tweet: Tweet | Quote): string =
- #let usernames = tweet.reply.mapIt(&"""<a href="/{it}">@{it}</a>""")
- <div class="replying-to">Replying to ${usernames.join(" ")}</div>
- #end proc
- #
- #proc renderQuote(quote: Quote): string =
- #let hasMedia = quote.thumb.len > 0 or quote.sensitive
- <div class="quote">
- <div class="quote-container">
- <a class="quote-link" href="${getLink(quote)}"></a>
- #if hasMedia:
- <div class="quote-media-container">
- <div class="quote-media">
- #if quote.thumb.len > 0:
- ${genImg(quote.thumb)}
- #if quote.badge.len > 0:
- <div class="quote-badge">
- <div class="quote-badge-text">${quote.badge}</div>
- </div>
- #end if
- #elif quote.sensitive:
- <div class="quote-sensitive">
- <span class="icon quote-sensitive-icon">❗</span>
- </div>
- #end if
- </div>
- </div>
- #end if
- <div class="fullname-and-username">
- ${linkUser(quote.profile, class="fullname")}
- ${linkUser(quote.profile, class="username")}
- </div>
- #if quote.reply.len > 0:
- ${renderReply(quote)}
- #end if
- <div class="quote-text">${linkifyText(quote.text)}</div>
- #if quote.hasThread:
- ${renderShowThread(quote)}
- #end if
- </div>
- </div>
- #end proc
- #
- #proc renderTweet*(tweet: Tweet; class=""; first=true; last=false): string =
- #var divClass = if last: "thread-last " & class else: class
- #if divClass.len > 0:
- <div class="${divClass}">
- #end if
- #if tweet.available:
- <div class="status-el">
- <div class="status-body">
- ${renderHeading(tweet)}
- #if first and tweet.reply.len > 0:
- ${renderReply(tweet)}
- #end if
- <div class="status-content-wrapper">
- <div class="status-content media-body">${linkifyText(tweet.text)}</div>
- </div>
- #if tweet.photos.len > 0:
- ${renderMediaGroup(tweet)}
- #elif tweet.video.isSome:
- ${renderVideo(tweet.video.get())}
- #elif tweet.gif.isSome:
- ${renderGif(tweet.gif.get())}
- #elif tweet.quote.isSome:
- ${renderQuote(tweet.quote.get())}
- #elif tweet.poll.isSome:
- ${renderPoll(tweet.poll.get())}
- #end if
- ${renderStats(tweet.stats)}
- #if tweet.hasThread and "timeline" in class:
- ${renderShowThread(tweet)}
- #end if
- </div>
- </div>
- #else:
- <div class="status-el unavailable">
- <div class="unavailable-box">This tweet is unavailable</div>
- </div>
- #end if
- #if divClass.len > 0:
- </div>
- #end if
- #end proc
|