From 2bd664ae7d3097bc0d3edc9a44282bddbcfb4f06 Mon Sep 17 00:00:00 2001 From: Zed Date: Thu, 19 Feb 2026 01:44:50 +0100 Subject: [PATCH] Add community notes support Fixes #727 Fixes #1023 --- public/css/fontello.css | 17 ++-- public/fonts/fontello.eot | Bin 9544 -> 9820 bytes public/fonts/fontello.svg | 4 +- public/fonts/fontello.ttf | Bin 9376 -> 9652 bytes public/fonts/fontello.woff | Bin 5924 -> 6152 bytes public/fonts/fontello.woff2 | Bin 4896 -> 5068 bytes src/consts.nim | 2 +- src/parser.nim | 9 ++ src/parserutils.nim | 20 +++++ src/prefs_impl.nim | 3 + src/sass/tweet/_base.scss | 35 ++++++++ src/sass/tweet/card.scss | 158 ++++++++++++++++++------------------ src/sass/tweet/quote.scss | 30 +++++-- src/types.nim | 1 + src/views/general.nim | 2 +- src/views/tweet.nim | 14 ++++ 16 files changed, 201 insertions(+), 94 deletions(-) diff --git a/public/css/fontello.css b/public/css/fontello.css index 52362d8..53a66a1 100644 --- a/public/css/fontello.css +++ b/public/css/fontello.css @@ -1,12 +1,12 @@ @font-face { font-family: "fontello"; - src: url("/fonts/fontello.eot?77185648"); + src: url("/fonts/fontello.eot?42791196"); src: - url("/fonts/fontello.eot?77185648#iefix") format("embedded-opentype"), - url("/fonts/fontello.woff2?77185648") format("woff2"), - url("/fonts/fontello.woff?77185648") format("woff"), - url("/fonts/fontello.ttf?77185648") format("truetype"), - url("/fonts/fontello.svg?77185648#fontello") format("svg"); + url("/fonts/fontello.eot?42791196#iefix") format("embedded-opentype"), + url("/fonts/fontello.woff2?42791196") format("woff2"), + url("/fonts/fontello.woff?42791196") format("woff"), + url("/fonts/fontello.ttf?42791196") format("truetype"), + url("/fonts/fontello.svg?42791196#fontello") format("svg"); font-weight: normal; font-style: normal; } @@ -56,6 +56,11 @@ } /* '' */ +.icon-group:before { + content: "\e804"; +} + +/* '' */ .icon-play:before { content: "\e805"; } diff --git a/public/fonts/fontello.eot b/public/fonts/fontello.eot index 8671134d7bcae39b2c2b05872362415a5a3bfbe7..2e05e0b254729c644c52a1291e36fa9d9c553a37 100644 GIT binary patch delta 964 zcmYLIUr19?82`?>cXxBnP4BilZ8N8Hn{zgu?oXnog_wxch>$cvr}-z@+(k_+&`G5T zL1I^^hYFz=p@?X)mmZ3qB(SG~f}rRh_bCwVAu#N_dZT;!o$vSizH`s{zVDp7(ebg9 z>-7LUbFXj_HuyA{S!ubEehWZi0MI{}jEk?kHD^&j0ibJx(^F3L<0I_iU>p`lk^_O? zR{(4Vl!lS`q=^1}jPIb;jU+A)w_dB{09ahl2%|&s3xSQiJ^&syL`Kn}y~;d5y@a}a zG&wcX(cHC%i}R1raW0V>jC*>@t^=4^)PZDtMkMvd`=~>xo#XN3(B{43!>BPyx+$h6 zr(VwaqnJQB#@~n&L*iVvAq(Ixl-9_3(l70j)ag|q7zMZq%s#6^tH&Z&frSC|>p=$; zs9dmBuvM|0v$qEz!+*a2El$UIRmv;9qJE7P9b9IMQj!nY3{?9g601bnx-{l5D>Z1) zssL<^tOB&iRp9O*tAHHjDwG^$6_ATug|eTl0`icnz>b5gq617QR46ATtAGOJDu4$p z^8jE*TX6ue0BmCt3c#A#Vc(H7gA^ET-umoWXWO-b4*MQS?H%Q|}It-ua$WO}7fE>(5uC zg?wlYl(>RE*YS1UK3zL*8e2TX#k{>ot9{fwE9UB=wx;Exb-TXJVe6{vOe8ulh7Y&t z?dxuq7Lx9 z;zbYE^%M|-UIJc(g&f3lwTB$-DF+V#b(A@ugvTaQu#4rpQ-3z-4`{QqvR9tyj$ZWjG0CE8sLMd%hCi*}-&)c!!P2YB!T z|6Tuk)d>ZnMPK=y%XGg}& Ezs>xbegFUf diff --git a/public/fonts/fontello.svg b/public/fonts/fontello.svg index 31bd38c..ccc0436 100644 --- a/public/fonts/fontello.svg +++ b/public/fonts/fontello.svg @@ -1,7 +1,7 @@ -Copyright (C) 2025 by original authors @ fontello.com +Copyright (C) 2026 by original authors @ fontello.com @@ -14,6 +14,8 @@ + + diff --git a/public/fonts/fontello.ttf b/public/fonts/fontello.ttf index 0c04c6c934c632486fc0fc56ce07b794a1fcba07..b4dcf100b9c57f6507424657c3d0dc77de2ffd11 100644 GIT binary patch delta 985 zcmYL|OH30{6o${e^Jpohr7dlN@+g!RO0iJr0|Z13K}4dcgb0#A!SV{FV<{C)phShR z@--}6s3CDfqA|vrZd~ZnnBYnmu3Y%YtTY5o)M)SwjIqr(=l}nEJ9F=u+x4SQkKJ&j z-T;su02m&PhJ{!CTrc{^0CascnXqGyAIopN=*EQc=!o~{B><}yt#&*-D`1|BkHh06QZofC{w&J|83n z$U?0kuToNgY}5*XPm&ZM2eksW93+J<(4$e1Uy-B$2Gj~*1l;HzV8U9p2jl^4<053h zobG1dk`#jy7>Q=U0(Ec%_8qKlZg3Upw5*B%>6SaV%%Xy2ju3_{1H&Y3E}PBm=J_H| zEAh7xSEWA`4AonCE3YTK%Iqk&2K;T*OG5r&y~UiTDkYX;94PY=60DSG%ApmrJXOjO z@YfQT@xfv0a0W{4zD{jUypD|*Jh$9#a(c<&(!lZ7Tlv)S=YuYfyleNCI(%-&p$(%g zSwEwnS}EjvDhC^D-PE)oWUE8g*6RfuHcdy7wXdOjdb)cuP|~5XZ8%w)Px_}8Ow{8( zaLU)Cv8>qX^(I?DO(1RO{n42$?K$PB*YugUGtv zGcjX0?U^F0l&3TF5mUu1F&VanU1C3TgItFD!sqgL@F>V<3{Nt2rt6Fc*s#tJ$MoJB!(hX6ylq##a({$=DlxcXLe@aUD;XO9^dK! zA`jqJ$ujKm-8UZnTR>@+)}2x2ywX0KSlO;vx2Jw>(jU-9D@Ma+ew6+zHBwo9SYFtC zz5r-ffgw~)^`ra6T^Y6}f<8tnb=urv0dWvCVgDFAi>qWw#*e z#U=!cz)Pt8-X!%1zp)7oRpwDdpg{9gKhaHev-<OK4ubqjAXX3jurLXv2J9M2sYi~j{} C37C5T diff --git a/public/fonts/fontello.woff b/public/fonts/fontello.woff index e4582ad0ee7148607d5a5e183e595a785167af4e..af578282692a25df27b6863c12ff80a911d4d12f 100644 GIT binary patch delta 4070 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 tAeT|orv|6#C1V diff --git a/public/fonts/fontello.woff2 b/public/fonts/fontello.woff2 index d2c246d1aa701c85f3438d4d3baa7e3a245aff90..7efdfbdbc78248f820089a97017c306e49c23955 100644 GIT binary patch literal 5068 zcmV;-6Ep00Pew8T0RR91029mr4*&oF041~l026Zn0RR9100000000000000000000 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 S*`!;CpE=t5KRzi04o(09?GiZv diff --git a/src/consts.nim b/src/consts.nim index 38fd870..17827f2 100644 --- a/src/consts.nim +++ b/src/consts.nim @@ -113,7 +113,7 @@ const $2 "includeHasBirdwatchNotes": false, "includePromotedContent": false, - "withBirdwatchNotes": false, + "withBirdwatchNotes": true, "withVoice": false, "withV2Timeline": true }""".replace(" ", "").replace("\n", "") diff --git a/src/parser.nim b/src/parser.nim index 6b8da60..da0ffb4 100644 --- a/src/parser.nim +++ b/src/parser.nim @@ -6,6 +6,12 @@ import experimental/parser/unifiedcard proc parseGraphTweet(js: JsonNode): Tweet +proc parseCommunityNote(js: JsonNode): string = + let subtitle = js{"subtitle"} + result = subtitle{"text"}.getStr + with entities, subtitle{"entities"}: + result = expandBirdwatchEntities(result, entities) + proc parseUser(js: JsonNode; id=""): User = if js.isNull: return result = User( @@ -439,6 +445,9 @@ proc parseGraphTweet(js: JsonNode): Tweet = for id in ids: result.history.add parseBiggestInt(id.getStr) + with birdwatch, js{"birdwatch_pivot"}: + result.note = parseCommunityNote(birdwatch) + proc parseGraphThread(js: JsonNode): tuple[thread: Chain; self: bool] = for t in ? js{"content", "items"}: let entryId = t.getEntryId diff --git a/src/parserutils.nim b/src/parserutils.nim index 08b3cf8..98dd2ee 100644 --- a/src/parserutils.nim +++ b/src/parserutils.nim @@ -330,6 +330,26 @@ proc expandNoteTweetEntities*(tweet: Tweet; js: JsonNode) = tweet.text = tweet.text.multiReplace((unicodeOpen, xmlOpen), (unicodeClose, xmlClose)) +proc expandBirdwatchEntities*(text: string; entities: JsonNode): string = + let runes = text.toRunes + var replacements: seq[ReplaceSlice] + + for entity in entities: + let + fromIdx = entity{"from_index"}.getInt + toIdx = entity{"to_index"}.getInt + url = entity{"ref", "url"}.getStr + if url.len > 0: + replacements.add ReplaceSlice( + kind: rkUrl, + slice: fromIdx ..< toIdx, + url: url, + display: $runes[fromIdx ..< min(toIdx, runes.len)] + ) + + replacements.sort(cmp) + result = runes.replacedWith(replacements, 0 ..< runes.len) + proc extractGalleryPhoto*(t: Tweet): GalleryPhoto = let url = if t.photos.len > 0: t.photos[0].url diff --git a/src/prefs_impl.nim b/src/prefs_impl.nim index 149eadf..047caef 100644 --- a/src/prefs_impl.nim +++ b/src/prefs_impl.nim @@ -78,6 +78,9 @@ genPrefs: hideReplies(checkbox, false): "Hide tweet replies" + hideCommunityNotes(checkbox, false): + "Hide community notes" + squareAvatars(checkbox, false): "Square profile pictures" diff --git a/src/sass/tweet/_base.scss b/src/sass/tweet/_base.scss index 28590e7..b9d64bc 100644 --- a/src/sass/tweet/_base.scss +++ b/src/sass/tweet/_base.scss @@ -254,3 +254,38 @@ pointer-events: all; } } + +.community-note { + background-color: var(--bg_elements); + margin-top: 10px; + border: solid 1px var(--dark_grey); + border-radius: 10px; + overflow: hidden; + pointer-events: all; + + &:hover { + background-color: var(--bg_panel); + border-color: var(--grey); + } +} + +.community-note-header { + background-color: var(--bg_hover); + font-weight: 700; + padding: 8px 10px; + padding-top: 6px; + display: flex; + align-items: center; + gap: 2px; + + .icon-container { + flex-shrink: 0; + color: var(--accent); + } +} + +.community-note-text { + white-space: pre-line; + padding: 10px 10px; + padding-top: 6px; +} diff --git a/src/sass/tweet/card.scss b/src/sass/tweet/card.scss index 5575191..7441d11 100644 --- a/src/sass/tweet/card.scss +++ b/src/sass/tweet/card.scss @@ -1,119 +1,119 @@ -@import '_variables'; -@import '_mixins'; +@import "_variables"; +@import "_mixins"; .card { - margin: 5px 0; - pointer-events: all; - max-height: unset; + margin: 5px 0; + pointer-events: all; + max-height: unset; } .card-container { - border-radius: 10px; - border-width: 1px; - border-style: solid; - border-color: var(--dark_grey); - background-color: var(--bg_elements); - overflow: hidden; - color: inherit; - display: flex; - flex-direction: row; - text-decoration: none !important; + border: solid 1px var(--dark_grey); + border-radius: 10px; + background-color: var(--bg_elements); + overflow: hidden; + color: inherit; + display: flex; + flex-direction: row; + text-decoration: none !important; - &:hover { - border-color: var(--grey); - } + &:hover { + border-color: var(--grey); + } - .attachments { - margin: 0; - border-radius: 0; - } + .attachments { + margin: 0; + border-radius: 0; + } } .card-content { - padding: 0.5em; + padding: 0.5em; } .card-title { - @include ellipsis; - white-space: unset; - font-weight: bold; - font-size: 1.1em; + @include ellipsis; + white-space: unset; + font-weight: bold; + font-size: 1.1em; } .card-description { - margin: 0.3em 0; - white-space: pre-wrap; + margin: 0.3em 0; + white-space: pre-wrap; } .card-destination { - @include ellipsis; - color: var(--grey); - display: block; + @include ellipsis; + color: var(--grey); + display: block; } .card-content-container { - color: unset; - overflow: auto; - &:hover { - text-decoration: none; - } + color: unset; + overflow: auto; + + &:hover { + text-decoration: none; + } } .card-image-container { - width: 98px; - flex-shrink: 0; - position: relative; - overflow: hidden; - &:before { - content: ""; - display: block; - padding-top: 100%; - } + width: 98px; + flex-shrink: 0; + position: relative; + overflow: hidden; + + &:before { + content: ""; + display: block; + padding-top: 100%; + } } .card-image { - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background-color: var(--bg_overlays); + position: absolute; + top: 0; + left: 0; + bottom: 0; + right: 0; + background-color: var(--bg_overlays); - img { - width: 100%; - height: 100%; - max-height: 400px; - display: block; - object-fit: cover; - } + img { + width: 100%; + height: 100%; + max-height: 400px; + display: block; + object-fit: cover; + } } .card-overlay { - @include play-button; - opacity: 0.8; - display: flex; - justify-content: center; - align-items: center; + @include play-button; + opacity: 0.8; + display: flex; + justify-content: center; + align-items: center; } .large { - .card-container { - display: block; - } + .card-container { + display: block; + } - .card-image-container { - width: unset; + .card-image-container { + width: unset; - &:before { - display: none; - } + &:before { + display: none; } + } - .card-image { - position: unset; - border-style: solid; - border-color: var(--dark_grey); - border-width: 0; - border-bottom-width: 1px; - } + .card-image { + position: unset; + border-style: solid; + border-color: var(--dark_grey); + border-width: 0; + border-bottom-width: 1px; + } } diff --git a/src/sass/tweet/quote.scss b/src/sass/tweet/quote.scss index 64d7e13..2f3122a 100644 --- a/src/sass/tweet/quote.scss +++ b/src/sass/tweet/quote.scss @@ -19,31 +19,49 @@ } .tweet-name-row { - padding: 6px 8px; - margin-top: 1px; + padding: 8px 10px 6px 10px; } .quote-text { overflow: hidden; white-space: pre-wrap; word-wrap: break-word; - padding: 0px 8px 8px 8px; + padding: 10px; + padding-top: 0; } .show-thread { - padding: 0px 8px 6px 8px; + padding: 0px 10px 6px 10px; margin-top: -6px; } .quote-latest { - padding: 0px 8px 6px 8px; + padding: 0px 10px 6px 10px; color: var(--grey); } .replying-to { - padding: 0px 8px; + padding: 0px 10px; + padding-bottom: 4px; margin: unset; } + + .community-note { + background-color: var(--bg_panel); + border: unset; + border-top: solid 1px var(--dark_grey); + border-radius: unset; + margin-top: 0; + + &:hover { + border-top-color: var(--grey); + } + + .community-note-header { + background-color: var(--bg_panel); + padding-bottom: 0; + } + } } .unavailable-quote { diff --git a/src/types.nim b/src/types.nim index 996f572..56bc2b2 100644 --- a/src/types.nim +++ b/src/types.nim @@ -223,6 +223,7 @@ type video*: Option[Video] photos*: seq[Photo] history*: seq[int64] + note*: string Tweets* = seq[Tweet] diff --git a/src/views/general.nim b/src/views/general.nim index d002777..ac087c1 100644 --- a/src/views/general.nim +++ b/src/views/general.nim @@ -50,7 +50,7 @@ proc renderHead*(prefs: Prefs; cfg: Config; req: Request; titleText=""; desc=""; let opensearchUrl = getUrlPrefix(cfg) & "/opensearch" buildHtml(head): - link(rel="stylesheet", type="text/css", href="/css/style.css?v=27") + link(rel="stylesheet", type="text/css", href="/css/style.css?v=28") link(rel="stylesheet", type="text/css", href="/css/fontello.css?v=4") if theme.len > 0: diff --git a/src/views/tweet.nim b/src/views/tweet.nim index f79c571..b0578c1 100644 --- a/src/views/tweet.nim +++ b/src/views/tweet.nim @@ -226,6 +226,14 @@ proc renderQuoteMedia(quote: Tweet; prefs: Prefs; path: string): VNode = elif quote.gif.isSome: renderGif(quote.gif.get(), prefs) +proc renderCommunityNote(note: string; prefs: Prefs): VNode = + buildHtml(tdiv(class="community-note")): + tdiv(class="community-note-header"): + icon "group" + span: text "Community note" + tdiv(class="community-note-text", dir="auto"): + verbatim replaceUrls(note, prefs) + proc renderQuote(quote: Tweet; prefs: Prefs; path: string): VNode = if not quote.available: return buildHtml(tdiv(class="quote unavailable")): @@ -261,6 +269,9 @@ proc renderQuote(quote: Tweet; prefs: Prefs; path: string): VNode = if quote.photos.len > 0 or quote.video.isSome or quote.gif.isSome: renderQuoteMedia(quote, prefs, path) + if quote.note.len > 0 and not prefs.hideCommunityNotes: + renderCommunityNote(quote.note, prefs) + if quote.hasThread: a(class="show-thread", href=getLink(quote)): text "Show this thread" @@ -346,6 +357,9 @@ proc renderTweet*(tweet: Tweet; prefs: Prefs; path: string; class=""; index=0; if tweet.quote.isSome: renderQuote(tweet.quote.get(), prefs, path) + if tweet.note.len > 0 and not prefs.hideCommunityNotes: + renderCommunityNote(tweet.note, prefs) + let hasEdits = tweet.history.len > 1 isLatest = hasEdits and tweet.id == max(tweet.history)