Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions desktop/src/features/messages/lib/imetaMediaMarkdown.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,22 @@ test("buildImetaTags keeps media filenames in imeta", () => {
);
});

test("buildImetaTags names a video poster by hash", () => {
const poster = "c".repeat(64);
const [tag] = buildImetaTags([
{
url: `https://b/media/${"a".repeat(64)}.mp4`,
type: "video/mp4",
sha256: "a".repeat(64),
size: 10,
uploaded: 1,
image: `https://b/media/${poster}.jpg`,
},
]);
assert.ok(tag.includes(`image https://b/media/${poster}.jpg`));
assert.ok(tag.includes(`image-x ${poster}`));
});

test("formatImetaMediaLine: video mime → ![video] line (regardless of URL suffix)", () => {
assert.equal(
formatImetaMediaLine({ url: "https://cdn/blob/xyz", type: "video/mp4" }),
Expand Down
9 changes: 9 additions & 0 deletions desktop/src/features/messages/lib/imetaMediaMarkdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,19 @@ export function buildImetaTags(
...(d.thumb ? [`thumb ${d.thumb}`] : []),
...(d.duration != null ? [`duration ${d.duration}`] : []),
...(d.image ? [`image ${d.image}`] : []),
...posterHashEntry(d.image),
...(d.filename ? [`filename ${d.filename}`] : []),
]);
}

const MEDIA_HASH_RE = /\/media\/([0-9a-f]{64})\./;

/** `image-x <sha256>` names the poster by hash so the relay can scope its reads. */
function posterHashEntry(image: string | undefined): string[] {
const hash = image?.match(MEDIA_HASH_RE)?.[1];
return hash ? [`image-x ${hash}`] : [];
}

const MEDIA_LINE_RE =
/^(?:\|\|)?!\[(?:image|video)\]\(([^)\s]+)\)(?:\|\|)?\s*$/;
const SPOILERED_MEDIA_LINE_RE =
Expand Down
5 changes: 5 additions & 0 deletions mobile/lib/shared/relay/media_upload.dart
Original file line number Diff line number Diff line change
Expand Up @@ -218,9 +218,14 @@ class BlobDescriptor {
if (thumb != null) 'thumb $thumb',
if (duration != null) 'duration $duration',
if (image != null) 'image $image',
if (_posterHash case final hash?) 'image-x $hash',
if (filename != null) 'filename $filename',
];

/// Names the poster by hash so the relay can scope who may read it.
String? get _posterHash =>
RegExp(r'/media/([0-9a-f]{64})\.').firstMatch(image ?? '')?.group(1);

String toMarkdownImage() {
final label = (filename ?? 'file').replaceAllMapped(
RegExp(r'[\\\[\]]'),
Expand Down
16 changes: 16 additions & 0 deletions mobile/test/shared/relay/media_upload_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,22 @@ void main() {
});
});

group('toImetaTag', () {
test('names a video poster by hash', () {
final poster = 'c' * 64;
final descriptor = BlobDescriptor(
url: 'https://relay.example/media/${'a' * 64}.mp4',
sha256: 'a' * 64,
size: 3,
type: 'video/mp4',
uploaded: 1,
image: 'https://relay.example/media/$poster.jpg',
);

expect(descriptor.toImetaTag(), contains('image-x $poster'));
});
});

group('uploadVoiceNote', () {
test('keeps ordinary audio attachments on inline audio markdown', () {
const descriptor = BlobDescriptor(
Expand Down
Loading