feat: server support contact display (MSC1929) and server notices UI
- Settings Help/About fetches /.well-known/matrix/support and displays admin contact + support page link (graceful 404 degradation) - Server notice rooms (m.server_notice) now show a Warning badge in the room header and hide the message composer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -603,6 +603,16 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
|
||||
});
|
||||
};
|
||||
|
||||
if (room.getType() === 'm.server_notice') {
|
||||
return (
|
||||
<div ref={ref} style={{ padding: config.space.S300, textAlign: 'center' }}>
|
||||
<Text size="T300" priority="300">
|
||||
This is a server notice room — you cannot send messages here.
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
{selectedFiles.length > 0 && (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Box, Text, IconButton, Icon, Icons, Scroll, Button, config, toRem } from 'folds';
|
||||
import { Page, PageContent, PageHeader } from '../../../components/page';
|
||||
import { SequenceCard } from '../../../components/sequence-card';
|
||||
@@ -8,12 +8,49 @@ import LotusLogo from '../../../../../public/res/Lotus.png';
|
||||
import pkg from '../../../../../package.json';
|
||||
import { clearCacheAndReload } from '../../../../client/initMatrix';
|
||||
import { useMatrixClient } from '../../../hooks/useMatrixClient';
|
||||
import { lotusTerminalBodyClass } from '../../../../lotus-terminal.css';
|
||||
|
||||
type MSC1929Contact = {
|
||||
matrix_id?: string;
|
||||
email_address?: string;
|
||||
role?: string;
|
||||
};
|
||||
|
||||
type MSC1929Support = {
|
||||
contacts?: MSC1929Contact[];
|
||||
support_page?: string;
|
||||
};
|
||||
|
||||
function useServerSupport(): MSC1929Support | null {
|
||||
const mx = useMatrixClient();
|
||||
const [support, setSupport] = useState<MSC1929Support | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const baseUrl = (mx as unknown as { baseUrl: string }).baseUrl;
|
||||
fetch(`${baseUrl}/.well-known/matrix/support`)
|
||||
.then((res) => {
|
||||
if (!res.ok) return null;
|
||||
return res.json() as Promise<MSC1929Support>;
|
||||
})
|
||||
.then((data) => {
|
||||
if (data && (data.contacts?.length || data.support_page)) {
|
||||
setSupport(data);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// Graceful degradation — server may not have this configured
|
||||
});
|
||||
}, [mx]);
|
||||
|
||||
return support;
|
||||
}
|
||||
|
||||
type AboutProps = {
|
||||
requestClose: () => void;
|
||||
};
|
||||
export function About({ requestClose }: AboutProps) {
|
||||
const mx = useMatrixClient();
|
||||
const serverSupport = useServerSupport();
|
||||
|
||||
return (
|
||||
<Page>
|
||||
@@ -108,6 +145,67 @@ export function About({ requestClose }: AboutProps) {
|
||||
/>
|
||||
</SequenceCard>
|
||||
</Box>
|
||||
{serverSupport && (
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Homeserver Support</Text>
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="400"
|
||||
>
|
||||
<Box direction="Column" gap="200" style={{ padding: config.space.S200 }}>
|
||||
{serverSupport.contacts && serverSupport.contacts.length > 0 && (
|
||||
<Box direction="Column" gap="100">
|
||||
{serverSupport.contacts.map((contact, i) => (
|
||||
<Box key={i} alignItems="Center" gap="200">
|
||||
<Text size="T300" priority="300">
|
||||
{contact.role === 'm.role.admin'
|
||||
? 'Admin'
|
||||
: contact.role === 'm.role.security'
|
||||
? 'Security'
|
||||
: 'Contact'}
|
||||
:
|
||||
</Text>
|
||||
<Text
|
||||
size="T300"
|
||||
style={{
|
||||
color: document.body.classList.contains(lotusTerminalBodyClass)
|
||||
? 'var(--lt-accent-cyan)'
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
{contact.matrix_id ?? contact.email_address ?? ''}
|
||||
</Text>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
{serverSupport.support_page && (
|
||||
<Box alignItems="Center" gap="200">
|
||||
<Text size="T300" priority="300">
|
||||
Support Page:
|
||||
</Text>
|
||||
<Text size="T300">
|
||||
<a
|
||||
href={serverSupport.support_page}
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
style={{
|
||||
color: document.body.classList.contains(lotusTerminalBodyClass)
|
||||
? 'var(--lt-accent-cyan)'
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
{serverSupport.support_page}
|
||||
</a>
|
||||
</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</SequenceCard>
|
||||
</Box>
|
||||
)}
|
||||
<Box direction="Column" gap="100">
|
||||
<Text size="L400">Credits</Text>
|
||||
<SequenceCard
|
||||
|
||||
Reference in New Issue
Block a user