Add authenticated media support (#1930)
* chore: Bump matrix-js-sdk to 34.4.0 * feat: Authenticated media support * chore: Use Vite PWA for service worker support * fix: Fix Vite PWA SW entry point Forget this. :P * fix: Also add Nginx rewrite for sw.js * fix: Correct Nginx rewrite * fix: Add Netlify redirect for sw.js Otherwise the generic SPA rewrite to index.html would take effect, breaking Service Worker. * fix: Account for subpath when regisering service worker * chore: Correct types
This commit is contained in:
parent
043012e809
commit
c6a8fb1117
46 changed files with 3603 additions and 528 deletions
1
.npmrc
1
.npmrc
|
|
@ -1,3 +1,2 @@
|
||||||
legacy-peer-deps=true
|
legacy-peer-deps=true
|
||||||
save-exact=true
|
save-exact=true
|
||||||
@matrix-org:registry=https://gitlab.matrix.org/api/v4/projects/27/packages/npm/
|
|
||||||
|
|
@ -24,6 +24,7 @@ server {
|
||||||
rewrite ^/manifest.json$ /manifest.json break;
|
rewrite ^/manifest.json$ /manifest.json break;
|
||||||
|
|
||||||
rewrite ^.*/olm.wasm$ /olm.wasm break;
|
rewrite ^.*/olm.wasm$ /olm.wasm break;
|
||||||
|
rewrite ^/sw.js$ /sw.js break;
|
||||||
rewrite ^/pdf.worker.min.js$ /pdf.worker.min.js break;
|
rewrite ^/pdf.worker.min.js$ /pdf.worker.min.js break;
|
||||||
|
|
||||||
rewrite ^/public/(.*)$ /public/$1 break;
|
rewrite ^/public/(.*)$ /public/$1 break;
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ server {
|
||||||
rewrite ^/manifest.json$ /manifest.json break;
|
rewrite ^/manifest.json$ /manifest.json break;
|
||||||
|
|
||||||
rewrite ^.*/olm.wasm$ /olm.wasm break;
|
rewrite ^.*/olm.wasm$ /olm.wasm break;
|
||||||
|
rewrite ^/sw.js$ /sw.js break;
|
||||||
rewrite ^/pdf.worker.min.js$ /pdf.worker.min.js break;
|
rewrite ^/pdf.worker.min.js$ /pdf.worker.min.js break;
|
||||||
|
|
||||||
rewrite ^/public/(.*)$ /public/$1 break;
|
rewrite ^/public/(.*)$ /public/$1 break;
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,11 @@
|
||||||
to = "/manifest.json"
|
to = "/manifest.json"
|
||||||
status = 200
|
status = 200
|
||||||
|
|
||||||
|
[[redirects]]
|
||||||
|
from = "/sw.js"
|
||||||
|
to = "/sw.js"
|
||||||
|
status = 200
|
||||||
|
|
||||||
[[redirects]]
|
[[redirects]]
|
||||||
from = "*/olm.wasm"
|
from = "*/olm.wasm"
|
||||||
to = "/olm.wasm"
|
to = "/olm.wasm"
|
||||||
|
|
|
||||||
3363
package-lock.json
generated
3363
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -24,7 +24,7 @@
|
||||||
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "1.3.0",
|
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "1.3.0",
|
||||||
"@atlaskit/pragmatic-drag-and-drop-hitbox": "1.0.3",
|
"@atlaskit/pragmatic-drag-and-drop-hitbox": "1.0.3",
|
||||||
"@fontsource/inter": "4.5.14",
|
"@fontsource/inter": "4.5.14",
|
||||||
"@matrix-org/olm": "3.2.14",
|
"@matrix-org/olm": "3.2.15",
|
||||||
"@tanstack/react-query": "5.24.1",
|
"@tanstack/react-query": "5.24.1",
|
||||||
"@tanstack/react-query-devtools": "5.24.1",
|
"@tanstack/react-query-devtools": "5.24.1",
|
||||||
"@tanstack/react-virtual": "3.2.0",
|
"@tanstack/react-virtual": "3.2.0",
|
||||||
|
|
@ -56,7 +56,7 @@
|
||||||
"jotai": "2.6.0",
|
"jotai": "2.6.0",
|
||||||
"linkify-react": "4.1.3",
|
"linkify-react": "4.1.3",
|
||||||
"linkifyjs": "4.1.3",
|
"linkifyjs": "4.1.3",
|
||||||
"matrix-js-sdk": "29.1.0",
|
"matrix-js-sdk": "34.4.0",
|
||||||
"millify": "6.1.0",
|
"millify": "6.1.0",
|
||||||
"pdfjs-dist": "4.2.67",
|
"pdfjs-dist": "4.2.67",
|
||||||
"prismjs": "1.29.0",
|
"prismjs": "1.29.0",
|
||||||
|
|
@ -90,6 +90,7 @@
|
||||||
"@types/react-dom": "18.2.17",
|
"@types/react-dom": "18.2.17",
|
||||||
"@types/react-google-recaptcha": "2.1.8",
|
"@types/react-google-recaptcha": "2.1.8",
|
||||||
"@types/sanitize-html": "2.9.0",
|
"@types/sanitize-html": "2.9.0",
|
||||||
|
"@types/serviceworker": "0.0.95",
|
||||||
"@types/ua-parser-js": "0.7.36",
|
"@types/ua-parser-js": "0.7.36",
|
||||||
"@typescript-eslint/eslint-plugin": "5.46.1",
|
"@typescript-eslint/eslint-plugin": "5.46.1",
|
||||||
"@typescript-eslint/parser": "5.46.1",
|
"@typescript-eslint/parser": "5.46.1",
|
||||||
|
|
@ -106,6 +107,7 @@
|
||||||
"sass": "1.56.2",
|
"sass": "1.56.2",
|
||||||
"typescript": "4.9.4",
|
"typescript": "4.9.4",
|
||||||
"vite": "5.0.13",
|
"vite": "5.0.13",
|
||||||
|
"vite-plugin-pwa": "0.20.5",
|
||||||
"vite-plugin-static-copy": "1.0.4",
|
"vite-plugin-static-copy": "1.0.4",
|
||||||
"vite-plugin-top-level-await": "1.4.1"
|
"vite-plugin-top-level-await": "1.4.1"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ import { CommandElement, EmoticonElement, LinkElement, MentionElement } from './
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
import { getBeginCommand } from './utils';
|
import { getBeginCommand } from './utils';
|
||||||
import { BlockType } from './types';
|
import { BlockType } from './types';
|
||||||
|
import { mxcUrlToHttp } from '../../utils/matrix';
|
||||||
|
import { useSpecVersions } from '../../hooks/useSpecVersions';
|
||||||
|
|
||||||
// Put this at the start and end of an inline component to work around this Chromium bug:
|
// Put this at the start and end of an inline component to work around this Chromium bug:
|
||||||
// https://bugs.chromium.org/p/chromium/issues/detail?id=1249405
|
// https://bugs.chromium.org/p/chromium/issues/detail?id=1249405
|
||||||
|
|
@ -76,6 +78,8 @@ function RenderEmoticonElement({
|
||||||
children,
|
children,
|
||||||
}: { element: EmoticonElement } & RenderElementProps) {
|
}: { element: EmoticonElement } & RenderElementProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const selected = useSelected();
|
const selected = useSelected();
|
||||||
const focused = useFocused();
|
const focused = useFocused();
|
||||||
|
|
||||||
|
|
@ -90,7 +94,7 @@ function RenderEmoticonElement({
|
||||||
{element.key.startsWith('mxc://') ? (
|
{element.key.startsWith('mxc://') ? (
|
||||||
<img
|
<img
|
||||||
className={css.EmoticonImg}
|
className={css.EmoticonImg}
|
||||||
src={mx.mxcUrlToHttp(element.key) ?? element.key}
|
src={mxcUrlToHttp(mx, element.key, useAuthentication) ?? element.key}
|
||||||
alt={element.shortcode}
|
alt={element.shortcode}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ import { useRelevantImagePacks } from '../../../hooks/useImagePacks';
|
||||||
import { IEmoji, emojis } from '../../../plugins/emoji';
|
import { IEmoji, emojis } from '../../../plugins/emoji';
|
||||||
import { ExtendedPackImage, PackUsage } from '../../../plugins/custom-emoji';
|
import { ExtendedPackImage, PackUsage } from '../../../plugins/custom-emoji';
|
||||||
import { useKeyDown } from '../../../hooks/useKeyDown';
|
import { useKeyDown } from '../../../hooks/useKeyDown';
|
||||||
|
import { mxcUrlToHttp } from '../../../utils/matrix';
|
||||||
|
import { useSpecVersions } from '../../../hooks/useSpecVersions';
|
||||||
|
|
||||||
type EmoticonCompleteHandler = (key: string, shortcode: string) => void;
|
type EmoticonCompleteHandler = (key: string, shortcode: string) => void;
|
||||||
|
|
||||||
|
|
@ -48,6 +50,8 @@ export function EmoticonAutocomplete({
|
||||||
requestClose,
|
requestClose,
|
||||||
}: EmoticonAutocompleteProps) {
|
}: EmoticonAutocompleteProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
|
|
||||||
const imagePacks = useRelevantImagePacks(mx, PackUsage.Emoticon, imagePackRooms);
|
const imagePacks = useRelevantImagePacks(mx, PackUsage.Emoticon, imagePackRooms);
|
||||||
const recentEmoji = useRecentEmoji(mx, 20);
|
const recentEmoji = useRecentEmoji(mx, 20);
|
||||||
|
|
@ -103,7 +107,7 @@ export function EmoticonAutocomplete({
|
||||||
<Box
|
<Box
|
||||||
shrink="No"
|
shrink="No"
|
||||||
as="img"
|
as="img"
|
||||||
src={mx.mxcUrlToHttp(key) || key}
|
src={mxcUrlToHttp(mx, key, useAuthentication) || key}
|
||||||
alt={emoticon.shortcode}
|
alt={emoticon.shortcode}
|
||||||
style={{ width: toRem(24), height: toRem(24), objectFit: 'contain' }}
|
style={{ width: toRem(24), height: toRem(24), objectFit: 'contain' }}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import { useKeyDown } from '../../../hooks/useKeyDown';
|
||||||
import { getMxIdLocalPart, getMxIdServer, validMxId } from '../../../utils/matrix';
|
import { getMxIdLocalPart, getMxIdServer, validMxId } from '../../../utils/matrix';
|
||||||
import { getMemberDisplayName, getMemberSearchStr } from '../../../utils/room';
|
import { getMemberDisplayName, getMemberSearchStr } from '../../../utils/room';
|
||||||
import { UserAvatar } from '../../user-avatar';
|
import { UserAvatar } from '../../user-avatar';
|
||||||
|
import { useSpecVersions } from '../../../hooks/useSpecVersions';
|
||||||
|
|
||||||
type MentionAutoCompleteHandler = (userId: string, name: string) => void;
|
type MentionAutoCompleteHandler = (userId: string, name: string) => void;
|
||||||
|
|
||||||
|
|
@ -84,6 +85,8 @@ export function UserMentionAutocomplete({
|
||||||
requestClose,
|
requestClose,
|
||||||
}: UserMentionAutocompleteProps) {
|
}: UserMentionAutocompleteProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const roomId: string = room.roomId!;
|
const roomId: string = room.roomId!;
|
||||||
const roomAliasOrId = room.getCanonicalAlias() || roomId;
|
const roomAliasOrId = room.getCanonicalAlias() || roomId;
|
||||||
const members = useRoomMembers(mx, roomId);
|
const members = useRoomMembers(mx, roomId);
|
||||||
|
|
@ -143,7 +146,8 @@ export function UserMentionAutocomplete({
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
autoCompleteMembers.map((roomMember) => {
|
autoCompleteMembers.map((roomMember) => {
|
||||||
const avatarUrl = roomMember.getAvatarUrl(mx.baseUrl, 32, 32, 'crop', undefined, false);
|
const avatarMxcUrl = roomMember.getMxcAvatarUrl();
|
||||||
|
const avatarUrl = avatarMxcUrl ? mx.mxcUrlToHttp(avatarMxcUrl, 32, 32, 'crop', undefined, false, useAuthentication) : undefined;
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={roomMember.userId}
|
key={roomMember.userId}
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,14 @@ import { useRelevantImagePacks } from '../../hooks/useImagePacks';
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
import { useRecentEmoji } from '../../hooks/useRecentEmoji';
|
import { useRecentEmoji } from '../../hooks/useRecentEmoji';
|
||||||
import { ExtendedPackImage, ImagePack, PackUsage } from '../../plugins/custom-emoji';
|
import { ExtendedPackImage, ImagePack, PackUsage } from '../../plugins/custom-emoji';
|
||||||
import { isUserId } from '../../utils/matrix';
|
import { isUserId, mxcUrlToHttp } from '../../utils/matrix';
|
||||||
import { editableActiveElement, isIntersectingScrollView, targetFromEvent } from '../../utils/dom';
|
import { editableActiveElement, isIntersectingScrollView, targetFromEvent } from '../../utils/dom';
|
||||||
import { useAsyncSearch, UseAsyncSearchOptions } from '../../hooks/useAsyncSearch';
|
import { useAsyncSearch, UseAsyncSearchOptions } from '../../hooks/useAsyncSearch';
|
||||||
import { useDebounce } from '../../hooks/useDebounce';
|
import { useDebounce } from '../../hooks/useDebounce';
|
||||||
import { useThrottle } from '../../hooks/useThrottle';
|
import { useThrottle } from '../../hooks/useThrottle';
|
||||||
import { addRecentEmoji } from '../../plugins/recent-emoji';
|
import { addRecentEmoji } from '../../plugins/recent-emoji';
|
||||||
import { mobileOrTablet } from '../../utils/user-agent';
|
import { mobileOrTablet } from '../../utils/user-agent';
|
||||||
|
import { useSpecVersions } from '../../hooks/useSpecVersions';
|
||||||
|
|
||||||
const RECENT_GROUP_ID = 'recent_group';
|
const RECENT_GROUP_ID = 'recent_group';
|
||||||
const SEARCH_GROUP_ID = 'search_group';
|
const SEARCH_GROUP_ID = 'search_group';
|
||||||
|
|
@ -354,11 +355,13 @@ function ImagePackSidebarStack({
|
||||||
packs,
|
packs,
|
||||||
usage,
|
usage,
|
||||||
onItemClick,
|
onItemClick,
|
||||||
|
useAuthentication,
|
||||||
}: {
|
}: {
|
||||||
mx: MatrixClient;
|
mx: MatrixClient;
|
||||||
packs: ImagePack[];
|
packs: ImagePack[];
|
||||||
usage: PackUsage;
|
usage: PackUsage;
|
||||||
onItemClick: (id: string) => void;
|
onItemClick: (id: string) => void;
|
||||||
|
useAuthentication?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const activeGroupId = useAtomValue(activeGroupIdAtom);
|
const activeGroupId = useAtomValue(activeGroupIdAtom);
|
||||||
return (
|
return (
|
||||||
|
|
@ -381,7 +384,7 @@ function ImagePackSidebarStack({
|
||||||
height: toRem(24),
|
height: toRem(24),
|
||||||
objectFit: 'contain',
|
objectFit: 'contain',
|
||||||
}}
|
}}
|
||||||
src={mx.mxcUrlToHttp(pack.getPackAvatarUrl(usage) ?? '') || pack.avatarUrl}
|
src={mxcUrlToHttp(mx, pack.getPackAvatarUrl(usage) ?? '', useAuthentication) || pack.avatarUrl}
|
||||||
alt={label || 'Unknown Pack'}
|
alt={label || 'Unknown Pack'}
|
||||||
/>
|
/>
|
||||||
</SidebarBtn>
|
</SidebarBtn>
|
||||||
|
|
@ -453,68 +456,70 @@ export function SearchEmojiGroup({
|
||||||
label,
|
label,
|
||||||
id,
|
id,
|
||||||
emojis: searchResult,
|
emojis: searchResult,
|
||||||
|
useAuthentication,
|
||||||
}: {
|
}: {
|
||||||
mx: MatrixClient;
|
mx: MatrixClient;
|
||||||
tab: EmojiBoardTab;
|
tab: EmojiBoardTab;
|
||||||
label: string;
|
label: string;
|
||||||
id: string;
|
id: string;
|
||||||
emojis: Array<ExtendedPackImage | IEmoji>;
|
emojis: Array<ExtendedPackImage | IEmoji>;
|
||||||
|
useAuthentication?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<EmojiGroup key={id} id={id} label={label}>
|
<EmojiGroup key={id} id={id} label={label}>
|
||||||
{tab === EmojiBoardTab.Emoji
|
{tab === EmojiBoardTab.Emoji
|
||||||
? searchResult.map((emoji) =>
|
? searchResult.map((emoji) =>
|
||||||
'unicode' in emoji ? (
|
'unicode' in emoji ? (
|
||||||
<EmojiItem
|
<EmojiItem
|
||||||
key={emoji.unicode}
|
key={emoji.unicode}
|
||||||
label={emoji.label}
|
label={emoji.label}
|
||||||
type={EmojiType.Emoji}
|
type={EmojiType.Emoji}
|
||||||
data={emoji.unicode}
|
data={emoji.unicode}
|
||||||
shortcode={emoji.shortcode}
|
shortcode={emoji.shortcode}
|
||||||
>
|
>
|
||||||
{emoji.unicode}
|
{emoji.unicode}
|
||||||
</EmojiItem>
|
</EmojiItem>
|
||||||
) : (
|
) : (
|
||||||
<EmojiItem
|
<EmojiItem
|
||||||
key={emoji.shortcode}
|
key={emoji.shortcode}
|
||||||
label={emoji.body || emoji.shortcode}
|
label={emoji.body || emoji.shortcode}
|
||||||
type={EmojiType.CustomEmoji}
|
type={EmojiType.CustomEmoji}
|
||||||
data={emoji.url}
|
data={emoji.url}
|
||||||
shortcode={emoji.shortcode}
|
shortcode={emoji.shortcode}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
className={css.CustomEmojiImg}
|
className={css.CustomEmojiImg}
|
||||||
alt={emoji.body || emoji.shortcode}
|
alt={emoji.body || emoji.shortcode}
|
||||||
src={mx.mxcUrlToHttp(emoji.url) ?? emoji.url}
|
src={mxcUrlToHttp(mx, emoji.url, useAuthentication) ?? emoji.url}
|
||||||
/>
|
/>
|
||||||
</EmojiItem>
|
</EmojiItem>
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
: searchResult.map((emoji) =>
|
: searchResult.map((emoji) =>
|
||||||
'unicode' in emoji ? null : (
|
'unicode' in emoji ? null : (
|
||||||
<StickerItem
|
<StickerItem
|
||||||
key={emoji.shortcode}
|
key={emoji.shortcode}
|
||||||
label={emoji.body || emoji.shortcode}
|
label={emoji.body || emoji.shortcode}
|
||||||
type={EmojiType.Sticker}
|
type={EmojiType.Sticker}
|
||||||
data={emoji.url}
|
data={emoji.url}
|
||||||
shortcode={emoji.shortcode}
|
shortcode={emoji.shortcode}
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
className={css.StickerImg}
|
className={css.StickerImg}
|
||||||
alt={emoji.body || emoji.shortcode}
|
alt={emoji.body || emoji.shortcode}
|
||||||
src={mx.mxcUrlToHttp(emoji.url) ?? emoji.url}
|
src={mxcUrlToHttp(mx, emoji.url, useAuthentication) ?? emoji.url}
|
||||||
/>
|
/>
|
||||||
</StickerItem>
|
</StickerItem>
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</EmojiGroup>
|
</EmojiGroup>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CustomEmojiGroups = memo(
|
export const CustomEmojiGroups = memo(
|
||||||
({ mx, groups }: { mx: MatrixClient; groups: ImagePack[] }) => (
|
({ mx, groups, useAuthentication }: { mx: MatrixClient; groups: ImagePack[]; useAuthentication?: boolean }) => (
|
||||||
<>
|
<>
|
||||||
{groups.map((pack) => (
|
{groups.map((pack) => (
|
||||||
<EmojiGroup key={pack.id} id={pack.id} label={pack.displayName || 'Unknown'}>
|
<EmojiGroup key={pack.id} id={pack.id} label={pack.displayName || 'Unknown'}>
|
||||||
|
|
@ -530,7 +535,7 @@ export const CustomEmojiGroups = memo(
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
className={css.CustomEmojiImg}
|
className={css.CustomEmojiImg}
|
||||||
alt={image.body || image.shortcode}
|
alt={image.body || image.shortcode}
|
||||||
src={mx.mxcUrlToHttp(image.url) ?? image.url}
|
src={mxcUrlToHttp(mx, image.url, useAuthentication) ?? image.url}
|
||||||
/>
|
/>
|
||||||
</EmojiItem>
|
</EmojiItem>
|
||||||
))}
|
))}
|
||||||
|
|
@ -540,7 +545,7 @@ export const CustomEmojiGroups = memo(
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
export const StickerGroups = memo(({ mx, groups }: { mx: MatrixClient; groups: ImagePack[] }) => (
|
export const StickerGroups = memo(({ mx, groups, useAuthentication }: { mx: MatrixClient; groups: ImagePack[]; useAuthentication?: boolean }) => (
|
||||||
<>
|
<>
|
||||||
{groups.length === 0 && (
|
{groups.length === 0 && (
|
||||||
<Box
|
<Box
|
||||||
|
|
@ -573,7 +578,7 @@ export const StickerGroups = memo(({ mx, groups }: { mx: MatrixClient; groups: I
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
className={css.StickerImg}
|
className={css.StickerImg}
|
||||||
alt={image.body || image.shortcode}
|
alt={image.body || image.shortcode}
|
||||||
src={mx.mxcUrlToHttp(image.url) ?? image.url}
|
src={mxcUrlToHttp(mx, image.url, useAuthentication) ?? image.url}
|
||||||
/>
|
/>
|
||||||
</StickerItem>
|
</StickerItem>
|
||||||
))}
|
))}
|
||||||
|
|
@ -645,6 +650,8 @@ export function EmojiBoard({
|
||||||
|
|
||||||
const setActiveGroupId = useSetAtom(activeGroupIdAtom);
|
const setActiveGroupId = useSetAtom(activeGroupIdAtom);
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const emojiGroupLabels = useEmojiGroupLabels();
|
const emojiGroupLabels = useEmojiGroupLabels();
|
||||||
const emojiGroupIcons = useEmojiGroupIcons();
|
const emojiGroupIcons = useEmojiGroupIcons();
|
||||||
const imagePacks = useRelevantImagePacks(mx, usage, imagePackRooms);
|
const imagePacks = useRelevantImagePacks(mx, usage, imagePackRooms);
|
||||||
|
|
@ -729,14 +736,14 @@ export function EmojiBoard({
|
||||||
} else if (emojiInfo.type === EmojiType.CustomEmoji && emojiPreviewRef.current) {
|
} else if (emojiInfo.type === EmojiType.CustomEmoji && emojiPreviewRef.current) {
|
||||||
const img = document.createElement('img');
|
const img = document.createElement('img');
|
||||||
img.className = css.CustomEmojiImg;
|
img.className = css.CustomEmojiImg;
|
||||||
img.setAttribute('src', mx.mxcUrlToHttp(emojiInfo.data) || emojiInfo.data);
|
img.setAttribute('src', mxcUrlToHttp(mx, emojiInfo.data, useAuthentication) || emojiInfo.data);
|
||||||
img.setAttribute('alt', emojiInfo.shortcode);
|
img.setAttribute('alt', emojiInfo.shortcode);
|
||||||
emojiPreviewRef.current.textContent = '';
|
emojiPreviewRef.current.textContent = '';
|
||||||
emojiPreviewRef.current.appendChild(img);
|
emojiPreviewRef.current.appendChild(img);
|
||||||
}
|
}
|
||||||
emojiPreviewTextRef.current.textContent = `:${emojiInfo.shortcode}:`;
|
emojiPreviewTextRef.current.textContent = `:${emojiInfo.shortcode}:`;
|
||||||
},
|
},
|
||||||
[mx]
|
[mx, useAuthentication]
|
||||||
);
|
);
|
||||||
|
|
||||||
const throttleEmojiHover = useThrottle(handleEmojiPreview, {
|
const throttleEmojiHover = useThrottle(handleEmojiPreview, {
|
||||||
|
|
@ -829,6 +836,7 @@ export function EmojiBoard({
|
||||||
usage={usage}
|
usage={usage}
|
||||||
packs={imagePacks}
|
packs={imagePacks}
|
||||||
onItemClick={handleScrollToGroup}
|
onItemClick={handleScrollToGroup}
|
||||||
|
useAuthentication={useAuthentication}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{emojiTab && (
|
{emojiTab && (
|
||||||
|
|
@ -890,13 +898,14 @@ export function EmojiBoard({
|
||||||
id={SEARCH_GROUP_ID}
|
id={SEARCH_GROUP_ID}
|
||||||
label={result.items.length ? 'Search Results' : 'No Results found'}
|
label={result.items.length ? 'Search Results' : 'No Results found'}
|
||||||
emojis={result.items}
|
emojis={result.items}
|
||||||
|
useAuthentication={useAuthentication}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{emojiTab && recentEmojis.length > 0 && (
|
{emojiTab && recentEmojis.length > 0 && (
|
||||||
<RecentEmojiGroup id={RECENT_GROUP_ID} label="Recent" emojis={recentEmojis} />
|
<RecentEmojiGroup id={RECENT_GROUP_ID} label="Recent" emojis={recentEmojis} />
|
||||||
)}
|
)}
|
||||||
{emojiTab && <CustomEmojiGroups mx={mx} groups={imagePacks} />}
|
{emojiTab && <CustomEmojiGroups mx={mx} groups={imagePacks} useAuthentication={useAuthentication} />}
|
||||||
{stickerTab && <StickerGroups mx={mx} groups={imagePacks} />}
|
{stickerTab && <StickerGroups mx={mx} groups={imagePacks} useAuthentication={useAuthentication} />}
|
||||||
{emojiTab && <NativeEmojiGroups groups={emojiGroups} labels={emojiGroupLabels} />}
|
{emojiTab && <NativeEmojiGroups groups={emojiGroups} labels={emojiGroupLabels} />}
|
||||||
</Box>
|
</Box>
|
||||||
</Scroll>
|
</Scroll>
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ import * as css from './EventReaders.css';
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
import { openProfileViewer } from '../../../client/action/navigation';
|
import { openProfileViewer } from '../../../client/action/navigation';
|
||||||
import { UserAvatar } from '../user-avatar';
|
import { UserAvatar } from '../user-avatar';
|
||||||
|
import { useSpecVersions } from '../../hooks/useSpecVersions';
|
||||||
|
|
||||||
export type EventReadersProps = {
|
export type EventReadersProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
|
@ -30,6 +31,8 @@ export type EventReadersProps = {
|
||||||
export const EventReaders = as<'div', EventReadersProps>(
|
export const EventReaders = as<'div', EventReadersProps>(
|
||||||
({ className, room, eventId, requestClose, ...props }, ref) => {
|
({ className, room, eventId, requestClose, ...props }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const latestEventReaders = useRoomEventReaders(room, eventId);
|
const latestEventReaders = useRoomEventReaders(room, eventId);
|
||||||
|
|
||||||
const getName = (userId: string) =>
|
const getName = (userId: string) =>
|
||||||
|
|
@ -55,9 +58,10 @@ export const EventReaders = as<'div', EventReadersProps>(
|
||||||
<Box className={css.Content} direction="Column">
|
<Box className={css.Content} direction="Column">
|
||||||
{latestEventReaders.map((readerId) => {
|
{latestEventReaders.map((readerId) => {
|
||||||
const name = getName(readerId);
|
const name = getName(readerId);
|
||||||
const avatarUrl = room
|
const avatarMxcUrl = room
|
||||||
.getMember(readerId)
|
.getMember(readerId)
|
||||||
?.getAvatarUrl(mx.baseUrl, 100, 100, 'crop', undefined, false);
|
?.getMxcAvatarUrl();
|
||||||
|
const avatarUrl = avatarMxcUrl ? mx.mxcUrlToHttp(avatarMxcUrl, 100, 100, 'crop', undefined, false, useAuthentication) : undefined;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { MatrixClient, MatrixEvent, Room } from 'matrix-js-sdk';
|
||||||
import * as css from './Reaction.css';
|
import * as css from './Reaction.css';
|
||||||
import { getHexcodeForEmoji, getShortcodeFor } from '../../plugins/emoji';
|
import { getHexcodeForEmoji, getShortcodeFor } from '../../plugins/emoji';
|
||||||
import { getMemberDisplayName } from '../../utils/room';
|
import { getMemberDisplayName } from '../../utils/room';
|
||||||
import { eventWithShortcode, getMxIdLocalPart } from '../../utils/matrix';
|
import { eventWithShortcode, getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix';
|
||||||
|
|
||||||
export const Reaction = as<
|
export const Reaction = as<
|
||||||
'button',
|
'button',
|
||||||
|
|
@ -13,8 +13,9 @@ export const Reaction = as<
|
||||||
mx: MatrixClient;
|
mx: MatrixClient;
|
||||||
count: number;
|
count: number;
|
||||||
reaction: string;
|
reaction: string;
|
||||||
|
useAuthentication?: boolean;
|
||||||
}
|
}
|
||||||
>(({ className, mx, count, reaction, ...props }, ref) => (
|
>(({ className, mx, count, reaction, useAuthentication, ...props }, ref) => (
|
||||||
<Box
|
<Box
|
||||||
as="button"
|
as="button"
|
||||||
className={classNames(css.Reaction, className)}
|
className={classNames(css.Reaction, className)}
|
||||||
|
|
@ -28,7 +29,8 @@ export const Reaction = as<
|
||||||
{reaction.startsWith('mxc://') ? (
|
{reaction.startsWith('mxc://') ? (
|
||||||
<img
|
<img
|
||||||
className={css.ReactionImg}
|
className={css.ReactionImg}
|
||||||
src={mx.mxcUrlToHttp(reaction) ?? reaction}
|
src={mxcUrlToHttp(mx, reaction, useAuthentication) ?? reaction
|
||||||
|
}
|
||||||
alt={reaction}
|
alt={reaction}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ import {
|
||||||
} from '../../../hooks/media';
|
} from '../../../hooks/media';
|
||||||
import { useThrottle } from '../../../hooks/useThrottle';
|
import { useThrottle } from '../../../hooks/useThrottle';
|
||||||
import { secondsToMinutesAndSeconds } from '../../../utils/common';
|
import { secondsToMinutesAndSeconds } from '../../../utils/common';
|
||||||
|
import { mxcUrlToHttp } from '../../../utils/matrix';
|
||||||
|
import { useSpecVersions } from '../../../hooks/useSpecVersions';
|
||||||
|
|
||||||
const PLAY_TIME_THROTTLE_OPS = {
|
const PLAY_TIME_THROTTLE_OPS = {
|
||||||
wait: 500,
|
wait: 500,
|
||||||
|
|
@ -44,11 +46,13 @@ export function AudioContent({
|
||||||
renderMediaControl,
|
renderMediaControl,
|
||||||
}: AudioContentProps) {
|
}: AudioContentProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
|
|
||||||
const [srcState, loadSrc] = useAsyncCallback(
|
const [srcState, loadSrc] = useAsyncCallback(
|
||||||
useCallback(
|
useCallback(
|
||||||
() => getFileSrcUrl(mx.mxcUrlToHttp(url) ?? '', mimeType, encInfo),
|
() => getFileSrcUrl(mxcUrlToHttp(mx, url, useAuthentication) ?? '', mimeType, encInfo),
|
||||||
[mx, url, mimeType, encInfo]
|
[mx, url, useAuthentication, mimeType, encInfo]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,8 @@ import {
|
||||||
} from '../../../utils/mimeTypes';
|
} from '../../../utils/mimeTypes';
|
||||||
import * as css from './style.css';
|
import * as css from './style.css';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
|
import { mxcUrlToHttp } from '../../../utils/matrix';
|
||||||
|
import { useSpecVersions } from '../../../hooks/useSpecVersions';
|
||||||
|
|
||||||
const renderErrorButton = (retry: () => void, text: string) => (
|
const renderErrorButton = (retry: () => void, text: string) => (
|
||||||
<TooltipProvider
|
<TooltipProvider
|
||||||
|
|
@ -75,11 +77,13 @@ type ReadTextFileProps = {
|
||||||
};
|
};
|
||||||
export function ReadTextFile({ body, mimeType, url, encInfo, renderViewer }: ReadTextFileProps) {
|
export function ReadTextFile({ body, mimeType, url, encInfo, renderViewer }: ReadTextFileProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const [textViewer, setTextViewer] = useState(false);
|
const [textViewer, setTextViewer] = useState(false);
|
||||||
|
|
||||||
const loadSrc = useCallback(
|
const loadSrc = useCallback(
|
||||||
() => getFileSrcUrl(mx.mxcUrlToHttp(url) ?? '', mimeType, encInfo),
|
() => getFileSrcUrl(mxcUrlToHttp(mx, url, useAuthentication) ?? '', mimeType, encInfo),
|
||||||
[mx, url, mimeType, encInfo]
|
[mx, url, useAuthentication, mimeType, encInfo]
|
||||||
);
|
);
|
||||||
|
|
||||||
const [textState, loadText] = useAsyncCallback(
|
const [textState, loadText] = useAsyncCallback(
|
||||||
|
|
@ -166,14 +170,16 @@ export type ReadPdfFileProps = {
|
||||||
};
|
};
|
||||||
export function ReadPdfFile({ body, mimeType, url, encInfo, renderViewer }: ReadPdfFileProps) {
|
export function ReadPdfFile({ body, mimeType, url, encInfo, renderViewer }: ReadPdfFileProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const [pdfViewer, setPdfViewer] = useState(false);
|
const [pdfViewer, setPdfViewer] = useState(false);
|
||||||
|
|
||||||
const [pdfState, loadPdf] = useAsyncCallback(
|
const [pdfState, loadPdf] = useAsyncCallback(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
const httpUrl = await getFileSrcUrl(mx.mxcUrlToHttp(url) ?? '', mimeType, encInfo);
|
const httpUrl = await getFileSrcUrl(mxcUrlToHttp(mx, url, useAuthentication) ?? '', mimeType, encInfo);
|
||||||
setPdfViewer(true);
|
setPdfViewer(true);
|
||||||
return httpUrl;
|
return httpUrl;
|
||||||
}, [mx, url, mimeType, encInfo])
|
}, [mx, url, useAuthentication, mimeType, encInfo])
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -240,13 +246,15 @@ export type DownloadFileProps = {
|
||||||
};
|
};
|
||||||
export function DownloadFile({ body, mimeType, url, info, encInfo }: DownloadFileProps) {
|
export function DownloadFile({ body, mimeType, url, info, encInfo }: DownloadFileProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
|
|
||||||
const [downloadState, download] = useAsyncCallback(
|
const [downloadState, download] = useAsyncCallback(
|
||||||
useCallback(async () => {
|
useCallback(async () => {
|
||||||
const httpUrl = await getFileSrcUrl(mx.mxcUrlToHttp(url) ?? '', mimeType, encInfo);
|
const httpUrl = await getFileSrcUrl(mxcUrlToHttp(mx, url, useAuthentication) ?? '', mimeType, encInfo);
|
||||||
FileSaver.saveAs(httpUrl, body);
|
FileSaver.saveAs(httpUrl, body);
|
||||||
return httpUrl;
|
return httpUrl;
|
||||||
}, [mx, url, mimeType, encInfo, body])
|
}, [mx, url, useAuthentication, mimeType, encInfo, body])
|
||||||
);
|
);
|
||||||
|
|
||||||
return downloadState.status === AsyncStatus.Error ? (
|
return downloadState.status === AsyncStatus.Error ? (
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ import * as css from './style.css';
|
||||||
import { bytesToSize } from '../../../utils/common';
|
import { bytesToSize } from '../../../utils/common';
|
||||||
import { FALLBACK_MIMETYPE } from '../../../utils/mimeTypes';
|
import { FALLBACK_MIMETYPE } from '../../../utils/mimeTypes';
|
||||||
import { stopPropagation } from '../../../utils/keyboard';
|
import { stopPropagation } from '../../../utils/keyboard';
|
||||||
|
import { mxcUrlToHttp } from '../../../utils/matrix';
|
||||||
|
import { useSpecVersions } from '../../../hooks/useSpecVersions';
|
||||||
|
|
||||||
type RenderViewerProps = {
|
type RenderViewerProps = {
|
||||||
src: string;
|
src: string;
|
||||||
|
|
@ -69,6 +71,8 @@ export const ImageContent = as<'div', ImageContentProps>(
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const blurHash = info?.[MATRIX_BLUR_HASH_PROPERTY_NAME];
|
const blurHash = info?.[MATRIX_BLUR_HASH_PROPERTY_NAME];
|
||||||
|
|
||||||
const [load, setLoad] = useState(false);
|
const [load, setLoad] = useState(false);
|
||||||
|
|
@ -77,8 +81,8 @@ export const ImageContent = as<'div', ImageContentProps>(
|
||||||
|
|
||||||
const [srcState, loadSrc] = useAsyncCallback(
|
const [srcState, loadSrc] = useAsyncCallback(
|
||||||
useCallback(
|
useCallback(
|
||||||
() => getFileSrcUrl(mx.mxcUrlToHttp(url) ?? '', mimeType || FALLBACK_MIMETYPE, encInfo),
|
() => getFileSrcUrl(mxcUrlToHttp(mx, url, useAuthentication) ?? '', mimeType || FALLBACK_MIMETYPE, encInfo),
|
||||||
[mx, url, mimeType, encInfo]
|
[mx, url, useAuthentication, mimeType, encInfo]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,8 @@ import { IThumbnailContent } from '../../../../types/matrix/common';
|
||||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||||
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
|
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
|
||||||
import { getFileSrcUrl } from './util';
|
import { getFileSrcUrl } from './util';
|
||||||
|
import { mxcUrlToHttp } from '../../../utils/matrix';
|
||||||
|
import { useSpecVersions } from '../../../hooks/useSpecVersions';
|
||||||
|
|
||||||
export type ThumbnailContentProps = {
|
export type ThumbnailContentProps = {
|
||||||
info: IThumbnailContent;
|
info: IThumbnailContent;
|
||||||
|
|
@ -10,6 +12,8 @@ export type ThumbnailContentProps = {
|
||||||
};
|
};
|
||||||
export function ThumbnailContent({ info, renderImage }: ThumbnailContentProps) {
|
export function ThumbnailContent({ info, renderImage }: ThumbnailContentProps) {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
|
|
||||||
const [thumbSrcState, loadThumbSrc] = useAsyncCallback(
|
const [thumbSrcState, loadThumbSrc] = useAsyncCallback(
|
||||||
useCallback(() => {
|
useCallback(() => {
|
||||||
|
|
@ -19,11 +23,11 @@ export function ThumbnailContent({ info, renderImage }: ThumbnailContentProps) {
|
||||||
throw new Error('Failed to load thumbnail');
|
throw new Error('Failed to load thumbnail');
|
||||||
}
|
}
|
||||||
return getFileSrcUrl(
|
return getFileSrcUrl(
|
||||||
mx.mxcUrlToHttp(thumbMxcUrl) ?? '',
|
mxcUrlToHttp(mx, thumbMxcUrl, useAuthentication) ?? '',
|
||||||
thumbInfo.mimetype,
|
thumbInfo.mimetype,
|
||||||
info.thumbnail_file
|
info.thumbnail_file
|
||||||
);
|
);
|
||||||
}, [mx, info])
|
}, [mx, info, useAuthentication])
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
|
||||||
import { getFileSrcUrl } from './util';
|
import { getFileSrcUrl } from './util';
|
||||||
import { bytesToSize } from '../../../../util/common';
|
import { bytesToSize } from '../../../../util/common';
|
||||||
import { millisecondsToMinutesAndSeconds } from '../../../utils/common';
|
import { millisecondsToMinutesAndSeconds } from '../../../utils/common';
|
||||||
|
import { mxcUrlToHttp } from '../../../utils/matrix';
|
||||||
|
import { useSpecVersions } from '../../../hooks/useSpecVersions';
|
||||||
|
|
||||||
type RenderVideoProps = {
|
type RenderVideoProps = {
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -61,6 +63,8 @@ export const VideoContent = as<'div', VideoContentProps>(
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const blurHash = info.thumbnail_info?.[MATRIX_BLUR_HASH_PROPERTY_NAME];
|
const blurHash = info.thumbnail_info?.[MATRIX_BLUR_HASH_PROPERTY_NAME];
|
||||||
|
|
||||||
const [load, setLoad] = useState(false);
|
const [load, setLoad] = useState(false);
|
||||||
|
|
@ -68,8 +72,8 @@ export const VideoContent = as<'div', VideoContentProps>(
|
||||||
|
|
||||||
const [srcState, loadSrc] = useAsyncCallback(
|
const [srcState, loadSrc] = useAsyncCallback(
|
||||||
useCallback(
|
useCallback(
|
||||||
() => getFileSrcUrl(mx.mxcUrlToHttp(url) ?? '', mimeType, encInfo),
|
() => getFileSrcUrl(mxcUrlToHttp(mx, url, useAuthentication) ?? '', mimeType, encInfo),
|
||||||
[mx, url, mimeType, encInfo]
|
[mx, url, useAuthentication, mimeType, encInfo]
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ import classNames from 'classnames';
|
||||||
import FocusTrap from 'focus-trap-react';
|
import FocusTrap from 'focus-trap-react';
|
||||||
import * as css from './style.css';
|
import * as css from './style.css';
|
||||||
import { RoomAvatar } from '../room-avatar';
|
import { RoomAvatar } from '../room-avatar';
|
||||||
import { getMxIdLocalPart } from '../../utils/matrix';
|
import { getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix';
|
||||||
import { nameInitials } from '../../utils/common';
|
import { nameInitials } from '../../utils/common';
|
||||||
import { millify } from '../../plugins/millify';
|
import { millify } from '../../plugins/millify';
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
|
|
@ -32,6 +32,7 @@ import { useJoinedRoomId } from '../../hooks/useJoinedRoomId';
|
||||||
import { useElementSizeObserver } from '../../hooks/useElementSizeObserver';
|
import { useElementSizeObserver } from '../../hooks/useElementSizeObserver';
|
||||||
import { getRoomAvatarUrl, getStateEvent } from '../../utils/room';
|
import { getRoomAvatarUrl, getStateEvent } from '../../utils/room';
|
||||||
import { useStateEventCallback } from '../../hooks/useStateEventCallback';
|
import { useStateEventCallback } from '../../hooks/useStateEventCallback';
|
||||||
|
import { useSpecVersions } from '../../hooks/useSpecVersions';
|
||||||
|
|
||||||
type GridColumnCount = '1' | '2' | '3';
|
type GridColumnCount = '1' | '2' | '3';
|
||||||
const getGridColumnCount = (gridWidth: number): GridColumnCount => {
|
const getGridColumnCount = (gridWidth: number): GridColumnCount => {
|
||||||
|
|
@ -161,6 +162,8 @@ export const RoomCard = as<'div', RoomCardProps>(
|
||||||
ref
|
ref
|
||||||
) => {
|
) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const joinedRoomId = useJoinedRoomId(allRooms, roomIdOrAlias);
|
const joinedRoomId = useJoinedRoomId(allRooms, roomIdOrAlias);
|
||||||
const joinedRoom = mx.getRoom(joinedRoomId);
|
const joinedRoom = mx.getRoom(joinedRoomId);
|
||||||
const [topicEvent, setTopicEvent] = useState(() =>
|
const [topicEvent, setTopicEvent] = useState(() =>
|
||||||
|
|
@ -171,8 +174,8 @@ export const RoomCard = as<'div', RoomCardProps>(
|
||||||
const fallbackTopic = roomIdOrAlias;
|
const fallbackTopic = roomIdOrAlias;
|
||||||
|
|
||||||
const avatar = joinedRoom
|
const avatar = joinedRoom
|
||||||
? getRoomAvatarUrl(mx, joinedRoom, 96)
|
? getRoomAvatarUrl(mx, joinedRoom, 96, useAuthentication)
|
||||||
: avatarUrl && mx.mxcUrlToHttp(avatarUrl, 96, 96, 'crop');
|
: avatarUrl && mxcUrlToHttp(mx, avatarUrl, useAuthentication, 96, 96, 'crop');
|
||||||
|
|
||||||
const roomName = joinedRoom?.name || name || fallbackName;
|
const roomName = joinedRoom?.name || name || fallbackName;
|
||||||
const roomTopic =
|
const roomTopic =
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { openInviteUser } from '../../../client/action/navigation';
|
||||||
import { IRoomCreateContent, Membership, StateEvent } from '../../../types/matrix/room';
|
import { IRoomCreateContent, Membership, StateEvent } from '../../../types/matrix/room';
|
||||||
import { getMemberDisplayName, getStateEvent } from '../../utils/room';
|
import { getMemberDisplayName, getStateEvent } from '../../utils/room';
|
||||||
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
import { useMatrixClient } from '../../hooks/useMatrixClient';
|
||||||
import { getMxIdLocalPart } from '../../utils/matrix';
|
import { getMxIdLocalPart, mxcUrlToHttp } from '../../utils/matrix';
|
||||||
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
import { AsyncStatus, useAsyncCallback } from '../../hooks/useAsyncCallback';
|
||||||
import { timeDayMonthYear, timeHourMinute } from '../../utils/time';
|
import { timeDayMonthYear, timeHourMinute } from '../../utils/time';
|
||||||
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
|
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
|
||||||
|
|
@ -14,6 +14,7 @@ import { RoomAvatar } from '../room-avatar';
|
||||||
import { nameInitials } from '../../utils/common';
|
import { nameInitials } from '../../utils/common';
|
||||||
import { useRoomAvatar, useRoomName, useRoomTopic } from '../../hooks/useRoomMeta';
|
import { useRoomAvatar, useRoomName, useRoomTopic } from '../../hooks/useRoomMeta';
|
||||||
import { mDirectAtom } from '../../state/mDirectList';
|
import { mDirectAtom } from '../../state/mDirectList';
|
||||||
|
import { useSpecVersions } from '../../hooks/useSpecVersions';
|
||||||
|
|
||||||
export type RoomIntroProps = {
|
export type RoomIntroProps = {
|
||||||
room: Room;
|
room: Room;
|
||||||
|
|
@ -21,6 +22,8 @@ export type RoomIntroProps = {
|
||||||
|
|
||||||
export const RoomIntro = as<'div', RoomIntroProps>(({ room, ...props }, ref) => {
|
export const RoomIntro = as<'div', RoomIntroProps>(({ room, ...props }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const { navigateRoom } = useRoomNavigate();
|
const { navigateRoom } = useRoomNavigate();
|
||||||
const mDirects = useAtomValue(mDirectAtom);
|
const mDirects = useAtomValue(mDirectAtom);
|
||||||
|
|
||||||
|
|
@ -28,7 +31,7 @@ export const RoomIntro = as<'div', RoomIntroProps>(({ room, ...props }, ref) =>
|
||||||
const avatarMxc = useRoomAvatar(room, mDirects.has(room.roomId));
|
const avatarMxc = useRoomAvatar(room, mDirects.has(room.roomId));
|
||||||
const name = useRoomName(room);
|
const name = useRoomName(room);
|
||||||
const topic = useRoomTopic(room);
|
const topic = useRoomTopic(room);
|
||||||
const avatarHttpUrl = avatarMxc ? mx.mxcUrlToHttp(avatarMxc) : undefined;
|
const avatarHttpUrl = avatarMxc ? mxcUrlToHttp(mx, avatarMxc, useAuthentication) : undefined;
|
||||||
|
|
||||||
const createContent = createEvent?.getContent<IRoomCreateContent>();
|
const createContent = createEvent?.getContent<IRoomCreateContent>();
|
||||||
const ts = createEvent?.getTs();
|
const ts = createEvent?.getTs();
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,16 @@ import {
|
||||||
} from '../../hooks/useIntersectionObserver';
|
} from '../../hooks/useIntersectionObserver';
|
||||||
import * as css from './UrlPreviewCard.css';
|
import * as css from './UrlPreviewCard.css';
|
||||||
import { tryDecodeURIComponent } from '../../utils/dom';
|
import { tryDecodeURIComponent } from '../../utils/dom';
|
||||||
|
import { mxcUrlToHttp } from '../../utils/matrix';
|
||||||
|
import { useSpecVersions } from '../../hooks/useSpecVersions';
|
||||||
|
|
||||||
const linkStyles = { color: color.Success.Main };
|
const linkStyles = { color: color.Success.Main };
|
||||||
|
|
||||||
export const UrlPreviewCard = as<'div', { url: string; ts: number }>(
|
export const UrlPreviewCard = as<'div', { url: string; ts: number }>(
|
||||||
({ url, ts, ...props }, ref) => {
|
({ url, ts, ...props }, ref) => {
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
|
const { versions } = useSpecVersions();
|
||||||
|
const useAuthentication = versions.includes('v1.11');
|
||||||
const [previewStatus, loadPreview] = useAsyncCallback(
|
const [previewStatus, loadPreview] = useAsyncCallback(
|
||||||
useCallback(() => mx.getUrlPreview(url, ts), [url, ts, mx])
|
useCallback(() => mx.getUrlPreview(url, ts), [url, ts, mx])
|
||||||
);
|
);
|
||||||
|
|
@ -27,7 +31,7 @@ export const UrlPreviewCard = as<'div', { url: string; ts: number }>(
|
||||||
if (previewStatus.status === AsyncStatus.Error) return null;
|
if (previewStatus.status === AsyncStatus.Error) return null;
|
||||||
|
|
||||||
const renderContent = (prev: IPreviewUrlResponse) => {
|
const renderContent = (prev: IPreviewUrlResponse) => {
|
||||||
const imgUrl = mx.mxcUrlToHttp(prev['og:image'] || '', 256, 256, 'scale', false);
|
const imgUrl = mxcUrlToHttp(mx, prev['og:image'] || '', useAuthentication, 256, 256, 'scale', false);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue