Refactor images to use an Image type to supply alt text
This commit is contained in:
parent
f2cac5190a
commit
8042c65ce3
@ -250,7 +250,9 @@ proc parseTweet(js: JsonNode; jsCard: JsonNode = newJNull()): Tweet =
|
||||
let name = jsCard{"name"}.getStr
|
||||
if "poll" in name:
|
||||
if "image" in name:
|
||||
result.photos.add jsCard{"binding_values", "image_large"}.getImageVal
|
||||
result.photos.add Image(
|
||||
url: jsCard{"binding_values", "image_large"}.getImageVal
|
||||
)
|
||||
|
||||
result.poll = some parsePoll(jsCard)
|
||||
elif name == "amplify":
|
||||
@ -264,7 +266,10 @@ proc parseTweet(js: JsonNode; jsCard: JsonNode = newJNull()): Tweet =
|
||||
for m in jsMedia:
|
||||
case m{"type"}.getStr
|
||||
of "photo":
|
||||
result.photos.add m{"media_url_https"}.getImageStr
|
||||
result.photos.add Image(
|
||||
url: m{"media_url_https"}.getImageStr,
|
||||
description: m{"ext_alt_text"}.getStr,
|
||||
)
|
||||
of "video":
|
||||
result.video = some(parseVideo(m))
|
||||
with user, m{"additional_media_info", "source_user"}:
|
||||
@ -418,7 +423,7 @@ proc parsePhotoRail*(js: JsonNode): PhotoRail =
|
||||
for tweet in js:
|
||||
let
|
||||
t = parseTweet(tweet, js{"tweet_card"})
|
||||
url = if t.photos.len > 0: t.photos[0]
|
||||
url = if t.photos.len > 0: t.photos[0].url
|
||||
elif t.video.isSome: get(t.video).thumb
|
||||
elif t.gif.isSome: get(t.gif).thumb
|
||||
elif t.card.isSome: get(t.card).image
|
||||
|
||||
@ -45,8 +45,8 @@ proc createActivityPubRouter*(cfg: Config) =
|
||||
var media: seq[JsonNode] = @[]
|
||||
|
||||
if tweet.photos.len > 0:
|
||||
for url in tweet.photos:
|
||||
let image = getUrlPrefix(cfg) & getPicUrl(url)
|
||||
for imageObj in tweet.photos:
|
||||
let image = getUrlPrefix(cfg) & getPicUrl(imageObj.url)
|
||||
var mediaObj = newJObject()
|
||||
|
||||
mediaObj["id"] = %"150745989836308480" # idk if discord even parses this snowflake, but its my user id why not
|
||||
@ -56,7 +56,7 @@ proc createActivityPubRouter*(cfg: Config) =
|
||||
mediaObj["remote_url"] = %image
|
||||
mediaObj["preview_remote_url"] = %image
|
||||
mediaObj["text_url"] = newJNull()
|
||||
mediaObj["description"] = newJNull() # FIXME this requires refactoring images
|
||||
mediaObj["description"] = %imageObj.description
|
||||
# FIXME but this probably isnt used by discord
|
||||
mediaObj["meta"] = newJObject()
|
||||
|
||||
|
||||
@ -123,7 +123,7 @@ proc createStatusRouter*(cfg: Config) =
|
||||
|
||||
if tweet.video.isSome():
|
||||
let videoObj = get(tweet.video)
|
||||
images = @[videoObj.thumb]
|
||||
images = @[Image(url:videoObj.thumb)]
|
||||
|
||||
let vars = videoObj.variants.filterIt(it.contentType == mp4)
|
||||
# idk why this wont sort when it sorts everywhere else
|
||||
@ -131,7 +131,7 @@ proc createStatusRouter*(cfg: Config) =
|
||||
video = vars[^1].url
|
||||
elif tweet.gif.isSome():
|
||||
let gif = get(tweet.gif)
|
||||
images = @[gif.thumb]
|
||||
images = @[Image(url:gif.thumb)]
|
||||
video = getUrlPrefix(cfg) & getPicUrl(gif.url)
|
||||
#elif tweet.card.isSome():
|
||||
# let card = tweet.card.get()
|
||||
|
||||
@ -96,7 +96,7 @@ proc showTimeline*(request: Request; query: Query; cfg: Config; prefs: Prefs;
|
||||
|
||||
let pHtml = renderProfile(profile, cfg, prefs, getPath())
|
||||
result = renderMain(pHtml, request, cfg, prefs, pageTitle(u), pageDesc(u),
|
||||
rss=rss, images = @[u.getUserPic("_400x400")],
|
||||
rss=rss, images = @[Image(url: u.getUserPic("_400x400"))],
|
||||
banner=u.banner)
|
||||
|
||||
template respTimeline*(timeline: typed) =
|
||||
|
||||
@ -48,6 +48,19 @@
|
||||
margin: 0;
|
||||
max-height: 530px;
|
||||
}
|
||||
|
||||
.alt {
|
||||
position: relative;
|
||||
bottom: 15px;
|
||||
left: 4px;
|
||||
padding: 4px;
|
||||
background: #101010;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
pointer-events: none;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.gallery-gif video {
|
||||
|
||||
@ -123,6 +123,10 @@ type
|
||||
playbackType*: VideoType
|
||||
variants*: seq[VideoVariant]
|
||||
|
||||
Image* = object
|
||||
url*: string
|
||||
description*: string
|
||||
|
||||
QueryKind* = enum
|
||||
posts, replies, media, users, tweets, userList, favorites
|
||||
|
||||
@ -228,7 +232,7 @@ type
|
||||
poll*: Option[Poll]
|
||||
gif*: Option[Gif]
|
||||
video*: Option[Video]
|
||||
photos*: seq[string]
|
||||
photos*: seq[Image]
|
||||
birdwatch*: Option[BirdwatchNote]
|
||||
|
||||
Tweets* = seq[Tweet]
|
||||
|
||||
@ -15,7 +15,7 @@ proc renderVideoEmbed*(tweet: Tweet; cfg: Config; req: Request): string =
|
||||
let vidUrl = vars.sortedByIt(it.bitrate)[^1].url
|
||||
let prefs = Prefs(hlsPlayback: true, mp4Playback: true)
|
||||
let node = buildHtml(html(lang="en")):
|
||||
renderHead(prefs, cfg, req, video=vidUrl, images=(@[thumb]))
|
||||
renderHead(prefs, cfg, req, video=vidUrl, images=(@[Image(url:thumb)]))
|
||||
|
||||
body:
|
||||
tdiv(class="embed-video"):
|
||||
|
||||
@ -37,7 +37,7 @@ proc renderNavbar(cfg: Config; req: Request; rss, canonical: string): VNode =
|
||||
icon "cog", title="Preferences", href=("/settings?referer=" & encodeUrl(path))
|
||||
|
||||
proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
|
||||
video=""; images: seq[string] = @[]; banner=""; ogTitle="";
|
||||
video=""; images: seq[Image] = @[]; banner=""; ogTitle="";
|
||||
rss=""; canonical=""; avatar=""; context=""; contextUrl="";
|
||||
id=""; time: Option[DateTime] = none(DateTime)): VNode =
|
||||
var theme = prefs.theme.toTheme
|
||||
@ -120,13 +120,16 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
|
||||
link(rel="preload", type="image/png", href=bannerUrl, `as`="image")
|
||||
|
||||
if images.len > 0:
|
||||
for url in images:
|
||||
let preloadUrl = if "400x400" in url: getPicUrl(url)
|
||||
for imageObj in images:
|
||||
let
|
||||
url = imageObj.url
|
||||
preloadUrl = if "400x400" in url: getPicUrl(url)
|
||||
else: getSmallPic(url)
|
||||
link(rel="preload", type="image/png", href=preloadUrl, `as`="image")
|
||||
|
||||
let image = getUrlPrefix(cfg) & getPicUrl(url)
|
||||
meta(property="og:image", content=image)
|
||||
meta(property="og:image:alt", content=imageObj.description)
|
||||
if video.len == 0:
|
||||
meta(property="twitter:image:src", content=image)
|
||||
meta(property="twitter:card", content="summary_large_image")
|
||||
@ -172,7 +175,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc="";
|
||||
|
||||
proc renderMain*(body: VNode; req: Request; cfg: Config; prefs=defaultPrefs;
|
||||
titleText=""; desc=""; ogTitle=""; rss=""; video="";
|
||||
images: seq[string] = @[]; banner=""; avatar=""; context="";
|
||||
images: seq[Image] = @[]; banner=""; avatar=""; context="";
|
||||
contextUrl=""; id=""; time: Option[DateTime] = none(DateTime)
|
||||
): string =
|
||||
|
||||
|
||||
@ -38,10 +38,10 @@ proc getActivityStream*(tweet: Tweet, cfg: Config, prefs: Prefs): JsonNode =
|
||||
var media: seq[JsonNode] = @[]
|
||||
|
||||
if tweet.photos.len > 0:
|
||||
for url in tweet.photos:
|
||||
for imageObj in tweet.photos:
|
||||
let
|
||||
image = getUrlPrefix(cfg) & getPicUrl(url)
|
||||
splitUrl = url.split('.')
|
||||
image = getUrlPrefix(cfg) & getPicUrl(imageObj.url)
|
||||
splitUrl = imageObj.url.split('.')
|
||||
var filetype = splitUrl[^1]
|
||||
if filetype == "jpg":
|
||||
filetype = "jpeg"
|
||||
@ -50,7 +50,7 @@ proc getActivityStream*(tweet: Tweet, cfg: Config, prefs: Prefs): JsonNode =
|
||||
mediaObj["type"] = %"Document"
|
||||
mediaObj["mediaType"] = %("image/" & filetype)
|
||||
mediaObj["url"] = %image
|
||||
mediaObj["name"] = newJNull() # FIXME a11y
|
||||
mediaObj["name"] = %imageObj.description
|
||||
|
||||
media.add(mediaObj)
|
||||
|
||||
|
||||
@ -89,9 +89,9 @@ proc genDate*(pref, state: string): VNode =
|
||||
input(name=pref, `type`="date", value=state)
|
||||
icon "calendar"
|
||||
|
||||
proc genImg*(url: string; class=""): VNode =
|
||||
proc genImg*(url: string; alt=""; class=""): VNode =
|
||||
buildHtml():
|
||||
img(src=getPicUrl(url), class=class, alt="")
|
||||
img(src=getPicUrl(url), class=class, alt=alt)
|
||||
|
||||
proc getTabClass*(query: Query; tab: QueryKind): string =
|
||||
if query.kind == tab: "tab-item active"
|
||||
|
||||
@ -49,12 +49,15 @@ proc renderAlbum(tweet: Tweet): VNode =
|
||||
let margin = if i > 0: ".25em" else: ""
|
||||
tdiv(class="gallery-row", style={marginTop: margin}):
|
||||
for photo in photos:
|
||||
tdiv(class="attachment image"):
|
||||
tdiv(class="attachment image", title=photo.description):
|
||||
let
|
||||
named = "name=" in photo
|
||||
small = if named: photo else: photo & smallWebp
|
||||
a(href=getOrigPicUrl(photo), class="still-image", target="_blank"):
|
||||
genImg(small)
|
||||
url = photo.url
|
||||
named = "name=" in url
|
||||
small = if named: url else: url & smallWebp
|
||||
a(href=getOrigPicUrl(url), class="still-image", target="_blank", data-caption=photo.description):
|
||||
genImg(small, alt=photo.description)
|
||||
if photo.description.len > 0:
|
||||
span(class="alt"): text "ALT"
|
||||
|
||||
proc isPlaybackEnabled(prefs: Prefs; playbackType: VideoType): bool =
|
||||
case playbackType
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user