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:
2026-01-23 22:31:37 +11:00
parent 94f8466d1c
commit 54f5fa95a6
19 changed files with 330 additions and 38 deletions

View File

@@ -7,7 +7,6 @@ import {
Icons,
IconButton,
Avatar,
AvatarImage,
AvatarFallback,
config,
Spinner,
@@ -31,6 +30,7 @@ import { SettingTile } from '../../../components/setting-tile';
import { mxcUrlToHttp } from '../../../utils/matrix';
import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { AuthenticatedAvatarImage } from '../../../components/authenticated-media';
import {
EmoteRoomsContent,
ImagePack,
@@ -190,7 +190,7 @@ function GlobalPackSelector({
<Box alignItems="Center" gap="300">
<Avatar size="300" radii="300">
{avatarUrl ? (
<AvatarImage style={{ objectFit: 'contain' }} src={avatarUrl} />
<AuthenticatedAvatarImage style={{ objectFit: 'contain' }} src={avatarUrl} />
) : (
<AvatarFallback>
<Icon size="400" src={Icons.Sticker} filled />
@@ -389,7 +389,7 @@ export function GlobalPacks({ onViewPack }: GlobalPacksProps) {
)}
<Avatar size="300" radii="300">
{avatarUrl ? (
<AvatarImage style={{ objectFit: 'contain' }} src={avatarUrl} />
<AuthenticatedAvatarImage style={{ objectFit: 'contain' }} src={avatarUrl} />
) : (
<AvatarFallback>
<Icon size="400" src={Icons.Sticker} filled />

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Avatar, AvatarFallback, AvatarImage, Box, Button, Icon, Icons, Text } from 'folds';
import { Avatar, AvatarFallback, Box, Button, Icon, Icons, Text } from 'folds';
import { useUserImagePack } from '../../../hooks/useImagePacks';
import { SequenceCard } from '../../../components/sequence-card';
import { SequenceCardStyle } from '../styles.css';
@@ -8,6 +8,7 @@ import { ImagePack, ImageUsage } from '../../../plugins/custom-emoji';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { mxcUrlToHttp } from '../../../utils/matrix';
import { useMediaAuthentication } from '../../../hooks/useMediaAuthentication';
import { AuthenticatedAvatarImage } from '../../../components/authenticated-media';
type UserPackProps = {
onViewPack: (imagePack: ImagePack) => void;
@@ -44,7 +45,7 @@ export function UserPack({ onViewPack }: UserPackProps) {
before={
<Avatar size="300" radii="300">
{avatarUrl ? (
<AvatarImage style={{ objectFit: 'contain' }} src={avatarUrl} />
<AuthenticatedAvatarImage style={{ objectFit: 'contain' }} src={avatarUrl} />
) : (
<AvatarFallback>
<Icon size="400" src={Icons.Sticker} filled />