diff --git a/public/css/fontello.css b/public/css/fontello.css new file mode 100644 index 0000000..2d9f3b8 --- /dev/null +++ b/public/css/fontello.css @@ -0,0 +1,53 @@ +@font-face { + font-family: 'fontello'; + src: url('/fonts/fontello.eot?39973630'); + src: url('/fonts/fontello.eot?39973630#iefix') format('embedded-opentype'), + url('/fonts/fontello.woff2?39973630') format('woff2'), + url('/fonts/fontello.woff?39973630') format('woff'), + url('/fonts/fontello.ttf?39973630') format('truetype'), + url('/fonts/fontello.svg?39973630#fontello') format('svg'); + font-weight: normal; + font-style: normal; +} + + [class^="icon-"]:before, [class*=" icon-"]:before { + font-family: "fontello"; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + text-align: center; + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* fix buttons height, for twitter bootstrap */ + line-height: 1em; + + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-help-circled:before { content: '\e800'; } /* '' */ +.icon-attention:before { content: '\e801'; } /* '' */ +.icon-comment:before { content: '\e802'; } /* '' */ +.icon-ok:before { content: '\e803'; } /* '' */ +.icon-link:before { content: '\e805'; } /* '' */ +.icon-calendar:before { content: '\e806'; } /* '' */ +.icon-location:before { content: '\e807'; } /* '' */ +.icon-down-open-1:before { content: '\e808'; } /* '' */ +.icon-picture-1:before { content: '\e809'; } /* '' */ +.icon-lock-circled:before { content: '\e80a'; } /* '' */ +.icon-down-open:before { content: '\e80b'; } /* '' */ +.icon-info-circled:before { content: '\e80c'; } /* '' */ +.icon-retweet-1:before { content: '\e80d'; } /* '' */ +.icon-search:before { content: '\e80e'; } /* '' */ +.icon-pin:before { content: '\e80f'; } /* '' */ +.icon-ok-circled:before { content: '\e810'; } /* '' */ +.icon-cog-2:before { content: '\e812'; } /* '' */ +.icon-thumbs-up-alt:before { content: '\f164'; } /* '' */ diff --git a/public/style.css b/public/css/style.css similarity index 97% rename from public/style.css rename to public/css/style.css index db44f47..a633117 100644 --- a/public/style.css +++ b/public/css/style.css @@ -107,29 +107,19 @@ a:hover { text-overflow: ellipsis; } -.icon { +.verified-icon { color: #fff; + background-color: #1da1f2; border-radius: 50%; + flex-shrink: 0; + margin: 2px 0 3px 3px; + padding-top: 2px; + height: 12px; + width: 14px; + font-size: 8px; display: inline-block; text-align: center; vertical-align: middle; - flex-shrink: 0; - margin: 2px 0 3px 3px; -} - -.verified-icon { - background-color: #1da1f2; - height: 14px; - width: 14px; - font-size: 10px; -} - -.protected-icon { - background-color: #353535; - height: 18px; - width: 18px; - font-size: 12px; - font-weight: bold; } .tweet-date { @@ -215,14 +205,14 @@ nav { height: 35px; } -.site-about { - font-size: 17px; - padding-right: 2px; - margin-top: -0.75px; +.item.right a { + font-size: 16px; + padding-left: 4px; } -.site-settings { - font-size: 18px; +.item.right a:hover { + color: #ffaca0; + text-decoration: unset; } .attachments { @@ -902,12 +892,8 @@ video, .video-container img { } .quote-sensitive-icon { - font-size: 25px; - width: 37px; - height: 32px; - background-color: #4e4e4e; - padding-bottom: 5px; - margin: 0; + font-size: 40px; + color: #909090; } .card { @@ -1119,3 +1105,7 @@ legend { margin-left: 6px; margin-top: 4px; } + +.icon-container { + display: inline; +} diff --git a/public/fonts/LICENSE.txt b/public/fonts/LICENSE.txt new file mode 100644 index 0000000..1d98124 --- /dev/null +++ b/public/fonts/LICENSE.txt @@ -0,0 +1,39 @@ +Font license info + + +## Entypo + + Copyright (C) 2012 by Daniel Bruce + + Author: Daniel Bruce + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://www.entypo.com + + +## MFG Labs + + Copyright (C) 2012 by Daniel Bruce + + Author: MFG Labs + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://www.mfglabs.com/ + + +## Font Awesome + + Copyright (C) 2016 by Dave Gandy + + Author: Dave Gandy + License: SIL () + Homepage: http://fortawesome.github.com/Font-Awesome/ + + +## Elusive + + Copyright (C) 2013 by Aristeides Stathopoulos + + Author: Aristeides Stathopoulos + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://aristeides.com/ + + diff --git a/public/fonts/fontello.eot b/public/fonts/fontello.eot new file mode 100644 index 0000000..43d722f Binary files /dev/null and b/public/fonts/fontello.eot differ diff --git a/public/fonts/fontello.svg b/public/fonts/fontello.svg new file mode 100644 index 0000000..90cf3ca --- /dev/null +++ b/public/fonts/fontello.svg @@ -0,0 +1,46 @@ + + + +Copyright (C) 2019 by original authors @ fontello.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/fonts/fontello.ttf b/public/fonts/fontello.ttf new file mode 100644 index 0000000..6d82a62 Binary files /dev/null and b/public/fonts/fontello.ttf differ diff --git a/public/fonts/fontello.woff b/public/fonts/fontello.woff new file mode 100644 index 0000000..100da96 Binary files /dev/null and b/public/fonts/fontello.woff differ diff --git a/public/fonts/fontello.woff2 b/public/fonts/fontello.woff2 new file mode 100644 index 0000000..56cd672 Binary files /dev/null and b/public/fonts/fontello.woff2 differ diff --git a/src/views/general.nim b/src/views/general.nim index d07037b..2ca43d6 100644 --- a/src/views/general.nim +++ b/src/views/general.nim @@ -1,5 +1,6 @@ import karax/[karaxdsl, vdom] +import renderutils import ../utils, ../types const doctype = "\n" @@ -13,14 +14,15 @@ proc renderNavbar*(title: string): VNode = a(href="/"): img(class="site-logo", src="/logo.png") tdiv(class="item right"): - a(class="site-about", href="/about"): text "🛈" - a(class="site-prefs", href="/settings"): text "⚙" + icon "info-circled", title="About", href="/about" + icon "cog-2", title="Preferences", href="/settings" proc renderMain*(body: VNode; prefs: Prefs; title="Nitter"; titleText=""; desc=""; `type`="article"; video=""; images: seq[string] = @[]): string = let node = buildHtml(html(lang="en")): head: - link(rel="stylesheet", `type`="text/css", href="/style.css") + link(rel="stylesheet", `type`="text/css", href="/css/style.css") + link(rel="stylesheet", `type`="text/css", href="/css/fontello.css") title: if titleText.len > 0: @@ -53,7 +55,7 @@ proc renderSearch*(): VNode = tdiv(class="search-panel"): form(`method`="post", action="search"): input(`type`="text", name="query", autofocus="", placeholder="Enter usernames...") - button(`type`="submit"): text "🔎" + button(`type`="submit"): icon "search" proc renderError*(error: string): VNode = buildHtml(tdiv(class="panel")): diff --git a/src/views/profile.nim b/src/views/profile.nim index c3c9358..513b0d9 100644 --- a/src/views/profile.nim +++ b/src/views/profile.nim @@ -1,8 +1,8 @@ import strutils, strformat import karax/[karaxdsl, vdom, vstyles] -import ../types, ../utils, ../formatters import tweet, timeline, renderutils +import ../types, ../utils, ../formatters proc renderStat(num, class: string; text=""): VNode = let t = if text.len > 0: text else: class @@ -27,17 +27,17 @@ proc renderProfileCard*(profile: Profile): VNode = if profile.location.len > 0: tdiv(class="profile-location"): - span: text "📍 " & profile.location + span: icon "location", profile.location if profile.website.len > 0: tdiv(class="profile-website"): span: - text "🔗 " + icon "link" linkText(profile.website) tdiv(class="profile-joindate"): span(title=getJoinDateFull(profile)): - text "📅 " & getJoinDate(profile) + icon "calendar", getJoinDate(profile) tdiv(class="profile-card-extra-links"): ul(class="profile-statlist"): @@ -50,7 +50,7 @@ proc renderPhotoRail(profile: Profile; photoRail: seq[GalleryPhoto]): VNode = buildHtml(tdiv(class="photo-rail-card")): tdiv(class="photo-rail-header"): a(href=(&"/{profile.username}/media")): - text &"🖼 {profile.media} Photos and videos" + icon "picture-1", $profile.media & " Photos and videos" tdiv(class="photo-rail-grid"): for i, photo in photoRail: diff --git a/src/views/renderutils.nim b/src/views/renderutils.nim index eab66cf..c42c76e 100644 --- a/src/views/renderutils.nim +++ b/src/views/renderutils.nim @@ -2,6 +2,18 @@ import karax/[karaxdsl, vdom, vstyles] import ../types, ../utils +proc icon*(icon: string; text=""; title=""; class=""; href=""): VNode = + var c = "icon-" & icon + if class.len > 0: c = c & " " & class + buildHtml(tdiv(class="icon-container")): + if href.len > 0: + a(class=c, title=title, href=href) + else: + span(class=c, title=title) + + if text.len > 0: + text " " & text + proc linkUser*(profile: Profile, class=""): VNode = let isName = "username" notin class @@ -12,9 +24,10 @@ proc linkUser*(profile: Profile, class=""): VNode = buildHtml(a(href=href, class=class, title=nameText)): text nameText if isName and profile.verified: - span(class="icon verified-icon", title="Verified account"): text "✔" + icon "ok", class="verified-icon", title="Verified account" if isName and profile.protected: - span(class="icon protected-icon", title="Protected account"): text "🔒" + text " " + icon "lock-circled", title="Protected account" proc genImg*(url: string; class=""): VNode = buildHtml(): diff --git a/src/views/tweet.nim b/src/views/tweet.nim index 1ae2be4..407dd4e 100644 --- a/src/views/tweet.nim +++ b/src/views/tweet.nim @@ -1,17 +1,18 @@ import strutils, sequtils import karax/[karaxdsl, vdom, vstyles] -import ../types, ../utils, ../formatters import renderutils +import ../types, ../utils, ../formatters proc renderHeader(tweet: Tweet): VNode = buildHtml(tdiv): if tweet.retweet.isSome: tdiv(class="retweet"): - span: text "🔄 " & get(tweet.retweet).by & " retweeted" + span: icon "retweet-1", get(tweet.retweet).by & " retweeted" + if tweet.pinned: tdiv(class="pinned"): - span: text "📌 Pinned Tweet" + span: icon "pin", "Pinned Tweet" tdiv(class="tweet-header"): a(class="tweet-avatar", href=("/" & tweet.profile.username)): @@ -70,7 +71,6 @@ proc renderGif(gif: Gif; prefs: Prefs): VNode = let thumb = gif.thumb.getSigUrl("pic") let url = gif.url.getSigUrl("video") if prefs.autoplayGifs: - video(class="gif", poster=thumb, autoplay="", muted="", loop=""): source(src=url, `type`="video/mp4") else: @@ -117,9 +117,9 @@ proc renderCard(card: Card; prefs: Prefs): VNode = proc renderStats(stats: TweetStats): VNode = buildHtml(tdiv(class="tweet-stats")): - span(class="tweet-stat"): text "💬 " & $stats.replies - span(class="tweet-stat"): text "🔄 " & $stats.retweets - span(class="tweet-stat"): text "👍 " & $stats.likes + span(class="tweet-stat"): icon "comment", $stats.replies + span(class="tweet-stat"): icon "retweet-1", $stats.retweets + span(class="tweet-stat"): icon "thumbs-up-alt", $stats.likes proc renderReply(tweet: Tweet): VNode = buildHtml(tdiv(class="replying-to")): @@ -145,7 +145,7 @@ proc renderQuoteMedia(quote: Quote): VNode = tdiv(class="quote-badge-text"): text quote.badge elif quote.sensitive: tdiv(class="quote-sensitive"): - span(class="icon quote-sensitive-icon"): text "❗" + icon "attention", class="quote-sensitive-icon" proc renderQuote(quote: Quote): VNode = if not quote.available: