Дизайн звонков

This commit is contained in:
RoyceDa
2026-02-28 12:48:53 +02:00
parent 8b16c4ce0f
commit 461ccbfa94
13 changed files with 416 additions and 97 deletions

View File

@@ -6,9 +6,8 @@ import { ConfirmSeed } from './views/ConfirmSeed/ConfirmSeed';
import { SetPassword } from './views/SetPassword/SetPassword'; import { SetPassword } from './views/SetPassword/SetPassword';
import { Main } from './views/Main/Main'; import { Main } from './views/Main/Main';
import { ExistsSeed } from './views/ExistsSeed/ExistsSeed'; import { ExistsSeed } from './views/ExistsSeed/ExistsSeed';
import { Box, Divider } from '@mantine/core'; import { Box } from '@mantine/core';
import './style.css' import './style.css'
import { useRosettaColors } from './hooks/useRosettaColors';
import { Buffer } from 'buffer'; import { Buffer } from 'buffer';
import { InformationProvider } from './providers/InformationProvider/InformationProvider'; import { InformationProvider } from './providers/InformationProvider/InformationProvider';
import { BlacklistProvider } from './providers/BlacklistProvider/BlacklistProvider'; import { BlacklistProvider } from './providers/BlacklistProvider/BlacklistProvider';
@@ -27,8 +26,6 @@ window.Buffer = Buffer;
export default function App() { export default function App() {
const { allAccounts, accountProviderLoaded } = useAccountProvider(); const { allAccounts, accountProviderLoaded } = useAccountProvider();
const colors = useRosettaColors();
const getViewByLoginState = () => { const getViewByLoginState = () => {
if (!accountProviderLoaded) { if (!accountProviderLoaded) {
@@ -59,7 +56,6 @@ export default function App() {
<SystemAccountProvider> <SystemAccountProvider>
<Box h={'100%'}> <Box h={'100%'}>
<Topbar></Topbar> <Topbar></Topbar>
<Divider color={colors.borderColor}></Divider>
<ContextMenuProvider> <ContextMenuProvider>
<ImageViwerProvider> <ImageViwerProvider>
<AvatarProvider> <AvatarProvider>

View File

@@ -0,0 +1,42 @@
.active {
background: linear-gradient(90deg,rgba(0, 186, 59, 1) 0%, rgba(0, 194, 81, 1) 50%);
background-size: 200% 200%;
animation: activeFlow 5s ease-in-out infinite;
}
@keyframes activeFlow {
0% {
background-position: 0% 50%;
filter: saturate(1);
}
50% {
background-position: 100% 50%;
filter: saturate(1.15);
}
100% {
background-position: 0% 50%;
filter: saturate(1);
}
}
.connecting {
background: linear-gradient(120deg, #ff2d2d, #ff7a00, #ff2d2d);
background-size: 220% 220%;
animation: connectingFlow 5s ease-in-out infinite;
}
@keyframes connectingFlow {
0% {
background-position: 0% 50%;
filter: saturate(1);
}
50% {
background-position: 100% 50%;
filter: saturate(1.15);
}
100% {
background-position: 0% 50%;
filter: saturate(1);
}
}
/* ...existing code... */

View File

@@ -0,0 +1,95 @@
import { useCalls } from "@/app/providers/CallProvider/useCalls";
import { useUserInformation } from "@/app/providers/InformationProvider/useUserInformation";
import { Box, Flex, Loader, Text } from "@mantine/core";
import classes from "./ActiveCall.module.css";
import { CallState } from "@/app/providers/CallProvider/CallProvider";
import { IconMicrophone, IconMicrophoneOff, IconPhoneX, IconVolume, IconVolumeOff } from "@tabler/icons-react";
import { translateDurationToTime } from "@/app/providers/CallProvider/translateDurationTime";
export function ActiveCall() {
const {activeCall, callState, duration, muted, sound, close, setMuted, setSound, setShowCallView} = useCalls();
const [userInfo] = useUserInformation(activeCall);
//const colors = useRosettaColors();
if(activeCall == ""){
return <></>
}
const getConnectingClass = () => {
if(callState === CallState.CONNECTING){
return classes.connecting;
}
if(callState === CallState.ACTIVE){
return classes.active;
}
return "";
}
return (
<>
<Box py={4} style={{
cursor: 'pointer'
}} px={10} className={getConnectingClass()} onClick={() => setShowCallView(true)}>
<Flex align={'center'} justify={'row'} gap={10}>
<Flex w={'100%'} justify={'space-between'} align={'center'}>
<Flex>
{!muted && (
<IconMicrophoneOff style={{
cursor: 'pointer'
}} onClick={(e) => {
e.stopPropagation();
setMuted(true);
}} size={16} color={'#fff'}></IconMicrophoneOff>
)}
{muted && (
<IconMicrophone style={{
cursor: 'pointer'
}} onClick={(e) => {
e.stopPropagation();
setMuted(false);
}} size={16} color={'#fff'}></IconMicrophone>
)}
</Flex>
<Flex justify={'center'} align={'center'} gap={'xs'}>
<Text fw={500} c={'#fff'} style={{
userSelect: 'none'
}} fz={13}>{userInfo?.title || activeCall}</Text>
{callState === CallState.CONNECTING && (
<Loader type={'dots'} size={12} color="white"></Loader>
)}
{callState == CallState.ACTIVE && (
<Text fw={500} c={'#ffffff'} style={{
userSelect: 'none'
}} fz={12}>{translateDurationToTime(duration)}</Text>
)}
</Flex>
<Flex gap={'xs'} align={'center'} justify={'center'}>
{sound && (
<IconVolumeOff style={{
cursor: 'pointer'
}} size={16} onClick={(e) => {
e.stopPropagation();
setSound(false)
}} color={'#fff'}></IconVolumeOff>
)}
{!sound && (
<IconVolume style={{
cursor: 'pointer'
}} size={16} onClick={(e) => {
e.stopPropagation();
setSound(true)
}} color={'#fff'}></IconVolume>
)}
<IconPhoneX style={{
cursor: 'pointer'
}} onClick={(e) => {
e.stopPropagation();
close();
}} size={16} color={'#fff'}></IconPhoneX>
</Flex>
</Flex>
</Flex>
</Box>
</>
);
}

View File

@@ -0,0 +1,111 @@
import { useRosettaColors } from "@/app/hooks/useRosettaColors";
import { useAvatars } from "@/app/providers/AvatarProvider/useAvatars";
import { CallContextValue, CallState } from "@/app/providers/CallProvider/CallProvider";
import { translateDurationToTime } from "@/app/providers/CallProvider/translateDurationTime";
import { useUserInformation } from "@/app/providers/InformationProvider/useUserInformation";
import { Avatar, Box, Flex, Text } from "@mantine/core";
import { IconChevronLeft, IconMicrophone, IconMicrophoneOff, IconPhone, IconPhoneX, IconQrcode, IconVolume, IconVolumeOff, IconX } from "@tabler/icons-react";
export interface CallProps {
context: CallContextValue;
}
export function Call(props: CallProps) {
const {
activeCall,
duration,
callState,
close,
sound,
setSound,
setMuted,
setShowCallView,
muted} = props.context;
const [userInfo] = useUserInformation(activeCall);
const avatars = useAvatars(activeCall);
const colors = useRosettaColors();
return (
<Box pos={'absolute'} top={0} left={0} w={'100%'} h={'100vh'} style={{
zIndex: 11,
background: 'linear-gradient(120deg,#141414 0%, #000000 100%)',
}}>
<Flex h={'100%'} w={'100vw'} direction={'column'} gap={'lg'} pt={'xl'}>
<Flex direction={'row'} w={'100%'} gap={'sm'} align={'center'} justify={'space-between'} p={'sm'}>
<Flex style={{
cursor: 'pointer'
}} onClick={() => setShowCallView(false)} justify={'center'} align={'center'}>
<IconChevronLeft size={20}></IconChevronLeft>
<Text fw={500}>Back</Text>
</Flex>
<Flex>
<IconQrcode size={24}></IconQrcode>
</Flex>
</Flex>
<Flex direction={'column'} mt={'xl'} style={{
userSelect: 'none'
}} w={'100vw'} gap={'sm'} align={'center'} justify={'center'}>
<Avatar size={128} bg={avatars.length > 0 ? '#fff' : undefined} src={avatars.length > 0 ? avatars[0].avatar : undefined} color={'initials'} name={userInfo.title}></Avatar>
<Text fz={20} fw={'bold'} c={'#FFF'}>{userInfo.title}</Text>
{callState == CallState.ACTIVE && (<Text fz={14} c={'#FFF'}>{translateDurationToTime(duration)}</Text>)}
{callState == CallState.CONNECTING && (<Text fz={14} c={'#FFF'}>Connecting...</Text>)}
{callState == CallState.INCOMING && (<Text fz={14} c={'#FFF'}>Incoming call...</Text>)}
<Flex gap={'xl'} align={'center'} justify={'center'} mt={'xl'}>
{callState == CallState.ACTIVE || callState == CallState.CONNECTING && (
<>
<Box w={50} onClick={() => setSound(!sound)} style={{
borderRadius: 25,
cursor: 'pointer'
}} h={50} bg={sound ? colors.chevrons.active : colors.chevrons.disabled}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
{!sound && <IconVolume size={24} color={'#fff'}></IconVolume>}
{sound && <IconVolumeOff size={24} color={'#fff'}></IconVolumeOff>}
</Flex>
</Box>
<Box w={50} onClick={() => setMuted(!muted)} style={{
borderRadius: 25,
cursor: 'pointer'
}} h={50} bg={!muted ? colors.chevrons.active : colors.chevrons.disabled}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
{muted && <IconMicrophone size={24} color={'#fff'}></IconMicrophone>}
{!muted && <IconMicrophoneOff size={24} color={'#fff'}></IconMicrophoneOff>}
</Flex>
</Box>
<Box w={50} onClick={close} style={{
borderRadius: 25,
cursor: 'pointer'
}} h={50} bg={colors.error}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
<IconPhoneX size={24} color={'#fff'}></IconPhoneX>
</Flex>
</Box>
</>
)}
{callState == CallState.INCOMING && (
<>
{userInfo.title != "Rosetta" && (
<Box w={50} onClick={close} style={{
borderRadius: 25,
cursor: 'pointer'
}} h={50} bg={colors.error}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
<IconX size={24} color={'#fff'}></IconX>
</Flex>
</Box>
)}
<Box w={userInfo.title != "Rosetta" ? 50 : 100} onClick={close} style={{
borderRadius: '50%',
cursor: 'pointer'
}} h={userInfo.title != "Rosetta" ? 50 : 100} bg={colors.success}>
<Flex w={'100%'} h={'100%'} justify={'center'} align={'center'}>
<IconPhone size={24} color={'#fff'}></IconPhone>
</Flex>
</Box>
</>
)}
</Flex>
</Flex>
</Flex>
</Box>
)
}

View File

@@ -1,14 +1,13 @@
import { useRosettaColors } from "@/app/hooks/useRosettaColors"; import { useRosettaColors } from "@/app/hooks/useRosettaColors";
import { OnlineState } from "@/app/providers/ProtocolProvider/protocol/packets/packet.onlinestate"; import { OnlineState } from "@/app/providers/ProtocolProvider/protocol/packets/packet.onlinestate";
import { usePublicKey } from "@/app/providers/AccountProvider/usePublicKey"; import { usePublicKey } from "@/app/providers/AccountProvider/usePublicKey";
import { useBlacklist } from "@/app/providers/BlacklistProvider/useBlacklist";
import { useDialog } from "@/app/providers/DialogProvider/useDialog"; import { useDialog } from "@/app/providers/DialogProvider/useDialog";
import { useUserInformation } from "@/app/providers/InformationProvider/useUserInformation"; import { useUserInformation } from "@/app/providers/InformationProvider/useUserInformation";
import { ProtocolState } from "@/app/providers/ProtocolProvider/ProtocolProvider"; import { ProtocolState } from "@/app/providers/ProtocolProvider/ProtocolProvider";
import { useProtocolState } from "@/app/providers/ProtocolProvider/useProtocolState"; import { useProtocolState } from "@/app/providers/ProtocolProvider/useProtocolState";
import { Avatar, Box, Divider, Flex, Loader, Text, Tooltip, useComputedColorScheme, useMantineTheme } from "@mantine/core"; import { Avatar, Box, Divider, Flex, Loader, Text, useComputedColorScheme, useMantineTheme } from "@mantine/core";
import { modals } from "@mantine/modals"; import { modals } from "@mantine/modals";
import { IconBookmark, IconLockAccess, IconLockCancel, IconTrashX } from "@tabler/icons-react"; import { IconBookmark, IconPhone, IconTrashX } from "@tabler/icons-react";
import { useEffect, useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import { VerifiedBadge } from "../VerifiedBadge/VerifiedBadge"; import { VerifiedBadge } from "../VerifiedBadge/VerifiedBadge";
@@ -20,6 +19,7 @@ import { ReplyHeader } from "../ReplyHeader/ReplyHeader";
import { useRosettaBreakpoints } from "@/app/hooks/useRosettaBreakpoints"; import { useRosettaBreakpoints } from "@/app/hooks/useRosettaBreakpoints";
import { BackToDialogs } from "../BackToDialogs/BackToDialogs"; import { BackToDialogs } from "../BackToDialogs/BackToDialogs";
import { useSystemAccounts } from "@/app/providers/SystemAccountsProvider/useSystemAccounts"; import { useSystemAccounts } from "@/app/providers/SystemAccountsProvider/useSystemAccounts";
import { useCalls } from "@/app/providers/CallProvider/useCalls";
export function ChatHeader() { export function ChatHeader() {
@@ -29,7 +29,6 @@ export function ChatHeader() {
const publicKey = usePublicKey(); const publicKey = usePublicKey();
const {deleteMessages, dialog} = useDialog(); const {deleteMessages, dialog} = useDialog();
const theme = useMantineTheme(); const theme = useMantineTheme();
const [blocked, blockUser, unblockUser] = useBlacklist(dialog);
const [opponent, ___, forceUpdateUserInformation] = useUserInformation(dialog); const [opponent, ___, forceUpdateUserInformation] = useUserInformation(dialog);
const [protocolState] = useProtocolState(); const [protocolState] = useProtocolState();
const [userTypeing, setUserTypeing] = useState(false); const [userTypeing, setUserTypeing] = useState(false);
@@ -39,6 +38,7 @@ export function ChatHeader() {
const {lg} = useRosettaBreakpoints(); const {lg} = useRosettaBreakpoints();
const systemAccounts = useSystemAccounts(); const systemAccounts = useSystemAccounts();
const isSystemAccount = systemAccounts.find((acc) => acc.publicKey == dialog) != undefined; const isSystemAccount = systemAccounts.find((acc) => acc.publicKey == dialog) != undefined;
const {call} = useCalls();
useEffect(() => { useEffect(() => {
@@ -78,20 +78,6 @@ export function ChatHeader() {
}); });
} }
const onClickBlockUser = () => {
if(opponent.publicKey != "DELETED"
&& opponent.publicKey != publicKey){
blockUser();
}
}
const onClickUnblockUser = () => {
if(opponent.publicKey != "DELETED"
&& opponent.publicKey != publicKey){
unblockUser();
}
}
const onClickProfile = () => { const onClickProfile = () => {
if(opponent.publicKey != "DELETED" && opponent.publicKey != publicKey){ if(opponent.publicKey != "DELETED" && opponent.publicKey != publicKey){
navigate("/main/profile/" + opponent.publicKey); navigate("/main/profile/" + opponent.publicKey);
@@ -149,32 +135,16 @@ export function ChatHeader() {
</Flex> </Flex>
</Flex> </Flex>
<Flex h={'100%'} align={'center'} gap={'sm'}> <Flex h={'100%'} align={'center'} gap={'sm'}>
<Tooltip onClick={onClickClearMessages} withArrow position={'bottom'} label={"Clear all messages"}> <IconPhone
onClick={() => call(dialog)}
style={{
cursor: 'pointer'
}} stroke={1.5} color={theme.colors.blue[7]} size={24}></IconPhone>
<IconTrashX <IconTrashX
onClick={onClickClearMessages}
style={{ style={{
cursor: 'pointer' cursor: 'pointer'
}} stroke={1.5} color={theme.colors.blue[7]} size={24}></IconTrashX> }} stroke={1.5} color={theme.colors.blue[7]} size={24}></IconTrashX>
</Tooltip>
{publicKey != opponent.publicKey && !blocked && !isSystemAccount && (
<Tooltip onClick={onClickBlockUser} withArrow position={'bottom'} label={"Block user"}>
<IconLockCancel
style={{
cursor: 'pointer'
}} stroke={1.5} color={theme.colors.red[7]} size={24}
>
</IconLockCancel>
</Tooltip>
)}
{blocked && !isSystemAccount && (
<Tooltip onClick={onClickUnblockUser} withArrow position={'bottom'} label={"Unblock user"}>
<IconLockAccess
style={{
cursor: 'pointer'
}} stroke={1.5} color={theme.colors.green[7]} size={24}
>
</IconLockAccess>
</Tooltip>
)}
</Flex> </Flex>
</Flex>} </Flex>}
{replyMessages.messages.length > 0 && !replyMessages.inDialogInput && <ReplyHeader></ReplyHeader>} {replyMessages.messages.length > 0 && !replyMessages.inDialogInput && <ReplyHeader></ReplyHeader>}

View File

@@ -10,6 +10,8 @@ import { DialogsPanelHeader } from '../DialogsPanelHeader/DialogsPanelHeader';
import { useDialogsList } from '@/app/providers/DialogListProvider/useDialogsList'; import { useDialogsList } from '@/app/providers/DialogListProvider/useDialogsList';
import { useVerifyRequest } from '@/app/providers/DeviceProvider/useVerifyRequest'; import { useVerifyRequest } from '@/app/providers/DeviceProvider/useVerifyRequest';
import { DeviceVerify } from '../DeviceVerify/DeviceVerify'; import { DeviceVerify } from '../DeviceVerify/DeviceVerify';
import { ActiveCall } from '../ActiveCall/ActiveCall';
import { useViewPanelsState, ViewPanelsState } from '@/app/hooks/useViewPanelsState';
export function DialogsPanel() { export function DialogsPanel() {
const [dialogsMode, setDialogsMode] = useState<'all' | 'requests'>('all'); const [dialogsMode, setDialogsMode] = useState<'all' | 'requests'>('all');
@@ -18,6 +20,7 @@ export function DialogsPanel() {
const colors = useRosettaColors(); const colors = useRosettaColors();
const navigate = useNavigate(); const navigate = useNavigate();
const device = useVerifyRequest(); const device = useVerifyRequest();
const [viewState] = useViewPanelsState();
useEffect(() => { useEffect(() => {
((async () => { ((async () => {
@@ -52,6 +55,9 @@ export function DialogsPanel() {
direction={'column'} direction={'column'}
justify={'space-between'} justify={'space-between'}
> >
{viewState == ViewPanelsState.DIALOGS_PANEL_ONLY && (
<ActiveCall></ActiveCall>
)}
<Box> <Box>
<DialogsPanelHeader></DialogsPanelHeader> <DialogsPanelHeader></DialogsPanelHeader>
{device && ( {device && (

View File

@@ -4,7 +4,7 @@
left: 12px; left: 12px;
display: flex; display: flex;
gap: 8px; gap: 8px;
z-index: 10; z-index: 15;
app-region: no-drag; app-region: no-drag;
} }
.close_btn, .minimize_btn, .maximize_btn { .close_btn, .minimize_btn, .maximize_btn {

View File

@@ -0,0 +1,70 @@
import { Call } from "@/app/components/Call/Call";
import { createContext, useState } from "react";
export interface CallContextValue {
call: (callable: string) => void;
close: () => void;
activeCall: string;
callState: CallState;
muted: boolean;
sound: boolean;
setMuted: (muted: boolean) => void;
setSound: (sound: boolean) => void;
duration: number;
setShowCallView: (show: boolean) => void;
}
export enum CallState {
CONNECTING,
ACTIVE,
ENDED,
INCOMING
}
export const CallContext = createContext<CallContextValue | null>(null);
export interface CallProviderProps {
children: React.ReactNode;
}
export function CallProvider(props : CallProviderProps) {
const [activeCall, setActiveCall] = useState<string>("");
const [callState, setCallState] = useState<CallState>(CallState.ENDED);
const [muted, setMuted] = useState<boolean>(false);
const [sound, setSound] = useState<boolean>(true);
const [duration, setDuration] = useState<number>(0);
const [showCallView, setShowCallView] = useState<boolean>(callState == CallState.INCOMING);
const call = (dialog: string) => {
setActiveCall(dialog);
setCallState(CallState.CONNECTING);
setShowCallView(true);
}
const close = () => {
setActiveCall("");
setCallState(CallState.ENDED);
setShowCallView(false);
setDuration(0);
}
const context = {
call,
close,
activeCall,
callState,
muted,
sound,
setMuted,
setSound,
duration,
setShowCallView
};
return (
<CallContext.Provider value={context}>
{props.children}
{showCallView && <Call context={context}></Call>}
</CallContext.Provider>
)
}

View File

@@ -0,0 +1,5 @@
export const translateDurationToTime = (duration: number) => {
const minutes = Math.floor(duration / 60);
const seconds = duration % 60;
return `${minutes}:${seconds < 10 ? '0' : ''}${seconds}`;
}

View File

@@ -0,0 +1,15 @@
import { useContext } from "react";
import { CallContext, CallContextValue } from "./CallProvider";
/**
* Хук предоставляет функции для работы с звонками, такие как инициирование звонка, принятие звонка, завершение звонка и т.д.
* Он может использоваться в компонентах, связанных с звонками, для управления состоянием звонков и взаимодействия с сервером.
*/
export function useCalls() : CallContextValue {
const context = useContext(CallContext);
if (!context) {
throw new Error("useCalls must be used within a CallProvider");
}
return context;
}

View File

@@ -9,12 +9,13 @@ import { useEffect } from "react";
import { useViewPanelsState, ViewPanelsState } from "@/app/hooks/useViewPanelsState"; import { useViewPanelsState, ViewPanelsState } from "@/app/hooks/useViewPanelsState";
import { GroupHeader } from "@/app/components/GroupHeader/GroupHeader"; import { GroupHeader } from "@/app/components/GroupHeader/GroupHeader";
import { useGroups } from "@/app/providers/DialogProvider/useGroups"; import { useGroups } from "@/app/providers/DialogProvider/useGroups";
import { ActiveCall } from "@/app/components/ActiveCall/ActiveCall";
export function Chat() { export function Chat() {
const params = useParams(); const params = useParams();
const dialog = params.id || "DELETED"; const dialog = params.id || "DELETED";
const {lg} = useRosettaBreakpoints(); const {lg} = useRosettaBreakpoints();
const [__, setViewState] = useViewPanelsState(); const [viewState, setViewState] = useViewPanelsState();
const {hasGroup} = useGroups(); const {hasGroup} = useGroups();
useEffect(() => { useEffect(() => {
@@ -30,6 +31,9 @@ export function Chat() {
return (<> return (<>
<DialogProvider dialog={dialog} key={dialog}> <DialogProvider dialog={dialog} key={dialog}>
<Flex direction={'column'} justify={'space-between'} h={'100%'}> <Flex direction={'column'} justify={'space-between'} h={'100%'}>
{viewState != ViewPanelsState.DIALOGS_PANEL_ONLY && (
<ActiveCall></ActiveCall>
)}
{/* Group Header */} {/* Group Header */}
{hasGroup(dialog) && <GroupHeader></GroupHeader>} {hasGroup(dialog) && <GroupHeader></GroupHeader>}
{/* Dialog peer to peer Header */} {/* Dialog peer to peer Header */}

View File

@@ -31,6 +31,7 @@ import { useUpdateMessage } from "@/app/hooks/useUpdateMessage";
import { useDeviceMessage } from "@/app/hooks/useDeviceMessage"; import { useDeviceMessage } from "@/app/hooks/useDeviceMessage";
import { UpdateProvider } from "@/app/providers/UpdateProvider/UpdateProvider"; import { UpdateProvider } from "@/app/providers/UpdateProvider/UpdateProvider";
import { useSynchronize } from "@/app/providers/DialogProvider/useSynchronize"; import { useSynchronize } from "@/app/providers/DialogProvider/useSynchronize";
import { CallProvider } from "@/app/providers/CallProvider/CallProvider";
export function Main() { export function Main() {
const { mainColor, borderColor } = useRosettaColors(); const { mainColor, borderColor } = useRosettaColors();
@@ -154,6 +155,7 @@ export function Main() {
<SystemAccountProvider> <SystemAccountProvider>
<TransportProvider> <TransportProvider>
<UpdateProvider> <UpdateProvider>
<CallProvider>
<Flex direction={'row'} style={{ <Flex direction={'row'} style={{
height: '100%', height: '100%',
width: '100vw', width: '100vw',
@@ -164,7 +166,9 @@ export function Main() {
}}> }}>
<DialogsPanel></DialogsPanel> <DialogsPanel></DialogsPanel>
</div> </div>
{lg && (
<Divider color={borderColor} orientation={'vertical'}></Divider> <Divider color={borderColor} orientation={'vertical'}></Divider>
)}
{viewState != ViewPanelsState.DIALOGS_PANEL_ONLY && <Box {viewState != ViewPanelsState.DIALOGS_PANEL_ONLY && <Box
bg={mainColor} bg={mainColor}
style={{ style={{
@@ -200,6 +204,7 @@ export function Main() {
</Flex> </Flex>
</Overlay> </Overlay>
)} )}
</CallProvider>
</UpdateProvider> </UpdateProvider>
</TransportProvider> </TransportProvider>
</SystemAccountProvider> </SystemAccountProvider>

View File

@@ -122,6 +122,7 @@
"@electron-toolkit/eslint-config": "^2.0.0", "@electron-toolkit/eslint-config": "^2.0.0",
"@electron-toolkit/eslint-config-ts": "^3.0.0", "@electron-toolkit/eslint-config-ts": "^3.0.0",
"@electron-toolkit/tsconfig": "^1.0.1", "@electron-toolkit/tsconfig": "^1.0.1",
"@electron/rebuild": "^4.0.3",
"@rushstack/eslint-patch": "^1.10.5", "@rushstack/eslint-patch": "^1.10.5",
"@tailwindcss/vite": "^4.0.9", "@tailwindcss/vite": "^4.0.9",
"@types/node": "^22.13.5", "@types/node": "^22.13.5",
@@ -132,7 +133,6 @@
"@vitejs/plugin-react": "^4.3.4", "@vitejs/plugin-react": "^4.3.4",
"electron": "^38.3.0", "electron": "^38.3.0",
"electron-builder": "^25.1.8", "electron-builder": "^25.1.8",
"@electron/rebuild": "^4.0.3",
"electron-vite": "^3.0.0", "electron-vite": "^3.0.0",
"eslint": "^9.21.0", "eslint": "^9.21.0",
"eslint-plugin-react": "^7.37.4", "eslint-plugin-react": "^7.37.4",