Skip to content

fix(mobile): preserve attachment filenames when opening files - #8066

Open
wenhaoone wants to merge 1 commit into
block:mainfrom
wenhaoone:codex/mobile-attachment-filename
Open

wenhaoone wants to merge 1 commit into
block:mainfrom
wenhaoone:codex/mobile-attachment-filename

Conversation

@wenhaoone

@wenhaoone wenhaoone commented Oct 3, 2026 •

Copy link
Copy Markdown

Summary

When an attachment has a descriptive link label, mobile opens the downloaded file under that label and loses its original name and extension. For example, [Quarterly report](...) opens as Quarterly report even when its imeta tag names q3-report.pdf.

Use the matching imeta filename when opening the attachment, falling back to the link text when it is absent. The existing filename sanitization still applies.

Related issue

Fixes #8065.

Closest related work: #7581 handles filename metadata on CLI uploads. No duplicate mobile filename fix found.

Testing

  • The new filename regression fails on the original code: expected q3-report.pdf, got Quarterly report.
  • message_content_test.dart: 88 passed, including filename precedence, missing filename, and metadata for a different attachment.
  • Unconfigured-push tests: 3 passed.
  • flutter analyze --no-pub, Dart format (615 files), mobile file-size check, gateway recipe checks, and git diff --check passed.
  • Android 14 emulator: both links downloaded and opened in a PDF reader, preserving the metadata filename and the missing-filename fallback. This used a local fixture with the real MessageContent, signed download, temporary file write, and OpenFilex; a live community was not tested.
  • Full mobile suite on Windows with Flutter 3.41.7 and the committed dependency versions: 2,621 passed, 5 skipped, 9 failed. Details below; this was not a green full-suite run.
Full-suite failures and baseline comparison

These two failures also reproduce on the unmodified base, 33f54de:

  • ComposeBar records, previews, uploads, and sends a voice note
  • ComposeBar voice note rejects an existing attachment like desktop

The following seven passed in targeted reruns on both the unmodified base and this branch:

  • retries failed startup and closes fetch-subscribe gap
  • ack replies obey payload bounds without reopening threads
  • 600 live replies coalesce into one exact recount before reopen
  • reconnect supersedes an in-flight overflow recount and resumes it
  • continued replies do not restart an active paginated recount
  • permanent first channel chunk failure exhausts retries and stops export
  • native retry budget is shared across all chunks

The extra file-size policy suite had 9 passes and one Windows symlink-permission failure (surface entrypoints execute through symlinked paths).

The author repeated both device tests and confirmed the results. Agent review found no blockers. There is no rendering change.

buzz-review-completed

@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

🔐 Codex Security Review

Status: review required for the current range.

The current range is 6cf45820025721367c9f174aae164c8cf9a52a19...63218ea146cd9becfd43aadbe4b788d28ff639d4.
A new review must complete for this exact range. When manual authorization
is required, a user with write access must comment exactly
@buzz-security-review 63218ea146cd9becfd43aadbe4b788d28ff639d4 to authorize a new review.
Any previous review applies only to its recorded range.

@wenhaoone
wenhaoone marked this pull request as ready for review October 3, 2026 17:25
@wenhaoone
wenhaoone requested a review from a team as a code owner October 3, 2026 17:25

@loganj loganj left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Larry and Auto: an independent adversarial review of 63218ea146cd. Source review only; we did not run it. Mobile CI has not run on this fork PR.

Approving. #8086 makes the same one-line change, and only one of the two can merge. We recommend landing this one: it was opened first, and its three tests (filename present, filename absent, and an imeta for a different URL) cover #8086's single test.

The filename is untrusted remote input, but it is safe here: _safeDownloadedFilename keeps only the last path segment, removes control characters and adds a timestamp prefix, so neither ../x nor .. can leave the temp directory. Audio links still return through _buildMedia before this branch.

url,
auth.headersFor(url),
text,
imeta?.filename ?? text,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Advice: an empty filename discards the label. ImetaEntry keeps a tag part filename (key, space, no value) as ''. Then '' ?? text is '', and _safeDownloadedFilename turns it into attachment, with no extension. Suggest:

final name = imeta?.filename?.trim();
// ...
(name == null || name.isEmpty) ? text : name,

Advice (follow-up is fine; this was already there before this PR): with no imeta filename, [Quarterly report](https://relay/media/<sha>.pdf) still opens as Quarterly report, with no extension. That is the #8065 symptom. Falling back to the URL's last path segment before the label, or passing imeta?.mimeType to OpenFilex.open(type:), would cover it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Mobile: opening an attachment names the file after the link text instead of the imeta filename

2 participants