CI / Build & Quality Checks (pull_request) Successful in 3m25s
CI / Trigger Desktop Build (pull_request) Skipped
CI / Docker image build & smoke test (pull_request) Skipped
CI / Secret scan (gitleaks) (pull_request) Successful in 8s
CI / Playwright smoke (e2e) (pull_request) Successful in 15m42s
Custom emoji and sticker images, pack avatars and power-level badge images were uploaded with their EXIF intact (GPS location, timestamp), although they are published to every member of the room or space. Route those three pickers through a new useStrippedFilePicker, which applies the same stripImageMetadata as attachments and avatars. Fixes #332 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017PCb59uY3UKqDqt7B6hzd5
37 lines
1.4 KiB
TypeScript
37 lines
1.4 KiB
TypeScript
import { useCallback } from 'react';
|
|
import { useFilePicker } from './useFilePicker';
|
|
import { useSetting } from '../state/hooks/settings';
|
|
import { settingsAtom } from '../state/settings';
|
|
import { stripImageMetadata } from '../utils/stripImageMetadata';
|
|
|
|
/**
|
|
* [Gitea #332] `useFilePicker` for images that get published (emoji / sticker
|
|
* packs, pack avatars, power-level badges): applies "Remove Photo Metadata"
|
|
* like message attachments and avatars, so a phone photo's GPS location and
|
|
* timestamp don't go to every member of the room or space.
|
|
*/
|
|
export const useStrippedFilePicker = <M extends boolean | undefined = undefined>(
|
|
onSelect: (file: M extends true ? File[] : File) => void,
|
|
multiple?: M,
|
|
) => {
|
|
const [strip] = useSetting(settingsAtom, 'stripImageMetadata');
|
|
const handle = useCallback(
|
|
(picked: File | File[]) => {
|
|
if (!strip) {
|
|
onSelect(picked as M extends true ? File[] : File);
|
|
return;
|
|
}
|
|
const clean = (f: File) => stripImageMetadata(f).then((r) => r.file);
|
|
if (Array.isArray(picked)) {
|
|
Promise.all(picked.map(clean)).then((files) =>
|
|
onSelect(files as M extends true ? File[] : File),
|
|
);
|
|
} else {
|
|
clean(picked).then((file) => onSelect(file as M extends true ? File[] : File));
|
|
}
|
|
},
|
|
[strip, onSelect],
|
|
);
|
|
return useFilePicker(handle as (file: M extends true ? File[] : File) => void, multiple);
|
|
};
|