Bladeren bron

Merge pull request #515 from LainLayer/embedded

Implement tweet embeds
Zed 4 jaren geleden
bovenliggende
commit
875e6c2cd6
7 gewijzigde bestanden met toevoegingen van 77 en 23 verwijderingen
  1. 9 7
      src/formatters.nim
  2. 25 4
      src/routes/embed.nim
  3. 2 2
      src/routes/router_utils.nim
  4. 19 0
      src/sass/tweet/_base.scss
  5. 3 2
      src/views/embed.nim
  6. 12 8
      src/views/general.nim
  7. 7 0
      src/views/tweet.nim

+ 9 - 7
src/formatters.nim

@@ -32,23 +32,25 @@ proc getUrlPrefix*(cfg: Config): string =
   if cfg.useHttps: https & cfg.hostname
   else: "http://" & cfg.hostname
 
-proc stripHtml*(text: string): string =
+proc shortLink*(text: string; length=28): string =
+  result = text.replace(wwwRegex, "")
+  if result.len > length:
+    result = result[0 ..< length] & "…"
+    
+proc stripHtml*(text: string; shorten=false): string =
   var html = parseHtml(text)
   for el in html.findAll("a"):
     let link = el.attr("href")
     if "http" in link:
       if el.len == 0: continue
-      el[0].text = link
+      el[0].text =
+        if shorten: link.shortLink
+        else: link
   html.innerText()
 
 proc sanitizeXml*(text: string): string =
   text.replace(illegalXmlRegex, "")
 
-proc shortLink*(text: string; length=28): string =
-  result = text.replace(wwwRegex, "")
-  if result.len > length:
-    result = result[0 ..< length] & "…"
-
 proc replaceUrls*(body: string; prefs: Prefs; absolute=""): string =
   result = body
 

+ 25 - 4
src/routes/embed.nim

@@ -1,9 +1,11 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 import asyncdispatch, strutils, options
-import jester
-import ".."/[types, api], ../views/embed
+import jester, karax/vdom
+import ".."/[types, api]
+import ../views/[embed, tweet, general]
+import router_utils
 
-export api, embed
+export api, embed, vdom, tweet, general, router_utils
 
 proc createEmbedRouter*(cfg: Config) =
   router embed:
@@ -12,4 +14,23 @@ proc createEmbedRouter*(cfg: Config) =
       if convo == nil or convo.tweet == nil or convo.tweet.video.isNone:
         resp Http404
 
-      resp renderVideoEmbed(cfg, convo.tweet)
+      resp renderVideoEmbed(convo.tweet, cfg, request)
+
+    get "/@user/status/@id/embed":
+      let
+        convo = await getTweet(@"id")
+        prefs = cookiePrefs()
+        path = getPath()
+
+      if convo == nil or convo.tweet == nil:
+        resp Http404
+
+      resp $renderTweetEmbed(convo.tweet, path, prefs, cfg, request)
+
+    get "/embed/Tweet.html":
+      let id = @"id"
+
+      if id.len > 0:
+        redirect("/i/status/" & id & "/embed")
+      else:
+        resp Http404

+ 2 - 2
src/routes/router_utils.nim

@@ -4,12 +4,12 @@ from jester import Request, cookies
 
 import ../views/general
 import ".."/[utils, prefs, types]
-export utils, prefs, types
+export utils, prefs, types, uri
 
 template savePref*(pref, value: string; req: Request; expire=false) =
   if not expire or pref in cookies(req):
     setCookie(pref, value, daysForward(when expire: -10 else: 360),
-              httpOnly=true, secure=cfg.useHttps)
+              httpOnly=true, secure=cfg.useHttps, sameSite=None)
 
 template cookiePrefs*(): untyped {.dirty.} =
   getPrefs(cookies(request))

+ 19 - 0
src/sass/tweet/_base.scss

@@ -98,6 +98,8 @@
 }
 
 .avatar {
+    position: absolute;
+
     &.round {
         border-radius: 50%;
     }
@@ -110,6 +112,23 @@
     }
 }
 
+.tweet-embed {
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+    height: 100%;
+
+    .tweet-content { 
+        font-size: 18px 
+    }
+    
+    .tweet-body { 
+        display: flex;
+        flex-direction: column;
+        max-height: calc(100vh - 0.75em * 2);
+    }
+}
+
 .attribution {
     display: flex;
     pointer-events: all;

+ 3 - 2
src/views/embed.nim

@@ -1,18 +1,19 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 import options
 import karax/[karaxdsl, vdom]
+from jester import Request
 
 import ".."/[types, formatters]
 import general, tweet
 
 const doctype = "<!DOCTYPE html>\n"
 
-proc renderVideoEmbed*(cfg: Config; tweet: Tweet): string =
+proc renderVideoEmbed*(tweet: Tweet; cfg: Config; req: Request): string =
   let thumb = get(tweet.video).thumb
   let vidUrl = getVideoEmbed(cfg, tweet.id)
   let prefs = Prefs(hlsPlayback: true)
   let node = buildHtml(html(lang="en")):
-    renderHead(prefs, cfg, video=vidUrl, images=(@[thumb]))
+    renderHead(prefs, cfg, req, video=vidUrl, images=(@[thumb]))
 
     tdiv(class="embed-video"):
       renderVideo(get(tweet.video), prefs, "")

+ 12 - 8
src/views/general.nim

@@ -11,6 +11,9 @@ const
   doctype = "<!DOCTYPE html>\n"
   lp = readFile("public/lp.svg")
 
+proc toTheme(theme: string): string =
+  theme.toLowerAscii.replace(" ", "_")
+
 proc renderNavbar(cfg: Config; req: Request; rss, canonical: string): VNode =
   var path = req.params.getOrDefault("referer")
   if path.len == 0:
@@ -33,9 +36,13 @@ proc renderNavbar(cfg: Config; req: Request; rss, canonical: string): VNode =
         icon "info", title="About", href="/about"
         icon "cog", title="Preferences", href=("/settings?referer=" & encodeUrl(path))
 
-proc renderHead*(prefs: Prefs; cfg: Config; titleText=""; desc=""; video="";
-                 images: seq[string] = @[]; banner=""; ogTitle=""; theme="";
+proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
+                 video=""; images: seq[string] = @[]; banner=""; ogTitle="";
                  rss=""; canonical=""): VNode =
+  var theme = prefs.theme.toTheme
+  if "theme" in req.params:
+    theme = req.params["theme"].toTheme
+    
   let ogType =
     if video.len > 0: "video"
     elif rss.len > 0: "object"
@@ -45,7 +52,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; titleText=""; desc=""; video="";
   let opensearchUrl = getUrlPrefix(cfg) & "/opensearch"
 
   buildHtml(head):
-    link(rel="stylesheet", type="text/css", href="/css/style.css?v=10")
+    link(rel="stylesheet", type="text/css", href="/css/style.css?v=12")
     link(rel="stylesheet", type="text/css", href="/css/fontello.css?v=2")
 
     if theme.len > 0:
@@ -118,15 +125,12 @@ proc renderHead*(prefs: Prefs; cfg: Config; titleText=""; desc=""; video="";
 proc renderMain*(body: VNode; req: Request; cfg: Config; prefs=defaultPrefs;
                  titleText=""; desc=""; ogTitle=""; rss=""; video="";
                  images: seq[string] = @[]; banner=""): string =
-  var theme = toLowerAscii(prefs.theme).replace(" ", "_")
-  if "theme" in req.params:
-    theme = toLowerAscii(req.params["theme"]).replace(" ", "_")
 
   let canonical = getTwitterLink(req.path, req.params)
 
   let node = buildHtml(html(lang="en")):
-    renderHead(prefs, cfg, titleText, desc, video, images, banner, ogTitle,
-               theme, rss, canonical)
+    renderHead(prefs, cfg, req, titleText, desc, video, images, banner, ogTitle,
+               rss, canonical)
 
     body:
       renderNavbar(cfg, req, rss, canonical)

+ 7 - 0
src/views/tweet.nim

@@ -1,9 +1,11 @@
 # SPDX-License-Identifier: AGPL-3.0-only
 import strutils, sequtils, strformat, options
 import karax/[karaxdsl, vdom, vstyles]
+from jester import Request
 
 import renderutils
 import ".."/[types, utils, formatters]
+import general
 
 proc getSmallPic(url: string): string =
   result = url
@@ -353,3 +355,8 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class=""; index=0;
       if showThread:
         a(class="show-thread", href=("/i/status/" & $tweet.threadId)):
           text "Show this thread"
+
+proc renderTweetEmbed*(tweet: Tweet; path: string; prefs: Prefs; cfg: Config; req: Request): VNode =
+  buildHtml(tdiv(class="tweet-embed")):
+    renderHead(prefs, cfg, req)
+    renderTweet(tweet, prefs, path, mainTweet=true)