fix: glassmorphism sidebar background visibility + image upload cleanup
Glassmorphism: the sidebar is a flex sibling of the room view, so
backdrop-filter had nothing behind it to blur. Fix: apply the active
chat background to document.body when glassmorphismSidebar is on
(cleaned up when it's turned off or the component unmounts). Now the
sidebar blurs through the same background pattern as the room view,
making the frosted-glass effect obvious.
Image upload cleanup: delete the pre-uploaded original MXC from the
homeserver after the compressed version is successfully uploaded
(Synapse 1.97+ DELETE /_matrix/client/v1/media/{server}/{mediaId}).
Also delete on cancel when a successful upload is removed by the user.
Both are best-effort — failures are swallowed so UX is unaffected.
Added tryDeleteMxcContent() utility to src/app/utils/matrix.ts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
import { useObjectURL } from '../../hooks/useObjectURL';
|
||||
import { useMediaConfig } from '../../hooks/useMediaConfig';
|
||||
import { compressImage, formatFileSize, isCompressible } from '../../utils/imageCompression';
|
||||
import { tryDeleteMxcContent } from '../../utils/matrix';
|
||||
|
||||
type PreviewImageProps = {
|
||||
fileItem: TUploadItem;
|
||||
@@ -274,6 +275,10 @@ export function UploadCardRenderer({
|
||||
};
|
||||
|
||||
const removeUpload = () => {
|
||||
if (upload.status === UploadStatus.Success) {
|
||||
// Upload already completed — delete the orphaned MXC from the server.
|
||||
tryDeleteMxcContent(mx, upload.mxc);
|
||||
}
|
||||
cancelUpload();
|
||||
onRemove(file);
|
||||
};
|
||||
|
||||
@@ -65,6 +65,7 @@ import {
|
||||
getImageInfo,
|
||||
getMxIdLocalPart,
|
||||
mxcUrlToHttp,
|
||||
tryDeleteMxcContent,
|
||||
} from '../../utils/matrix';
|
||||
import { compressImage } from '../../utils/imageCompression';
|
||||
import { useTypingStatusUpdater } from '../../hooks/useTypingStatusUpdater';
|
||||
@@ -434,6 +435,8 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
|
||||
});
|
||||
const compressedMxc = (uploadRes as { content_uri: string }).content_uri;
|
||||
if (compressedMxc) {
|
||||
// Delete the pre-uploaded original so only one copy lives on the server.
|
||||
tryDeleteMxcContent(mx, upload.mxc);
|
||||
mxc = compressedMxc;
|
||||
// Build a synthetic fileItem that refers to the compressed file so
|
||||
// getImageMsgContent picks up the correct dimensions and type.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useRef } from 'react';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { Scroll } from 'folds';
|
||||
import classNames from 'classnames';
|
||||
|
||||
@@ -23,10 +23,42 @@ import {
|
||||
import { CreateTab } from './sidebar/CreateTab';
|
||||
import { useSetting } from '../../state/hooks/settings';
|
||||
import { settingsAtom } from '../../state/settings';
|
||||
import { useTheme, ThemeKind } from '../../hooks/useTheme';
|
||||
import { getChatBg } from '../../features/lotus/chatBackground';
|
||||
|
||||
export function SidebarNav() {
|
||||
const scrollRef = useRef<HTMLDivElement>(null) as React.RefObject<HTMLDivElement>;
|
||||
const [glassmorphismSidebar] = useSetting(settingsAtom, 'glassmorphismSidebar');
|
||||
const [chatBackground] = useSetting(settingsAtom, 'chatBackground');
|
||||
const [lotusTerminal] = useSetting(settingsAtom, 'lotusTerminal');
|
||||
const theme = useTheme();
|
||||
const isDark = theme.kind === ThemeKind.Dark;
|
||||
|
||||
// backdrop-filter only blurs content directly behind the element in the z-axis.
|
||||
// The sidebar is a flex sibling of the room view, so nothing sits behind it by default.
|
||||
// Fix: mirror the active chat background onto document.body so the sidebar blurs through it.
|
||||
useEffect(() => {
|
||||
const { style } = document.body;
|
||||
if (!glassmorphismSidebar) {
|
||||
style.removeProperty('background-image');
|
||||
style.removeProperty('background-color');
|
||||
style.removeProperty('background-size');
|
||||
style.removeProperty('background-position');
|
||||
return;
|
||||
}
|
||||
const effectiveBg = lotusTerminal && chatBackground === 'none' ? 'tactical' : chatBackground;
|
||||
const bgStyle = getChatBg(effectiveBg, isDark);
|
||||
style.backgroundImage = (bgStyle.backgroundImage as string | undefined) ?? '';
|
||||
style.backgroundColor = (bgStyle.backgroundColor as string | undefined) ?? '';
|
||||
style.backgroundSize = (bgStyle.backgroundSize as string | undefined) ?? '';
|
||||
style.backgroundPosition = (bgStyle.backgroundPosition as string | undefined) ?? '';
|
||||
return () => {
|
||||
style.removeProperty('background-image');
|
||||
style.removeProperty('background-color');
|
||||
style.removeProperty('background-size');
|
||||
style.removeProperty('background-position');
|
||||
};
|
||||
}, [glassmorphismSidebar, chatBackground, lotusTerminal, isDark]);
|
||||
|
||||
return (
|
||||
<Sidebar className={classNames(glassmorphismSidebar && SidebarGlass)}>
|
||||
|
||||
@@ -401,3 +401,20 @@ export const creatorsSupported = (version: string): boolean => {
|
||||
const unsupportedVersion = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11'];
|
||||
return !unsupportedVersion.includes(version);
|
||||
};
|
||||
|
||||
// Best-effort deletion of a user-owned MXC URI from the homeserver.
|
||||
// Synapse 1.97+ supports DELETE /_matrix/client/v1/media/{server}/{mediaId} for media owners.
|
||||
// Failures are silently ignored — this is cleanup only, not critical path.
|
||||
export const tryDeleteMxcContent = async (mx: MatrixClient, mxcUrl: string): Promise<void> => {
|
||||
try {
|
||||
const path = mxcUrl.replace('mxc://', '');
|
||||
const token = mx.getAccessToken();
|
||||
if (!token || !path.includes('/')) return;
|
||||
await fetch(`${mx.getHomeserverUrl()}/_matrix/client/v1/media/${path}`, {
|
||||
method: 'DELETE',
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
} catch {
|
||||
// Intentionally swallowed
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user