mirror of
https://github.com/officialdakari/Extera.git
synced 2025-04-11 23:08:46 +02:00
widgets (WIP, DO NOT USE!)
add back button for rooms
This commit is contained in:
parent
a5773c3207
commit
e5e35acc1c
16 changed files with 11208 additions and 10878 deletions
28
.github/dependabot.yml
vendored
28
.github/dependabot.yml
vendored
|
@ -1,30 +1,4 @@
|
|||
# Docs: <https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/customizing-dependency-updates>
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: npm
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: "tuesday"
|
||||
time: "01:00"
|
||||
timezone: "Asia/Kolkata"
|
||||
open-pull-requests-limit: 15
|
||||
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: "tuesday"
|
||||
time: "01:00"
|
||||
timezone: "Asia/Kolkata"
|
||||
open-pull-requests-limit: 5
|
||||
|
||||
- package-ecosystem: docker
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
day: "tuesday"
|
||||
time: "01:00"
|
||||
timezone: "Asia/Kolkata"
|
||||
open-pull-requests-limit: 5
|
||||
updates: []
|
19873
package-lock.json
generated
19873
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -78,6 +78,7 @@
|
|||
"react-quill": "2.0.0",
|
||||
"react-quilljs": "2.0.2",
|
||||
"react-range": "1.8.14",
|
||||
"react-resizable": "3.0.5",
|
||||
"react-router-dom": "6.20.0",
|
||||
"sanitize-html": "2.12.1",
|
||||
"showdown": "2.1.0",
|
||||
|
@ -121,4 +122,4 @@
|
|||
"vite-plugin-static-copy": "1.0.4",
|
||||
"vite-plugin-top-level-await": "1.4.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ export const toMatrixCustomHTML = (
|
|||
content: string,
|
||||
getDisplayName: any
|
||||
): string => {
|
||||
const table = {};
|
||||
const table: Record<string, string> = {};
|
||||
var str = parseBlockMD(
|
||||
content.replaceAll('<', '<')
|
||||
.replaceAll('>', '>')
|
||||
|
@ -45,7 +45,7 @@ export const toMatrixCustomHTML = (
|
|||
})
|
||||
.replaceAll(userMentionRegexp, (match: string, mxId: string) => {
|
||||
const id = `{[${v4()}]}`;
|
||||
table[id] = `<a href="https://matrix.to/#/${mxId}">@${getDisplayName(mxId)}</a>`;
|
||||
table[id] = `<a href="https://matrix.to/#/${mxId}">${getDisplayName(mxId)}</a>`;
|
||||
return id;
|
||||
})
|
||||
.replaceAll(roomMentionRegexp, (match: string, name: string, id: string) => {
|
||||
|
@ -83,7 +83,6 @@ export const getMentions = (content: string): Mentions => {
|
|||
user_ids.push(match[1]);
|
||||
}
|
||||
}
|
||||
// TODO Implement @room checking
|
||||
const room = /{@room}/g.test(content);
|
||||
return {
|
||||
user_ids, room
|
||||
|
|
8
src/app/components/modal/Modal.css.ts
Normal file
8
src/app/components/modal/Modal.css.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { style } from "@vanilla-extract/css";
|
||||
|
||||
export const DraggableContainer = style({
|
||||
position: 'absolute',
|
||||
zIndex: '100',
|
||||
minHeight: '500px',
|
||||
//minWidth: '600px'
|
||||
});
|
61
src/app/components/modal/Modal.tsx
Normal file
61
src/app/components/modal/Modal.tsx
Normal file
|
@ -0,0 +1,61 @@
|
|||
import { Box, config, Header, IconButton, Modal, Text } from 'folds';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import Draggable from 'react-draggable';
|
||||
|
||||
import * as css from './Modal.css';
|
||||
import { ModalsType } from '../../hooks/useModals';
|
||||
import Icon from '@mdi/react';
|
||||
import { mdiClose } from '@mdi/js';
|
||||
|
||||
type ModalsProps = {
|
||||
modals: ModalsType;
|
||||
};
|
||||
|
||||
export function Modals({ modals }: ModalsProps) {
|
||||
const [record, setRecord] = useState(modals.record);
|
||||
|
||||
useEffect(() => {
|
||||
console.debug('UPDATE !!! ');
|
||||
setRecord(modals.record);
|
||||
}, [modals.record]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{record && Object.entries(record).map(
|
||||
([id, content]) => (
|
||||
<Draggable
|
||||
|
||||
defaultPosition={{ x: 0, y: 0 }}
|
||||
handle='.modal-header'
|
||||
>
|
||||
<div className={css.DraggableContainer}>
|
||||
<Modal variant="Surface" size="500">
|
||||
<Header
|
||||
className='modal-header'
|
||||
style={{
|
||||
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
|
||||
borderBottomWidth: config.borderWidth.B300,
|
||||
}}
|
||||
variant="Surface"
|
||||
size="500"
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="H4">{content.title ?? 'Modal'}</Text>
|
||||
</Box>
|
||||
{
|
||||
content.allowClose && (
|
||||
<IconButton size="300" onClick={() => modals.removeModal(id)} radii="300">
|
||||
<Icon size={1} path={mdiClose} />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
</Header>
|
||||
{content.node}
|
||||
</Modal>
|
||||
</div>
|
||||
</Draggable>
|
||||
)
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
13
src/app/components/widget/WidgetItem.css.ts
Normal file
13
src/app/components/widget/WidgetItem.css.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { style } from "@vanilla-extract/css";
|
||||
import { color, config } from "folds";
|
||||
|
||||
export const WidgetItem = style({
|
||||
width: 'auto',
|
||||
margin: '10px',
|
||||
color: color.SurfaceVariant.OnContainer,
|
||||
padding: config.space.S400,
|
||||
justifyContent: 'space-between',
|
||||
backgroundColor: color.SurfaceVariant.Container,
|
||||
boxShadow: `inset 0 0 0 ${config.borderWidth.B300} ${color.SurfaceVariant.ContainerLine}`,
|
||||
borderRadius: config.radii.R400
|
||||
});
|
31
src/app/components/widget/WidgetItem.tsx
Normal file
31
src/app/components/widget/WidgetItem.tsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import React from 'react';
|
||||
import { Box, Button, Text } from "folds";
|
||||
import { getText } from '../../../lang';
|
||||
|
||||
import * as css from './WidgetItem.css';
|
||||
|
||||
type WidgetItemProps = {
|
||||
name?: string;
|
||||
url: string;
|
||||
type: string;
|
||||
onClick?: () => void;
|
||||
};
|
||||
|
||||
export function WidgetItem({ name, type, url, onClick }: WidgetItemProps) {
|
||||
|
||||
return (
|
||||
<Box className={css.WidgetItem} direction='Row'>
|
||||
<Box direction='Column'>
|
||||
<Text priority='400' size='H3'>
|
||||
{name ?? 'Widget'}
|
||||
</Text>
|
||||
<Text priority='400' size='B400'>
|
||||
{type}
|
||||
</Text>
|
||||
</Box>
|
||||
<Button variant='Primary' onClick={onClick}>
|
||||
{getText('btn.widget.open')}
|
||||
</Button>
|
||||
</Box>
|
||||
);
|
||||
}
|
|
@ -303,7 +303,16 @@ export function RoomNavItem({
|
|||
<UnreadBadge highlight={unread.highlight > 0} count={unread.total} />
|
||||
</UnreadBadgeCenter>
|
||||
)}
|
||||
{muted && !optionsVisible && <Icon size={1} path={mdiBellCancel} />}
|
||||
{muted && !optionsVisible && (
|
||||
<IconButton
|
||||
variant="Background"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="300"
|
||||
>
|
||||
<Icon size={0.8} path={mdiBellCancel} />
|
||||
</IconButton>
|
||||
)}
|
||||
</Box>
|
||||
</NavItemContent>
|
||||
</NavLink>
|
||||
|
|
|
@ -5,11 +5,11 @@ export const RoomCallBox = style({
|
|||
width: 'auto',
|
||||
//minHeight: '200px',
|
||||
margin: '10px',
|
||||
//backgroundColor: color.SurfaceVariant.Container,
|
||||
color: color.SurfaceVariant.OnContainer,
|
||||
padding: config.space.S400,
|
||||
//backgroundColor: color.SurfaceVariant.Container,
|
||||
//boxShadow: `inset 0 0 0 ${config.borderWidth.B300} ${color.SurfaceVariant.ContainerLine}`,
|
||||
//borderRadius: config.radii.R400,
|
||||
padding: config.space.S400,
|
||||
gap: '20px'
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { FormEventHandler, MouseEventHandler, forwardRef, useEffect, useMemo, useState } from 'react';
|
||||
import React, { FormEventHandler, MouseEventHandler, ReactNode, forwardRef, useEffect, useMemo, useState } from 'react';
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
import {
|
||||
Box,
|
||||
|
@ -71,8 +71,10 @@ 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 { mdiAccount, mdiAccountPlus, mdiArrowLeft, mdiCheckAll, mdiChevronLeft, mdiChevronRight, mdiClose, mdiCog, mdiDotsVertical, mdiLinkVariant, mdiMagnify, mdiPhone, mdiPin, mdiWidgets } from '@mdi/js';
|
||||
import Icon from '@mdi/react';
|
||||
import { WidgetItem } from '../../components/widget/WidgetItem';
|
||||
import { useModals } from '../../hooks/useModals';
|
||||
|
||||
type RoomMenuProps = {
|
||||
room: Room;
|
||||
|
@ -215,7 +217,9 @@ export function RoomViewHeader({
|
|||
const topic = useRoomTopic(room);
|
||||
const [statusMessage, setStatusMessage] = useState('');
|
||||
const [showPinned, setShowPinned] = useState(false);
|
||||
const [pinned, setPinned]: [any[], any] = useState([]);
|
||||
const [showWidgets, setShowWidgets] = useState(false);
|
||||
const [pinned, setPinned] = useState<ReactNode[]>([]);
|
||||
const [widgets, setWidgets] = useState<ReactNode[]>([]);
|
||||
const avatarUrl = avatarMxc ? mx.mxcUrlToHttp(avatarMxc, 96, 96, 'crop') ?? undefined : undefined;
|
||||
|
||||
const setPeopleDrawer = useSetSetting(settingsAtom, 'isPeopleDrawer');
|
||||
|
@ -282,9 +286,64 @@ export function RoomViewHeader({
|
|||
const [jumpAnchor, setJumpAnchor] = useState<RectCords>();
|
||||
const [pageNo, setPageNo] = useState(1);
|
||||
const [loadingPinList, setLoadingPinList] = useState(true);
|
||||
const modals = useModals();
|
||||
|
||||
// officialdakari 24.07.2024 - надо зарефакторить это всё, но мне пока лень
|
||||
|
||||
const handleWidgetsClick = async () => {
|
||||
const userId = mx.getUserId();
|
||||
if (typeof userId !== 'string') return;
|
||||
const profile = mx.getUser(userId);
|
||||
const timeline = room.getLiveTimeline();
|
||||
const state = timeline.getState(EventTimeline.FORWARDS);
|
||||
const widgets = [
|
||||
...(state?.getStateEvents('m.widget') ?? []),
|
||||
...(state?.getStateEvents('im.vector.modular.widgets') ?? [])
|
||||
];
|
||||
const widgetList: ReactNode[] = [];
|
||||
console.log(widgets);
|
||||
if (!widgets || widgets.length < 1) {
|
||||
setWidgets(
|
||||
[
|
||||
<Text>{getText('widgets.none')}</Text>
|
||||
]
|
||||
);
|
||||
} else {
|
||||
for (const ev of widgets) {
|
||||
const content = ev.getContent();
|
||||
if (typeof content.url !== 'string') continue;
|
||||
const data = {
|
||||
matrix_user_id: userId,
|
||||
matrix_room_id: room.roomId,
|
||||
matrix_display_name: profile?.displayName ?? userId,
|
||||
matrix_avatar_url: profile?.avatarUrl && mx.mxcUrlToHttp(profile?.avatarUrl),
|
||||
...content.data
|
||||
};
|
||||
var url = `${content.url}`; // Should not be a reference
|
||||
for (const key in data) {
|
||||
if (typeof data[key] === 'string') {
|
||||
url = url.replaceAll(`$${key}`, data[key]);
|
||||
}
|
||||
}
|
||||
if (!url.startsWith('https://')) continue;
|
||||
const openWidget = () => {
|
||||
modals.addModal({
|
||||
allowClose: true,
|
||||
title: content.name ?? 'Widget',
|
||||
node: (
|
||||
<iframe style={{ border: 'none' }} allow="autoplay; camera; clipboard-write; compute-pressure; display-capture; hid; microphone; screen-wake-lock" allowFullScreen src={url}></iframe>
|
||||
)
|
||||
});
|
||||
};
|
||||
widgetList.push(
|
||||
<WidgetItem onClick={openWidget} name={typeof content.name === 'string' ? content.name : undefined} url={url} type={content.type} />
|
||||
);
|
||||
}
|
||||
}
|
||||
setWidgets(widgetList);
|
||||
setShowWidgets(true);
|
||||
};
|
||||
|
||||
const updatePinnedList = async () => {
|
||||
const pinnedMessages = [];
|
||||
const timeline = room.getLiveTimeline();
|
||||
|
@ -384,6 +443,10 @@ export function RoomViewHeader({
|
|||
setShowPinned(false);
|
||||
};
|
||||
|
||||
const handleWidgetsClose = () => {
|
||||
setShowWidgets(false);
|
||||
};
|
||||
|
||||
const getPresenceFn = usePresences();
|
||||
|
||||
const handlePrevPage = () => {
|
||||
|
@ -533,7 +596,50 @@ export function RoomViewHeader({
|
|||
</FocusTrap>
|
||||
</OverlayCenter>
|
||||
</Overlay>
|
||||
<Overlay open={showWidgets} backdrop={<OverlayBackdrop />}>
|
||||
<OverlayCenter>
|
||||
<FocusTrap
|
||||
focusTrapOptions={{
|
||||
initialFocus: false,
|
||||
onDeactivate: handleWidgetsClose,
|
||||
clickOutsideDeactivates: true
|
||||
}}
|
||||
>
|
||||
<Modal variant="Surface" size="500">
|
||||
<Header
|
||||
style={{
|
||||
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
|
||||
borderBottomWidth: config.borderWidth.B300,
|
||||
}}
|
||||
variant="Surface"
|
||||
size="500"
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="H4">{getText('widgets.title')}</Text>
|
||||
</Box>
|
||||
<IconButton size="300" onClick={handleWidgetsClose} radii="300">
|
||||
<Icon size={1} path={mdiClose} />
|
||||
</IconButton>
|
||||
</Header>
|
||||
<Box tabIndex={-1} direction='Column' style={{ width: 'auto', height: 'inherit' }}>
|
||||
{widgets}
|
||||
</Box>
|
||||
</Modal>
|
||||
</FocusTrap>
|
||||
</OverlayCenter>
|
||||
</Overlay>
|
||||
<Box grow="Yes" gap="300">
|
||||
<Box shrink="No">
|
||||
<IconButton
|
||||
variant="Background"
|
||||
fill="None"
|
||||
size="300"
|
||||
radii="300"
|
||||
onClick={() => history.back()}
|
||||
>
|
||||
<Icon size={1} path={mdiArrowLeft} />
|
||||
</IconButton>
|
||||
</Box>
|
||||
<Box grow="Yes" alignItems="Center" gap="300">
|
||||
<Avatar onClick={handleAvClick} size="300">
|
||||
<RoomAvatar
|
||||
|
@ -605,6 +711,21 @@ export function RoomViewHeader({
|
|||
)}
|
||||
</TooltipProvider>
|
||||
)}
|
||||
<TooltipProvider
|
||||
position="Bottom"
|
||||
offset={4}
|
||||
tooltip={
|
||||
<Tooltip>
|
||||
<Text>{getText('tooltip.widgets')}</Text>
|
||||
</Tooltip>
|
||||
}
|
||||
>
|
||||
{(triggerRef) => (
|
||||
<IconButton ref={triggerRef} onClick={handleWidgetsClick}>
|
||||
<Icon size={1} path={mdiWidgets} />
|
||||
</IconButton>
|
||||
)}
|
||||
</TooltipProvider>
|
||||
<TooltipProvider
|
||||
position="Bottom"
|
||||
offset={4}
|
||||
|
@ -616,7 +737,7 @@ export function RoomViewHeader({
|
|||
>
|
||||
{(triggerRef) => (
|
||||
<IconButton ref={triggerRef} onClick={handlePinnedClick}>
|
||||
<Icon size={1} path={mdiPin} />
|
||||
<Icon size={1} path={mdiPin} />
|
||||
</IconButton>
|
||||
)}
|
||||
</TooltipProvider>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { createContext, useContext } from 'react';
|
||||
import { MatrixClient } from 'matrix-js-sdk';
|
||||
|
||||
const CallContext = createContext<any | null>(null);
|
||||
|
||||
|
|
53
src/app/hooks/useModals.ts
Normal file
53
src/app/hooks/useModals.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import { createContext, ReactNode, useContext, useState } from 'react';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export type ModalsType = {
|
||||
addModal: (element: Modal) => string;
|
||||
removeModal: (id: string) => void;
|
||||
getModals: () => Record<string, Modal> | undefined;
|
||||
getModal: (id: string) => Modal | undefined;
|
||||
record: Record<string, Modal> | undefined;
|
||||
};
|
||||
|
||||
type Modal = {
|
||||
node: ReactNode;
|
||||
allowClose?: boolean;
|
||||
title?: string;
|
||||
};
|
||||
|
||||
const ModalsContext = createContext<ModalsType | undefined>(undefined);
|
||||
|
||||
export const ModalsProvider = ModalsContext.Provider;
|
||||
|
||||
export function useModals(): ModalsType {
|
||||
const modals = useContext(ModalsContext);
|
||||
if (!modals) throw new Error('Modals not initialized!');
|
||||
return modals;
|
||||
}
|
||||
|
||||
export function createModals(): ModalsType {
|
||||
const [record, setRecord] = useState<Record<string, Modal>>({});
|
||||
|
||||
const modals: ModalsType = {
|
||||
addModal: (element) => {
|
||||
const id = v4();
|
||||
setRecord(o => {
|
||||
const updatedRecord = { ...o, [id]: element };
|
||||
return updatedRecord;
|
||||
});
|
||||
return id;
|
||||
},
|
||||
getModal: (id: string): Modal | undefined => record[id] ?? undefined,
|
||||
getModals: (): Record<string, Modal> | undefined => record,
|
||||
removeModal: (id: string) => {
|
||||
setRecord(o => {
|
||||
const updatedRecord = { ...o };
|
||||
delete updatedRecord[id];
|
||||
return updatedRecord;
|
||||
});
|
||||
},
|
||||
record
|
||||
};
|
||||
|
||||
return modals;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import { Box, config, Header, Modal, Spinner, Text } from 'folds';
|
||||
import React, { ReactNode, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { Box, config, Header, IconButton, Modal, Spinner, Text } from 'folds';
|
||||
import React, { ReactElement, ReactNode, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import initMatrix from '../../../client/initMatrix';
|
||||
import { initHotkeys } from '../../../client/event/hotkeys';
|
||||
import { getSecret } from '../../../client/state/auth';
|
||||
|
@ -19,6 +19,10 @@ import Draggable from 'react-draggable';
|
|||
|
||||
import * as css from './ClientRoot.css';
|
||||
import { CallProvider } from '../../hooks/useCall';
|
||||
import { createModals, ModalsProvider } from '../../hooks/useModals';
|
||||
import Icon from '@mdi/react';
|
||||
import { mdiClose } from '@mdi/js';
|
||||
import { Modals } from '../../components/modal/Modal';
|
||||
|
||||
function SystemEmojiFeature() {
|
||||
const [twitterEmoji] = useSetting(settingsAtom, 'twitterEmoji');
|
||||
|
@ -63,6 +67,40 @@ export function ClientRoot({ children }: ClientRootProps) {
|
|||
}, []);
|
||||
|
||||
const callWindowState = useState<any>(null);
|
||||
const modals = createModals();
|
||||
|
||||
// todo refactor that shit
|
||||
// TODO means I will never do that
|
||||
useEffect(() => {
|
||||
const onMessage = (evt: MessageEvent<any>) => {
|
||||
const { data, source } = evt;
|
||||
const respond = (response: any) => {
|
||||
source?.postMessage({
|
||||
...data,
|
||||
response
|
||||
});
|
||||
};
|
||||
if (data.api === 'fromWidget') {
|
||||
if (data.action === 'supported_api_versions') {
|
||||
respond({
|
||||
supported_versions: ['0.0.1', '0.0.2']
|
||||
});
|
||||
} else if (data.action === 'content_loaded') {
|
||||
respond({ success: true });
|
||||
} else if (data.action === 'send_event') {
|
||||
// TODO send_event
|
||||
// 1. we should know from which room that widget is
|
||||
// 2. we should ask user for permission and remember permission
|
||||
// 3. we should make a setting tab to manage widget permissions
|
||||
}
|
||||
}
|
||||
};
|
||||
window.addEventListener('message', onMessage);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('message', onMessage);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<SpecVersions baseUrl={baseUrl!}>
|
||||
|
@ -70,46 +108,50 @@ export function ClientRoot({ children }: ClientRootProps) {
|
|||
<ClientRootLoading />
|
||||
) : (
|
||||
<CallProvider value={callWindowState}>
|
||||
<MatrixClientProvider value={initMatrix.matrixClient!}>
|
||||
<CapabilitiesAndMediaConfigLoader>
|
||||
{(capabilities, mediaConfig) => (
|
||||
<CapabilitiesProvider value={capabilities ?? {}}>
|
||||
<MediaConfigProvider value={mediaConfig ?? {}}>
|
||||
{callWindowState[0] && (
|
||||
<Draggable
|
||||
defaultPosition={{ x: 0, y: 0 }}
|
||||
handle='.modal-header'
|
||||
>
|
||||
<div className={css.DraggableContainer}>
|
||||
<Modal variant="Surface" size="500">
|
||||
<Header
|
||||
className='modal-header'
|
||||
style={{
|
||||
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
|
||||
borderBottomWidth: config.borderWidth.B300,
|
||||
}}
|
||||
variant="Surface"
|
||||
size="500"
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="H4">Call</Text>
|
||||
</Box>
|
||||
</Header>
|
||||
{callWindowState[0]}
|
||||
</Modal>
|
||||
</div>
|
||||
</Draggable>
|
||||
)}
|
||||
{children}
|
||||
<Windows />
|
||||
<Dialogs />
|
||||
<ReusableContextMenu />
|
||||
<SystemEmojiFeature />
|
||||
</MediaConfigProvider>
|
||||
</CapabilitiesProvider>
|
||||
)}
|
||||
</CapabilitiesAndMediaConfigLoader>
|
||||
</MatrixClientProvider>
|
||||
<ModalsProvider value={modals}>
|
||||
<MatrixClientProvider value={initMatrix.matrixClient!}>
|
||||
<CapabilitiesAndMediaConfigLoader>
|
||||
{(capabilities, mediaConfig) => (
|
||||
<CapabilitiesProvider value={capabilities ?? {}}>
|
||||
<MediaConfigProvider value={mediaConfig ?? {}}>
|
||||
<Modals modals={modals} />
|
||||
{callWindowState[0] && (
|
||||
<Draggable
|
||||
defaultPosition={{ x: 0, y: 0 }}
|
||||
handle='.modal-header'
|
||||
>
|
||||
<div className={css.DraggableContainer}>
|
||||
<Modal variant="Surface" size="500">
|
||||
<Header
|
||||
className='modal-header'
|
||||
style={{
|
||||
padding: `0 ${config.space.S200} 0 ${config.space.S400}`,
|
||||
borderBottomWidth: config.borderWidth.B300,
|
||||
}}
|
||||
variant="Surface"
|
||||
size="500"
|
||||
>
|
||||
<Box grow="Yes">
|
||||
<Text size="H4">Call</Text>
|
||||
</Box>
|
||||
</Header>
|
||||
{callWindowState[0]}
|
||||
</Modal>
|
||||
</div>
|
||||
</Draggable>
|
||||
)}
|
||||
|
||||
{children}
|
||||
<Windows />
|
||||
<Dialogs />
|
||||
<ReusableContextMenu />
|
||||
<SystemEmojiFeature />
|
||||
</MediaConfigProvider>
|
||||
</CapabilitiesProvider>
|
||||
)}
|
||||
</CapabilitiesAndMediaConfigLoader>
|
||||
</MatrixClientProvider>
|
||||
</ModalsProvider>
|
||||
</CallProvider>
|
||||
)}
|
||||
</SpecVersions>
|
||||
|
|
|
@ -864,5 +864,8 @@
|
|||
"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_video_call": "Incoming video call from {0}"
|
||||
"title.incoming_video_call": "Incoming video call from {0}",
|
||||
"tooltip.widgets": "Widgets",
|
||||
"widgets.title": "Widgets",
|
||||
"btn.widget.open": "Open"
|
||||
}
|
1735
src/lang/ru.json
1735
src/lang/ru.json
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue