Fix authenticated media loading for Tauri/WebKit environments
- Add useAuthenticatedMediaUrl hook that fetches media with auth headers - Add AuthenticatedMedia, AuthenticatedAvatarImage components - Update downloadMedia and downloadEncryptedMedia to accept access token - Update all media components to pass access token for auth media - Fix 401 errors on Matrix servers requiring authenticated media (v1.11+) This fixes media loading in Tauri desktop apps where service workers may not work reliably for cross-origin authenticated requests.
This commit is contained in:
@@ -296,18 +296,39 @@ export const mxcUrlToHttp = (
|
||||
useAuthentication
|
||||
);
|
||||
|
||||
export const downloadMedia = async (src: string): Promise<Blob> => {
|
||||
// this request is authenticated by service worker
|
||||
const res = await fetch(src, { method: 'GET' });
|
||||
/**
|
||||
* Check if a URL is an authenticated media endpoint.
|
||||
*/
|
||||
export const isAuthenticatedMediaUrl = (url: string): boolean =>
|
||||
url.includes('/_matrix/client/v1/media/download') ||
|
||||
url.includes('/_matrix/client/v1/media/thumbnail');
|
||||
|
||||
/**
|
||||
* Downloads media with optional authentication.
|
||||
* For authenticated media URLs, the access token is required.
|
||||
*/
|
||||
export const downloadMedia = async (src: string, accessToken?: string | null): Promise<Blob> => {
|
||||
const needsAuth = isAuthenticatedMediaUrl(src);
|
||||
const headers: HeadersInit = {};
|
||||
|
||||
if (needsAuth && accessToken) {
|
||||
headers.Authorization = `Bearer ${accessToken}`;
|
||||
}
|
||||
|
||||
const res = await fetch(src, { method: 'GET', headers });
|
||||
if (!res.ok) {
|
||||
throw new Error(`Failed to download media: ${res.status}`);
|
||||
}
|
||||
const blob = await res.blob();
|
||||
return blob;
|
||||
};
|
||||
|
||||
export const downloadEncryptedMedia = async (
|
||||
src: string,
|
||||
decryptContent: (buf: ArrayBuffer) => Promise<Blob>
|
||||
decryptContent: (buf: ArrayBuffer) => Promise<Blob>,
|
||||
accessToken?: string | null
|
||||
): Promise<Blob> => {
|
||||
const encryptedContent = await downloadMedia(src);
|
||||
const encryptedContent = await downloadMedia(src, accessToken);
|
||||
const decryptedContent = await decryptContent(await encryptedContent.arrayBuffer());
|
||||
|
||||
return decryptedContent;
|
||||
|
||||
Reference in New Issue
Block a user