Improve pasted image filenames

This commit is contained in:
trevor-signal
2025-05-19 17:23:22 -04:00
committed by GitHub
parent 33c1c39da4
commit efa9102a1b
2 changed files with 53 additions and 5 deletions

View File

@@ -4,6 +4,8 @@
import React from 'react';
import classNames from 'classnames';
import { useEscapeHandling } from '../../hooks/useEscapeHandling';
import { getSuggestedFilename } from '../../types/Attachment';
import { IMAGE_PNG, type MIMEType } from '../../types/MIME';
export type PropsType = {
conversationId: string;
@@ -23,6 +25,37 @@ export type PropsType = {
shouldHideConversationView?: boolean;
};
// https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/clipboard/data_object_item.cc;l=184;drc=1d545578bf3756af94e89f274544c6017267f885
const DEFAULT_CHROMIUM_IMAGE_FILENAME = 'image.png';
function getAsFile(item: DataTransferItem): File | null {
const file = item.getAsFile();
if (!file) {
return null;
}
if (
file.type === IMAGE_PNG &&
file.name === DEFAULT_CHROMIUM_IMAGE_FILENAME
) {
return new File(
[file.slice(0, file.size, file.type)],
getSuggestedFilename({
attachment: {
contentType: file.type as MIMEType,
},
timestamp: Date.now(),
scenario: 'sending',
}),
{
type: file.type,
lastModified: file.lastModified,
}
);
}
return file;
}
export function ConversationView({
conversationId,
hasOpenModal,
@@ -82,7 +115,7 @@ export function ConversationView({
if (allVisual) {
const files: Array<File> = [];
for (let i = 0; i < items.length; i += 1) {
const file = items[i].getAsFile();
const file = getAsFile(items[i]);
if (file) {
files.push(file);
}
@@ -100,7 +133,7 @@ export function ConversationView({
return;
}
const firstAttachment = fileItems[0]?.getAsFile();
const firstAttachment = fileItems[0] ? getAsFile(fileItems[0]) : null;
if (firstAttachment) {
processAttachments({
conversationId,

View File

@@ -37,6 +37,7 @@ import { getMessageQueueTime } from '../util/getMessageQueueTime';
import { getLocalAttachmentUrl } from '../util/getLocalAttachmentUrl';
import type { ReencryptionInfo } from '../AttachmentCrypto';
import { redactGenericText } from '../util/privacy';
import { missingCaseError } from '../util/missingCaseError';
const MAX_WIDTH = 300;
const MAX_HEIGHT = MAX_WIDTH * 1.5;
@@ -1100,17 +1101,31 @@ export const getSuggestedFilename = ({
attachment,
timestamp,
index,
scenario = 'saving-locally',
}: {
attachment: AttachmentType;
attachment: Pick<AttachmentType, 'fileName' | 'contentType'>;
timestamp?: number | Date;
index?: number;
scenario?: 'sending' | 'saving-locally';
}): string => {
const { fileName } = attachment;
if (fileName) {
return fileName;
}
const prefix = 'signal';
let prefix: string;
switch (scenario) {
case 'sending':
// when sending, we prefer a generic 'signal-less' name
prefix = 'image';
break;
case 'saving-locally':
prefix = 'signal';
break;
default:
throw missingCaseError(scenario);
}
const suffix = timestamp
? moment(timestamp).format('-YYYY-MM-DD-HHmmss')
: '';
@@ -1125,7 +1140,7 @@ export const getSuggestedFilename = ({
};
export const getFileExtension = (
attachment: AttachmentType
attachment: Pick<AttachmentType, 'contentType'>
): string | undefined => {
if (!attachment.contentType) {
return undefined;