2019-07-11 00:42:31 +02:00
|
|
|
import strutils, strformat
|
|
|
|
import karax/[karaxdsl, vdom, vstyles]
|
|
|
|
|
2019-09-19 01:01:47 +02:00
|
|
|
import renderutils, search
|
2019-09-06 02:42:35 +02:00
|
|
|
import ".."/[types, utils, formatters]
|
2019-07-11 00:42:31 +02:00
|
|
|
|
2019-08-06 15:57:47 +02:00
|
|
|
proc renderStat(num, class: string; text=""): VNode =
|
|
|
|
let t = if text.len > 0: text else: class
|
|
|
|
buildHtml(li(class=class)):
|
|
|
|
span(class="profile-stat-header"): text capitalizeAscii(t)
|
2019-08-11 23:30:33 +02:00
|
|
|
span(class="profile-stat-num"):
|
|
|
|
text if num.len == 0: "?" else: num
|
2019-07-11 00:42:31 +02:00
|
|
|
|
2019-08-15 15:51:20 +02:00
|
|
|
proc renderProfileCard*(profile: Profile; prefs: Prefs): VNode =
|
2019-07-11 00:42:31 +02:00
|
|
|
buildHtml(tdiv(class="profile-card")):
|
2019-09-08 00:55:12 +02:00
|
|
|
tdiv(class="profile-card-info"):
|
2019-09-13 12:27:04 +02:00
|
|
|
let url = getPicUrl(profile.getUserPic())
|
2019-09-08 01:43:54 +02:00
|
|
|
a(class="profile-card-avatar", href=url, target="_blank"):
|
2019-09-08 00:55:12 +02:00
|
|
|
genImg(profile.getUserpic("_200x200"))
|
2019-07-11 00:42:31 +02:00
|
|
|
|
2019-09-08 00:55:12 +02:00
|
|
|
tdiv(class="profile-card-tabs-name"):
|
|
|
|
linkUser(profile, class="profile-card-fullname")
|
|
|
|
linkUser(profile, class="profile-card-username")
|
2019-07-11 00:42:31 +02:00
|
|
|
|
|
|
|
tdiv(class="profile-card-extra"):
|
|
|
|
if profile.bio.len > 0:
|
|
|
|
tdiv(class="profile-bio"):
|
2019-10-18 00:54:22 +02:00
|
|
|
p(dir="auto"):
|
|
|
|
verbatim replaceUrl(profile.bio, prefs)
|
2019-07-11 00:42:31 +02:00
|
|
|
|
2019-08-11 21:26:55 +02:00
|
|
|
if profile.location.len > 0:
|
|
|
|
tdiv(class="profile-location"):
|
2019-10-08 23:25:59 +02:00
|
|
|
span: icon "location"
|
2019-12-21 05:44:58 +01:00
|
|
|
let (place, url) = profile.getLocation()
|
|
|
|
if url.len > 1:
|
|
|
|
a(href=url): text place
|
2019-10-08 23:25:59 +02:00
|
|
|
else:
|
2019-12-21 05:44:58 +01:00
|
|
|
span: text place
|
2019-08-11 21:26:55 +02:00
|
|
|
|
|
|
|
if profile.website.len > 0:
|
|
|
|
tdiv(class="profile-website"):
|
|
|
|
span:
|
2019-10-09 16:06:51 +02:00
|
|
|
let url = replaceUrl(profile.website, prefs)
|
2019-08-15 04:00:40 +02:00
|
|
|
icon "link"
|
2019-10-09 16:06:51 +02:00
|
|
|
a(href=url): text shortLink(url)
|
2019-08-11 21:26:55 +02:00
|
|
|
|
|
|
|
tdiv(class="profile-joindate"):
|
|
|
|
span(title=getJoinDateFull(profile)):
|
2019-08-15 04:00:40 +02:00
|
|
|
icon "calendar", getJoinDate(profile)
|
2019-08-11 21:26:55 +02:00
|
|
|
|
2019-07-11 00:42:31 +02:00
|
|
|
tdiv(class="profile-card-extra-links"):
|
|
|
|
ul(class="profile-statlist"):
|
2019-08-06 15:57:47 +02:00
|
|
|
renderStat(profile.tweets, "posts", text="Tweets")
|
2019-07-11 00:42:31 +02:00
|
|
|
renderStat(profile.following, "following")
|
2019-10-08 20:51:25 +02:00
|
|
|
renderStat(profile.followers, "followers")
|
2019-08-11 21:26:55 +02:00
|
|
|
renderStat(profile.likes, "likes")
|
2019-07-11 00:42:31 +02:00
|
|
|
|
2019-08-11 23:24:02 +02:00
|
|
|
proc renderPhotoRail(profile: Profile; photoRail: seq[GalleryPhoto]): VNode =
|
2019-07-11 00:42:31 +02:00
|
|
|
buildHtml(tdiv(class="photo-rail-card")):
|
|
|
|
tdiv(class="photo-rail-header"):
|
2019-08-11 23:24:02 +02:00
|
|
|
a(href=(&"/{profile.username}/media")):
|
2019-08-19 21:18:18 +02:00
|
|
|
icon "picture", $profile.media & " Photos and videos"
|
2019-07-11 00:42:31 +02:00
|
|
|
|
2019-09-19 01:01:47 +02:00
|
|
|
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 "down"
|
2019-09-08 00:55:12 +02:00
|
|
|
|
2019-07-11 00:42:31 +02:00
|
|
|
tdiv(class="photo-rail-grid"):
|
|
|
|
for i, photo in photoRail:
|
|
|
|
if i == 16: break
|
2020-01-10 02:00:00 +01:00
|
|
|
a(href=(&"/{profile.username}/status/{photo.tweetId}#m"),
|
2019-07-11 00:42:31 +02:00
|
|
|
style={backgroundColor: photo.color}):
|
|
|
|
genImg(photo.url & ":thumb")
|
|
|
|
|
|
|
|
proc renderBanner(profile: Profile): VNode =
|
|
|
|
buildHtml():
|
|
|
|
if "#" in profile.banner:
|
|
|
|
tdiv(class="profile-banner-color", style={backgroundColor: profile.banner})
|
|
|
|
else:
|
2019-09-13 12:27:04 +02:00
|
|
|
a(href=getPicUrl(profile.banner), target="_blank"):
|
2019-07-11 00:42:31 +02:00
|
|
|
genImg(profile.banner)
|
|
|
|
|
2019-09-13 19:57:27 +02:00
|
|
|
proc renderProtected(username: string): VNode =
|
2019-09-19 01:01:47 +02:00
|
|
|
buildHtml(tdiv(class="timeline-container")):
|
2019-09-19 02:29:24 +02:00
|
|
|
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."
|
2019-09-13 19:57:27 +02:00
|
|
|
|
2019-07-11 00:42:31 +02:00
|
|
|
proc renderProfile*(profile: Profile; timeline: Timeline;
|
2019-09-05 22:40:36 +02:00
|
|
|
photoRail: seq[GalleryPhoto]; prefs: Prefs; path: string): VNode =
|
2019-09-19 02:23:22 +02:00
|
|
|
timeline.query.fromUser = @[profile.username]
|
2019-07-11 00:42:31 +02:00
|
|
|
buildHtml(tdiv(class="profile-tabs")):
|
2019-08-13 21:25:29 +02:00
|
|
|
if not prefs.hideBanner:
|
|
|
|
tdiv(class="profile-banner"):
|
|
|
|
renderBanner(profile)
|
2019-07-11 00:42:31 +02:00
|
|
|
|
2019-08-13 21:25:29 +02:00
|
|
|
let sticky = if prefs.stickyProfile: "sticky" else: "unset"
|
|
|
|
tdiv(class="profile-tab", style={position: sticky}):
|
2019-08-15 15:51:20 +02:00
|
|
|
renderProfileCard(profile, prefs)
|
2019-07-11 00:42:31 +02:00
|
|
|
if photoRail.len > 0:
|
2019-08-11 23:24:02 +02:00
|
|
|
renderPhotoRail(profile, photoRail)
|
2019-07-11 00:42:31 +02:00
|
|
|
|
2019-09-19 01:01:47 +02:00
|
|
|
if profile.protected:
|
|
|
|
renderProtected(profile.username)
|
|
|
|
else:
|
|
|
|
renderTweetSearch(timeline, prefs, path)
|