More usage of MD Icons and video calls

This commit is contained in:
OfficialDakari 2024-08-10 13:56:12 +00:00
parent 7cb1c8ff3d
commit a5773c3207
59 changed files with 663 additions and 550 deletions

View file

@ -4,14 +4,14 @@
"officialdakari.ru",
"usesarchbtw.lol",
"private.coffee",
"catgirl.cloud",
"secroot.xyz"
"matrix.im"
],
"allowCustomHomeservers": true,
"featuredCommunities": {
"openAsDefault": false,
"spaces": [],
"rooms": [
"#extera:officialdakari.ru",
"#basement:officialdakari.ru"
],
"servers": [

View file

@ -6,13 +6,18 @@ const files = fs.readdirSync('src/', {
const q = process.argv[2];
var total = 0;
for (const f of files) {
try {
const b = fs.readFileSync(`src/${f}`, 'utf-8');
if (b.includes(q) || f.includes(q)) {
total ++;
console.log(f);
}
} catch (error) {
}
}
}
console.log(`${total} files in total`);

View file

@ -1,124 +1,124 @@
{
"name": "cinny",
"version": "3.2.0",
"description": "Yet another matrix client",
"main": "index.js",
"type": "module",
"engines": {
"node": ">=16.0.0"
},
"scripts": {
"start": "vite",
"build": "vite build",
"lint": "yarn check:eslint && yarn check:prettier",
"check:eslint": "eslint src/*",
"check:prettier": "prettier --check .",
"fix:prettier": "prettier --write .",
"typecheck": "tsc --noEmit"
},
"keywords": [],
"author": "Ajay Bura",
"license": "AGPL-3.0-only",
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "1.1.6",
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "1.3.0",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "1.0.3",
"@fontsource/inter": "4.5.14",
"@matrix-org/olm": "3.2.14",
"@mdi/js": "7.4.47",
"@mdi/react": "1.6.1",
"@tanstack/react-query": "5.24.1",
"@tanstack/react-query-devtools": "5.24.1",
"@tanstack/react-virtual": "3.2.0",
"@tippyjs/react": "4.2.6",
"@vanilla-extract/css": "1.9.3",
"@vanilla-extract/recipes": "0.3.0",
"@vanilla-extract/vite-plugin": "3.7.1",
"anafanafo": "2.0.0",
"await-to-js": "3.0.0",
"badge-maker": "4.0.0",
"blurhash": "2.0.4",
"browser-encrypt-attachment": "0.3.0",
"classnames": "2.3.2",
"dateformat": "5.0.3",
"dayjs": "1.11.10",
"domhandler": "5.0.3",
"emojibase": "6.1.0",
"emojibase-data": "7.0.1",
"file-saver": "2.0.5",
"flux": "4.0.3",
"focus-trap-react": "10.0.2",
"folds": "2.0.0",
"formik": "2.4.6",
"html-dom-parser": "4.0.0",
"html-react-parser": "4.2.0",
"immer": "9.0.16",
"is-hotkey": "0.2.0",
"jotai": "2.6.0",
"linkify-react": "4.1.3",
"linkifyjs": "4.1.3",
"marked": "13.0.2",
"matrix-js-sdk": "29.1.0",
"millify": "6.1.0",
"pdfjs-dist": "4.2.67",
"prismjs": "1.29.0",
"prop-types": "15.8.1",
"quill": "2.0.2",
"quill-markdown-shortcuts": "0.0.10",
"quilljs-markdown": "1.2.0",
"react": "18.2.0",
"react-aria": "3.29.1",
"react-autosize-textarea": "7.1.0",
"react-blurhash": "0.2.0",
"react-dom": "18.2.0",
"react-draggable": "4.4.6",
"react-error-boundary": "4.0.13",
"react-google-recaptcha": "2.1.0",
"react-modal": "3.16.1",
"react-quill": "2.0.0",
"react-quilljs": "2.0.2",
"react-range": "1.8.14",
"react-router-dom": "6.20.0",
"sanitize-html": "2.12.1",
"showdown": "2.1.0",
"slate": "0.94.1",
"slate-history": "0.93.0",
"slate-react": "0.98.4",
"tippy.js": "6.3.7",
"ua-parser-js": "1.0.35",
"url": "0.11.3",
"uuid": "10.0.0"
},
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rollup/plugin-inject": "5.0.3",
"@rollup/plugin-wasm": "6.1.1",
"@types/file-saver": "2.0.5",
"@types/node": "18.11.18",
"@types/prismjs": "1.26.0",
"@types/react": "18.2.39",
"@types/react-dom": "18.2.17",
"@types/react-google-recaptcha": "2.1.8",
"@types/sanitize-html": "2.9.0",
"@types/showdown": "2.0.6",
"@types/ua-parser-js": "0.7.36",
"@types/uuid": "10.0.0",
"@typescript-eslint/eslint-plugin": "5.46.1",
"@typescript-eslint/parser": "5.46.1",
"@vitejs/plugin-react": "4.2.0",
"buffer": "6.0.3",
"eslint": "8.29.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jsx-a11y": "6.6.1",
"eslint-plugin-react": "7.31.11",
"eslint-plugin-react-hooks": "4.6.0",
"prettier": "2.8.1",
"sass": "1.56.2",
"typescript": "4.9.4",
"vite": "5.0.13",
"vite-plugin-static-copy": "1.0.4",
"vite-plugin-top-level-await": "1.4.1"
}
}
"name": "extera",
"version": "1.1.0",
"description": "Fork of Cinny with new features and slightly different design",
"main": "index.js",
"type": "module",
"engines": {
"node": ">=16.0.0"
},
"scripts": {
"start": "vite",
"build": "vite build",
"lint": "yarn check:eslint && yarn check:prettier",
"check:eslint": "eslint src/*",
"check:prettier": "prettier --check .",
"fix:prettier": "prettier --write .",
"typecheck": "tsc --noEmit"
},
"keywords": [],
"author": "OfficialDakari",
"license": "AGPL-3.0-only",
"dependencies": {
"@atlaskit/pragmatic-drag-and-drop": "1.1.6",
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "1.3.0",
"@atlaskit/pragmatic-drag-and-drop-hitbox": "1.0.3",
"@fontsource/inter": "4.5.14",
"@matrix-org/olm": "3.2.14",
"@mdi/js": "7.4.47",
"@mdi/react": "1.6.1",
"@tanstack/react-query": "5.24.1",
"@tanstack/react-query-devtools": "5.24.1",
"@tanstack/react-virtual": "3.2.0",
"@tippyjs/react": "4.2.6",
"@vanilla-extract/css": "1.9.3",
"@vanilla-extract/recipes": "0.3.0",
"@vanilla-extract/vite-plugin": "3.7.1",
"anafanafo": "2.0.0",
"await-to-js": "3.0.0",
"badge-maker": "4.0.0",
"blurhash": "2.0.4",
"browser-encrypt-attachment": "0.3.0",
"classnames": "2.3.2",
"dateformat": "5.0.3",
"dayjs": "1.11.10",
"domhandler": "5.0.3",
"emojibase": "6.1.0",
"emojibase-data": "7.0.1",
"file-saver": "2.0.5",
"flux": "4.0.3",
"focus-trap-react": "10.0.2",
"folds": "2.0.0",
"formik": "2.4.6",
"html-dom-parser": "4.0.0",
"html-react-parser": "4.2.0",
"immer": "9.0.16",
"is-hotkey": "0.2.0",
"jotai": "2.6.0",
"linkify-react": "4.1.3",
"linkifyjs": "4.1.3",
"marked": "13.0.2",
"matrix-js-sdk": "29.1.0",
"millify": "6.1.0",
"pdfjs-dist": "4.2.67",
"prismjs": "1.29.0",
"prop-types": "15.8.1",
"quill": "2.0.2",
"quill-markdown-shortcuts": "0.0.10",
"quilljs-markdown": "1.2.0",
"react": "18.2.0",
"react-aria": "3.29.1",
"react-autosize-textarea": "7.1.0",
"react-blurhash": "0.2.0",
"react-dom": "18.2.0",
"react-draggable": "4.4.6",
"react-error-boundary": "4.0.13",
"react-google-recaptcha": "2.1.0",
"react-modal": "3.16.1",
"react-quill": "2.0.0",
"react-quilljs": "2.0.2",
"react-range": "1.8.14",
"react-router-dom": "6.20.0",
"sanitize-html": "2.12.1",
"showdown": "2.1.0",
"slate": "0.94.1",
"slate-history": "0.93.0",
"slate-react": "0.98.4",
"tippy.js": "6.3.7",
"ua-parser-js": "1.0.35",
"url": "0.11.3",
"uuid": "10.0.0"
},
"devDependencies": {
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
"@rollup/plugin-inject": "5.0.3",
"@rollup/plugin-wasm": "6.1.1",
"@types/file-saver": "2.0.5",
"@types/node": "18.11.18",
"@types/prismjs": "1.26.0",
"@types/react": "18.2.39",
"@types/react-dom": "18.2.17",
"@types/react-google-recaptcha": "2.1.8",
"@types/sanitize-html": "2.9.0",
"@types/showdown": "2.0.6",
"@types/ua-parser-js": "0.7.36",
"@types/uuid": "10.0.0",
"@typescript-eslint/eslint-plugin": "5.46.1",
"@typescript-eslint/parser": "5.46.1",
"@vitejs/plugin-react": "4.2.0",
"buffer": "6.0.3",
"eslint": "8.29.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-jsx-a11y": "6.6.1",
"eslint-plugin-react": "7.31.11",
"eslint-plugin-react-hooks": "4.6.0",
"prettier": "2.8.1",
"sass": "1.56.2",
"typescript": "4.9.4",
"vite": "5.0.13",
"vite-plugin-static-copy": "1.0.4",
"vite-plugin-top-level-await": "1.4.1"
}
}

View file

@ -1,5 +1,5 @@
import React, { KeyboardEvent as ReactKeyboardEvent, useCallback, useEffect } from 'react';
import { Avatar, Icon, Icons, MenuItem, Text } from 'folds';
import { Avatar, MenuItem, Text } from 'folds';
import { JoinRule, MatrixClient } from 'matrix-js-sdk';
import { useAtomValue } from 'jotai';
@ -15,6 +15,8 @@ import { mDirectAtom } from '../../../state/mDirectList';
import { allRoomsAtom } from '../../../state/room-list/roomList';
import { factoryRoomIdByActivity } from '../../../utils/sort';
import { RoomAvatar, RoomIcon } from '../../room-avatar';
import Icon from '@mdi/react';
import { mdiPound } from '@mdi/js';
type MentionAutoCompleteHandler = (roomAliasOrId: string, name: string) => void;
@ -44,7 +46,7 @@ function UnknownRoomMentionItem({
onMouseDown={(evt: any) => { evt.preventDefault() }}
before={
<Avatar size="200">
<Icon src={Icons.Hash} size="100" />
<Icon size={0.7} path={mdiPound} />
</Avatar>
}
>

View file

@ -1,5 +1,5 @@
import React, { useEffect, KeyboardEvent as ReactKeyboardEvent } from 'react';
import { Avatar, Icon, Icons, MenuItem, Text } from 'folds';
import { Avatar, MenuItem, Text } from 'folds';
import { MatrixClient, Room, RoomMember } from 'matrix-js-sdk';
import { AutocompleteQuery } from './autocompleteQuery';
@ -16,6 +16,8 @@ import { useKeyDown } from '../../../hooks/useKeyDown';
import { getMxIdLocalPart, getMxIdServer, validMxId } from '../../../utils/matrix';
import { getMemberDisplayName, getMemberSearchStr } from '../../../utils/room';
import { UserAvatar } from '../../user-avatar';
import { mdiAccount } from '@mdi/js';
import Icon from '@mdi/react';
type MentionAutoCompleteHandler = (userId: string, name: string) => void;
@ -46,7 +48,7 @@ function UnknownMentionItem({
<Avatar size="200">
<UserAvatar
userId={userId}
renderFallback={() => <Icon size="50" src={Icons.User} filled />}
renderFallback={() => <Icon size={0.7} path={mdiAccount} />}
/>
</Avatar>
}
@ -170,7 +172,7 @@ export function UserMentionAutocomplete({
userId={roomMember.userId}
src={avatarUrl ?? undefined}
alt={getName(roomMember)}
renderFallback={() => <Icon size="50" src={Icons.User} filled />}
renderFallback={() => <Icon size={0.7} path={mdiAccount} />}
/>
</Avatar>
}

View file

@ -1,6 +1,6 @@
/* eslint-disable jsx-a11y/media-has-caption */
import React, { ReactNode, useCallback, useRef, useState } from 'react';
import { Badge, Chip, Icon, IconButton, Icons, ProgressBar, Spinner, Text, toRem } from 'folds';
import { Badge, Chip, IconButton, ProgressBar, Spinner, Text, toRem } from 'folds';
import { EncryptedAttachmentInfo } from 'browser-encrypt-attachment';
import { Range } from 'react-range';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
@ -17,6 +17,8 @@ import {
} from '../../../hooks/media';
import { useThrottle } from '../../../hooks/useThrottle';
import { secondsToMinutesAndSeconds } from '../../../utils/common';
import Icon from '@mdi/react';
import { mdiPause, mdiPlayOutline, mdiVolumeHigh, mdiVolumeMute } from '@mdi/js';
const PLAY_TIME_THROTTLE_OPS = {
wait: 500,
@ -130,7 +132,7 @@ export function AudioContent({
srcState.status === AsyncStatus.Loading || loading ? (
<Spinner variant="Secondary" size="50" />
) : (
<Icon src={playing ? Icons.Pause : Icons.Play} size="50" filled={playing} />
<Icon size={0.8} path={playing ? mdiPause : mdiPlayOutline} />
)
}
>
@ -151,7 +153,7 @@ export function AudioContent({
onClick={() => setMute(!mute)}
aria-pressed={mute}
>
<Icon src={mute ? Icons.VolumeMute : Icons.VolumeHigh} size="50" />
<Icon size={0.8} path={mute ? mdiVolumeMute : mdiVolumeHigh} />
</IconButton>
<Range
step={0.1}

View file

@ -1,11 +1,12 @@
import { Box, Icon, IconSrc } from 'folds';
import { Box } from 'folds';
import React, { ReactNode } from 'react';
import { CompactLayout, ModernLayout } from '..';
import Icon from '@mdi/react';
export type EventContentProps = {
messageLayout: number;
time: ReactNode;
iconSrc: IconSrc;
iconSrc: string;
content: ReactNode;
};
export function EventContent({ messageLayout, time, iconSrc, content }: EventContentProps) {
@ -17,7 +18,7 @@ export function EventContent({ messageLayout, time, iconSrc, content }: EventCon
alignItems="Center"
justifyContent="Center"
>
<Icon style={{ opacity: 0.6 }} size="50" src={iconSrc} />
<Icon style={{ opacity: 0.6 }} size={0.8} path={iconSrc} />
</Box>
</Box>
);

View file

@ -1,6 +1,8 @@
import { Box, Icon, Icons, Text, as, color, config } from 'folds';
import { Box, Text, as, color, config } from 'folds';
import React from 'react';
import { getText } from '../../../../lang';
import { mdiAlert, mdiDelete, mdiLock, mdiLockAlert } from '@mdi/js';
import Icon from '@mdi/react';
const warningStyle = { color: color.Warning.Main, opacity: config.opacity.P300 };
const criticalStyle = { color: color.Critical.Main, opacity: config.opacity.P300 };
@ -8,7 +10,7 @@ const criticalStyle = { color: color.Critical.Main, opacity: config.opacity.P300
export const MessageDeletedContent = as<'div', { children?: never; reason?: string }>(
({ reason, ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" style={warningStyle} {...props} ref={ref}>
<Icon size="50" src={Icons.Delete} />
<Icon size={0.85} path={mdiDelete} />
{reason ? (
<i>{getText('msg.redacted.reason', reason)}</i>
) : (
@ -20,42 +22,42 @@ export const MessageDeletedContent = as<'div', { children?: never; reason?: stri
export const MessageUnsupportedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" style={criticalStyle} {...props} ref={ref}>
<Icon size="50" src={Icons.Warning} />
<Icon size={0.85} path={mdiAlert} />
<i>{getText('msg.unsupported')}</i>
</Box>
));
export const MessageFailedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" style={criticalStyle} {...props} ref={ref}>
<Icon size="50" src={Icons.Warning} />
<Icon size={0.85} path={mdiAlert} />
<i>{getText('msg.failed.load')}</i>
</Box>
));
export const MessageBadEncryptedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" style={warningStyle} {...props} ref={ref}>
<Icon size="50" src={Icons.Lock} />
<Icon size={0.85} path={mdiLockAlert} />
<i>{getText('msg.failed.decrypt')}</i>
</Box>
));
export const MessageNotDecryptedContent = as<'div', { children?: never }>(({ ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" style={warningStyle} {...props} ref={ref}>
<Icon size="50" src={Icons.Lock} />
<Icon size={0.85} path={mdiLockAlert} />
<i>{getText('msg.not_decrypted')}</i>
</Box>
));
export const MessageBrokenContent = as<'div', { children?: never }>(({ ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" style={criticalStyle} {...props} ref={ref}>
<Icon size="50" src={Icons.Warning} />
<Icon size={0.85} path={mdiAlert} />
<i>{getText('msg.broken')}</i>
</Box>
));
export const MessageEmptyContent = as<'div', { children?: never }>(({ ...props }, ref) => (
<Box as="span" alignItems="Center" gap="100" style={criticalStyle} {...props} ref={ref}>
<Icon size="50" src={Icons.Warning} />
<Icon size={0.85} path={mdiAlert} />
<i>{getText('msg.empty')}</i>
</Box>
));

View file

@ -2,8 +2,6 @@ import React, { ReactNode, useCallback, useState } from 'react';
import {
Box,
Button,
Icon,
Icons,
Modal,
Overlay,
OverlayBackdrop,
@ -32,6 +30,8 @@ import * as css from './style.css';
import { HTMLReactParserOptions } from 'html-react-parser';
import { RenderBody } from '../RenderBody';
import { getText } from '../../../../lang';
import Icon from '@mdi/react';
import { mdiAlert, mdiArrowDownBold, mdiArrowRight } from '@mdi/js';
const renderErrorButton = (retry: () => void, text: string) => (
<TooltipProvider
@ -52,7 +52,7 @@ const renderErrorButton = (retry: () => void, text: string) => (
outlined
radii="300"
onClick={retry}
before={<Icon size="100" src={Icons.Warning} filled />}
before={<Icon size={1} path={mdiAlert} />}
>
<Text size="B400" truncate>
{text}
@ -143,7 +143,7 @@ export function ReadTextFile({ body, mimeType, url, encInfo, renderViewer, forma
textState.status === AsyncStatus.Loading ? (
<Spinner fill="Solid" size="100" variant="Secondary" />
) : (
<Icon size="100" src={Icons.ArrowRight} filled />
<Icon size={1} path={mdiArrowRight} />
)
}
>
@ -224,7 +224,7 @@ export function ReadPdfFile({ body, mimeType, url, encInfo, renderViewer, format
pdfState.status === AsyncStatus.Loading ? (
<Spinner fill="Solid" size="100" variant="Secondary" />
) : (
<Icon size="100" src={Icons.ArrowRight} filled />
<Icon size={1} path={mdiArrowRight} />
)
}
>
@ -278,7 +278,7 @@ export function DownloadFile({ body, mimeType, url, info, encInfo, filename, for
downloadState.status === AsyncStatus.Loading ? (
<Spinner fill="Soft" size="100" variant="Secondary" />
) : (
<Icon size="100" src={Icons.Download} filled />
<Icon size={1} path={mdiArrowDownBold} />
)
}
>

View file

@ -3,8 +3,6 @@ import {
Badge,
Box,
Button,
Icon,
Icons,
Modal,
Overlay,
OverlayBackdrop,
@ -30,6 +28,8 @@ import { RenderBody } from '../RenderBody';
import HTMLReactParser, { HTMLReactParserOptions } from 'html-react-parser';
import { getReactCustomHtmlParser } from '../../../plugins/react-custom-html-parser';
import { getText } from '../../../../lang';
import { mdiAlert, mdiImage } from '@mdi/js';
import Icon from '@mdi/react';
type RenderViewerProps = {
src: string;
@ -152,7 +152,7 @@ export const ImageContent = as<'div', ImageContentProps>(
radii="300"
size="300"
onClick={loadSrc}
before={<Icon size="Inherit" src={Icons.Photo} filled />}
before={<Icon size={1} path={mdiImage} />}
>
<Text size="B300">{getText('btn.view')}</Text>
</Button>
@ -197,7 +197,7 @@ export const ImageContent = as<'div', ImageContentProps>(
outlined
radii="300"
onClick={handleRetry}
before={<Icon size="Inherit" src={Icons.Warning} filled />}
before={<Icon size={1} path={mdiAlert} />}
>
<Text size="B300">{getText('btn.retry')}</Text>
</Button>

View file

@ -1,4 +1,4 @@
import { Box, Icon, Icons, MenuItem, Text, as, color, config } from 'folds';
import { Box, MenuItem, Text, as, color, config } from 'folds';
import React, { useState, useEffect, useCallback } from 'react';
import * as css from './style.css';
import ProgressBar from '../../progressbar';

View file

@ -3,8 +3,6 @@ import {
Badge,
Box,
Button,
Icon,
Icons,
Spinner,
Text,
Tooltip,
@ -26,6 +24,8 @@ import { getFileSrcUrl } from './util';
import { bytesToSize } from '../../../../util/common';
import { millisecondsToMinutesAndSeconds } from '../../../utils/common';
import { getText } from '../../../../lang';
import Icon from '@mdi/react';
import { mdiAlert, mdiPlay } from '@mdi/js';
type RenderVideoProps = {
title: string;
@ -115,7 +115,7 @@ export const VideoContent = as<'div', VideoContentProps>(
radii="300"
size="300"
onClick={loadSrc}
before={<Icon size="Inherit" src={Icons.Play} filled />}
before={<Icon size={1} path={mdiPlay} />}
>
<Text size="B300">{getText('btn.watch')}</Text>
</Button>
@ -159,7 +159,7 @@ export const VideoContent = as<'div', VideoContentProps>(
outlined
radii="300"
onClick={handleRetry}
before={<Icon size="Inherit" src={Icons.Warning} filled />}
before={<Icon size={1} path={mdiAlert} />}
>
<Text size="B300">{getText('btn.retry')}</Text>
</Button>

View file

@ -4,8 +4,6 @@ import {
Badge,
Box,
Chip,
Icon,
Icons,
Line,
Overlay,
OverlayBackdrop,
@ -40,6 +38,8 @@ import { ErrorCode } from '../../cs-errorcode';
import { getDirectRoomAvatarUrl, getRoomAvatarUrl } from '../../utils/room';
import { ItemDraggableTarget, useDraggableItem } from './DnD';
import { getText } from '../../../lang';
import Icon from '@mdi/react';
import { mdiAlert, mdiArrowRight, mdiPlus } from '@mdi/js';
type RoomJoinButtonProps = {
roomId: string;
@ -70,15 +70,14 @@ function RoomJoinButton({ roomId, via }: RoomJoinButtonProps) {
}
>
{(triggerRef) => (
<Icon
ref={triggerRef}
style={{ color: color.Critical.Main, cursor: 'pointer' }}
src={Icons.Warning}
size="400"
filled
tabIndex={0}
aria-label={joinState.error.data?.error || joinState.error.message}
/>
<span ref={triggerRef}>
<Icon
style={{ color: color.Critical.Main, cursor: 'pointer' }}
path={mdiAlert}
size={1}
aria-label={joinState.error.data?.error || joinState.error.message}
/>
</span>
)}
</TooltipProvider>
)}
@ -88,7 +87,7 @@ function RoomJoinButton({ roomId, via }: RoomJoinButtonProps) {
size="400"
radii="Pill"
before={
canJoin ? <Icon src={Icons.Plus} size="50" /> : <Spinner variant="Secondary" size="100" />
canJoin ? <Icon size={0.8} path={mdiPlus} /> : <Spinner variant="Secondary" size="100" />
}
onClick={join}
disabled={!canJoin}
@ -381,7 +380,7 @@ export const RoomItemCard = as<'div', RoomItemCardProps>(
radii="Pill"
aria-label="Open Room"
>
<Icon size="50" src={Icons.ArrowRight} />
<Icon size={0.8} path={mdiArrowRight} />
</Chip>
</Box>
) : (

View file

@ -4,8 +4,6 @@ import {
Avatar,
Text,
Chip,
Icon,
Icons,
as,
Badge,
toRem,
@ -35,6 +33,8 @@ import { ErrorCode } from '../../cs-errorcode';
import { useDraggableItem } from './DnD';
import { openCreateRoom, openSpaceAddExisting } from '../../../client/action/navigation';
import { getText } from '../../../lang';
import { mdiChevronDown, mdiChevronRight, mdiPlus } from '@mdi/js';
import Icon from '@mdi/react';
function SpaceProfileLoading() {
return (
@ -145,7 +145,7 @@ function UnknownSpaceProfile({
</Avatar>
}
after={
canJoin ? <Icon src={Icons.Plus} size="50" /> : <Spinner variant="Secondary" size="200" />
canJoin ? <Icon size={0.8} path={mdiPlus} /> : <Spinner variant="Secondary" size="200" />
}
>
<Box alignItems="Center" gap="200">
@ -208,7 +208,7 @@ function SpaceProfile({
/>
</Avatar>
}
after={<Icon src={closed ? Icons.ChevronRight : Icons.ChevronBottom} size="50" />}
after={<Icon size={0.8} path={closed ? mdiChevronRight : mdiChevronDown} />}
>
<Box alignItems="Center" gap="200">
<Text size="H4" truncate>
@ -237,7 +237,7 @@ function RootSpaceProfile({ closed, categoryId, handleClose }: RootSpaceProfileP
className={css.HeaderChip}
variant="Surface"
size="500"
after={<Icon src={closed ? Icons.ChevronRight : Icons.ChevronBottom} size="50" />}
after={<Icon size={0.8} path={closed ? mdiChevronRight : mdiChevronDown} />}
>
<Box alignItems="Center" gap="200">
<Text size="H4" truncate>
@ -300,7 +300,7 @@ function AddRoomButton({ item }: { item: HierarchyItem }) {
<Chip
variant="Primary"
radii="Pill"
before={<Icon src={Icons.Plus} size="50" />}
before={<Icon size={0.8} path={mdiPlus} />}
onClick={handleAddRoom}
aria-pressed={!!cords}
>
@ -361,7 +361,7 @@ function AddSpaceButton({ item }: { item: HierarchyItem }) {
<Chip
variant="SurfaceVariant"
radii="Pill"
before={<Icon src={Icons.Plus} size="50" />}
before={<Icon size={0.8} path={mdiPlus} />}
onClick={handleAddSpace}
aria-pressed={!!cords}
>

View file

@ -1,5 +1,5 @@
import React, { RefObject, useEffect, useMemo, useRef } from 'react';
import { Text, Box, Icon, Icons, config, Spinner, IconButton, Line, toRem } from 'folds';
import { Text, Box, config, Spinner, IconButton, Line, toRem } from 'folds';
import { useAtomValue } from 'jotai';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useInfiniteQuery } from '@tanstack/react-query';
@ -24,6 +24,8 @@ import { SearchInput } from './SearchInput';
import { SearchFilters } from './SearchFilters';
import { VirtualTile } from '../../components/virtualizer';
import { getText, translate } from '../../../lang';
import Icon from '@mdi/react';
import { mdiAlertCircleOutline, mdiChevronUp, mdiMessageOutline } from '@mdi/js';
const useSearchPathSearchParams = (searchParams: URLSearchParams): _SearchPathSearchParams =>
useMemo(
@ -196,7 +198,7 @@ export function MessageSearch({
size="300"
aria-label={getText('aria.scroll_to_top')}
>
<Icon src={Icons.ChevronTop} size="300" />
<Icon size={0.8} path={mdiChevronUp} />
</IconButton>
</ScrollTopContainer>
<Box ref={scrollTopAnchorRef} direction="Column" gap="300">
@ -235,7 +237,7 @@ export function MessageSearch({
>
<PageHeroSection>
<PageHero
icon={<Icon size="600" src={Icons.Message} />}
icon={<Icon size={0.8} path={mdiMessageOutline} />}
title={getText('msg_search.title.2')}
subTitle={getText('msg_search.subtitle.2')}
/>
@ -250,7 +252,7 @@ export function MessageSearch({
alignItems="Center"
gap="200"
>
<Icon size="200" src={Icons.Info} />
<Icon size={0.8} path={mdiAlertCircleOutline} />
<Text>
{translate('generic.no_results', <b>{`"${msgSearchParams.term}"`}</b>)}
</Text>

View file

@ -10,8 +10,6 @@ import {
Box,
Chip,
Text,
Icon,
Icons,
Line,
config,
PopOut,
@ -25,7 +23,7 @@ import {
Badge,
RectCords,
} from 'folds';
import { SearchOrderBy } from 'matrix-js-sdk';
import { JoinRule, SearchOrderBy } from 'matrix-js-sdk';
import FocusTrap from 'focus-trap-react';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useMatrixClient } from '../../hooks/useMatrixClient';
@ -39,6 +37,8 @@ import {
import { DebounceOptions, useDebounce } from '../../hooks/useDebounce';
import { VirtualTile } from '../../components/virtualizer';
import { getText } from '../../../lang';
import Icon from '@mdi/react';
import { mdiCheck, mdiClose, mdiMessageLockOutline, mdiMessageOutline, mdiPlusCircleOutline, mdiSort } from '@mdi/js';
type OrderButtonProps = {
order?: string;
@ -101,7 +101,7 @@ function OrderButton({ order, onChange }: OrderButtonProps) {
<Chip
variant="SurfaceVariant"
radii="Pill"
after={<Icon size="50" src={Icons.Sort} />}
after={<Icon size={0.8} path={mdiSort} />}
onClick={handleOpenMenu}
>
{<Text size="T200">{getText(rankOrder ? 'sort.relevance' : 'sort.recent')}</Text>}
@ -271,9 +271,11 @@ function SelectRoomButton({ roomList, selectedRooms, onChange }: SelectRoomButto
aria-pressed={selected}
before={
<Icon
size="50"
src={
joinRuleToIconSrc(Icons, room.getJoinRule(), false) ?? Icons.Hash
size={0.8}
path={
room.getJoinRule() !== JoinRule.Public ?
mdiMessageLockOutline :
mdiMessageOutline
}
/>
}
@ -317,7 +319,7 @@ function SelectRoomButton({ roomList, selectedRooms, onChange }: SelectRoomButto
onClick={handleOpenMenu}
variant="SurfaceVariant"
radii="Pill"
before={<Icon size="100" src={Icons.PlusCircle} />}
before={<Icon size={0.8} path={mdiPlusCircleOutline} />}
>
<Text size="T200">{getText('search_filters.select_rooms')}</Text>
</Chip>
@ -356,7 +358,7 @@ export function SearchFilters({
<Chip
variant={!global ? 'Success' : 'Surface'}
aria-pressed={!global}
before={!global && <Icon size="100" src={Icons.Check} />}
before={!global && <Icon size={0.8} path={mdiCheck} />}
outlined
onClick={() => onGlobalChange()}
>
@ -366,7 +368,7 @@ export function SearchFilters({
<Chip
variant={global ? 'Success' : 'Surface'}
aria-pressed={global}
before={global && <Icon size="100" src={Icons.Check} />}
before={global && <Icon size={0.8} path={mdiCheck} />}
outlined
onClick={() => onGlobalChange(true)}
>
@ -391,11 +393,15 @@ export function SearchFilters({
radii="Pill"
before={
<Icon
size="50"
src={joinRuleToIconSrc(Icons, room.getJoinRule(), false) ?? Icons.Hash}
size={0.8}
path={
room.getJoinRule() !== JoinRule.Public ?
mdiMessageLockOutline :
mdiMessageOutline
}
/>
}
after={<Icon size="50" src={Icons.Cross} />}
after={<Icon size={0.8} path={mdiClose} />}
>
<Text size="T200">{room.name}</Text>
</Chip>

View file

@ -1,67 +1,69 @@
import React, { FormEventHandler, RefObject } from 'react';
import { Box, Text, Input, Icon, Icons, Spinner, Chip, config } from 'folds';
import { Box, Text, Input, Spinner, Chip, config } from 'folds';
import { getText } from '../../../lang';
import Icon from '@mdi/react';
import { mdiClose, mdiMagnify } from '@mdi/js';
type SearchProps = {
active?: boolean;
loading?: boolean;
searchInputRef: RefObject<HTMLInputElement>;
onSearch: (term: string) => void;
onReset: () => void;
active?: boolean;
loading?: boolean;
searchInputRef: RefObject<HTMLInputElement>;
onSearch: (term: string) => void;
onReset: () => void;
};
export function SearchInput({ active, loading, searchInputRef, onSearch, onReset }: SearchProps) {
const handleSearchSubmit: FormEventHandler<HTMLFormElement> = (evt) => {
evt.preventDefault();
const { searchInput } = evt.target as HTMLFormElement & {
searchInput: HTMLInputElement;
const handleSearchSubmit: FormEventHandler<HTMLFormElement> = (evt) => {
evt.preventDefault();
const { searchInput } = evt.target as HTMLFormElement & {
searchInput: HTMLInputElement;
};
const searchTerm = searchInput.value.trim() || undefined;
if (searchTerm) {
onSearch(searchTerm);
}
};
const searchTerm = searchInput.value.trim() || undefined;
if (searchTerm) {
onSearch(searchTerm);
}
};
return (
<Box as="form" direction="Column" gap="100" onSubmit={handleSearchSubmit}>
<span data-spacing-node />
<Text size="L400">{getText('search_input.header')}</Text>
<Input
ref={searchInputRef}
style={{ paddingRight: config.space.S300 }}
name="searchInput"
size="500"
variant="Background"
placeholder={getText('placeholder.search_input')}
autoComplete="off"
before={
active && loading ? (
<Spinner variant="Secondary" size="200" />
) : (
<Icon size="200" src={Icons.Search} />
)
}
after={
active ? (
<Chip
key="resetButton"
type="reset"
variant="Secondary"
size="400"
radii="Pill"
outlined
after={<Icon size="50" src={Icons.Cross} />}
onClick={onReset}
>
<Text size="B300">{getText('btn.search.clear')}</Text>
</Chip>
) : (
<Chip type="submit" variant="Primary" size="400" radii="Pill" outlined>
<Text size="B300">{getText('search_input.clear')}</Text>
</Chip>
)
}
/>
</Box>
);
return (
<Box as="form" direction="Column" gap="100" onSubmit={handleSearchSubmit}>
<span data-spacing-node />
<Text size="L400">{getText('search_input.header')}</Text>
<Input
ref={searchInputRef}
style={{ paddingRight: config.space.S300 }}
name="searchInput"
size="500"
variant="Background"
placeholder={getText('placeholder.search_input')}
autoComplete="off"
before={
active && loading ? (
<Spinner variant="Secondary" size="200" />
) : (
<Icon size={1} path={mdiMagnify} />
)
}
after={
active ? (
<Chip
key="resetButton"
type="reset"
variant="Secondary"
size="400"
radii="Pill"
outlined
after={<Icon size={1} path={mdiClose} />}
onClick={onReset}
>
<Text size="B300">{getText('btn.search.clear')}</Text>
</Chip>
) : (
<Chip type="submit" variant="Primary" size="400" radii="Pill" outlined>
<Text size="B300">{getText('search_input.clear')}</Text>
</Chip>
)
}
/>
</Box>
);
}

View file

@ -2,7 +2,7 @@
import React, { MouseEventHandler, useMemo } from 'react';
import { IEventWithRoomId, JoinRule, RelationType, Room } from 'matrix-js-sdk';
import { HTMLReactParserOptions } from 'html-react-parser';
import { Avatar, Box, Chip, Header, Icon, Icons, Text, config } from 'folds';
import { Avatar, Box, Chip, Header, Text, config } from 'folds';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import {
getReactCustomHtmlParser,
@ -34,6 +34,8 @@ import { SequenceCard } from '../../components/sequence-card';
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
import { UserAvatar } from '../../components/user-avatar';
import { getText, translate } from '../../../lang';
import Icon from '@mdi/react';
import { mdiAccount } from '@mdi/js';
type SearchResultGroupProps = {
room: Room;
@ -215,7 +217,7 @@ export function SearchResultGroup({
: undefined
}
alt={displayName}
renderFallback={() => <Icon size="200" src={Icons.User} filled />}
renderFallback={() => <Icon size={1} path={mdiAccount} />}
/>
</Avatar>
</AvatarBase>

View file

@ -1,7 +1,9 @@
import React from 'react';
import { as, Chip, Icon, Icons, Text } from 'folds';
import { as, Chip, Text } from 'folds';
import classNames from 'classnames';
import * as css from './styles.css';
import Icon from '@mdi/react';
import { mdiChevronDown, mdiChevronRight } from '@mdi/js';
export const RoomNavCategoryButton = as<'button', { closed?: boolean }>(
({ className, closed, children, ...props }, ref) => (
@ -12,8 +14,8 @@ export const RoomNavCategoryButton = as<'button', { closed?: boolean }>(
before={
<Icon
className={css.CategoryButtonIcon}
size="50"
src={closed ? Icons.ChevronRight : Icons.ChevronBottom}
size={1}
path={closed ? mdiChevronRight : mdiChevronDown}
/>
}
{...props}

View file

@ -3,9 +3,7 @@ import { Room } from 'matrix-js-sdk';
import {
Avatar,
Box,
Icon,
IconButton,
Icons,
Text,
Menu,
MenuItem,
@ -42,6 +40,8 @@ import { allRoomsAtom } from '../../state/room-list/roomList';
import { useDirects } from '../../state/hooks/roomList';
import { usePresences } from '../../hooks/usePresences';
import { getText } from '../../../lang';
import Icon from '@mdi/react';
import { mdiAccountPlus, mdiArrowLeft, mdiBellCancel, mdiCheckAll, mdiCog, mdiDotsVertical, mdiLinkVariant } from '@mdi/js';
type RoomNavItemMenuProps = {
room: Room;
@ -83,7 +83,7 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
<MenuItem
onClick={handleMarkAsRead}
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<Icon size={1} path={mdiCheckAll} />}
radii="300"
disabled={!unread}
>
@ -99,7 +99,7 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
variant="Primary"
fill="None"
size="300"
after={<Icon size="100" src={Icons.UserPlus} />}
after={<Icon size={1} path={mdiAccountPlus} />}
radii="300"
disabled={!canInvite}
>
@ -110,7 +110,7 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
<MenuItem
onClick={handleCopyLink}
size="300"
after={<Icon size="100" src={Icons.Link} />}
after={<Icon size={1} path={mdiLinkVariant} />}
radii="300"
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
@ -120,7 +120,7 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
<MenuItem
onClick={handleRoomSettings}
size="300"
after={<Icon size="100" src={Icons.Setting} />}
after={<Icon size={1} path={mdiCog} />}
radii="300"
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
@ -138,7 +138,7 @@ const RoomNavItemMenu = forwardRef<HTMLDivElement, RoomNavItemMenuProps>(
variant="Critical"
fill="None"
size="300"
after={<Icon size="100" src={Icons.ArrowGoLeft} />}
after={<Icon size={1} path={mdiArrowLeft} />}
radii="300"
aria-pressed={promptLeave}
>
@ -303,7 +303,7 @@ export function RoomNavItem({
<UnreadBadge highlight={unread.highlight > 0} count={unread.total} />
</UnreadBadgeCenter>
)}
{muted && !optionsVisible && <Icon size="50" src={Icons.BellMute} />}
{muted && !optionsVisible && <Icon size={1} path={mdiBellCancel} />}
</Box>
</NavItemContent>
</NavLink>
@ -342,7 +342,7 @@ export function RoomNavItem({
size="300"
radii="300"
>
<Icon size="50" src={Icons.VerticalDots} />
<Icon size={1} path={mdiDotsVertical} />
</IconButton>
</PopOut>
</NavItemOptions>

View file

@ -14,9 +14,7 @@ import {
Chip,
ContainerColor,
Header,
Icon,
IconButton,
Icons,
Input,
Menu,
MenuItem,
@ -58,6 +56,8 @@ import { UserAvatar } from '../../components/user-avatar';
import { useRoomTypingMember } from '../../hooks/useRoomTypingMembers';
import { usePresences } from '../../hooks/usePresences';
import { getText } from '../../../lang';
import { mdiAccount, mdiChevronUp, mdiClose, mdiFilterOutline, mdiMagnify, mdiSort } from '@mdi/js';
import Icon from '@mdi/react';
export const MembershipFilters = {
filterJoined: (m: RoomMember) => m.membership === Membership.Join,
@ -317,7 +317,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
variant="Background"
onClick={() => setPeopleDrawer(false)}
>
<Icon src={Icons.Cross} />
<Icon size={1} path={mdiClose} />
</IconButton>
)}
</TooltipProvider>
@ -380,7 +380,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
variant={membershipFilter.color}
size="400"
radii="300"
before={<Icon src={Icons.Filter} size="50" />}
before={<Icon size={1} path={mdiFilterOutline} />}
>
<Text size="T200">{membershipFilter.name}</Text>
</Chip>
@ -434,7 +434,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
variant="Background"
size="400"
radii="300"
after={<Icon src={Icons.Sort} size="50" />}
after={<Icon size={1} path={mdiSort} />}
>
<Text size="T200">{sortFilter.name}</Text>
</Chip>
@ -451,7 +451,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
variant="Surface"
size="400"
radii="400"
before={<Icon size="50" src={Icons.Search} />}
before={<Icon size={1} path={mdiMagnify} />}
after={
result && (
<Chip
@ -466,7 +466,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
}
resetSearch();
}}
after={<Icon size="50" src={Icons.Cross} />}
after={<Icon size={1} path={mdiClose} />}
>
<Text size="B300">{result.items.length ? getText('generic.result_count', result.items.length) : getText('generic.no_results.2')}</Text>
</Chip>
@ -485,7 +485,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
size="300"
aria-label={getText('aria.scroll_to_top')}
>
<Icon src={Icons.ChevronTop} size="300" />
<Icon size={1} path={mdiChevronUp} />
</IconButton>
</ScrollTopContainer>
@ -552,7 +552,7 @@ export function MembersDrawer({ room }: MembersDrawerProps) {
userId={member.userId}
src={avatarUrl ?? undefined}
alt={name}
renderFallback={() => <Icon size="50" src={Icons.User} filled />}
renderFallback={() => <Icon size={1} path={mdiAccount} />}
/>
</Avatar>
}

View file

@ -62,5 +62,6 @@ export const UserAvatar = style({
export const VideoFeed = style({
maxWidth: '400px',
maxHeight: '400px'
maxHeight: '400px',
borderRadius: config.radii.R300
});

View file

@ -1,6 +1,6 @@
import React, { CSSProperties, useCallback, useEffect, useRef, useState } from 'react';
import { Avatar, Box, Icon, IconButton, Icons, Text } from "folds";
import { Avatar, Box, IconButton, Text } from "folds";
import { CallEvent, Room, User } from "matrix-js-sdk";
import * as css from './RoomCall.css';
@ -10,8 +10,8 @@ import { AvatarBase } from '../../components/message';
import { CallErrorCode, CallState, MatrixCall } from 'matrix-js-sdk/lib/webrtc/call';
import { CallFeed } from 'matrix-js-sdk/lib/webrtc/callFeed';
import { SDPStreamMetadataPurpose } from 'matrix-js-sdk/lib/webrtc/callEventTypes';
import { Icon as MDIIcon } from '@mdi/react';
import { mdiMicrophone, mdiMicrophoneOff, mdiPhone, mdiPhoneHangup } from '@mdi/js';
import Icon, { Icon as MDIcon } from '@mdi/react';
import { mdiAccount, mdiCamera, mdiCameraOff, mdiMicrophone, mdiMicrophoneOff, mdiPhone, mdiPhoneHangup, mdiVideo, mdiVideoOff } from '@mdi/js';
import { translate } from '../../../lang';
// TODO refactor
@ -42,9 +42,10 @@ type RoomCallProps = {
call: MatrixCall;
onHangup: () => void;
invitation?: boolean;
video?: boolean;
};
export function RoomCall({ room, call, onHangup, invitation }: RoomCallProps) {
export function RoomCall({ room, call, onHangup, invitation, video }: RoomCallProps) {
const mx = useMatrixClient();
const mxId = mx.getUserId();
if (typeof mxId !== 'string') return null;
@ -63,9 +64,13 @@ export function RoomCall({ room, call, onHangup, invitation }: RoomCallProps) {
const [recipientShowVideo, setRecipientShowVideo] = useState(false);
const recipientVideoRef = useRef<HTMLVideoElement>(null);
const [localShowVideo, setLocalShowVideo] = useState(false);
const localVideoRef = useRef<HTMLVideoElement>(null);
const ringtoneRef = useRef<HTMLAudioElement>(null);
const [isMuted, setMuted] = useState(false);
const [isVideoMuted, setVideoMuted] = useState(false);
const handleHang = useCallback(() => {
console.debug(`hanging up`, call);
@ -89,6 +94,18 @@ export function RoomCall({ room, call, onHangup, invitation }: RoomCallProps) {
setMuted(newState);
}, []);
const handleVideoMute = useCallback(async () => {
if (!call) {
console.debug('No call, dont handling mute');
return;
}
const newState = !call.isLocalVideoMuted();
call.setLocalVideoMuted(newState);
setVideoMuted(newState);
}, []);
const handleReject = useCallback(async () => {
if (!call) return;
@ -105,26 +122,50 @@ export function RoomCall({ room, call, onHangup, invitation }: RoomCallProps) {
if (!call) return;
await call.answer(true, false);
if (video) {
call.setLocalVideoMuted(true);
}
}, []);
const handleVideoAccept = useCallback(async () => {
if (!call) return;
await call.answer(true, true);
}, []);
console.debug(`Rerendering RoomCall`);
call.on(CallEvent.FeedsChanged, (feeds: CallFeed[]) => {
feeds.forEach(feed => {
if (!feed.isLocal()) {
const remoteStream = feed.stream;
const remoteStream = feed.stream;
if (feed.isLocal()) {
if (!feed.isVideoMuted()) {
setLocalShowVideo(true);
setTimeout(() => {
if (localVideoRef.current) {
localVideoRef.current.srcObject = remoteStream;
localVideoRef.current.play().catch(console.error);
}
}, 1000);
}
} else {
console.debug(`REMOTE FEED!!!`, feed);
if (feed.hasAudioTrack) {
if (audioRef.current) {
audioRef.current.srcObject = remoteStream;
audioRef.current.play().catch(console.error);
}
} else {
if (recipientVideoRef.current) {
recipientVideoRef.current.srcObject = remoteStream;
recipientVideoRef.current.play().catch(console.error);
setRecipientShowVideo(true);
}
}
if (!feed.isVideoMuted()) {
setRecipientShowVideo(true);
setTimeout(() => {
if (recipientVideoRef.current) {
recipientVideoRef.current.srcObject = remoteStream;
recipientVideoRef.current.play().catch(console.error);
} else {
console.error(`NO RECIPIENT VIDEO REF!!!!!!! CRITICAL ERROR`);
}
}, 1000);
}
}
});
@ -162,23 +203,24 @@ export function RoomCall({ room, call, onHangup, invitation }: RoomCallProps) {
<Box grow='Yes' direction='Row'>
<div className={css.UsersDiv}>
<div className={css.UserAvatarBox}>
<AvatarBase className={css.UserAvatar}>
<Avatar
style={userStyle}
>
<UserAvatar
userId={user.userId}
alt={user.displayName ?? user.userId}
src={typeof user.avatarUrl === 'string' ? mx.mxcUrlToHttp(user.avatarUrl, 96, 96, 'scale', true) ?? undefined : undefined}
renderFallback={() => <Icon size="200" src={Icons.User} filled />}
/>
</Avatar>
</AvatarBase>
<video controls={false} autoPlay className={css.VideoFeed} style={{ display: localShowVideo ? 'block' : 'none' }} ref={localVideoRef} />
{!localShowVideo && (
<AvatarBase className={css.UserAvatar}>
<Avatar
style={userStyle}
>
<UserAvatar
userId={user.userId}
alt={user.displayName ?? user.userId}
src={typeof user.avatarUrl === 'string' ? mx.mxcUrlToHttp(user.avatarUrl, 96, 96, 'scale', true) ?? undefined : undefined}
renderFallback={() => <Icon size={1} path={mdiAccount} />}
/>
</Avatar>
</AvatarBase>
)}
</div>
<div className={css.UserAvatarBox}>
{recipientShowVideo && (
<video controls={false} autoPlay ref={recipientVideoRef} />
)}
<video controls={false} autoPlay className={css.VideoFeed} style={{ display: recipientShowVideo ? 'block' : 'none' }} ref={recipientVideoRef} />
{!recipientShowVideo && (
<AvatarBase className={css.UserAvatar}>
<Avatar
@ -188,7 +230,7 @@ export function RoomCall({ room, call, onHangup, invitation }: RoomCallProps) {
userId={recipient.userId}
alt={recipient.displayName ?? recipient.userId}
src={typeof recipient.avatarUrl === 'string' ? mx.mxcUrlToHttp(recipient.avatarUrl, 96, 96, 'scale', true) ?? undefined : undefined}
renderFallback={() => <Icon size="200" src={Icons.User} filled />}
renderFallback={() => <Icon size={1} path={mdiAccount} />}
/>
</Avatar>
</AvatarBase>
@ -197,17 +239,20 @@ export function RoomCall({ room, call, onHangup, invitation }: RoomCallProps) {
</div>
</Box>
<Box className={css.CallControlsContainer} grow='No' direction='Row'>
<IconButton variant='SurfaceVariant' onClick={handleVideoMute} aria-pressed={isVideoMuted}>
<MDIcon path={isVideoMuted ? mdiVideoOff : mdiVideo} size={1} />
</IconButton>
<IconButton variant='SurfaceVariant' onClick={handleMute} aria-pressed={isMuted}>
<MDIIcon path={isMuted ? mdiMicrophoneOff : mdiMicrophone} size={1} />
<MDIcon path={isMuted ? mdiMicrophoneOff : mdiMicrophone} size={1} />
</IconButton>
<IconButton variant='Critical' onClick={handleHang}>
<MDIIcon path={mdiPhoneHangup} size={1} />
<MDIcon path={mdiPhoneHangup} size={1} />
</IconButton>
</Box>
</>
)}
{
[CallState.Ringing, CallState.InviteSent, CallState.Connecting].includes(call.state) &&
[CallState.InviteSent, CallState.Connecting].includes(call.state) &&
(
<audio
src='https://officialdakari.ru/_matrix/media/r0/download/officialdakari.ru/rAiqpTddZoUUhcBVjPQORWJb'
@ -227,18 +272,30 @@ export function RoomCall({ room, call, onHangup, invitation }: RoomCallProps) {
/>
<div className={css.UsersDiv}>
<Text priority='400' size='H3'>{translate(
'title.incoming_call',
video ? 'title.incoming_video_call' : 'title.incoming_call',
<b>
{recipient.displayName ?? recipient.userId}
</b>
)}</Text>
</div>
{video && (
<div>
<Text style={{ color: 'red' }}>
<b>ATTENTION!</b> Due to a bug, recipient <i>will see your video feed</i> for less than a second, and then it will be <i>frozen picture</i> (Not blank screen, but a frozen picture!)
</Text>
</div>
)}
<Box className={css.CallControlsContainer} grow='No' direction='Row'>
{video && (
<IconButton variant='Success' onClick={handleVideoAccept}>
<MDIcon path={mdiVideo} size={1} />
</IconButton>
)}
<IconButton variant='Success' onClick={handleAccept}>
<MDIIcon path={mdiPhone} size={1} />
<MDIcon path={mdiPhone} size={1} />
</IconButton>
<IconButton variant='Critical' onClick={handleReject}>
<MDIIcon path={mdiPhoneHangup} size={1} />
<MDIcon path={mdiPhoneHangup} size={1} />
</IconButton>
</Box>
</>

View file

@ -18,9 +18,7 @@ import { EventTimeline, EventType, IContent, MsgType, Room } from 'matrix-js-sdk
import {
Box,
Dialog,
Icon,
IconButton,
Icons,
Line,
Overlay,
OverlayBackdrop,
@ -111,6 +109,8 @@ import { roomToParentsAtom } from '../../state/room/roomToParents';
import { getText } from '../../../lang';
import { openHiddenRooms } from '../../../client/action/navigation';
import { ScreenSize, useScreenSize } from '../../hooks/useScreenSize';
import Icon from '@mdi/react';
import { mdiCheckAll, mdiClose, mdiEmoticon, mdiEmoticonOutline, mdiFile, mdiPlusCircle, mdiPlusCircleOutline, mdiSend, mdiSendOutline, mdiSticker, mdiStickerOutline } from '@mdi/js';
interface RoomInputProps {
fileDropContainerRef: RefObject<HTMLElement>;
@ -479,7 +479,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
gap="500"
style={{ padding: toRem(60) }}
>
<Icon size="600" src={Icons.File} />
<Icon size={1} path={mdiFile} />
<Text size="H4" align="Center">
{getText('room_input.drop_files', room?.name || getText('room_input.drop_files.this_room'))}
</Text>
@ -561,7 +561,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
size="300"
radii="300"
>
<Icon src={Icons.Cross} size="50" />
<Icon size={1} path={mdiClose} />
</IconButton>
</Box>
</div>
@ -574,13 +574,13 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
size="300"
radii="300"
>
<Icon src={Icons.PlusCircle} />
<Icon size={1} path={mdiPlusCircleOutline} />
</IconButton>
}
after={
<>
<IconButton onMouseDown={dontHideKeyboard} onClick={readReceipt} variant="SurfaceVariant" size="300" radii="300">
<Icon src={Icons.CheckTwice} />
<Icon size={1} path={mdiCheckAll} />
</IconButton>
<UseStateProvider initial={undefined}>
{(emojiBoardTab: EmojiBoardTab | undefined, setEmojiBoardTab) => (
@ -623,8 +623,8 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
ref={emojiBtnRef}
>
<Icon
src={showStickerButton ? Icons.Sticker : Icons.Smile}
filled={!!emojiBoardTab}
size={1}
path={showStickerButton ? (!!emojiBoardTab ? mdiSticker : mdiStickerOutline) : (!!emojiBoardTab ? mdiEmoticon : mdiEmoticonOutline)}
/>
</IconButton>
)}
@ -633,7 +633,7 @@ export const RoomInput = forwardRef<HTMLDivElement, RoomInputProps>(
</UseStateProvider>
{screenSize !== ScreenSize.Mobile && (
<IconButton onMouseDown={dontHideKeyboard} onClick={submit} variant="SurfaceVariant" size="300" radii="300">
<Icon src={Icons.Send} />
<Icon size={1} path={mdiSendOutline} />
</IconButton>
)}
</>

View file

@ -34,8 +34,6 @@ import {
Box,
Chip,
ContainerColor,
Icon,
Icons,
Line,
Scroll,
Text,
@ -118,6 +116,8 @@ import { useSwipeLeft } from '../../hooks/useSwipeLeft';
import { clamp } from '../../utils/common';
import { parse } from 'url';
import { getText, translate } from '../../../lang';
import { mdiCheckAll, mdiChevronDown, mdiCodeBraces, mdiCodeBracesBox, mdiImageEdit, mdiMessageAlert, mdiPencilBox } from '@mdi/js';
import Icon from '@mdi/react';
const TimelineFloat = as<'div', css.TimelineFloatVariants>(
({ position, className, ...props }, ref) => (
@ -1378,7 +1378,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, textAreaRef }: RoomT
<EventContent
messageLayout={messageLayout}
time={timeJSX}
iconSrc={Icons.Hash}
iconSrc={mdiPencilBox}
content={
<Box grow="Yes" direction="Column">
<Text size="T300" priority="300">
@ -1411,7 +1411,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, textAreaRef }: RoomT
<EventContent
messageLayout={messageLayout}
time={timeJSX}
iconSrc={Icons.Hash}
iconSrc={mdiPencilBox}
content={
<Box grow="Yes" direction="Column">
<Text size="T300" priority="300">
@ -1444,7 +1444,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, textAreaRef }: RoomT
<EventContent
messageLayout={messageLayout}
time={timeJSX}
iconSrc={Icons.Hash}
iconSrc={mdiImageEdit}
content={
<Box grow="Yes" direction="Column">
<Text size="T300" priority="300">
@ -1479,7 +1479,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, textAreaRef }: RoomT
<EventContent
messageLayout={messageLayout}
time={timeJSX}
iconSrc={Icons.Code}
iconSrc={mdiCodeBracesBox}
content={
<Box grow="Yes" direction="Column">
<Text size="T300" priority="300">
@ -1517,7 +1517,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, textAreaRef }: RoomT
<EventContent
messageLayout={messageLayout}
time={timeJSX}
iconSrc={Icons.Code}
iconSrc={mdiCodeBracesBox}
content={
<Box grow="Yes" direction="Column">
<Text size="T300" priority="300">
@ -1626,7 +1626,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, textAreaRef }: RoomT
variant="Primary"
radii="Pill"
outlined
before={<Icon size="50" src={Icons.MessageUnread} />}
before={<Icon size={0.7} path={mdiMessageAlert} />}
onClick={handleJumpToUnread}
>
<Text size="L400">{getText('btn.timeline.jump_to_unread')}</Text>
@ -1636,7 +1636,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, textAreaRef }: RoomT
variant="SurfaceVariant"
radii="Pill"
outlined
before={<Icon size="50" src={Icons.CheckTwice} />}
before={<Icon size={0.7} path={mdiCheckAll} />}
onClick={handleMarkAsRead}
>
<Text size="L400">{getText('btn.timeline.mark_as_read')}</Text>
@ -1703,7 +1703,7 @@ export function RoomTimeline({ room, eventId, roomInputRef, textAreaRef }: RoomT
variant="SurfaceVariant"
radii="Pill"
outlined
before={<Icon size="50" src={Icons.ArrowBottom} />}
before={<Icon size={0.7} path={mdiChevronDown} />}
onClick={handleJumpToLatest}
>
<Text size="L400">{getText('btn.timeline.jump_to_latest')}</Text>

View file

@ -57,7 +57,7 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
const [callWindow, setCallWindow] = useRoomCall();
const handleCall = async () => {
if (callWindow) return;
if (callWindow) return console.error('A call is already going on');
const newCall = mx.createCall(room.roomId);
if (!newCall) return alert('Calls are not supported in your browser!');
setMxCall(newCall);
@ -93,6 +93,8 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
if (i > 10) return clearInterval(interval);
i++;
console.debug('Invited to a call!!!', content.offer);
const call = mx.callEventHandler?.calls.get(content.call_id);
if (!call) return console.debug('No call found', content.call_id, mx.callEventHandler?.calls);
@ -105,9 +107,11 @@ export function RoomView({ room, eventId }: { room: Room; eventId?: string }) {
return;
}
console.debug(`Call offer!!!`, content.offer);
setMxCall(call);
setCallWindow(
<RoomCall room={room} call={call} onHangup={onHangup} invitation={true} />
<RoomCall room={room} call={call} onHangup={onHangup} invitation={true} video={content.offer.sdp.includes('video')} />
);
}, 1000);
}

View file

@ -1,8 +1,6 @@
import React, { useState } from 'react';
import {
Box,
Icon,
Icons,
Modal,
Overlay,
OverlayBackdrop,
@ -23,6 +21,8 @@ import { useRoomLatestRenderedEvent } from '../../hooks/useRoomLatestRenderedEve
import { useRoomEventReaders } from '../../hooks/useRoomEventReaders';
import { EventReaders } from '../../components/event-readers';
import { getText, translate } from '../../../lang';
import { mdiCheckAll } from '@mdi/js';
import Icon from '@mdi/react';
export type RoomViewFollowingProps = {
room: Room;
@ -72,7 +72,7 @@ export const RoomViewFollowing = as<'div', RoomViewFollowingProps>(
>
{names.length > 0 && (
<>
<Icon style={{ opacity: config.opacity.P300 }} size="100" src={Icons.CheckTwice} />
<Icon style={{ opacity: config.opacity.P300 }} size={0.7} path={mdiCheckAll} />
<Text size="T300" truncate>
{names.length === 1 && (
<>

View file

@ -8,8 +8,6 @@ import {
OverlayCenter,
OverlayBackdrop,
IconButton,
Icon,
Icons,
Tooltip,
TooltipProvider,
Menu,
@ -27,7 +25,7 @@ import {
Button,
} from 'folds';
import { useLocation, useNavigate } from 'react-router-dom';
import { EventTimeline, JoinRule, MatrixCall, MatrixEvent, Room } from 'matrix-js-sdk';
import { EventTimeline, JoinRule, MatrixEvent, Room } from 'matrix-js-sdk';
import { useAtomValue } from 'jotai';
import { useStateEvent } from '../../hooks/useStateEvent';
@ -73,6 +71,8 @@ import { getReactCustomHtmlParser } from '../../plugins/react-custom-html-parser
import { HTMLReactParserOptions } from 'html-react-parser';
import { Message } from './message';
import { Image } from '../../components/media';
import { mdiAccount, mdiAccountPlus, mdiArrowLeft, mdiCheckAll, mdiChevronLeft, mdiChevronRight, mdiClose, mdiCog, mdiDotsVertical, mdiLinkVariant, mdiMagnify, mdiPhone, mdiPin } from '@mdi/js';
import Icon from '@mdi/react';
type RoomMenuProps = {
room: Room;
@ -114,7 +114,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
<MenuItem
onClick={handleMarkAsRead}
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<Icon size={1} path={mdiCheckAll} />}
radii="300"
disabled={!unread}
>
@ -130,7 +130,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
variant="Primary"
fill="None"
size="300"
after={<Icon size="100" src={Icons.UserPlus} />}
after={<Icon size={1} path={mdiAccountPlus} />}
radii="300"
disabled={!canInvite}
>
@ -141,7 +141,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
<MenuItem
onClick={handleCopyLink}
size="300"
after={<Icon size="100" src={Icons.Link} />}
after={<Icon size={1} path={mdiLinkVariant} />}
radii="300"
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
@ -151,7 +151,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
<MenuItem
onClick={handleRoomSettings}
size="300"
after={<Icon size="100" src={Icons.Setting} />}
after={<Icon size={1} path={mdiCog} />}
radii="300"
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
@ -169,7 +169,7 @@ const RoomMenu = forwardRef<HTMLDivElement, RoomMenuProps>(
variant="Critical"
fill="None"
size="300"
after={<Icon size="100" src={Icons.ArrowGoLeft} />}
after={<Icon size={1} path={mdiArrowLeft} />}
radii="300"
aria-pressed={promptLeave}
>
@ -247,7 +247,7 @@ export function RoomViewHeader({
const [messageSpacing] = useSetting(settingsAtom, 'messageSpacing');
const { navigateRoom, navigateSpace } = useRoomNavigate();
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
const htmlReactParserOptions = useMemo<HTMLReactParserOptions>(
() =>
getReactCustomHtmlParser(mx, room, {
@ -446,7 +446,7 @@ export function RoomViewHeader({
<Text size="H4">{getText('pinned.title')}</Text>
</Box>
<IconButton size="300" onClick={handlePinnedClose} radii="300">
<Icon src={Icons.Cross} />
<Icon size={1} path={mdiClose} />
</IconButton>
</Header>
<Box tabIndex={-1} direction='Column' style={{ height: 'inherit' }}>
@ -461,7 +461,7 @@ export function RoomViewHeader({
<Chip
variant="Secondary"
radii="300"
before={<Icon size="50" src={Icons.ChevronLeft} />}
before={<Icon size={1} path={mdiChevronLeft} />}
onClick={handlePrevPage}
aria-disabled={pageNo <= 1 || loadingPinList}
>
@ -522,7 +522,7 @@ export function RoomViewHeader({
<Chip
variant="Primary"
radii="300"
after={<Icon size="50" src={Icons.ChevronRight} />}
after={<Icon size={1} path={mdiChevronRight} />}
onClick={handleNextPage}
aria-disabled={pageNo >= pinnedPages || loadingPinList}
>
@ -600,7 +600,7 @@ export function RoomViewHeader({
>
{(triggerRef) => (
<IconButton ref={triggerRef} onClick={handleSearchClick}>
<Icon size="400" src={Icons.Search} />
<Icon size={1} path={mdiMagnify} />
</IconButton>
)}
</TooltipProvider>
@ -616,7 +616,7 @@ export function RoomViewHeader({
>
{(triggerRef) => (
<IconButton ref={triggerRef} onClick={handlePinnedClick}>
<Icon size="400" src={Icons.Pin} />
<Icon size={1} path={mdiPin} />
</IconButton>
)}
</TooltipProvider>
@ -632,14 +632,14 @@ export function RoomViewHeader({
>
{(triggerRef) => (
<IconButton ref={triggerRef} onClick={() => setPeopleDrawer((drawer) => !drawer)}>
<Icon size="400" src={Icons.User} />
<Icon size={1} path={mdiAccount} />
</IconButton>
)}
</TooltipProvider>
)}
{mDirects.has(room.roomId) && (
<IconButton onClick={handleCall}>
<Icon size="400" src={Icons.Phone} />
<Icon size={1} path={mdiPhone} />
</IconButton>
)}
<TooltipProvider
@ -654,7 +654,7 @@ export function RoomViewHeader({
>
{(triggerRef) => (
<IconButton onClick={handleOpenMenu} ref={triggerRef} aria-pressed={!!menuAnchor}>
<Icon size="400" src={Icons.VerticalDots} filled={!!menuAnchor} />
<Icon size={1} path={mdiDotsVertical} />
</IconButton>
)}
</TooltipProvider>

View file

@ -1,5 +1,5 @@
import React from 'react';
import { Box, Icon, IconButton, Icons, Text, as } from 'folds';
import { Box, Text, as } from 'folds';
import { Room } from 'matrix-js-sdk';
import classNames from 'classnames';
import { useSetAtom } from 'jotai';

View file

@ -4,9 +4,7 @@ import {
Button,
Dialog,
Header,
Icon,
IconButton,
Icons,
Input,
Line,
Menu,
@ -90,6 +88,8 @@ import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
import { ImageViewer } from '../../../components/image-viewer';
import { Image } from '../../../components/media';
import { getText } from '../../../../lang';
import Icon from '@mdi/react';
import { mdiAccount, mdiAlertCircleOutline, mdiCheck, mdiCheckAll, mdiClose, mdiCodeBraces, mdiDelete, mdiDotsVertical, mdiEmoticon, mdiEmoticonPlus, mdiLinkVariant, mdiPencil, mdiPin, mdiPinOff, mdiReply, mdiRestore } from '@mdi/js';
export type ReactionHandler = (keyOrMxc: string, shortcode: string) => void;
@ -178,7 +178,7 @@ export const MessageAllReactionItem = as<
</Overlay>
<MenuItem
size="300"
after={<Icon size="100" src={Icons.Smile} />}
after={<Icon size={1} path={mdiEmoticon} />}
radii="300"
onClick={() => setOpen(true)}
{...props}
@ -227,7 +227,7 @@ export const MessageReadReceiptItem = as<
</Overlay>
<MenuItem
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<Icon size={1} path={mdiCheckAll} />}
radii="300"
onClick={() => setOpen(true)}
{...props}
@ -309,7 +309,7 @@ export const MessageSourceCodeItem = as<
</Overlay>
<MenuItem
size="300"
after={<Icon size="100" src={Icons.BlockCode} />}
after={<Icon size={1} path={mdiCodeBraces} />}
radii="300"
onClick={() => setOpen(true)}
{...props}
@ -366,7 +366,7 @@ export const MessagePinItem = as<
return (
<MenuItem
size="300"
after={<Icon size="100" src={Icons.Pin} />}
after={<Icon size={1} path={isPinned ? mdiPin : mdiPinOff} />}
radii="300"
{...props}
ref={ref}
@ -545,7 +545,7 @@ export const MessageRecoverItem = as<
<Text size="H4">{getText('recovered.title')}</Text>
</Box>
<IconButton size="300" onClick={handleClose} radii="300">
<Icon src={Icons.Cross} />
<Icon size={1} path={mdiClose} />
</IconButton>
</Header>
{message}
@ -555,7 +555,7 @@ export const MessageRecoverItem = as<
</Overlay>
<MenuItem
size="300"
after={<Icon size="100" src={Icons.Eye} />}
after={<Icon size={1} path={mdiRestore} />}
radii="300"
onClick={handleClick}
{...props}
@ -588,7 +588,7 @@ export const MessageCopyLinkItem = as<
return (
<MenuItem
size="300"
after={<Icon size="100" src={Icons.Link} />}
after={<Icon size={1} path={mdiLinkVariant} />}
radii="300"
onClick={handleCopy}
{...props}
@ -664,7 +664,7 @@ export const MessageDeleteItem = as<
<Text size="H4">{getText('msg_redact.title')}</Text>
</Box>
<IconButton size="300" onClick={handleClose} radii="300">
<Icon src={Icons.Cross} />
<Icon size={1} path={mdiClose} />
</IconButton>
</Header>
<Box
@ -684,7 +684,7 @@ export const MessageDeleteItem = as<
{getText('msg_redact.reason.2')}
</Text>
</Text>
<Input name="reasonInput" variant="Background" />
<Input name="reasonInput" variant="Background" autoComplete='off' />
{deleteState.status === AsyncStatus.Error && (
<Text style={{ color: color.Critical.Main }} size="T300">
{getText('error.redact_msg')}
@ -714,7 +714,7 @@ export const MessageDeleteItem = as<
variant="Critical"
fill="None"
size="300"
after={<Icon size="100" src={Icons.Delete} />}
after={<Icon size={1} path={mdiDelete} />}
radii="300"
onClick={() => setOpen(true)}
aria-pressed={open}
@ -793,7 +793,7 @@ export const MessageReportItem = as<
<Text size="H4">{getText('msg_report.title')}</Text>
</Box>
<IconButton size="300" onClick={handleClose} radii="300">
<Icon src={Icons.Cross} />
<Icon size={1} path={mdiClose} />
</IconButton>
</Header>
<Box
@ -846,7 +846,7 @@ export const MessageReportItem = as<
variant="Critical"
fill="None"
size="300"
after={<Icon size="100" src={Icons.Warning} />}
after={<Icon size={1} path={mdiAlertCircleOutline} />}
radii="300"
onClick={() => setOpen(true)}
aria-pressed={open}
@ -1024,7 +1024,7 @@ export const Message = as<'div', MessageProps>(
: undefined
}
alt={senderDisplayName}
renderFallback={() => <Icon size="200" src={Icons.User} filled />}
renderFallback={() => <Icon size={1} path={mdiAccount} />}
/>
</Avatar>
</AvatarBase>
@ -1154,7 +1154,7 @@ export const Message = as<'div', MessageProps>(
radii="300"
aria-pressed={!!emojiBoardAnchor}
>
<Icon src={Icons.SmilePlus} size="100" />
<Icon size={1} path={mdiEmoticonPlus} />
</IconButton>
</PopOut>
)}
@ -1165,7 +1165,7 @@ export const Message = as<'div', MessageProps>(
size="300"
radii="300"
>
<Icon src={Icons.ReplyArrow} size="100" />
<Icon size={1} path={mdiReply} />
</IconButton>
{canEditEvent(mx, mEvent) && onEditId && (
<IconButton
@ -1174,7 +1174,7 @@ export const Message = as<'div', MessageProps>(
size="300"
radii="300"
>
<Icon src={Icons.Pencil} size="100" />
<Icon size={1} path={mdiPencil} />
</IconButton>
)}
<PopOut
@ -1205,7 +1205,7 @@ export const Message = as<'div', MessageProps>(
{mEvent.getType() == 'org.matrix.msc3381.poll.start' && mEvent.sender?.userId == (mx.getUserId() ?? '') && (
<MenuItem
size="300"
after={<Icon size="100" src={Icons.Check} />}
after={<Icon size={1} path={mdiCheck} />}
radii="300"
onClick={handleEndPoll}
>
@ -1222,7 +1222,7 @@ export const Message = as<'div', MessageProps>(
{canSendReaction && (
<MenuItem
size="300"
after={<Icon size="100" src={Icons.SmilePlus} />}
after={<Icon size={1} path={mdiEmoticonPlus} />}
radii="300"
onClick={handleAddReactions}
>
@ -1245,7 +1245,7 @@ export const Message = as<'div', MessageProps>(
)}
<MenuItem
size="300"
after={<Icon size="100" src={Icons.ReplyArrow} />}
after={<Icon size={1} path={mdiReply} />}
radii="300"
data-event-id={mEvent.getId()}
onClick={(evt: any) => {
@ -1265,7 +1265,7 @@ export const Message = as<'div', MessageProps>(
{canEditEvent(mx, mEvent) && onEditId && (
<MenuItem
size="300"
after={<Icon size="100" src={Icons.Pencil} />}
after={<Icon size={1} path={mdiPencil} />}
radii="300"
data-event-id={mEvent.getId()}
onClick={() => {
@ -1330,7 +1330,7 @@ export const Message = as<'div', MessageProps>(
onClick={handleOpenMenu}
aria-pressed={!!menuAnchor}
>
<Icon src={Icons.VerticalDots} size="100" />
<Icon size={1} path={mdiDotsVertical} />
</IconButton>
</PopOut>
</Box>
@ -1475,7 +1475,7 @@ export const Event = as<'div', EventProps>(
onClick={handleOpenMenu}
aria-pressed={!!menuAnchor}
>
<Icon src={Icons.VerticalDots} size="100" />
<Icon size={1} path={mdiDotsVertical} />
</IconButton>
</PopOut>
</Box>

View file

@ -9,10 +9,7 @@ import React, {
import {
Box,
Chip,
Icon,
IconButton,
Icons,
Line,
PopOut,
RectCords,
Spinner,
@ -49,6 +46,8 @@ import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { getEditedEvent, trimReplyFromFormattedBody } from '../../../utils/room';
import { mobileOrTablet } from '../../../utils/user-agent';
import { getText } from '../../../../lang';
import Icon from '@mdi/react';
import { mdiEmoticon, mdiEmoticonOutline } from '@mdi/js';
type MessageEditorProps = {
roomId: string;
@ -290,7 +289,7 @@ export const MessageEditor = as<'div', MessageEditorProps>(
size="300"
radii="300"
>
<Icon size="400" src={Icons.Smile} filled={anchor !== undefined} />
<Icon size={1} path={anchor !== undefined ? mdiEmoticon : mdiEmoticonOutline} />
</IconButton>
</PopOut>
)}

View file

@ -4,9 +4,7 @@ import {
Avatar,
Box,
Header,
Icon,
IconButton,
Icons,
Line,
MenuItem,
Scroll,
@ -26,6 +24,8 @@ import { Reaction } from '../../../components/message';
import { getHexcodeForEmoji, getShortcodeFor } from '../../../plugins/emoji';
import { UserAvatar } from '../../../components/user-avatar';
import { getText } from '../../../../lang';
import Icon from '@mdi/react';
import { mdiAccount, mdiClose } from '@mdi/js';
export type ReactionViewerProps = {
room: Room;
@ -95,7 +95,7 @@ export const ReactionViewer = as<'div', ReactionViewerProps>(
<Text size="H3">{getText('reaction_viewer.reacted_with', selectedShortcode)}</Text>
</Box>
<IconButton size="300" onClick={requestClose}>
<Icon src={Icons.Cross} />
<Icon size={1} path={mdiClose} />
</IconButton>
</Header>
@ -132,7 +132,7 @@ export const ReactionViewer = as<'div', ReactionViewerProps>(
userId={senderId}
src={avatarUrl ?? undefined}
alt={name}
renderFallback={() => <Icon size="50" src={Icons.User} filled />}
renderFallback={() => <Icon size={1} path={mdiAccount} />}
/>
</Avatar>
}

View file

@ -1,13 +1,15 @@
import React, { ReactNode } from 'react';
import { IconSrc, Icons } from 'folds';
import { EventTimeline, MatrixEvent, Room } from 'matrix-js-sdk';
import { IMemberContent, Membership } from '../../types/matrix/room';
import { getMxIdLocalPart } from '../utils/matrix';
import { isMembershipChanged } from '../utils/room';
import { useMatrixClient } from './useMatrixClient';
import { mdiAccount, mdiAccountLock, mdiAccountLockOpen, mdiAccountPlus, mdiAccountRemove, mdiArrowRight, mdiAt } from '@mdi/js';
/// TODO: TRANSLATE THIS!
export type ParsedResult = {
icon: IconSrc;
icon: string;
body: ReactNode;
};
@ -37,7 +39,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (!senderId || !userId)
return {
icon: Icons.User,
icon: mdiAccount,
body: 'Broken membership event',
};
@ -48,7 +50,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (content.membership === Membership.Invite) {
if (prevContent.membership === Membership.Knock) {
return {
icon: Icons.ArrowGoRightPlus,
icon: mdiAccountPlus,
body: (
<>
<b>{senderName}</b>
@ -62,7 +64,7 @@ export const useMemberEventParser = (): MemberEventParser => {
}
return {
icon: Icons.ArrowGoRightPlus,
icon: mdiAccountPlus,
body: (
<>
<b>{senderName}</b>
@ -75,7 +77,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (content.membership === Membership.Knock) {
return {
icon: Icons.ArrowGoRightPlus,
icon: mdiAccountPlus,
body: (
<>
<b>{userName}</b>
@ -88,7 +90,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (content.membership === Membership.Join) {
return {
icon: Icons.ArrowGoRight,
icon: mdiAccountPlus,
body: (
<>
<b>{userName}</b>
@ -101,7 +103,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (content.membership === Membership.Leave) {
if (prevContent.membership === Membership.Invite) {
return {
icon: Icons.ArrowGoRightCross,
icon: mdiAccountRemove,
body:
senderId === userId ? (
<>
@ -123,7 +125,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (prevContent.membership === Membership.Knock) {
return {
icon: Icons.ArrowGoRightCross,
icon: mdiAccountRemove,
body:
senderId === userId ? (
<>
@ -145,7 +147,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (prevContent.membership === Membership.Ban) {
return {
icon: Icons.ArrowGoLeft,
icon: mdiAccountLockOpen,
body: (
<>
<b>{senderName}</b>
@ -157,7 +159,7 @@ export const useMemberEventParser = (): MemberEventParser => {
}
return {
icon: Icons.ArrowGoLeft,
icon: mdiAccountRemove,
body:
senderId === userId ? (
<>
@ -177,7 +179,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (content.membership === Membership.Ban) {
return {
icon: Icons.ArrowGoLeft,
icon: mdiAccountLock,
body: (
<>
<b>{senderName}</b>
@ -193,7 +195,7 @@ export const useMemberEventParser = (): MemberEventParser => {
const prevUserName = prevContent.displayname || userId;
return {
icon: Icons.Mention,
icon: mdiAt,
body: content.displayname ? (
<>
<b>{prevUserName}</b>
@ -210,7 +212,7 @@ export const useMemberEventParser = (): MemberEventParser => {
}
if (content.avatar_url !== prevContent.avatar_url) {
return {
icon: Icons.User,
icon: mdiAccount,
body: content.displayname ? (
<>
<b>{userName}</b>
@ -227,7 +229,7 @@ export const useMemberEventParser = (): MemberEventParser => {
if (content['ru.officialdakari.extera_banner'] !== prevContent['ru.officialdakari.extera_banner']) {
return {
icon: Icons.User,
icon: mdiAccount,
body: content['ru.officialdakari.extera_banner'] ? (
<>
<b>{userName}</b>
@ -243,7 +245,7 @@ export const useMemberEventParser = (): MemberEventParser => {
}
return {
icon: Icons.User,
icon: mdiAccount,
body: 'Broken membership event',
};
};

View file

@ -53,7 +53,7 @@ import { settingsAtom } from '../../state/settings';
import { isMacOS } from '../../utils/user-agent';
import { KeySymbol } from '../../utils/key-symbol';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { Icons, Input } from 'folds';
import { Input } from 'folds';
import Banner from '../profile-editor/Banner';
import { getText } from '../../../lang';
import { useBackButton } from '../../hooks/useBackButton';

View file

@ -1,10 +1,12 @@
import React from 'react';
import { Box, Icon, Icons, color, Text } from 'folds';
import { Box, color, Text } from 'folds';
import Icon from '@mdi/react';
import { mdiAlert } from '@mdi/js';
export function FieldError({ message }: { message: string }) {
return (
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="100">
<Icon size="50" filled src={Icons.Warning} />
<Icon size={1} path={mdiAlert} />
<Text size="T200">
<b>{message}</b>
</Text>

View file

@ -8,9 +8,7 @@ import React, {
} from 'react';
import {
Header,
Icon,
IconButton,
Icons,
Input,
Menu,
MenuItem,
@ -23,6 +21,8 @@ import FocusTrap from 'focus-trap-react';
import { useDebounce } from '../../hooks/useDebounce';
import { getText } from '../../../lang';
import Icon from '@mdi/react';
import { mdiChevronDown } from '@mdi/js';
export function ServerPicker({
server,
@ -134,7 +134,7 @@ export function ServerPicker({
aria-pressed={!!serverMenuAnchor}
radii="300"
>
<Icon src={Icons.ChevronBottom} />
<Icon size={1} path={mdiChevronDown} />
</IconButton>
</PopOut>
)

View file

@ -3,9 +3,7 @@ import {
Box,
Button,
Header,
Icon,
IconButton,
Icons,
Input,
Menu,
Overlay,
@ -38,6 +36,8 @@ import { FieldError } from '../FiledError';
import { getResetPasswordPath } from '../../pathUtils';
import { getText } from '../../../../lang';
import cons from '../../../../client/state/cons';
import Icon from '@mdi/react';
import { mdiAlertCircleOutline } from '@mdi/js';
function UsernameHint({ server }: { server: string }) {
const [anchor, setAnchor] = useState<RectCords>();
@ -100,7 +100,7 @@ function UsernameHint({ server }: { server: string }) {
radii="300"
aria-pressed={!!anchor}
>
<Icon style={{ opacity: config.opacity.P300 }} size="100" src={Icons.Info} />
<Icon style={{ opacity: config.opacity.P300 }} size={1} path={mdiAlertCircleOutline} />
</IconButton>
</PopOut>
);

View file

@ -1,7 +1,5 @@
import {
Box,
Icon,
Icons,
Overlay,
OverlayBackdrop,
OverlayCenter,
@ -17,6 +15,8 @@ import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
import { CustomLoginResponse, LoginError, login, useLoginComplete } from './loginUtil';
import { getText } from '../../../../lang';
import cons from '../../../../client/state/cons';
import Icon from '@mdi/react';
import { mdiAlert } from '@mdi/js';
function LoginTokenError({ message }: { message: string }) {
return (
@ -31,7 +31,7 @@ function LoginTokenError({ message }: { message: string }) {
alignItems="Start"
gap="300"
>
<Icon size="300" filled src={Icons.Warning} />
<Icon size={1} path={mdiAlert} />
<Box direction="Column" gap="100">
<Text size="L400">Token Login</Text>
<Text size="T300">

View file

@ -1,5 +1,5 @@
import React, { useRef } from 'react';
import { Icon, Icons, Scroll } from 'folds';
import { Scroll } from 'folds';
import {
Sidebar,
@ -13,6 +13,8 @@ import {
import { DirectTab, HomeTab, SpaceTabs, InboxTab, ExploreTab, UserTab } from './sidebar';
import { openCreateRoom, openSearch } from '../../../client/action/navigation';
import { getText } from '../../../lang';
import Icon from '@mdi/react';
import { mdiMagnify, mdiPlus } from '@mdi/js';
export function SidebarNav() {
const scrollRef = useRef<HTMLDivElement>(null);
@ -39,7 +41,7 @@ export function SidebarNav() {
outlined
onClick={() => openCreateRoom(true)}
>
<Icon src={Icons.Plus} />
<Icon size={1} path={mdiPlus} />
</SidebarAvatar>
)}
</SidebarItemTooltip>
@ -60,7 +62,7 @@ export function SidebarNav() {
outlined
onClick={() => openSearch()}
>
<Icon src={Icons.Search} />
<Icon size={1} path={mdiMagnify} />
</SidebarAvatar>
)}
</SidebarItemTooltip>

View file

@ -1,9 +1,11 @@
import React from 'react';
import { Box, Button, Icon, Icons, Text, config, toRem } from 'folds';
import { Box, Button, Text, config, toRem } from 'folds';
import { Page, PageHero, PageHeroSection } from '../../components/page';
import CinnySVG from '../../../../public/res/svg/cinny.svg';
import cons from '../../../client/state/cons';
import { getText } from '../../../lang';
import Icon from '@mdi/react';
import { mdiCodeBraces, mdiHeart } from '@mdi/js';
export function WelcomePage() {
return (
@ -38,7 +40,7 @@ export function WelcomePage() {
href="https://github.com/OfficialDakari/Extera"
target="_blank"
rel="noreferrer noopener"
before={<Icon size="200" src={Icons.Code} />}
before={<Icon size={1} path={mdiCodeBraces} />}
>
<Text as="span" size="B400">
{getText('btn.source_code')}
@ -50,7 +52,7 @@ export function WelcomePage() {
target="_blank"
rel="noreferrer noopener"
fill="Soft"
before={<Icon size="200" src={Icons.Heart} />}
before={<Icon size={1} path={mdiHeart} />}
>
<Text as="span" size="B400">
{getText('btn.sponsor')}

View file

@ -4,9 +4,7 @@ import {
Avatar,
Box,
Button,
Icon,
IconButton,
Icons,
Menu,
MenuItem,
PopOut,
@ -46,6 +44,8 @@ import { useRoomsUnread } from '../../../state/hooks/unread';
import { markAsRead } from '../../../../client/action/notifications';
import { getText } from '../../../../lang';
import { isHidden } from '../../../state/hooks/roomList';
import Icon from '@mdi/react';
import { mdiAt, mdiCheckAll, mdiDotsVertical, mdiPlusCircleOutline } from '@mdi/js';
type DirectMenuProps = {
requestClose: () => void;
@ -66,7 +66,7 @@ const DirectMenu = forwardRef<HTMLDivElement, DirectMenuProps>(({ requestClose }
<MenuItem
onClick={handleMarkAsRead}
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<Icon size={1} path={mdiCheckAll} />}
radii="300"
aria-disabled={!unread}
>
@ -101,7 +101,7 @@ function DirectHeader() {
</Box>
<Box>
<IconButton aria-pressed={!!menuAnchor} variant="Background" onClick={handleOpenMenu}>
<Icon src={Icons.VerticalDots} size="200" />
<Icon size={1} path={mdiDotsVertical} />
</IconButton>
</Box>
</Box>
@ -134,7 +134,7 @@ function DirectEmpty() {
return (
<NavEmptyCenter>
<NavEmptyLayout
icon={<Icon size="600" src={Icons.Mention} />}
icon={<Icon size={1} path={mdiAt} />}
title={
<Text size="H5" align="Center">
{getText('direct_menu.empty')}
@ -204,7 +204,7 @@ export function Direct() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.Plus} size="100" />
<Icon size={1} path={mdiPlusCircleOutline} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit" truncate>

View file

@ -7,9 +7,7 @@ import {
Button,
Dialog,
Header,
Icon,
IconButton,
Icons,
Input,
Overlay,
OverlayBackdrop,
@ -37,6 +35,8 @@ import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page';
import { getText } from '../../../../lang';
import Icon from '@mdi/react';
import { mdiClose, mdiPlus, mdiServerNetwork, mdiServerNetworkOutline, mdiStar, mdiStarOutline } from '@mdi/js';
export function AddServer() {
const mx = useMatrixClient();
@ -96,7 +96,7 @@ export function AddServer() {
<Text size="H4">{getText('explore.add_server')}</Text>
</Box>
<IconButton size="300" onClick={() => setDialog(false)} radii="300">
<Icon src={Icons.Cross} />
<Icon size={1} path={mdiClose} />
</IconButton>
</Header>
<Box
@ -143,7 +143,7 @@ export function AddServer() {
variant="Secondary"
fill="Soft"
size="300"
before={<Icon size="100" src={Icons.Plus} />}
before={<Icon size={1} path={mdiPlus} />}
onClick={() => setDialog(true)}
>
<Text size="B300" truncate>
@ -186,7 +186,7 @@ export function Explore() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.Bulb} size="100" filled={featuredSelected} />
<Icon size={1} path={featuredSelected ? mdiStar : mdiStarOutline} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit" truncate>
@ -208,9 +208,8 @@ export function Explore() {
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon
src={Icons.Category}
size="100"
filled={selectedServer === userServer}
path={selectedServer === userServer ? mdiServerNetwork : mdiServerNetworkOutline}
size={1}
/>
</Avatar>
<Box as="span" grow="Yes">
@ -243,9 +242,8 @@ export function Explore() {
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon
src={Icons.Category}
size="100"
filled={server === selectedServer}
path={mdiServerNetworkOutline}
size={1}
/>
</Avatar>
<Box as="span" grow="Yes">

View file

@ -1,5 +1,5 @@
import React from 'react';
import { Box, Icon, Icons, Scroll, Text } from 'folds';
import { Box, Scroll, Text } from 'folds';
import { useAtomValue } from 'jotai';
import { useClientConfig } from '../../../hooks/useClientConfig';
import { RoomCard, RoomCardGrid } from '../../../components/room-card';
@ -16,6 +16,8 @@ import { RoomTopicViewer } from '../../../components/room-topic-viewer';
import * as css from './style.css';
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
import { getText } from '../../../../lang';
import Icon from '@mdi/react';
import { mdiAlertCircleOutline, mdiStar, mdiStarCircleOutline } from '@mdi/js';
export function FeaturedRooms() {
const { featuredCommunities } = useClientConfig();
@ -32,7 +34,7 @@ export function FeaturedRooms() {
<Box direction="Column" gap="200">
<PageHeroSection>
<PageHero
icon={<Icon size="600" src={Icons.Bulb} />}
icon={<Icon size={1} path={mdiStar} />}
title={getText('explore.featured.title')}
subTitle={getText('explore.featured.subtitle')}
/>
@ -105,7 +107,7 @@ export function FeaturedRooms() {
alignItems="Center"
gap="200"
>
<Icon size="400" src={Icons.Info} />
<Icon size={1} path={mdiAlertCircleOutline} />
<Text size="T300" align="Center">
{getText('explore.no_featured')}
</Text>

View file

@ -8,12 +8,11 @@ import React, {
useRef,
useState,
} from 'react';
import { Icon as MDIcon } from '@mdi/react';
import {
Box,
Button,
Chip,
Icon,
Icons,
Input,
Line,
Menu,
@ -42,6 +41,7 @@ import { allRoomsAtom } from '../../../state/room-list/roomList';
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
import { getMxIdServer } from '../../../utils/matrix';
import { getText } from '../../../../lang';
import { mdiAlertCircleOutline, mdiArrowLeft, mdiCheck, mdiChevronDown, mdiClose, mdiMagnify, mdiServer, mdiServerNetwork, mdiShape } from '@mdi/js';
const useServerSearchParams = (searchParams: URLSearchParams): ExploreServerPathSearchParams =>
useMemo(
@ -115,7 +115,7 @@ function Search({ active, loading, searchInputRef, onSearch, onReset }: SearchPr
active && loading ? (
<Spinner variant="Secondary" size="200" />
) : (
<Icon size="200" src={Icons.Search} />
<MDIcon size={1} path={mdiMagnify} />
)
}
after={
@ -126,7 +126,7 @@ function Search({ active, loading, searchInputRef, onSearch, onReset }: SearchPr
size="400"
radii="Pill"
outlined
after={<Icon size="50" src={Icons.Cross} />}
after={<MDIcon size={0.7} path={mdiClose} />}
onClick={onReset}
>
<Text size="B300">{getText('btn.clear_search')}</Text>
@ -233,7 +233,7 @@ function ThirdPartyProtocolsSelector({
radii="Pill"
size="400"
variant={instanceId ? 'Success' : 'SurfaceVariant'}
after={<Icon size="100" src={Icons.ChevronBottom} />}
after={<MDIcon size={1} path={mdiChevronDown} />}
>
<Text size="T200" truncate>
{selectedInstance?.desc ?? DEFAULT_INSTANCE_NAME}
@ -327,7 +327,7 @@ function LimitButton({ limit, onLimitChange }: LimitButtonProps) {
radii="Pill"
size="400"
variant="SurfaceVariant"
after={<Icon size="100" src={Icons.ChevronBottom} />}
after={<MDIcon size={1} path={mdiChevronDown} />}
>
<Text size="T200" truncate>{getText('count.page_limit', limit)}</Text>
</Chip>
@ -472,7 +472,7 @@ export function PublicRooms() {
size="500"
variant="Surface"
radii="Pill"
before={<Icon size="100" src={Icons.ArrowLeft} />}
before={<MDIcon size={1} path={mdiArrowLeft} />}
onClick={handleSearchClear}
>
<Text size="T300">{server}</Text>
@ -480,7 +480,7 @@ export function PublicRooms() {
</Box>
<Box grow="No" justifyContent="Center" alignItems="Center" gap="200">
<Icon size="400" src={Icons.Search} />
<MDIcon size={1} path={mdiMagnify} />
<Text size="H3" truncate>
{getText('explore.server.search')}
</Text>
@ -489,7 +489,7 @@ export function PublicRooms() {
</>
) : (
<Box grow="Yes" justifyContent="Center" alignItems="Center" gap="200">
<Icon size="400" src={Icons.Category} />
<MDIcon size={1} path={mdiServerNetwork} />
<Text size="H3" truncate>
{server}
</Text>
@ -526,7 +526,7 @@ export function PublicRooms() {
aria-pressed={filter.value === serverSearchParams.type}
before={
filter.value === serverSearchParams.type && (
<Icon size="100" src={Icons.Check} />
<MDIcon size={1} path={mdiCheck} />
)
}
outlined
@ -629,7 +629,7 @@ export function PublicRooms() {
alignItems="Center"
gap="200"
>
<Icon size="400" src={Icons.Info} />
<MDIcon size={1} path={mdiAlertCircleOutline} />
<Text size="T300" align="Center">
{getText('explore.server.no_communities')}
</Text>

View file

@ -4,9 +4,7 @@ import {
Avatar,
Box,
Button,
Icon,
IconButton,
Icons,
Menu,
MenuItem,
PopOut,
@ -15,6 +13,7 @@ import {
config,
toRem,
} from 'folds';
import { Icon as MDIcon } from '@mdi/react';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useAtom, useAtomValue } from 'jotai';
import FocusTrap from 'focus-trap-react';
@ -49,6 +48,7 @@ import { markAsRead } from '../../../../client/action/notifications';
import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCategories';
import { getText } from '../../../../lang';
import { isHidden } from '../../../state/hooks/roomList';
import { mdiCheckAll, mdiDotsVertical, mdiLinkVariant, mdiMagnify, mdiPlus, mdiPlusCircle, mdiPlusCircleOutline, mdiPound } from '@mdi/js';
type HomeMenuProps = {
requestClose: () => void;
@ -69,7 +69,7 @@ const HomeMenu = forwardRef<HTMLDivElement, HomeMenuProps>(({ requestClose }, re
<MenuItem
onClick={handleMarkAsRead}
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<MDIcon size={1} path={mdiCheckAll} />}
radii="300"
aria-disabled={!unread}
>
@ -104,7 +104,7 @@ function HomeHeader() {
</Box>
<Box>
<IconButton aria-pressed={!!menuAnchor} variant="Background" onClick={handleOpenMenu}>
<Icon src={Icons.VerticalDots} size="200" />
<MDIcon size={1} path={mdiDotsVertical} />
</IconButton>
</Box>
</Box>
@ -139,7 +139,7 @@ function HomeEmpty() {
return (
<NavEmptyCenter>
<NavEmptyLayout
icon={<Icon size="600" src={Icons.Hash} />}
icon={<MDIcon size={1} path={mdiPound} />}
title={
<Text size="H5" align="Center">
{getText('home.empty')}
@ -226,7 +226,7 @@ export function Home() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.Plus} size="100" />
<MDIcon size={1} path={mdiPlusCircleOutline} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit">
@ -242,7 +242,7 @@ export function Home() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.Link} size="100" />
<MDIcon size={1} path={mdiLinkVariant} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit">
@ -258,7 +258,7 @@ export function Home() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.Search} size="100" filled={searchSelected} />
<MDIcon size={1} path={mdiMagnify} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit">

View file

@ -1,9 +1,11 @@
import React, { useRef } from 'react';
import { Box, Icon, Icons, Text, Scroll } from 'folds';
import { Box, Text, Scroll } from 'folds';
import { Icon as MDIcon } from '@mdi/react';
import { Page, PageContent, PageContentCenter, PageHeader } from '../../../components/page';
import { MessageSearch } from '../../../features/message-search';
import { useHomeRooms } from './useHomeRooms';
import { getText } from '../../../../lang';
import { mdiMagnify } from '@mdi/js';
export function HomeSearch() {
const scrollRef = useRef<HTMLDivElement>(null);
@ -13,7 +15,7 @@ export function HomeSearch() {
<Page>
<PageHeader>
<Box grow="Yes" justifyContent="Center" alignItems="Center" gap="200">
<Icon size="400" src={Icons.Search} />
<MDIcon size={1} path={mdiMagnify} />
<Text size="H3">
{getText('msg_search.title')}
</Text>

View file

@ -1,8 +1,9 @@
import React from 'react';
import { Avatar, Box, Icon, Icons, Text } from 'folds';
import { Avatar, Box, Text } from 'folds';
import { useAtomValue } from 'jotai';
import { NavCategory, NavItem, NavItemContent, NavLink } from '../../../components/nav';
import { getInboxInvitesPath, getInboxNotificationsPath } from '../../pathUtils';
import { Icon as MDIcon } from '@mdi/react';
import {
useInboxInvitesSelected,
useInboxNotificationsSelected,
@ -12,6 +13,7 @@ import { allInvitesAtom } from '../../../state/room-list/inviteList';
import { useNavToActivePathMapper } from '../../../hooks/useNavToActivePathMapper';
import { PageNav, PageNavContent, PageNavHeader } from '../../../components/page';
import { getText } from '../../../../lang';
import { mdiEmail, mdiEmailOutline, mdiMail, mdiMailboxOutline, mdiMessageAlert, mdiMessageAlertOutline } from '@mdi/js';
function InvitesNavItem() {
const invitesSelected = useInboxInvitesSelected();
@ -29,7 +31,7 @@ function InvitesNavItem() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.Mail} size="100" filled={invitesSelected} />
<MDIcon size={1} path={invitesSelected ? mdiEmail : mdiEmailOutline} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit" truncate>
@ -68,7 +70,7 @@ export function Inbox() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.MessageUnread} size="100" filled={notificationsSelected} />
<MDIcon size={1} path={notificationsSelected ? mdiMessageAlert : mdiMessageAlertOutline} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit" truncate>

View file

@ -3,8 +3,6 @@ import {
Avatar,
Box,
Button,
Icon,
Icons,
Overlay,
OverlayBackdrop,
OverlayCenter,
@ -15,6 +13,7 @@ import {
config,
} from 'folds';
import { useAtomValue } from 'jotai';
import { Icon as MDIcon } from '@mdi/react';
import FocusTrap from 'focus-trap-react';
import { MatrixError, Room } from 'matrix-js-sdk';
import { Page, PageContent, PageContentCenter, PageHeader } from '../../../components/page';
@ -40,6 +39,7 @@ import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
import { useRoomTopic } from '../../../hooks/useRoomMeta';
import { getText, translate } from '../../../../lang';
import { mdiMail } from '@mdi/js';
const COMPACT_CARD_WIDTH = 548;
@ -227,7 +227,7 @@ export function Invites() {
<Page>
<PageHeader>
<Box grow="Yes" justifyContent="Center" alignItems="Center" gap="200">
<Icon size="400" src={Icons.Mail} />
<MDIcon size={1} path={mdiMail} />
<Text size="H3">
{getText('inbox.invites.title')}
</Text>

View file

@ -5,15 +5,14 @@ import {
Box,
Chip,
Header,
Icon,
IconButton,
Icons,
Scroll,
Text,
config,
toRem,
} from 'folds';
import { useSearchParams } from 'react-router-dom';
import { Icon as MDIcon } from '@mdi/react';
import {
INotification,
INotificationsResponse,
@ -71,6 +70,7 @@ import { VirtualTile } from '../../../components/virtualizer';
import { UserAvatar } from '../../../components/user-avatar';
import { EncryptedContent } from '../../../features/room/message';
import { getText, translate } from '../../../../lang';
import { mdiAccount, mdiCheck, mdiCheckAll, mdiChevronUp, mdiMessage } from '@mdi/js';
type RoomNotificationsGroup = {
roomId: string;
@ -382,7 +382,7 @@ function RoomNotificationsGroupComp({
variant="Primary"
radii="Pill"
onClick={handleMarkAsRead}
before={<Icon size="100" src={Icons.CheckTwice} />}
before={<MDIcon size={0.6} path={mdiCheckAll} />}
>
<Text size="T200">{getText('notifications.mark_as_read')}</Text>
</Chip>
@ -421,7 +421,7 @@ function RoomNotificationsGroupComp({
: undefined
}
alt={displayName}
renderFallback={() => <Icon size="200" src={Icons.User} filled />}
renderFallback={() => <MDIcon size={1} path={mdiAccount} />}
/>
</Avatar>
</AvatarBase>
@ -550,7 +550,7 @@ export function Notifications() {
<Page>
<PageHeader>
<Box grow="Yes" justifyContent="Center" alignItems="Center" gap="200">
<Icon size="400" src={Icons.Message} />
<MDIcon size={1} path={mdiMessage} />
<Text size="H3">
{getText('notifications.title')}
</Text>
@ -570,7 +570,7 @@ export function Notifications() {
onClick={() => setOnlyHighlighted(false)}
variant={!onlyHighlight ? 'Success' : 'Surface'}
aria-pressed={!onlyHighlight}
before={!onlyHighlight && <Icon size="100" src={Icons.Check} />}
before={!onlyHighlight && <MDIcon size={0.7} path={mdiCheck} />}
outlined
>
<Text size="T200">{getText('notifications.filter.all')}</Text>
@ -579,7 +579,7 @@ export function Notifications() {
onClick={() => setOnlyHighlighted(true)}
variant={onlyHighlight ? 'Success' : 'Surface'}
aria-pressed={onlyHighlight}
before={onlyHighlight && <Icon size="100" src={Icons.Check} />}
before={onlyHighlight && <MDIcon size={0.7} path={mdiCheck} />}
outlined
>
<Text size="T200">{getText('notifications.filter.highlighted')}</Text>
@ -599,7 +599,7 @@ export function Notifications() {
size="300"
aria-label={getText('scroll_to_top')}
>
<Icon src={Icons.ChevronTop} size="300" />
<MDIcon size={1} path={mdiChevronUp} />
</IconButton>
</ScrollTopContainer>
<div

View file

@ -1,6 +1,7 @@
import React, { MouseEventHandler, forwardRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Box, Icon, Icons, Menu, MenuItem, PopOut, RectCords, Text, config, toRem } from 'folds';
import { Box, Menu, MenuItem, PopOut, RectCords, Text, config, toRem } from 'folds';
import { Icon as MDIcon } from '@mdi/react';
import FocusTrap from 'focus-trap-react';
import { useAtomValue } from 'jotai';
import { useDirects } from '../../../state/hooks/roomList';
@ -23,6 +24,7 @@ import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
import { useDirectRooms } from '../direct/useDirectRooms';
import { markAsRead } from '../../../../client/action/notifications';
import { getText } from '../../../../lang';
import { mdiAccount, mdiAccountOutline, mdiCheckAll } from '@mdi/js';
type DirectMenuProps = {
requestClose: () => void;
@ -43,7 +45,7 @@ const DirectMenu = forwardRef<HTMLDivElement, DirectMenuProps>(({ requestClose }
<MenuItem
onClick={handleMarkAsRead}
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<MDIcon path={mdiCheckAll} size={1} />}
radii="300"
aria-disabled={!unread}
>
@ -98,7 +100,7 @@ export function DirectTab() {
onClick={handleDirectClick}
onContextMenu={handleContextMenu}
>
<Icon src={Icons.User} filled={directSelected} />
<MDIcon size={1} path={directSelected ? mdiAccount : mdiAccountOutline} />
</SidebarAvatar>
)}
</SidebarItemTooltip>

View file

@ -2,13 +2,14 @@ import React from 'react';
import { Icon, Icons } from 'folds';
import { useNavigate } from 'react-router-dom';
import { useAtomValue } from 'jotai';
import { Icon as MDIcon } from '@mdi/react';
import { SidebarAvatar, SidebarItem, SidebarItemTooltip } from '../../../components/sidebar';
import { useExploreSelected } from '../../../hooks/router/useExploreSelected';
import {
getExploreFeaturedPath,
getExplorePath,
getExploreServerPath,
joinPathComponent,
getExploreFeaturedPath,
getExplorePath,
getExploreServerPath,
joinPathComponent,
} from '../../pathUtils';
import { useClientConfig } from '../../../hooks/useClientConfig';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
@ -16,50 +17,51 @@ import { getMxIdServer } from '../../../utils/matrix';
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
import { getText } from '../../../../lang';
import { mdiCompass, mdiCompassOutline } from '@mdi/js';
export function ExploreTab() {
const mx = useMatrixClient();
const screenSize = useScreenSizeContext();
const clientConfig = useClientConfig();
const navigate = useNavigate();
const navToActivePath = useAtomValue(useNavToActivePathAtom());
const mx = useMatrixClient();
const screenSize = useScreenSizeContext();
const clientConfig = useClientConfig();
const navigate = useNavigate();
const navToActivePath = useAtomValue(useNavToActivePathAtom());
const exploreSelected = useExploreSelected();
const exploreSelected = useExploreSelected();
const handleExploreClick = () => {
if (screenSize === ScreenSize.Mobile) {
navigate(getExplorePath());
return;
}
const handleExploreClick = () => {
if (screenSize === ScreenSize.Mobile) {
navigate(getExplorePath());
return;
}
const activePath = navToActivePath.get('explore');
if (activePath) {
navigate(joinPathComponent(activePath));
return;
}
const activePath = navToActivePath.get('explore');
if (activePath) {
navigate(joinPathComponent(activePath));
return;
}
if (clientConfig.featuredCommunities?.openAsDefault) {
navigate(getExploreFeaturedPath());
return;
}
const userId = mx.getUserId();
const userServer = userId ? getMxIdServer(userId) : undefined;
if (userServer) {
navigate(getExploreServerPath(userServer));
return;
}
navigate(getExplorePath());
};
if (clientConfig.featuredCommunities?.openAsDefault) {
navigate(getExploreFeaturedPath());
return;
}
const userId = mx.getUserId();
const userServer = userId ? getMxIdServer(userId) : undefined;
if (userServer) {
navigate(getExploreServerPath(userServer));
return;
}
navigate(getExplorePath());
};
return (
<SidebarItem active={exploreSelected}>
<SidebarItemTooltip tooltip={getText('explore.title')}>
{(triggerRef) => (
<SidebarAvatar as="button" ref={triggerRef} outlined onClick={handleExploreClick}>
<Icon src={Icons.Explore} filled={exploreSelected} />
</SidebarAvatar>
)}
</SidebarItemTooltip>
</SidebarItem>
);
return (
<SidebarItem active={exploreSelected}>
<SidebarItemTooltip tooltip={getText('explore.title')}>
{(triggerRef) => (
<SidebarAvatar as="button" ref={triggerRef} outlined onClick={handleExploreClick}>
<MDIcon size={1} path={exploreSelected ? mdiCompass : mdiCompassOutline} />
</SidebarAvatar>
)}
</SidebarItemTooltip>
</SidebarItem>
);
}

View file

@ -1,6 +1,6 @@
import React, { MouseEventHandler, forwardRef, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Box, Icon, Icons, Menu, MenuItem, PopOut, RectCords, Text, config, toRem } from 'folds';
import { Box, Menu, MenuItem, PopOut, RectCords, Text, config, toRem } from 'folds';
import { useAtomValue } from 'jotai';
import FocusTrap from 'focus-trap-react';
import { useOrphanRooms } from '../../../state/hooks/roomList';
@ -8,6 +8,7 @@ import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { mDirectAtom } from '../../../state/mDirectList';
import { roomToParentsAtom } from '../../../state/room/roomToParents';
import { allRoomsAtom } from '../../../state/room-list/roomList';
import Icon, { Icon as MDIcon } from '@mdi/react';
import { roomToUnreadAtom } from '../../../state/room/roomToUnread';
import { getHomePath, joinPathComponent } from '../../pathUtils';
import { useRoomsUnread } from '../../../state/hooks/unread';
@ -24,6 +25,7 @@ import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
import { useHomeRooms } from '../home/useHomeRooms';
import { markAsRead } from '../../../../client/action/notifications';
import { getText } from '../../../../lang';
import { mdiCheckAll, mdiHome, mdiHomeOutline } from '@mdi/js';
type HomeMenuProps = {
requestClose: () => void;
@ -44,7 +46,7 @@ const HomeMenu = forwardRef<HTMLDivElement, HomeMenuProps>(({ requestClose }, re
<MenuItem
onClick={handleMarkAsRead}
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<Icon size={1} path={mdiCheckAll} />}
radii="300"
aria-disabled={!unread}
>
@ -100,7 +102,7 @@ export function HomeTab() {
onClick={handleHomeClick}
onContextMenu={handleContextMenu}
>
<Icon src={Icons.Home} filled={homeSelected} />
<MDIcon size={1} path={homeSelected ? mdiHome : mdiHomeOutline} />
</SidebarAvatar>
)}
</SidebarItemTooltip>

View file

@ -1,6 +1,7 @@
import React from 'react';
import { useNavigate } from 'react-router-dom';
import { Icon, Icons } from 'folds';
import { Icon as MDIcon } from '@mdi/react';
import { useAtomValue } from 'jotai';
import {
SidebarAvatar,
@ -20,6 +21,7 @@ import { UnreadBadge } from '../../../components/unread-badge';
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
import { useNavToActivePathAtom } from '../../../state/hooks/navToActivePath';
import { getText } from '../../../../lang';
import { mdiInbox, mdiInboxOutline } from '@mdi/js';
export function InboxTab() {
const screenSize = useScreenSizeContext();
@ -49,7 +51,7 @@ export function InboxTab() {
<SidebarItemTooltip tooltip={getText('inbox.title')}>
{(triggerRef) => (
<SidebarAvatar as="button" ref={triggerRef} outlined onClick={handleInboxClick}>
<Icon src={Icons.Inbox} filled={inboxSelected} />
<MDIcon path={inboxSelected ? mdiInbox : mdiInboxOutline} size={1} />
</SidebarAvatar>
)}
</SidebarItemTooltip>

View file

@ -12,9 +12,7 @@ import React, {
import { useNavigate } from 'react-router-dom';
import {
Box,
Icon,
IconButton,
Icons,
Line,
Menu,
MenuItem,
@ -24,6 +22,7 @@ import {
config,
toRem,
} from 'folds';
import { Icon as MDIcon } from '@mdi/react';
import { useAtom, useAtomValue } from 'jotai';
import { Room } from 'matrix-js-sdk';
import {
@ -91,6 +90,7 @@ import { markAsRead } from '../../../../client/action/notifications';
import { copyToClipboard } from '../../../utils/dom';
import { openInviteUser, openSpaceSettings } from '../../../../client/action/navigation';
import { getText } from '../../../../lang';
import { mdiAccount, mdiAccountPlus, mdiCheckAll, mdiChevronUp, mdiCog, mdiLink, mdiLinkVariant, mdiPin, mdiPlus, mdiTune } from '@mdi/js';
type SpaceMenuProps = {
room: Room;
@ -145,7 +145,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
<MenuItem
onClick={handleMarkAsRead}
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<MDIcon size={1} path={mdiCheckAll} />}
radii="300"
disabled={!unread}
>
@ -158,7 +158,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
size="300"
radii="300"
onClick={handleUnpin}
after={<Icon size="100" src={Icons.Pin} />}
after={<MDIcon size={1} path={mdiPin} />}
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
{getText('btn.unpin')}
@ -173,7 +173,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
variant="Primary"
fill="None"
size="300"
after={<Icon size="100" src={Icons.UserPlus} />}
after={<MDIcon size={1} path={mdiAccountPlus} />}
radii="300"
disabled={!canInvite}
>
@ -184,7 +184,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
<MenuItem
onClick={handleCopyLink}
size="300"
after={<Icon size="100" src={Icons.Link} />}
after={<MDIcon size={1} path={mdiLinkVariant} />}
radii="300"
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
@ -194,7 +194,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(
<MenuItem
onClick={handleRoomSettings}
size="300"
after={<Icon size="100" src={Icons.Setting} />}
after={<MDIcon size={1} path={mdiCog} />}
radii="300"
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
@ -504,7 +504,7 @@ function OpenedSpaceFolder({ folder, onClose, children }: OpenedSpaceFolderProps
<SidebarFolderDropTarget ref={aboveTargetRef} position="Top" />
<SidebarAvatar size="300">
<IconButton data-id={folder.id} size="300" variant="Background" onClick={onClose}>
<Icon size="400" src={Icons.ChevronTop} filled />
<MDIcon size={1} path={mdiChevronUp} />
</IconButton>
</SidebarAvatar>
{children}

View file

@ -1,5 +1,5 @@
import React, { useRef } from 'react';
import { Box, Icon, Icons, Text, Scroll } from 'folds';
import { Box, Text, Scroll } from 'folds';
import { useAtomValue } from 'jotai';
import { Page, PageContent, PageContentCenter, PageHeader } from '../../../components/page';
import { MessageSearch } from '../../../features/message-search';
@ -10,6 +10,8 @@ import { mDirectAtom } from '../../../state/mDirectList';
import { roomToParentsAtom } from '../../../state/room/roomToParents';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
import { getText } from '../../../../lang';
import { Icon as MDIcon } from '@mdi/react';
import { mdiMagnify } from '@mdi/js';
export function SpaceSearch() {
const mx = useMatrixClient();
@ -28,7 +30,7 @@ export function SpaceSearch() {
<Page>
<PageHeader>
<Box grow="Yes" justifyContent="Center" alignItems="Center" gap="200">
<Icon size="400" src={Icons.Search} />
<MDIcon size={1} path={mdiMagnify} />
<Text size="H3" truncate>
{getText('home.search_messages')}
</Text>

View file

@ -10,9 +10,7 @@ import { useAtom, useAtomValue } from 'jotai';
import {
Avatar,
Box,
Icon,
IconButton,
Icons,
Line,
Menu,
MenuItem,
@ -22,6 +20,7 @@ import {
config,
toRem,
} from 'folds';
import { Icon as MDIcon } from '@mdi/react';
import { useVirtualizer } from '@tanstack/react-virtual';
import { IJoinRuleEventContent, JoinRule, Room } from 'matrix-js-sdk';
import FocusTrap from 'focus-trap-react';
@ -74,6 +73,7 @@ import { useClosedNavCategoriesAtom } from '../../../state/hooks/closedNavCatego
import { useStateEvent } from '../../../hooks/useStateEvent';
import { StateEvent } from '../../../../types/matrix/room';
import { getText } from '../../../../lang';
import { mdiAccountPlus, mdiArrowLeft, mdiCheckAll, mdiCog, mdiDotsVertical, mdiFlag, mdiFlagOutline, mdiLink, mdiLock, mdiMagnify } from '@mdi/js';
type SpaceMenuProps = {
room: Room;
@ -121,7 +121,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
<MenuItem
onClick={handleMarkAsRead}
size="300"
after={<Icon size="100" src={Icons.CheckTwice} />}
after={<MDIcon size={1} path={mdiCheckAll} />}
radii="300"
disabled={!unread}
>
@ -137,7 +137,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
variant="Primary"
fill="None"
size="300"
after={<Icon size="100" src={Icons.UserPlus} />}
after={<MDIcon size={1} path={mdiAccountPlus} />}
radii="300"
disabled={!canInvite}
>
@ -148,7 +148,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
<MenuItem
onClick={handleCopyLink}
size="300"
after={<Icon size="100" src={Icons.Link} />}
after={<MDIcon size={1} path={mdiLink} />}
radii="300"
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
@ -158,7 +158,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
<MenuItem
onClick={handleRoomSettings}
size="300"
after={<Icon size="100" src={Icons.Setting} />}
after={<MDIcon size={1} path={mdiCog} />}
radii="300"
>
<Text style={{ flexGrow: 1 }} as="span" size="T300">
@ -176,7 +176,7 @@ const SpaceMenu = forwardRef<HTMLDivElement, SpaceMenuProps>(({ room, requestClo
variant="Critical"
fill="None"
size="300"
after={<Icon size="100" src={Icons.ArrowGoLeft} />}
after={<MDIcon size={1} path={mdiArrowLeft} />}
radii="300"
aria-pressed={promptLeave}
>
@ -222,14 +222,14 @@ function SpaceHeader() {
<PageNavHeader>
<Box alignItems="Center" grow="Yes" gap="300">
<Box grow="Yes" alignItems="Center" gap="100">
{joinRules?.join_rule !== JoinRule.Public && <MDIcon size={0.7} path={mdiLock} />}
<Text size="H4" truncate>
{spaceName}
</Text>
{joinRules?.join_rule !== JoinRule.Public && <Icon src={Icons.Lock} size="50" />}
</Box>
<Box>
<IconButton aria-pressed={!!menuAnchor} variant="Background" onClick={handleOpenMenu}>
<Icon src={Icons.VerticalDots} size="200" />
<MDIcon size={1} path={mdiDotsVertical} />
</IconButton>
</Box>
</Box>
@ -334,7 +334,7 @@ export function Space() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.Flag} size="100" filled={lobbySelected} />
<MDIcon size={1} path={lobbySelected ? mdiFlag : mdiFlagOutline} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit" truncate>
@ -350,7 +350,7 @@ export function Space() {
<NavItemContent>
<Box as="span" grow="Yes" alignItems="Center" gap="200">
<Avatar size="200" radii="400">
<Icon src={Icons.Search} size="100" filled={searchSelected} />
<MDIcon size={1} path={mdiMagnify} />
</Avatar>
<Box as="span" grow="Yes">
<Text as="span" size="Inherit" truncate>

View file

@ -863,5 +863,6 @@
"settings.presence.title": "Presence status",
"settings.new_design_input.title": "New input design",
"settings.new_design_input.desc": "Apply new design for message composer.",
"title.incoming_call": "Incoming call from {0}"
"title.incoming_call": "Incoming call from {0}",
"title.incoming_video_call": "Incoming video call from {0}"
}

View file

@ -21,5 +21,6 @@
"login.forgot_password_link": "ふぉるごっとぱすをーど?",
"login.login_button": "ろぎん",
"error.register.invalid_request": "Failed to register.ようろれくべすとだたわずいんわりど。",
"title.incoming_call": "インコメンがカール {0}"
"title.incoming_call": "インコメンがカール {0}",
"title.incoming_video_call": "インコメンがウィデオカール {0}"
}

View file

@ -863,5 +863,6 @@
"settings.presence.title": "Статус",
"settings.new_design_input.title": "Новый дизайн ввода сообщения",
"settings.new_design_input.desc": "Использовать новый дизайн редактора сообщений.",
"title.incoming_call": "Входящий звонок от {0}"
"title.incoming_call": "Входящий звонок от {0}",
"title.incoming_video_call": "Входящий видеозвонок от {0}"
}