deltalab-android icon indicating copy to clipboard operation
deltalab-android copied to clipboard

Add link preview cards for URLs in messages

Open Copilot opened this issue 2 months ago • 0 comments

Implements rich link previews for HTTP/HTTPS URLs shared in messages. Extracts Open Graph metadata (title, description, image) with HTML fallbacks and displays in Material card below message text.

Implementation

Core components:

  • LinkPreviewFetcher - Fetches metadata via HTTP with SOCKS5 proxy support from Delta Chat config
  • LinkPreviewCache - Thread-safe LRU cache (100 entries) to avoid redundant fetches
  • LinkPreviewExecutor - Fixed thread pool (2 threads) for async fetching
  • LinkPreviewView - MaterialCardView component displaying title/description/image/domain
  • LinkPreviewUtil - Regex-based URL extraction from message text

Integration:

  • ConversationItem.setLinkPreview() - Checks cache, spawns async fetch if needed, updates UI on main thread
  • ViewStub pattern in conversation layouts (sent/received) for lazy initialization
  • Visibility management ensures preview hidden when other media types shown

Settings:

  • Privacy preference pref_link_previews (default: enabled)
  • Located in Settings → Privacy → Link Previews

Technical details

  • Only processes text messages containing HTTP/HTTPS URLs (first URL used)
  • Parses og:title, og:description, og:image with fallback to <title> and <meta name="description">
  • 500KB HTML size limit, 10s connect/read timeouts
  • Image URLs converted from relative to absolute
  • Caches failed fetches to prevent retry storms

Example flow:

// In ConversationItem.bind()
if (Prefs.areLinkPreviewsEnabled(context)) {
  String url = LinkPreviewUtil.extractFirstUrl(messageText);
  LinkPreview cached = LinkPreviewCache.getInstance().get(url);
  if (cached == null) {
    LinkPreviewExecutor.getInstance().execute(() -> {
      LinkPreview preview = new LinkPreviewFetcher(context).fetchPreview(url);
      LinkPreviewCache.getInstance().put(url, preview);
      post(() -> linkPreviewStub.get().bind(preview, glideRequests));
    });
  }
}

No new dependencies. Uses existing Glide for image loading and Material Design components.

[!WARNING]

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dl.google.com
    • Triggering command: /usr/lib/jvm/temurin-17-jdk-amd64/bin/java /usr/lib/jvm/temurin-17-jdk-amd64/bin/java --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.prefs/java.util.prefs=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.xml/javax.xml.namespace=ALL-UNNAMED -Xmx4608m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /home/REDACTED/.gradle/wrapper/dists/gradle-8.13-bin/5xuhj0ry160q40clulazy9h7d/gradle-8.13/lib/gradle-daemon-main-8.13.jar (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Link previews</issue_title> <issue_description>### Describe your feature: Link previews (link cards) like in telegram and other messengers Example Screenshot 2024-09-20 at 16 18 00

Why do you think it is useful:

It helps to search for relevant content</issue_description>

Comments on the Issue (you are @copilot in this section)

@adbenitez some notes:
  • it should be possible to disable this feature for privacy reasons
  • the fetching of the preview should respect the proxy settings in the app</comment_new>
  • Fixes ArcaneChat/android#30

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot avatar Dec 15 '25 15:12 Copilot