Skip to content

Files as attachments - #2179

Merged
karlitschek merged 2 commits into
masterfrom
feat/file-attachments
Sep 14, 2026
Merged

karlitschek merged 2 commits into
masterfrom
feat/file-attachments

Conversation

@karlitschek

Copy link
Copy Markdown
Member

Item 12 of the fresh look: the "no document or file attachments" entry in the README — on a Nextcloud, of all places, where the file people want to share is the one thing already there.

What changes

  • Allowlist (CacheDocumentService::DOCUMENT_MIME_TYPES): PDF, plain text, Markdown, CSV, ZIP, EPUB, the ODF and Office document formats. Nothing a browser would run — HTML, SVG and scripts stay refused (tests pin .exe, JavaScript and a web page). The picture ceiling (max_size, 10 MB) applies; a file is stored as it is and served as a download. supported_mime_types on /api/v1/instance lists them, since it is asked of the same allowlist.
  • Client entity: a file is Mastodon's type: "unknown", with no preview_url — the file used to be handed back as its own preview, which had a client try to draw a PDF. Uploaded without a description, it is named after itself (both POST /media and the Files-picker route pass the name through); a picture with no alt text stays undescribed, which is a fact worth keeping.
  • Wire: an ActivityPub Document with its mime (that is Serve a stored post's attachments as Documents, with their mime #2172's media_type doing its job); Mastodon shows it as a link, another Nextcloud as a file. Remote files of these kinds are now cached rather than dropped.
  • Composer accepts them in the file dialog (mimes plus extensions, for browsers that report no type), in the Files picker (now "Pick files to attach"), and in a drop or paste.
  • Rendering: MediaAttachment shows a file as a named download card (icon, name, kind); PostAttachment lists files under the pictures and keeps them out of the mosaic, the carousel and the viewer — a post that is only a file shows the file, not an empty gallery.

Verification

  • PHP: allowlist providers extended both ways, isDocumentMime(), a PDF converts to unknown without a preview and keeps its name, the extension guess knows the new kinds, the Files-picker route names the file. Full suite green (4631), psalm no errors, php-cs-fixer clean.
  • JS: the file card (name from description or from the address, kind from the extension, no spinner, no "failed" placeholder), files listed under pictures and never tiled, only-a-file posts, the composer's picker filter, and the drop/paste refusal tests moved to a kind that is still refused. vitest 1540 passed; eslint/stylelint/typecheck clean; bundle rebuilt.
  • README and docs/API.md updated. Version 0.19.43.

🤖 Generated with Claude Code

@karlitschek
karlitschek force-pushed the feat/file-attachments branch 5 times, most recently from 735a90f to d1f6339 Compare September 14, 2026 09:26
Frank Karlitschek and others added 2 commits September 14, 2026 11:56
A post could carry pictures, video and audio and nothing else -- on a
Nextcloud, where the file people want to share is the one thing that is
already there. The allowlist gains the document kinds people actually
share (PDF, plain text, Markdown, CSV, ZIP, EPUB, ODF and Office), and
nothing a browser would run: no HTML, SVG or scripts. The picture ceiling
(max_size) applies; a file is stored as it is, served as a download.

On the client entity a file is Mastodon's `unknown` type with no preview
of itself (the file used to be handed back as its own preview, which had
a client try to draw a PDF), and when it was uploaded without a
description it is named after itself -- the one field the entity has for
saying what a file is. On the wire it is an ActivityPub Document with its
mime, which Mastodon renders as a link and another Nextcloud as a file.

The composer accepts, picks (the Files picker now offers them too) and
takes dropped files of these kinds; a post shows a file as a named
download card under its pictures, never in the mosaic or the viewer.

Signed-off-by: Frank Karlitschek <frank@nextcloud.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: Frank Karlitschek <frank@nextcloud.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@karlitschek
karlitschek merged commit c0baad6 into master Sep 14, 2026
43 checks passed
@karlitschek
karlitschek deleted the feat/file-attachments branch September 14, 2026 11:05
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.

1 participant