DimensionDev / DimensionDev/Flare

Images embedded mid-text (not at line end) are not rendered on Nostr posts

Open
#2,427 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
1.5k
Forks
67
Avg merge
11h 8m
Merged PRs (30d)
84

Description

Description

On Nostr timelines, some posts with an image or video URL don't render any media at all — the URL just shows up as a plain text link. This happens specifically when the publisher puts the media URL in the middle of a line or paragraph, rather than as the last token on its own trailing line.

I'm a Flare user browsing mixed Nostr timelines daily and ran into this often enough to dig into why.

Steps to reproduce

Post text like this (no imeta or r tags, just inline content):

check this out https://example.com/photo.jpg it's great

Expected: the image renders as a media attachment on the post.
Actual: the URL renders as a plain clickable text link; no image card appears.

Root cause

In social/nostr/src/commonMain/kotlin/dev/dimension/flare/data/network/nostr/NostrRichTextParser.kt, the function that pulls untagged media URLs out of the post body (extractTrailingMediaUrls) only checks the last whitespace-separated token of the last non-blank line. Any media URL that appears earlier in the text — mid-sentence, or on a line that isn't the final one — is never extracted, so it's never added to the post's image list. It still gets treated as a normal link elsewhere in the parser, which is why the URL is visible as text but the image itself is missing.

Suggested fix

I've written a fix that generalizes the extraction to scan every token on every line, not just the trailing one, and removes matched tokens from the display text the same way the original trailing-only version did. It's a net simplification — two now-unused helper functions (lastWhitespaceSeparatedTokenOrNull, removeTrailingToken) go away since the new version doesn't need them.

I also added two new unit tests alongside the existing ones in NostrRichTextParserTest.kt:

  • a media URL embedded mid-sentence
  • multiple media URLs spread across different lines

All existing tests should still pass under the new logic — I traced the logic by hand against each one and they hold up, but I haven't been able to run ./gradlew test or ktlintFormat in my own setup. I'd rather flag that plainly than claim it's verified: if a maintainer or another contributor can run the test suite and lint against this patch, that'd be a big help before it's considered mergeable.

Patch attached: [nostr-mid-text-media-url-fix.patch](https://www.swisstransfer.com/d/25b5dd3c-c760-40ca-a55d-21047a3d71bf)

Happy to open this as a PR directly if that's preferred, though I should mention I'm not set up to run the local build/test suite myself right now — I can share the diff and reasoning, but would rely on a maintainer or another contributor to actually run and verify it. Let me know if that works or if you'd rather I hold off on a PR until I can test properly.

One open question for maintainers: this fix will now also pull out media-looking URLs (e.g. ending in .jpg) from anywhere in the text, including cases where a publisher intended it as a plain link rather than an attachment. I don't see an easy way to distinguish "meant as embedded media" from "meant as a link that happens to point to an image" without an explicit tag (like imeta) — curious if this tradeoff seems right to you, or if there's a pattern in the codebase I'm missing for that distinction.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in social/nostr/src/commonMain/kotlin/dev/dimension/flare/data/network/nostr/NostrRichTextParser.kt, inspect extractTrailingMediaUrls and its existing helpers, then review NostrRichTextParserTest.kt. Run ./gradlew test and ktlintFormat; done means inline and multi-line media URLs are covered without breaking existing tests, with the intended plain-link behavior resolved.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
content, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.