mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-05-15 14:16:58 +00:00
Remove files for mobile
This commit is contained in:
parent
e1bb064d1a
commit
de0f52311e
@ -1,357 +0,0 @@
|
|||||||
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
||||||
import { AppsHome } from './AppsHome';
|
|
||||||
import { Spacer } from '../../common/Spacer';
|
|
||||||
import { getBaseApiReact } from '../../App';
|
|
||||||
import { AppInfo } from './AppInfo';
|
|
||||||
import {
|
|
||||||
executeEvent,
|
|
||||||
subscribeToEvent,
|
|
||||||
unsubscribeFromEvent,
|
|
||||||
} from '../../utils/events';
|
|
||||||
import { AppsParent } from './Apps-styles';
|
|
||||||
import AppViewerContainer from './AppViewerContainer';
|
|
||||||
import ShortUniqueId from 'short-unique-id';
|
|
||||||
import { AppPublish } from './AppPublish';
|
|
||||||
import { AppsCategory } from './AppsCategory';
|
|
||||||
import { AppsLibrary } from './AppsLibrary';
|
|
||||||
|
|
||||||
const uid = new ShortUniqueId({ length: 8 });
|
|
||||||
|
|
||||||
export const Apps = ({ mode, setMode, show, myName }) => {
|
|
||||||
const [availableQapps, setAvailableQapps] = useState([]);
|
|
||||||
const [selectedAppInfo, setSelectedAppInfo] = useState(null);
|
|
||||||
const [selectedCategory, setSelectedCategory] = useState(null);
|
|
||||||
const [tabs, setTabs] = useState([]);
|
|
||||||
const [selectedTab, setSelectedTab] = useState(null);
|
|
||||||
const [isNewTabWindow, setIsNewTabWindow] = useState(false);
|
|
||||||
const [categories, setCategories] = useState([]);
|
|
||||||
const iframeRefs = useRef({});
|
|
||||||
|
|
||||||
const myApp = useMemo(() => {
|
|
||||||
return availableQapps.find(
|
|
||||||
(app) => app.name === myName && app.service === 'APP'
|
|
||||||
);
|
|
||||||
}, [myName, availableQapps]);
|
|
||||||
|
|
||||||
const myWebsite = useMemo(() => {
|
|
||||||
return availableQapps.find(
|
|
||||||
(app) => app.name === myName && app.service === 'WEBSITE'
|
|
||||||
);
|
|
||||||
}, [myName, availableQapps]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
setTimeout(() => {
|
|
||||||
executeEvent('setTabsToNav', {
|
|
||||||
data: {
|
|
||||||
tabs: tabs,
|
|
||||||
selectedTab: selectedTab,
|
|
||||||
isNewTabWindow: isNewTabWindow,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
}, [show, tabs, selectedTab, isNewTabWindow]);
|
|
||||||
|
|
||||||
const getCategories = React.useCallback(async () => {
|
|
||||||
try {
|
|
||||||
const url = `${getBaseApiReact()}/arbitrary/categories`;
|
|
||||||
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!response?.ok) return;
|
|
||||||
const responseData = await response.json();
|
|
||||||
|
|
||||||
setCategories(responseData);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
// dispatch(setIsLoadingGlobal(false))
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const getQapps = React.useCallback(async () => {
|
|
||||||
try {
|
|
||||||
let apps = [];
|
|
||||||
let websites = [];
|
|
||||||
// dispatch(setIsLoadingGlobal(true))
|
|
||||||
const url = `${getBaseApiReact()}/arbitrary/resources/search?service=APP&mode=ALL&limit=0&includestatus=true&includemetadata=true`;
|
|
||||||
|
|
||||||
const response = await fetch(url, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!response?.ok) return;
|
|
||||||
const responseData = await response.json();
|
|
||||||
const urlWebsites = `${getBaseApiReact()}/arbitrary/resources/search?service=WEBSITE&mode=ALL&limit=0&includestatus=true&includemetadata=true`;
|
|
||||||
|
|
||||||
const responseWebsites = await fetch(urlWebsites, {
|
|
||||||
method: 'GET',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
if (!responseWebsites?.ok) return;
|
|
||||||
const responseDataWebsites = await responseWebsites.json();
|
|
||||||
|
|
||||||
apps = responseData;
|
|
||||||
websites = responseDataWebsites;
|
|
||||||
const combine = [...apps, ...websites];
|
|
||||||
setAvailableQapps(combine);
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
} finally {
|
|
||||||
// dispatch(setIsLoadingGlobal(false))
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
useEffect(() => {
|
|
||||||
getQapps();
|
|
||||||
getCategories();
|
|
||||||
}, [getQapps, getCategories]);
|
|
||||||
|
|
||||||
const selectedAppInfoFunc = (e) => {
|
|
||||||
const data = e.detail?.data;
|
|
||||||
setSelectedAppInfo(data);
|
|
||||||
setMode('appInfo');
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('selectedAppInfo', selectedAppInfoFunc);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent('selectedAppInfo', selectedAppInfoFunc);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const selectedAppInfoCategoryFunc = (e) => {
|
|
||||||
const data = e.detail?.data;
|
|
||||||
setSelectedAppInfo(data);
|
|
||||||
setMode('appInfo-from-category');
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('selectedAppInfoCategory', selectedAppInfoCategoryFunc);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent(
|
|
||||||
'selectedAppInfoCategory',
|
|
||||||
selectedAppInfoCategoryFunc
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const selectedCategoryFunc = (e) => {
|
|
||||||
const data = e.detail?.data;
|
|
||||||
setSelectedCategory(data);
|
|
||||||
setMode('category');
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('selectedCategory', selectedCategoryFunc);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent('selectedCategory', selectedCategoryFunc);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const navigateBackFunc = (e) => {
|
|
||||||
if (
|
|
||||||
[
|
|
||||||
'category',
|
|
||||||
'appInfo-from-category',
|
|
||||||
'appInfo',
|
|
||||||
'library',
|
|
||||||
'publish',
|
|
||||||
].includes(mode)
|
|
||||||
) {
|
|
||||||
// Handle the various modes as needed
|
|
||||||
if (mode === 'category') {
|
|
||||||
setMode('library');
|
|
||||||
setSelectedCategory(null);
|
|
||||||
} else if (mode === 'appInfo-from-category') {
|
|
||||||
setMode('category');
|
|
||||||
} else if (mode === 'appInfo') {
|
|
||||||
setMode('library');
|
|
||||||
} else if (mode === 'library') {
|
|
||||||
if (isNewTabWindow) {
|
|
||||||
setMode('viewer');
|
|
||||||
} else {
|
|
||||||
setMode('home');
|
|
||||||
}
|
|
||||||
} else if (mode === 'publish') {
|
|
||||||
setMode('library');
|
|
||||||
}
|
|
||||||
} else if (selectedTab?.tabId) {
|
|
||||||
executeEvent(`navigateBackApp-${selectedTab?.tabId}`, {});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('navigateBack', navigateBackFunc);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent('navigateBack', navigateBackFunc);
|
|
||||||
};
|
|
||||||
}, [mode, selectedTab]);
|
|
||||||
|
|
||||||
const addTabFunc = (e) => {
|
|
||||||
const data = e.detail?.data;
|
|
||||||
const newTab = {
|
|
||||||
...data,
|
|
||||||
tabId: uid.rnd(),
|
|
||||||
};
|
|
||||||
setTabs((prev) => [...prev, newTab]);
|
|
||||||
setSelectedTab(newTab);
|
|
||||||
setMode('viewer');
|
|
||||||
|
|
||||||
setIsNewTabWindow(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('addTab', addTabFunc);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent('addTab', addTabFunc);
|
|
||||||
};
|
|
||||||
}, [tabs]);
|
|
||||||
|
|
||||||
const setSelectedTabFunc = (e) => {
|
|
||||||
const data = e.detail?.data;
|
|
||||||
|
|
||||||
setSelectedTab(data);
|
|
||||||
setTimeout(() => {
|
|
||||||
executeEvent('setTabsToNav', {
|
|
||||||
data: {
|
|
||||||
tabs: tabs,
|
|
||||||
selectedTab: data,
|
|
||||||
isNewTabWindow: isNewTabWindow,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}, 100);
|
|
||||||
setIsNewTabWindow(false);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('setSelectedTab', setSelectedTabFunc);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent('setSelectedTab', setSelectedTabFunc);
|
|
||||||
};
|
|
||||||
}, [tabs, isNewTabWindow]);
|
|
||||||
|
|
||||||
const removeTabFunc = (e) => {
|
|
||||||
const data = e.detail?.data;
|
|
||||||
const copyTabs = [...tabs].filter((tab) => tab?.tabId !== data?.tabId);
|
|
||||||
if (copyTabs?.length === 0) {
|
|
||||||
setMode('home');
|
|
||||||
} else {
|
|
||||||
setSelectedTab(copyTabs[0]);
|
|
||||||
}
|
|
||||||
setTabs(copyTabs);
|
|
||||||
setSelectedTab(copyTabs[0]);
|
|
||||||
setTimeout(() => {
|
|
||||||
executeEvent('setTabsToNav', {
|
|
||||||
data: {
|
|
||||||
tabs: copyTabs,
|
|
||||||
selectedTab: copyTabs[0],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}, 400);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('removeTab', removeTabFunc);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent('removeTab', removeTabFunc);
|
|
||||||
};
|
|
||||||
}, [tabs]);
|
|
||||||
|
|
||||||
const setNewTabWindowFunc = (e) => {
|
|
||||||
setIsNewTabWindow(true);
|
|
||||||
setSelectedTab(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('newTabWindow', setNewTabWindowFunc);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent('newTabWindow', setNewTabWindowFunc);
|
|
||||||
};
|
|
||||||
}, [tabs]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppsParent
|
|
||||||
sx={{
|
|
||||||
display: !show && 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{mode !== 'viewer' && !selectedTab && <Spacer height="30px" />}
|
|
||||||
{mode === 'home' && (
|
|
||||||
<AppsHome
|
|
||||||
availableQapps={availableQapps}
|
|
||||||
setMode={setMode}
|
|
||||||
myApp={myApp}
|
|
||||||
myWebsite={myWebsite}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<AppsLibrary
|
|
||||||
isShow={mode === 'library' && !selectedTab}
|
|
||||||
availableQapps={availableQapps}
|
|
||||||
setMode={setMode}
|
|
||||||
myName={myName}
|
|
||||||
hasPublishApp={!!(myApp || myWebsite)}
|
|
||||||
categories={categories}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{mode === 'appInfo' && !selectedTab && (
|
|
||||||
<AppInfo app={selectedAppInfo} myName={myName} />
|
|
||||||
)}
|
|
||||||
{mode === 'appInfo-from-category' && !selectedTab && (
|
|
||||||
<AppInfo app={selectedAppInfo} myName={myName} />
|
|
||||||
)}
|
|
||||||
<AppsCategory
|
|
||||||
availableQapps={availableQapps}
|
|
||||||
isShow={mode === 'category' && !selectedTab}
|
|
||||||
category={selectedCategory}
|
|
||||||
myName={myName}
|
|
||||||
/>
|
|
||||||
{mode === 'publish' && !selectedTab && (
|
|
||||||
<AppPublish names={myName ? [myName] : []} categories={categories} />
|
|
||||||
)}
|
|
||||||
|
|
||||||
{tabs.map((tab) => {
|
|
||||||
if (!iframeRefs.current[tab.tabId]) {
|
|
||||||
iframeRefs.current[tab.tabId] = React.createRef();
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<AppViewerContainer
|
|
||||||
key={tab?.tabId}
|
|
||||||
hide={isNewTabWindow}
|
|
||||||
isSelected={tab?.tabId === selectedTab?.tabId}
|
|
||||||
app={tab}
|
|
||||||
ref={iframeRefs.current[tab.tabId]}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
|
|
||||||
{isNewTabWindow && mode === 'viewer' && (
|
|
||||||
<>
|
|
||||||
<Spacer height="30px" />
|
|
||||||
<AppsHome
|
|
||||||
availableQapps={availableQapps}
|
|
||||||
setMode={setMode}
|
|
||||||
myApp={myApp}
|
|
||||||
myWebsite={myWebsite}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
{mode !== 'viewer' && !selectedTab && <Spacer height="180px" />}
|
|
||||||
</AppsParent>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,204 +0,0 @@
|
|||||||
import React, {
|
|
||||||
useCallback,
|
|
||||||
useContext,
|
|
||||||
useEffect,
|
|
||||||
useMemo,
|
|
||||||
useRef,
|
|
||||||
useState,
|
|
||||||
} from 'react';
|
|
||||||
import {
|
|
||||||
AppCircle,
|
|
||||||
AppCircleContainer,
|
|
||||||
AppCircleLabel,
|
|
||||||
AppLibrarySubTitle,
|
|
||||||
AppsContainer,
|
|
||||||
AppsLibraryContainer,
|
|
||||||
AppsParent,
|
|
||||||
AppsSearchContainer,
|
|
||||||
AppsSearchLeft,
|
|
||||||
AppsSearchRight,
|
|
||||||
AppsWidthLimiter,
|
|
||||||
PublishQAppCTAButton,
|
|
||||||
PublishQAppCTALeft,
|
|
||||||
PublishQAppCTAParent,
|
|
||||||
PublishQAppCTARight,
|
|
||||||
PublishQAppDotsBG,
|
|
||||||
} from './Apps-styles';
|
|
||||||
import { Avatar, Box, ButtonBase, InputBase, styled } from '@mui/material';
|
|
||||||
import { Add } from '@mui/icons-material';
|
|
||||||
import { MyContext, getBaseApiReact } from '../../App';
|
|
||||||
import LogoSelected from '../../assets/svgs/LogoSelected.svg';
|
|
||||||
import IconSearch from '../../assets/svgs/Search.svg';
|
|
||||||
import IconClearInput from '../../assets/svgs/ClearInput.svg';
|
|
||||||
import qappDevelopText from '../../assets/svgs/qappDevelopText.svg';
|
|
||||||
import qappDots from '../../assets/svgs/qappDots.svg';
|
|
||||||
|
|
||||||
import { Spacer } from '../../common/Spacer';
|
|
||||||
import { AppInfoSnippet } from './AppInfoSnippet';
|
|
||||||
import { Virtuoso } from 'react-virtuoso';
|
|
||||||
import { executeEvent } from '../../utils/events';
|
|
||||||
const officialAppList = [
|
|
||||||
'q-tube',
|
|
||||||
'q-blog',
|
|
||||||
'q-share',
|
|
||||||
'q-support',
|
|
||||||
'q-mail',
|
|
||||||
'q-fund',
|
|
||||||
'q-shop',
|
|
||||||
'q-trade',
|
|
||||||
'q-support',
|
|
||||||
'q-manager',
|
|
||||||
'q-wallets',
|
|
||||||
'q-search',
|
|
||||||
'q-nodecontrol',
|
|
||||||
];
|
|
||||||
|
|
||||||
const ScrollerStyled = styled('div')({
|
|
||||||
// Hide scrollbar for WebKit browsers (Chrome, Safari)
|
|
||||||
'::-webkit-scrollbar': {
|
|
||||||
width: '0px',
|
|
||||||
height: '0px',
|
|
||||||
},
|
|
||||||
|
|
||||||
// Hide scrollbar for Firefox
|
|
||||||
scrollbarWidth: 'none',
|
|
||||||
|
|
||||||
// Hide scrollbar for IE and older Edge
|
|
||||||
'-msOverflowStyle': 'none',
|
|
||||||
});
|
|
||||||
|
|
||||||
const StyledVirtuosoContainer = styled('div')({
|
|
||||||
position: 'relative',
|
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
|
|
||||||
// Hide scrollbar for WebKit browsers (Chrome, Safari)
|
|
||||||
'::-webkit-scrollbar': {
|
|
||||||
width: '0px',
|
|
||||||
height: '0px',
|
|
||||||
},
|
|
||||||
|
|
||||||
// Hide scrollbar for Firefox
|
|
||||||
scrollbarWidth: 'none',
|
|
||||||
|
|
||||||
// Hide scrollbar for IE and older Edge
|
|
||||||
'-msOverflowStyle': 'none',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const AppsCategory = ({ availableQapps, myName, category, isShow }) => {
|
|
||||||
const [searchValue, setSearchValue] = useState('');
|
|
||||||
const virtuosoRef = useRef();
|
|
||||||
const { rootHeight } = useContext(MyContext);
|
|
||||||
|
|
||||||
const categoryList = useMemo(() => {
|
|
||||||
return availableQapps.filter(
|
|
||||||
(app) => app?.metadata?.category === category?.id
|
|
||||||
);
|
|
||||||
}, [availableQapps, category]);
|
|
||||||
|
|
||||||
const [debouncedValue, setDebouncedValue] = useState(''); // Debounced value
|
|
||||||
|
|
||||||
// Debounce logic
|
|
||||||
useEffect(() => {
|
|
||||||
const handler = setTimeout(() => {
|
|
||||||
setDebouncedValue(searchValue);
|
|
||||||
}, 350);
|
|
||||||
|
|
||||||
// Cleanup timeout if searchValue changes before the timeout completes
|
|
||||||
return () => {
|
|
||||||
clearTimeout(handler);
|
|
||||||
};
|
|
||||||
}, [searchValue]); // Runs effect when searchValue changes
|
|
||||||
|
|
||||||
// Example: Perform search or other actions based on debouncedValue
|
|
||||||
|
|
||||||
const searchedList = useMemo(() => {
|
|
||||||
if (!debouncedValue) return categoryList;
|
|
||||||
return categoryList.filter((app) =>
|
|
||||||
app.name.toLowerCase().includes(debouncedValue.toLowerCase())
|
|
||||||
);
|
|
||||||
}, [debouncedValue, categoryList]);
|
|
||||||
|
|
||||||
const rowRenderer = (index) => {
|
|
||||||
let app = searchedList[index];
|
|
||||||
return (
|
|
||||||
<AppInfoSnippet
|
|
||||||
key={`${app?.service}-${app?.name}`}
|
|
||||||
app={app}
|
|
||||||
myName={myName}
|
|
||||||
isFromCategory={true}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppsLibraryContainer
|
|
||||||
sx={{
|
|
||||||
display: !isShow && 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AppsWidthLimiter>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AppsSearchContainer>
|
|
||||||
<AppsSearchLeft>
|
|
||||||
<img src={IconSearch} />
|
|
||||||
<InputBase
|
|
||||||
value={searchValue}
|
|
||||||
onChange={(e) => setSearchValue(e.target.value)}
|
|
||||||
sx={{ ml: 1, flex: 1 }}
|
|
||||||
placeholder="Search for apps"
|
|
||||||
inputProps={{
|
|
||||||
'aria-label': 'Search for apps',
|
|
||||||
fontSize: '16px',
|
|
||||||
fontWeight: 400,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</AppsSearchLeft>
|
|
||||||
<AppsSearchRight>
|
|
||||||
{searchValue && (
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
setSearchValue('');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img src={IconClearInput} />
|
|
||||||
</ButtonBase>
|
|
||||||
)}
|
|
||||||
</AppsSearchRight>
|
|
||||||
</AppsSearchContainer>
|
|
||||||
</Box>
|
|
||||||
</AppsWidthLimiter>
|
|
||||||
<Spacer height="25px" />
|
|
||||||
<AppsWidthLimiter>
|
|
||||||
<AppLibrarySubTitle>{`Category: ${category?.name}`}</AppLibrarySubTitle>
|
|
||||||
|
|
||||||
<Spacer height="25px" />
|
|
||||||
</AppsWidthLimiter>
|
|
||||||
<AppsWidthLimiter>
|
|
||||||
<StyledVirtuosoContainer
|
|
||||||
sx={{
|
|
||||||
height: rootHeight,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Virtuoso
|
|
||||||
ref={virtuosoRef}
|
|
||||||
data={searchedList}
|
|
||||||
itemContent={rowRenderer}
|
|
||||||
atBottomThreshold={50}
|
|
||||||
followOutput="smooth"
|
|
||||||
components={{
|
|
||||||
Scroller: ScrollerStyled, // Use the styled scroller component
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</StyledVirtuosoContainer>
|
|
||||||
</AppsWidthLimiter>
|
|
||||||
</AppsLibraryContainer>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,51 +0,0 @@
|
|||||||
import {
|
|
||||||
AppCircle,
|
|
||||||
AppCircleContainer,
|
|
||||||
AppCircleLabel,
|
|
||||||
AppLibrarySubTitle,
|
|
||||||
AppsContainer,
|
|
||||||
} from './Apps-styles';
|
|
||||||
import { ButtonBase } from '@mui/material';
|
|
||||||
import { Add } from '@mui/icons-material';
|
|
||||||
import { SortablePinnedApps } from './SortablePinnedApps';
|
|
||||||
import { Spacer } from '../../common/Spacer';
|
|
||||||
|
|
||||||
export const AppsHome = ({ setMode, myApp, myWebsite, availableQapps }) => {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<AppsContainer
|
|
||||||
sx={{
|
|
||||||
justifyContent: 'flex-start',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AppLibrarySubTitle>Apps Dashboard</AppLibrarySubTitle>
|
|
||||||
</AppsContainer>
|
|
||||||
<Spacer height="20px" />
|
|
||||||
|
|
||||||
<AppsContainer>
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
setMode('library');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AppCircleContainer
|
|
||||||
sx={{
|
|
||||||
gap: '10px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AppCircle>
|
|
||||||
<Add>+</Add>
|
|
||||||
</AppCircle>
|
|
||||||
<AppCircleLabel>Library</AppCircleLabel>
|
|
||||||
</AppCircleContainer>
|
|
||||||
</ButtonBase>
|
|
||||||
|
|
||||||
<SortablePinnedApps
|
|
||||||
availableQapps={availableQapps}
|
|
||||||
myWebsite={myWebsite}
|
|
||||||
myApp={myApp}
|
|
||||||
/>
|
|
||||||
</AppsContainer>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,384 +0,0 @@
|
|||||||
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
||||||
import {
|
|
||||||
AppCircle,
|
|
||||||
AppCircleContainer,
|
|
||||||
AppCircleLabel,
|
|
||||||
AppLibrarySubTitle,
|
|
||||||
AppsContainer,
|
|
||||||
AppsLibraryContainer,
|
|
||||||
AppsSearchContainer,
|
|
||||||
AppsSearchLeft,
|
|
||||||
AppsSearchRight,
|
|
||||||
AppsWidthLimiter,
|
|
||||||
PublishQAppCTAButton,
|
|
||||||
PublishQAppCTALeft,
|
|
||||||
PublishQAppCTAParent,
|
|
||||||
PublishQAppCTARight,
|
|
||||||
PublishQAppDotsBG,
|
|
||||||
} from './Apps-styles';
|
|
||||||
import {
|
|
||||||
Avatar,
|
|
||||||
Box,
|
|
||||||
ButtonBase,
|
|
||||||
InputBase,
|
|
||||||
styled,
|
|
||||||
useTheme,
|
|
||||||
} from '@mui/material';
|
|
||||||
import { MyContext, getBaseApiReact } from '../../App';
|
|
||||||
import LogoSelected from '../../assets/svgs/LogoSelected.svg';
|
|
||||||
import IconSearch from '../../assets/svgs/Search.svg';
|
|
||||||
import IconClearInput from '../../assets/svgs/ClearInput.svg';
|
|
||||||
import qappDevelopText from '../../assets/svgs/qappDevelopText.svg';
|
|
||||||
import qappDots from '../../assets/svgs/qappDots.svg';
|
|
||||||
// import { Return } from './assets/svgs/Return.tsx';
|
|
||||||
import ReturnSVG from '../../assets/svgs/Return.svg';
|
|
||||||
import { Spacer } from '../../common/Spacer';
|
|
||||||
import { AppInfoSnippet } from './AppInfoSnippet';
|
|
||||||
import { Virtuoso } from 'react-virtuoso';
|
|
||||||
import { executeEvent } from '../../utils/events';
|
|
||||||
import {
|
|
||||||
ComposeP,
|
|
||||||
MailIconImg,
|
|
||||||
ShowMessageReturnButton,
|
|
||||||
} from '../Group/Forum/Mail-styles';
|
|
||||||
|
|
||||||
const officialAppList = [
|
|
||||||
'q-tube',
|
|
||||||
'q-blog',
|
|
||||||
'q-share',
|
|
||||||
'q-support',
|
|
||||||
'q-mail',
|
|
||||||
'q-fund',
|
|
||||||
'q-shop',
|
|
||||||
'q-trade',
|
|
||||||
'q-support',
|
|
||||||
'q-manager',
|
|
||||||
'q-wallets',
|
|
||||||
'q-search',
|
|
||||||
'q-nodecontrol',
|
|
||||||
];
|
|
||||||
|
|
||||||
const ScrollerStyled = styled('div')({
|
|
||||||
// Hide scrollbar for WebKit browsers (Chrome, Safari)
|
|
||||||
'::-webkit-scrollbar': {
|
|
||||||
width: '0px',
|
|
||||||
height: '0px',
|
|
||||||
},
|
|
||||||
|
|
||||||
// Hide scrollbar for Firefox
|
|
||||||
scrollbarWidth: 'none',
|
|
||||||
|
|
||||||
// Hide scrollbar for IE and older Edge
|
|
||||||
'-msOverflowStyle': 'none',
|
|
||||||
});
|
|
||||||
|
|
||||||
const StyledVirtuosoContainer = styled('div')({
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
position: 'relative',
|
|
||||||
width: '100%',
|
|
||||||
|
|
||||||
// Hide scrollbar for WebKit browsers (Chrome, Safari)
|
|
||||||
'::-webkit-scrollbar': {
|
|
||||||
width: '0px',
|
|
||||||
height: '0px',
|
|
||||||
},
|
|
||||||
|
|
||||||
// Hide scrollbar for Firefox
|
|
||||||
scrollbarWidth: 'none',
|
|
||||||
|
|
||||||
// Hide scrollbar for IE and older Edge
|
|
||||||
'-msOverflowStyle': 'none',
|
|
||||||
});
|
|
||||||
|
|
||||||
export const AppsLibrary = ({
|
|
||||||
availableQapps,
|
|
||||||
setMode,
|
|
||||||
myName,
|
|
||||||
hasPublishApp,
|
|
||||||
isShow,
|
|
||||||
categories = { categories },
|
|
||||||
}) => {
|
|
||||||
const [searchValue, setSearchValue] = useState('');
|
|
||||||
const virtuosoRef = useRef();
|
|
||||||
const { rootHeight } = useContext(MyContext);
|
|
||||||
|
|
||||||
const officialApps = useMemo(() => {
|
|
||||||
return availableQapps.filter(
|
|
||||||
(app) =>
|
|
||||||
app.service === 'APP' &&
|
|
||||||
officialAppList.includes(app?.name?.toLowerCase())
|
|
||||||
);
|
|
||||||
}, [availableQapps]);
|
|
||||||
|
|
||||||
const [debouncedValue, setDebouncedValue] = useState(''); // Debounced value
|
|
||||||
|
|
||||||
// Debounce logic
|
|
||||||
useEffect(() => {
|
|
||||||
const handler = setTimeout(() => {
|
|
||||||
setDebouncedValue(searchValue);
|
|
||||||
}, 350);
|
|
||||||
|
|
||||||
// Cleanup timeout if searchValue changes before the timeout completes
|
|
||||||
return () => {
|
|
||||||
clearTimeout(handler);
|
|
||||||
};
|
|
||||||
}, [searchValue]); // Runs effect when searchValue changes
|
|
||||||
|
|
||||||
// Example: Perform search or other actions based on debouncedValue
|
|
||||||
|
|
||||||
const searchedList = useMemo(() => {
|
|
||||||
if (!debouncedValue) return [];
|
|
||||||
return availableQapps.filter((app) =>
|
|
||||||
app.name.toLowerCase().includes(debouncedValue.toLowerCase())
|
|
||||||
);
|
|
||||||
}, [debouncedValue]);
|
|
||||||
|
|
||||||
const rowRenderer = (index) => {
|
|
||||||
let app = searchedList[index];
|
|
||||||
return (
|
|
||||||
<AppInfoSnippet
|
|
||||||
key={`${app?.service}-${app?.name}`}
|
|
||||||
app={app}
|
|
||||||
myName={myName}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const theme = useTheme();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<AppsLibraryContainer
|
|
||||||
sx={{
|
|
||||||
display: !isShow && 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AppsWidthLimiter>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
justifyContent: 'center',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AppsSearchContainer>
|
|
||||||
<AppsSearchLeft>
|
|
||||||
<img src={IconSearch} />
|
|
||||||
|
|
||||||
<InputBase
|
|
||||||
value={searchValue}
|
|
||||||
onChange={(e) => setSearchValue(e.target.value)}
|
|
||||||
sx={{ ml: 1, flex: 1 }}
|
|
||||||
placeholder="Search for apps"
|
|
||||||
inputProps={{
|
|
||||||
'aria-label': 'Search for apps',
|
|
||||||
fontSize: '16px',
|
|
||||||
fontWeight: 400,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</AppsSearchLeft>
|
|
||||||
<AppsSearchRight>
|
|
||||||
{searchValue && (
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
setSearchValue('');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<img src={IconClearInput} />
|
|
||||||
</ButtonBase>
|
|
||||||
)}
|
|
||||||
</AppsSearchRight>
|
|
||||||
</AppsSearchContainer>
|
|
||||||
</Box>
|
|
||||||
</AppsWidthLimiter>
|
|
||||||
|
|
||||||
<Spacer height="25px" />
|
|
||||||
|
|
||||||
<ShowMessageReturnButton
|
|
||||||
sx={{
|
|
||||||
padding: '2px',
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
executeEvent('navigateBack', {});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MailIconImg src={ReturnSVG} /> // TODO return icon
|
|
||||||
<ComposeP>Return to Apps Dashboard</ComposeP>
|
|
||||||
</ShowMessageReturnButton>
|
|
||||||
|
|
||||||
<Spacer height="25px" />
|
|
||||||
|
|
||||||
{searchedList?.length > 0 ? (
|
|
||||||
<AppsWidthLimiter>
|
|
||||||
<StyledVirtuosoContainer
|
|
||||||
sx={{
|
|
||||||
height: rootHeight,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Virtuoso
|
|
||||||
ref={virtuosoRef}
|
|
||||||
data={searchedList}
|
|
||||||
itemContent={rowRenderer}
|
|
||||||
atBottomThreshold={50}
|
|
||||||
followOutput="smooth"
|
|
||||||
components={{
|
|
||||||
Scroller: ScrollerStyled, // Use the styled scroller component
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</StyledVirtuosoContainer>
|
|
||||||
</AppsWidthLimiter>
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
<AppsWidthLimiter>
|
|
||||||
<AppLibrarySubTitle>Official Apps</AppLibrarySubTitle>
|
|
||||||
|
|
||||||
<Spacer height="18px" />
|
|
||||||
|
|
||||||
<AppsContainer>
|
|
||||||
{officialApps?.map((qapp) => {
|
|
||||||
return (
|
|
||||||
<ButtonBase
|
|
||||||
sx={{
|
|
||||||
height: '80px',
|
|
||||||
width: '60px',
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
// executeEvent("addTab", {
|
|
||||||
// data: qapp
|
|
||||||
// })
|
|
||||||
executeEvent('selectedAppInfo', {
|
|
||||||
data: qapp,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<AppCircleContainer>
|
|
||||||
<AppCircle
|
|
||||||
sx={{
|
|
||||||
border: 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Avatar
|
|
||||||
sx={{
|
|
||||||
height: '31px',
|
|
||||||
width: '31px',
|
|
||||||
}}
|
|
||||||
alt={qapp?.name}
|
|
||||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
|
|
||||||
qapp?.name
|
|
||||||
}/qortal_avatar?async=true`}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
style={{
|
|
||||||
width: '31px',
|
|
||||||
height: 'auto',
|
|
||||||
}}
|
|
||||||
src={LogoSelected}
|
|
||||||
alt="center-icon"
|
|
||||||
/>
|
|
||||||
</Avatar>
|
|
||||||
</AppCircle>
|
|
||||||
|
|
||||||
<AppCircleLabel>
|
|
||||||
{qapp?.metadata?.title || qapp?.name}
|
|
||||||
</AppCircleLabel>
|
|
||||||
</AppCircleContainer>
|
|
||||||
</ButtonBase>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</AppsContainer>
|
|
||||||
|
|
||||||
<Spacer height="30px" />
|
|
||||||
|
|
||||||
<AppLibrarySubTitle>
|
|
||||||
{hasPublishApp ? 'Update Apps!' : 'Create Apps!'}
|
|
||||||
</AppLibrarySubTitle>
|
|
||||||
|
|
||||||
<Spacer height="18px" />
|
|
||||||
</AppsWidthLimiter>
|
|
||||||
|
|
||||||
<PublishQAppCTAParent>
|
|
||||||
<PublishQAppCTALeft>
|
|
||||||
<PublishQAppDotsBG>
|
|
||||||
<img src={qappDots} />
|
|
||||||
</PublishQAppDotsBG>
|
|
||||||
|
|
||||||
<Spacer width="29px" />
|
|
||||||
|
|
||||||
<img src={qappDevelopText} />
|
|
||||||
</PublishQAppCTALeft>
|
|
||||||
|
|
||||||
<PublishQAppCTARight
|
|
||||||
onClick={() => {
|
|
||||||
setMode('publish');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PublishQAppCTAButton>
|
|
||||||
{hasPublishApp ? 'Update' : 'Publish'}
|
|
||||||
</PublishQAppCTAButton>
|
|
||||||
|
|
||||||
<Spacer width="20px" />
|
|
||||||
</PublishQAppCTARight>
|
|
||||||
</PublishQAppCTAParent>
|
|
||||||
|
|
||||||
<AppsWidthLimiter>
|
|
||||||
<Spacer height="18px" />
|
|
||||||
|
|
||||||
<AppLibrarySubTitle>Categories</AppLibrarySubTitle>
|
|
||||||
|
|
||||||
<Spacer height="18px" />
|
|
||||||
|
|
||||||
<AppsWidthLimiter
|
|
||||||
sx={{
|
|
||||||
flexDirection: 'row',
|
|
||||||
overflowX: 'auto',
|
|
||||||
width: '100%',
|
|
||||||
gap: '5px',
|
|
||||||
'::-webkit-scrollbar': {
|
|
||||||
width: '0px',
|
|
||||||
height: '0px',
|
|
||||||
},
|
|
||||||
|
|
||||||
// Hide scrollbar for Firefox
|
|
||||||
scrollbarWidth: 'none',
|
|
||||||
|
|
||||||
// Hide scrollbar for IE and older Edge
|
|
||||||
'-msOverflowStyle': 'none',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{categories?.map((category) => {
|
|
||||||
return (
|
|
||||||
<ButtonBase
|
|
||||||
key={category?.id}
|
|
||||||
onClick={() => {
|
|
||||||
executeEvent('selectedCategory', {
|
|
||||||
data: category,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
alignItems: 'center',
|
|
||||||
background: theme.palette.background.default,
|
|
||||||
borderRadius: '11px',
|
|
||||||
color: theme.palette.text.primary,
|
|
||||||
display: 'flex',
|
|
||||||
flexShrink: 0,
|
|
||||||
fontSize: '16px',
|
|
||||||
fontWeight: 700,
|
|
||||||
height: '110px',
|
|
||||||
justifyContent: 'center',
|
|
||||||
width: '110px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{category?.name}
|
|
||||||
</Box>
|
|
||||||
</ButtonBase>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</AppsWidthLimiter>
|
|
||||||
</AppsWidthLimiter>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</AppsLibraryContainer>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,367 +0,0 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
||||||
import {
|
|
||||||
AppsNavBarLeft,
|
|
||||||
AppsNavBarParent,
|
|
||||||
AppsNavBarRight,
|
|
||||||
} from './Apps-styles';
|
|
||||||
import { NavBack } from '../../assets/Icons/NavBack.tsx';
|
|
||||||
import { NavAdd } from '../../assets/Icons/NavAdd.tsx';
|
|
||||||
import { NavMoreMenu } from '../../assets/Icons/NavMoreMenu.tsx';
|
|
||||||
import {
|
|
||||||
ButtonBase,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
Menu,
|
|
||||||
MenuItem,
|
|
||||||
Tab,
|
|
||||||
Tabs,
|
|
||||||
} from '@mui/material';
|
|
||||||
import {
|
|
||||||
executeEvent,
|
|
||||||
subscribeToEvent,
|
|
||||||
unsubscribeFromEvent,
|
|
||||||
} from '../../utils/events';
|
|
||||||
import TabComponent from './TabComponent';
|
|
||||||
import PushPinIcon from '@mui/icons-material/PushPin';
|
|
||||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
|
||||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
|
||||||
import {
|
|
||||||
navigationControllerAtom,
|
|
||||||
settingsLocalLastUpdatedAtom,
|
|
||||||
sortablePinnedAppsAtom,
|
|
||||||
} from '../../atoms/global';
|
|
||||||
|
|
||||||
export function saveToLocalStorage(
|
|
||||||
key,
|
|
||||||
subKey,
|
|
||||||
newValue,
|
|
||||||
otherRootData = {},
|
|
||||||
deleteWholeKey
|
|
||||||
) {
|
|
||||||
try {
|
|
||||||
if (deleteWholeKey) {
|
|
||||||
localStorage.setItem(key, null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Fetch existing data
|
|
||||||
const existingData = localStorage.getItem(key);
|
|
||||||
let combinedData = {};
|
|
||||||
|
|
||||||
if (existingData) {
|
|
||||||
// Parse the existing data
|
|
||||||
const parsedData = JSON.parse(existingData);
|
|
||||||
// Merge with the new data under the subKey
|
|
||||||
combinedData = {
|
|
||||||
...parsedData,
|
|
||||||
...otherRootData,
|
|
||||||
timestamp: Date.now(), // Update the root timestamp
|
|
||||||
[subKey]: newValue, // Assuming the data is an array
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
// If no existing data, just use the new data under the subKey
|
|
||||||
combinedData = {
|
|
||||||
...otherRootData,
|
|
||||||
timestamp: Date.now(), // Set the initial root timestamp
|
|
||||||
[subKey]: newValue,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save combined data back to localStorage
|
|
||||||
const serializedValue = JSON.stringify(combinedData);
|
|
||||||
localStorage.setItem(key, serializedValue);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error saving to localStorage:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const AppsNavBar = () => {
|
|
||||||
const [tabs, setTabs] = useState([]);
|
|
||||||
const [selectedTab, setSelectedTab] = useState(null);
|
|
||||||
const [isNewTabWindow, setIsNewTabWindow] = useState(false);
|
|
||||||
const tabsRef = useRef(null);
|
|
||||||
const [anchorEl, setAnchorEl] = useState(null);
|
|
||||||
const open = Boolean(anchorEl);
|
|
||||||
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(
|
|
||||||
sortablePinnedAppsAtom
|
|
||||||
);
|
|
||||||
const [navigationController, setNavigationController] = useRecoilState(
|
|
||||||
navigationControllerAtom
|
|
||||||
);
|
|
||||||
|
|
||||||
const isDisableBackButton = useMemo(() => {
|
|
||||||
if (selectedTab && navigationController[selectedTab?.tabId]?.hasBack)
|
|
||||||
return false;
|
|
||||||
if (selectedTab && !navigationController[selectedTab?.tabId]?.hasBack)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}, [navigationController, selectedTab]);
|
|
||||||
|
|
||||||
const setSettingsLocalLastUpdated = useSetRecoilState(
|
|
||||||
settingsLocalLastUpdatedAtom
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleClick = (event) => {
|
|
||||||
setAnchorEl(event.currentTarget);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
setAnchorEl(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Scroll to the last tab whenever the tabs array changes (e.g., when a new tab is added)
|
|
||||||
if (tabsRef.current) {
|
|
||||||
const tabElements = tabsRef.current.querySelectorAll('.MuiTab-root');
|
|
||||||
if (tabElements.length > 0) {
|
|
||||||
const lastTab = tabElements[tabElements.length - 1];
|
|
||||||
lastTab.scrollIntoView({
|
|
||||||
behavior: 'smooth',
|
|
||||||
block: 'nearest',
|
|
||||||
inline: 'end',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [tabs.length]); // Dependency on the number of tabs
|
|
||||||
|
|
||||||
const setTabsToNav = (e) => {
|
|
||||||
const { tabs, selectedTab, isNewTabWindow } = e.detail?.data;
|
|
||||||
|
|
||||||
setTabs([...tabs]);
|
|
||||||
setSelectedTab(!selectedTab ? null : { ...selectedTab });
|
|
||||||
setIsNewTabWindow(isNewTabWindow);
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
subscribeToEvent('setTabsToNav', setTabsToNav);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
unsubscribeFromEvent('setTabsToNav', setTabsToNav);
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const isSelectedAppPinned = !!sortablePinnedApps?.find(
|
|
||||||
(item) =>
|
|
||||||
item?.name === selectedTab?.name && item?.service === selectedTab?.service
|
|
||||||
);
|
|
||||||
return (
|
|
||||||
<AppsNavBarParent>
|
|
||||||
<AppsNavBarLeft>
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
executeEvent('navigateBack', selectedTab?.tabId);
|
|
||||||
}}
|
|
||||||
disabled={isDisableBackButton}
|
|
||||||
sx={{
|
|
||||||
opacity: !isDisableBackButton ? 1 : 0.3,
|
|
||||||
cursor: !isDisableBackButton ? 'pointer' : 'default',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<NavBack />
|
|
||||||
</ButtonBase>
|
|
||||||
|
|
||||||
<Tabs
|
|
||||||
ref={tabsRef}
|
|
||||||
aria-label="basic tabs example"
|
|
||||||
variant="scrollable" // Make tabs scrollable
|
|
||||||
scrollButtons={false}
|
|
||||||
sx={{
|
|
||||||
'& .MuiTabs-indicator': {
|
|
||||||
backgroundColor: 'white',
|
|
||||||
},
|
|
||||||
maxWidth: `calc(100vw - 150px)`, // Ensure the tabs container fits within the available space
|
|
||||||
overflow: 'hidden', // Prevents overflow on small screens
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{tabs?.map((tab) => (
|
|
||||||
<Tab
|
|
||||||
key={tab.tabId}
|
|
||||||
label={
|
|
||||||
<TabComponent
|
|
||||||
isSelected={
|
|
||||||
tab?.tabId === selectedTab?.tabId && !isNewTabWindow
|
|
||||||
}
|
|
||||||
app={tab}
|
|
||||||
/>
|
|
||||||
} // Pass custom component
|
|
||||||
sx={{
|
|
||||||
'&.Mui-selected': {
|
|
||||||
color: 'white',
|
|
||||||
},
|
|
||||||
padding: '0px',
|
|
||||||
margin: '0px',
|
|
||||||
minWidth: '0px',
|
|
||||||
width: '50px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
))}
|
|
||||||
</Tabs>
|
|
||||||
</AppsNavBarLeft>
|
|
||||||
|
|
||||||
{selectedTab && (
|
|
||||||
<AppsNavBarRight
|
|
||||||
sx={{
|
|
||||||
gap: '10px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedTab(null);
|
|
||||||
executeEvent('newTabWindow', {});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<NavAdd
|
|
||||||
style={{
|
|
||||||
height: '40px',
|
|
||||||
width: '40px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ButtonBase>
|
|
||||||
|
|
||||||
<ButtonBase
|
|
||||||
onClick={(e) => {
|
|
||||||
if (!selectedTab) return;
|
|
||||||
handleClick(e);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<NavMoreMenu
|
|
||||||
style={{
|
|
||||||
height: '34px',
|
|
||||||
width: '34px',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ButtonBase>
|
|
||||||
</AppsNavBarRight>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Menu
|
|
||||||
id="navbar-more-mobile"
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
open={open}
|
|
||||||
onClose={handleClose}
|
|
||||||
MenuListProps={{
|
|
||||||
'aria-labelledby': 'basic-button',
|
|
||||||
}}
|
|
||||||
anchorOrigin={{
|
|
||||||
vertical: 'bottom',
|
|
||||||
horizontal: 'center',
|
|
||||||
}}
|
|
||||||
transformOrigin={{
|
|
||||||
vertical: 'top',
|
|
||||||
horizontal: 'center',
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
paper: {
|
|
||||||
sx: {
|
|
||||||
backgroundColor: 'var(--bg-primary)',
|
|
||||||
color: '#fff',
|
|
||||||
width: '148px',
|
|
||||||
borderRadius: '5px',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
marginTop: '10px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
if (!selectedTab) return;
|
|
||||||
|
|
||||||
setSortablePinnedApps((prev) => {
|
|
||||||
let updatedApps;
|
|
||||||
|
|
||||||
if (isSelectedAppPinned) {
|
|
||||||
// Remove the selected app if it is pinned
|
|
||||||
updatedApps = prev.filter(
|
|
||||||
(item) =>
|
|
||||||
!(
|
|
||||||
item?.name === selectedTab?.name &&
|
|
||||||
item?.service === selectedTab?.service
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Add the selected app if it is not pinned
|
|
||||||
updatedApps = [
|
|
||||||
...prev,
|
|
||||||
{
|
|
||||||
name: selectedTab?.name,
|
|
||||||
service: selectedTab?.service,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
saveToLocalStorage(
|
|
||||||
'ext_saved_settings',
|
|
||||||
'sortablePinnedApps',
|
|
||||||
updatedApps
|
|
||||||
);
|
|
||||||
return updatedApps;
|
|
||||||
});
|
|
||||||
setSettingsLocalLastUpdated(Date.now());
|
|
||||||
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListItemIcon
|
|
||||||
sx={{
|
|
||||||
minWidth: '24px !important',
|
|
||||||
marginRight: '5px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PushPinIcon
|
|
||||||
height={20}
|
|
||||||
sx={{
|
|
||||||
color: isSelectedAppPinned ? 'red' : 'rgba(250, 250, 250, 0.5)',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
|
||||||
|
|
||||||
<ListItemText
|
|
||||||
sx={{
|
|
||||||
'& .MuiTypography-root': {
|
|
||||||
fontSize: '12px',
|
|
||||||
fontWeight: 600,
|
|
||||||
color: isSelectedAppPinned ? 'red' : 'rgba(250, 250, 250, 0.5)',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
primary={`${isSelectedAppPinned ? 'Unpin app' : 'Pin app'}`}
|
|
||||||
/>
|
|
||||||
</MenuItem>
|
|
||||||
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
executeEvent('refreshApp', {
|
|
||||||
tabId: selectedTab?.tabId,
|
|
||||||
});
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListItemIcon
|
|
||||||
sx={{
|
|
||||||
minWidth: '24px !important',
|
|
||||||
marginRight: '5px',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<RefreshIcon
|
|
||||||
height={20}
|
|
||||||
sx={{
|
|
||||||
color: 'rgba(250, 250, 250, 0.5)',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
|
||||||
|
|
||||||
<ListItemText
|
|
||||||
sx={{
|
|
||||||
'& .MuiTypography-root': {
|
|
||||||
fontSize: '12px',
|
|
||||||
fontWeight: 600,
|
|
||||||
color: 'rgba(250, 250, 250, 0.5)',
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
primary="Refresh"
|
|
||||||
/>
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</AppsNavBarParent>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,203 +0,0 @@
|
|||||||
import * as React from "react";
|
|
||||||
import {
|
|
||||||
BottomNavigation,
|
|
||||||
BottomNavigationAction,
|
|
||||||
ButtonBase,
|
|
||||||
Typography,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { Home, Groups, Message, ShowChart } from "@mui/icons-material";
|
|
||||||
import Box from "@mui/material/Box";
|
|
||||||
import BottomLogo from "../../assets/svgs/BottomLogo5.svg";
|
|
||||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
|
||||||
import { Browser } from '@capacitor/browser';
|
|
||||||
|
|
||||||
import { CustomSvg } from "../../common/CustomSvg";
|
|
||||||
import { WalletIcon } from "../../assets/Icons/WalletIcon";
|
|
||||||
import { HubsIcon } from "../../assets/Icons/HubsIcon";
|
|
||||||
import { TradingIcon } from "../../assets/Icons/TradingIcon";
|
|
||||||
import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
|
|
||||||
import { executeEvent } from "../../utils/events";
|
|
||||||
|
|
||||||
const IconWrapper = ({ children, label, color }) => {
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "5px",
|
|
||||||
flexDirection: "column",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontFamily: "Inter",
|
|
||||||
fontSize: "12px",
|
|
||||||
fontWeight: 500,
|
|
||||||
color: color,
|
|
||||||
wordBreak: 'normal'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MobileFooter = ({
|
|
||||||
selectedGroup,
|
|
||||||
groupSection,
|
|
||||||
isUnread,
|
|
||||||
goToAnnouncements,
|
|
||||||
isUnreadChat,
|
|
||||||
goToChat,
|
|
||||||
goToThreads,
|
|
||||||
setOpenManageMembers,
|
|
||||||
groupChatHasUnread,
|
|
||||||
groupsAnnHasUnread,
|
|
||||||
directChatHasUnread,
|
|
||||||
chatMode,
|
|
||||||
openDrawerGroups,
|
|
||||||
goToHome,
|
|
||||||
setIsOpenDrawerProfile,
|
|
||||||
mobileViewMode,
|
|
||||||
setMobileViewMode,
|
|
||||||
setMobileViewModeKeepOpen,
|
|
||||||
hasUnreadGroups,
|
|
||||||
hasUnreadDirects
|
|
||||||
}) => {
|
|
||||||
const [value, setValue] = React.useState(0);
|
|
||||||
return (
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "100%",
|
|
||||||
position: "fixed",
|
|
||||||
bottom: 0,
|
|
||||||
backgroundColor: "var(--bg-primary)",
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
height: "67px", // Footer height
|
|
||||||
zIndex: 1,
|
|
||||||
borderTopRightRadius: "25px",
|
|
||||||
borderTopLeftRadius: "25px",
|
|
||||||
boxShadow: '0px -2px 10px rgba(0, 0, 0, 0.1)',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<BottomNavigation
|
|
||||||
showLabels
|
|
||||||
value={value}
|
|
||||||
onChange={(event, newValue) => setValue(newValue)}
|
|
||||||
sx={{ backgroundColor: "transparent", flexGrow: 1 }}
|
|
||||||
>
|
|
||||||
<BottomNavigationAction
|
|
||||||
onClick={() => {
|
|
||||||
// setMobileViewMode('wallet')
|
|
||||||
setIsOpenDrawerProfile(true);
|
|
||||||
}}
|
|
||||||
icon={
|
|
||||||
<IconWrapper color="rgba(250, 250, 250, 0.5)" label="Wallet">
|
|
||||||
<WalletIcon color="rgba(250, 250, 250, 0.5)" />
|
|
||||||
</IconWrapper>
|
|
||||||
}
|
|
||||||
sx={{ color: value === 0 ? "white" : "gray", padding: "0px 10px" }}
|
|
||||||
/>
|
|
||||||
<BottomNavigationAction
|
|
||||||
onClick={() => {
|
|
||||||
setMobileViewMode("groups");
|
|
||||||
}}
|
|
||||||
icon={
|
|
||||||
<IconWrapper color="rgba(250, 250, 250, 0.5)" label="Groups">
|
|
||||||
<HubsIcon color={hasUnreadGroups ? "var(--danger)" : "rgba(250, 250, 250, 0.5)"} />
|
|
||||||
</IconWrapper>
|
|
||||||
}
|
|
||||||
sx={{
|
|
||||||
color: value === 0 ? "white" : "gray",
|
|
||||||
paddingLeft: "10px",
|
|
||||||
paddingRight: "42px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</BottomNavigation>
|
|
||||||
|
|
||||||
{/* Floating Center Button */}
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
bottom: "34px", // Adjusted to float properly based on footer height
|
|
||||||
left: "50%",
|
|
||||||
transform: "translateX(-50%)", // Center horizontally
|
|
||||||
width: "59px",
|
|
||||||
height: "59px",
|
|
||||||
backgroundColor: "var(--bg-primary)",
|
|
||||||
borderRadius: "50%",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
boxShadow: "0 4px 10px rgba(0, 0, 0, 0.3)", // Subtle shadow for the floating effect
|
|
||||||
zIndex: 3,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ButtonBase onClick={()=> {
|
|
||||||
if(mobileViewMode === 'home'){
|
|
||||||
setMobileViewMode('apps')
|
|
||||||
|
|
||||||
} else {
|
|
||||||
setMobileViewMode('home')
|
|
||||||
|
|
||||||
}
|
|
||||||
}}>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
width: "49px", // Slightly smaller inner circle
|
|
||||||
height: "49px",
|
|
||||||
backgroundColor: "var(--bg-primary)",
|
|
||||||
borderRadius: "50%",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* Custom Center Icon */}
|
|
||||||
<img src={mobileViewMode === 'apps' ? LogoSelected : BottomLogo} alt="center-icon" />
|
|
||||||
</Box>
|
|
||||||
</ButtonBase>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<BottomNavigation
|
|
||||||
showLabels
|
|
||||||
value={value}
|
|
||||||
onChange={(event, newValue) => setValue(newValue)}
|
|
||||||
sx={{ backgroundColor: "transparent", flexGrow: 1 }}
|
|
||||||
>
|
|
||||||
<BottomNavigationAction
|
|
||||||
onClick={() => {
|
|
||||||
setMobileViewModeKeepOpen("messaging");
|
|
||||||
}}
|
|
||||||
icon={
|
|
||||||
<IconWrapper label="Messaging" color="rgba(250, 250, 250, 0.5)">
|
|
||||||
<MessagingIcon color={hasUnreadDirects ? "var(--danger)" :"rgba(250, 250, 250, 0.5)"} />
|
|
||||||
</IconWrapper>
|
|
||||||
}
|
|
||||||
sx={{
|
|
||||||
color: value === 2 ? "white" : "gray",
|
|
||||||
paddingLeft: "55px",
|
|
||||||
paddingRight: "10px",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<BottomNavigationAction
|
|
||||||
onClick={async () => {
|
|
||||||
executeEvent("addTab", { data: { service: 'APP', name: 'q-trade' } });
|
|
||||||
executeEvent("open-apps-mode", { });
|
|
||||||
}}
|
|
||||||
|
|
||||||
icon={
|
|
||||||
<IconWrapper label="Trading" color="rgba(250, 250, 250, 0.5)">
|
|
||||||
<TradingIcon color="rgba(250, 250, 250, 0.5)" />
|
|
||||||
</IconWrapper>
|
|
||||||
}
|
|
||||||
sx={{ color: value === 3 ? "white" : "gray", padding: "0px 10px" }}
|
|
||||||
/>
|
|
||||||
</BottomNavigation>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,528 +0,0 @@
|
|||||||
import React, { useState } from "react";
|
|
||||||
import {
|
|
||||||
AppBar,
|
|
||||||
Toolbar,
|
|
||||||
IconButton,
|
|
||||||
Typography,
|
|
||||||
Box,
|
|
||||||
MenuItem,
|
|
||||||
Select,
|
|
||||||
ButtonBase,
|
|
||||||
Menu,
|
|
||||||
ListItemIcon,
|
|
||||||
ListItemText,
|
|
||||||
} from "@mui/material";
|
|
||||||
import { HomeIcon } from "../../assets/Icons/HomeIcon";
|
|
||||||
import { LogoutIcon } from "../../assets/Icons/LogoutIcon";
|
|
||||||
import { NotificationIcon } from "../../assets/Icons/NotificationIcon";
|
|
||||||
import { ArrowDownIcon } from "../../assets/Icons/ArrowDownIcon";
|
|
||||||
import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
|
|
||||||
import { MessagingIcon2 } from "../../assets/Icons/MessagingIcon2";
|
|
||||||
import { HubsIcon } from "../../assets/Icons/HubsIcon";
|
|
||||||
import { Save } from "../Save/Save";
|
|
||||||
import CloseFullscreenIcon from "@mui/icons-material/CloseFullscreen";
|
|
||||||
import { useRecoilState } from "recoil";
|
|
||||||
import { fullScreenAtom, hasSettingsChangedAtom } from "../../atoms/global";
|
|
||||||
import { useAppFullScreen } from "../../useAppFullscreen";
|
|
||||||
|
|
||||||
const Header = ({
|
|
||||||
logoutFunc,
|
|
||||||
goToHome,
|
|
||||||
setIsOpenDrawerProfile,
|
|
||||||
isThin,
|
|
||||||
setMobileViewModeKeepOpen,
|
|
||||||
hasUnreadGroups,
|
|
||||||
hasUnreadDirects,
|
|
||||||
setMobileViewMode,
|
|
||||||
myName,
|
|
||||||
setSelectedDirect,
|
|
||||||
setNewChat,
|
|
||||||
}) => {
|
|
||||||
const [anchorEl, setAnchorEl] = useState(null);
|
|
||||||
const open = Boolean(anchorEl);
|
|
||||||
const [fullScreen, setFullScreen] = useRecoilState(fullScreenAtom);
|
|
||||||
const { exitFullScreen } = useAppFullScreen(setFullScreen);
|
|
||||||
const handleClick = (event) => {
|
|
||||||
setAnchorEl(event.currentTarget);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
setAnchorEl(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
if (isThin) {
|
|
||||||
return (
|
|
||||||
<AppBar
|
|
||||||
position="static"
|
|
||||||
sx={{
|
|
||||||
backgroundColor: "background: rgba(0, 0, 0, 0.2)",
|
|
||||||
boxShadow: "none",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Toolbar
|
|
||||||
sx={{
|
|
||||||
justifyContent: "space-between",
|
|
||||||
padding: "0 16px",
|
|
||||||
height: "45px",
|
|
||||||
minHeight: "45px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* Left Home Icon */}
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "18px",
|
|
||||||
width: "75px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
setMobileViewModeKeepOpen("");
|
|
||||||
goToHome();
|
|
||||||
}}
|
|
||||||
// onClick={onHomeClick}
|
|
||||||
>
|
|
||||||
<HomeIcon height={20} width={27} />
|
|
||||||
</ButtonBase>
|
|
||||||
<ButtonBase onClick={handleClick}>
|
|
||||||
<NotificationIcon
|
|
||||||
height={20}
|
|
||||||
width={21}
|
|
||||||
color={
|
|
||||||
hasUnreadDirects || hasUnreadGroups
|
|
||||||
? "var(--danger)"
|
|
||||||
: "rgba(145, 145, 147, 1)"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ButtonBase>
|
|
||||||
{fullScreen && (
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
exitFullScreen();
|
|
||||||
setFullScreen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CloseFullscreenIcon
|
|
||||||
sx={{
|
|
||||||
color: "rgba(145, 145, 147, 1)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ButtonBase>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Center Title */}
|
|
||||||
<Typography
|
|
||||||
variant="h6"
|
|
||||||
sx={{
|
|
||||||
color: "rgba(255, 255, 255, 1)",
|
|
||||||
fontWeight: 700,
|
|
||||||
letterSpacing: "2px",
|
|
||||||
fontSize: "13px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
QORTAL
|
|
||||||
</Typography>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "18px",
|
|
||||||
width: "75px",
|
|
||||||
justifyContent: "flex-end",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* Right Logout Icon */}
|
|
||||||
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
setMobileViewModeKeepOpen("messaging");
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MessagingIcon2
|
|
||||||
height={20}
|
|
||||||
color={
|
|
||||||
hasUnreadDirects ? "var(--danger)" : "rgba(145, 145, 147, 1)"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ButtonBase>
|
|
||||||
<Save />
|
|
||||||
<ButtonBase onClick={logoutFunc}>
|
|
||||||
<LogoutIcon
|
|
||||||
height={20}
|
|
||||||
width={21}
|
|
||||||
color="rgba(145, 145, 147, 1)"
|
|
||||||
/>
|
|
||||||
</ButtonBase>
|
|
||||||
</Box>
|
|
||||||
</Toolbar>
|
|
||||||
<Menu
|
|
||||||
id="home-menu"
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
open={open}
|
|
||||||
onClose={handleClose}
|
|
||||||
MenuListProps={{
|
|
||||||
"aria-labelledby": "basic-button",
|
|
||||||
}}
|
|
||||||
anchorOrigin={{
|
|
||||||
vertical: "bottom",
|
|
||||||
horizontal: "center",
|
|
||||||
}}
|
|
||||||
transformOrigin={{
|
|
||||||
vertical: "top",
|
|
||||||
horizontal: "center",
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
paper: {
|
|
||||||
sx: {
|
|
||||||
backgroundColor: "var(--bg-primary)",
|
|
||||||
color: "#fff",
|
|
||||||
width: "148px",
|
|
||||||
borderRadius: "5px",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
marginTop: "10px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
setSelectedDirect(null);
|
|
||||||
setNewChat(false);
|
|
||||||
setMobileViewMode("groups");
|
|
||||||
setMobileViewModeKeepOpen("");
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListItemIcon
|
|
||||||
sx={{
|
|
||||||
minWidth: "24px !important",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<HubsIcon
|
|
||||||
height={20}
|
|
||||||
color={
|
|
||||||
hasUnreadGroups ? "var(--danger)" : "rgba(250, 250, 250, 0.5)"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
|
||||||
sx={{
|
|
||||||
"& .MuiTypography-root": {
|
|
||||||
fontSize: "12px",
|
|
||||||
fontWeight: 600,
|
|
||||||
color: hasUnreadGroups
|
|
||||||
? "var(--danger)"
|
|
||||||
: "rgba(250, 250, 250, 0.5)",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
primary="Groups"
|
|
||||||
/>
|
|
||||||
</MenuItem>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
setMobileViewModeKeepOpen("messaging");
|
|
||||||
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListItemIcon
|
|
||||||
sx={{
|
|
||||||
minWidth: "24px !important",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MessagingIcon
|
|
||||||
height={20}
|
|
||||||
color={
|
|
||||||
hasUnreadDirects
|
|
||||||
? "var(--danger)"
|
|
||||||
: "rgba(250, 250, 250, 0.5)"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
|
||||||
sx={{
|
|
||||||
"& .MuiTypography-root": {
|
|
||||||
fontSize: "12px",
|
|
||||||
fontWeight: 600,
|
|
||||||
color: hasUnreadDirects
|
|
||||||
? "var(--danger)"
|
|
||||||
: "rgba(250, 250, 250, 0.5)",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
primary="Messaging"
|
|
||||||
/>
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</AppBar>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
{/* Main Header */}
|
|
||||||
<AppBar
|
|
||||||
position="static"
|
|
||||||
sx={{ backgroundColor: "var(--bg-primary)", boxShadow: "none" }}
|
|
||||||
>
|
|
||||||
<Toolbar
|
|
||||||
sx={{
|
|
||||||
justifyContent: "space-between",
|
|
||||||
padding: "0 16px",
|
|
||||||
height: "60px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* Left Home Icon */}
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "18px",
|
|
||||||
width: "75px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ButtonBase
|
|
||||||
onClick={goToHome}
|
|
||||||
// onClick={onHomeClick}
|
|
||||||
>
|
|
||||||
<HomeIcon />
|
|
||||||
</ButtonBase>
|
|
||||||
{fullScreen && (
|
|
||||||
<ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
exitFullScreen();
|
|
||||||
setFullScreen(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<CloseFullscreenIcon
|
|
||||||
sx={{
|
|
||||||
color: "rgba(145, 145, 147, 1)",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ButtonBase>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
{/* Center Title */}
|
|
||||||
<Typography
|
|
||||||
variant="h6"
|
|
||||||
sx={{
|
|
||||||
color: "rgba(255, 255, 255, 1)",
|
|
||||||
fontWeight: 700,
|
|
||||||
letterSpacing: "2px",
|
|
||||||
fontSize: "13px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
QORTAL
|
|
||||||
</Typography>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "30px",
|
|
||||||
width: "75px",
|
|
||||||
justifyContent: "flex-end",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{/* Right Logout Icon */}
|
|
||||||
<Save />
|
|
||||||
<ButtonBase
|
|
||||||
onClick={logoutFunc}
|
|
||||||
|
|
||||||
// onClick={onLogoutClick}
|
|
||||||
>
|
|
||||||
<LogoutIcon color="rgba(145, 145, 147, 1)" />
|
|
||||||
</ButtonBase>
|
|
||||||
</Box>
|
|
||||||
</Toolbar>
|
|
||||||
</AppBar>
|
|
||||||
|
|
||||||
{/* Secondary Section */}
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
backgroundColor: "var(--bg-3)",
|
|
||||||
padding: "8px 16px",
|
|
||||||
position: "relative",
|
|
||||||
height: "27px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
gap: "10px",
|
|
||||||
alignItems: "center",
|
|
||||||
userSelect: "none",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
color: "rgba(255, 255, 255, 1)",
|
|
||||||
fontWeight: 400,
|
|
||||||
fontSize: "11px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{myName}
|
|
||||||
</Typography>
|
|
||||||
{/*
|
|
||||||
<ArrowDownIcon /> */}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
position: "absolute",
|
|
||||||
left: "50%",
|
|
||||||
transform: "translate(-50%, 50%)",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
zIndex: 6,
|
|
||||||
width: "30px", // Adjust as needed
|
|
||||||
height: "30px", // Adjust as needed
|
|
||||||
backgroundColor: "#232428", // Circle background
|
|
||||||
borderRadius: "50%",
|
|
||||||
boxShadow: "0px 4px 10px rgba(0, 0, 0, 0.3)", // Optional shadow for the circle
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<IconButton onClick={handleClick} color="inherit">
|
|
||||||
<NotificationIcon
|
|
||||||
color={
|
|
||||||
hasUnreadDirects || hasUnreadGroups
|
|
||||||
? "var(--danger)"
|
|
||||||
: "rgba(255, 255, 255, 1)"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
{/* Right Dropdown */}
|
|
||||||
{/* <ButtonBase
|
|
||||||
onClick={() => {
|
|
||||||
setIsOpenDrawerProfile(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
gap: "10px",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
color: "rgba(255, 255, 255, 1)",
|
|
||||||
fontWeight: 400,
|
|
||||||
fontSize: "11px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
View Wallet
|
|
||||||
</Typography>
|
|
||||||
|
|
||||||
<ArrowDownIcon />
|
|
||||||
</Box>
|
|
||||||
</ButtonBase> */}
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Menu
|
|
||||||
id="home-menu"
|
|
||||||
anchorEl={anchorEl}
|
|
||||||
open={open}
|
|
||||||
onClose={handleClose}
|
|
||||||
MenuListProps={{
|
|
||||||
"aria-labelledby": "basic-button",
|
|
||||||
}}
|
|
||||||
anchorOrigin={{
|
|
||||||
vertical: "bottom",
|
|
||||||
horizontal: "center",
|
|
||||||
}}
|
|
||||||
transformOrigin={{
|
|
||||||
vertical: "top",
|
|
||||||
horizontal: "center",
|
|
||||||
}}
|
|
||||||
slotProps={{
|
|
||||||
paper: {
|
|
||||||
sx: {
|
|
||||||
backgroundColor: "var(--bg-primary)",
|
|
||||||
color: "#fff",
|
|
||||||
width: "148px",
|
|
||||||
borderRadius: "5px",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
sx={{
|
|
||||||
marginTop: "10px",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
setMobileViewMode("groups");
|
|
||||||
setMobileViewModeKeepOpen("");
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListItemIcon
|
|
||||||
sx={{
|
|
||||||
minWidth: "24px !important",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<HubsIcon
|
|
||||||
height={20}
|
|
||||||
color={
|
|
||||||
hasUnreadGroups ? "var(--danger)" : "rgba(250, 250, 250, 0.5)"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
|
||||||
sx={{
|
|
||||||
"& .MuiTypography-root": {
|
|
||||||
fontSize: "12px",
|
|
||||||
fontWeight: 600,
|
|
||||||
color: hasUnreadDirects
|
|
||||||
? "var(--danger)"
|
|
||||||
: "rgba(250, 250, 250, 0.5)",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
primary="Groups"
|
|
||||||
/>
|
|
||||||
</MenuItem>
|
|
||||||
|
|
||||||
<MenuItem
|
|
||||||
onClick={() => {
|
|
||||||
setMobileViewModeKeepOpen("messaging");
|
|
||||||
|
|
||||||
handleClose();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ListItemIcon
|
|
||||||
sx={{
|
|
||||||
minWidth: "24px !important",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<MessagingIcon
|
|
||||||
height={20}
|
|
||||||
color={
|
|
||||||
hasUnreadDirects ? "var(--danger)" : "rgba(250, 250, 250, 0.5)"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
|
||||||
<ListItemText
|
|
||||||
sx={{
|
|
||||||
"& .MuiTypography-root": {
|
|
||||||
fontSize: "12px",
|
|
||||||
fontWeight: 600,
|
|
||||||
color: hasUnreadDirects
|
|
||||||
? "var(--danger)"
|
|
||||||
: "rgba(250, 250, 250, 0.5)",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
primary="Messaging"
|
|
||||||
/>
|
|
||||||
</MenuItem>
|
|
||||||
</Menu>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Header;
|
|
Loading…
x
Reference in New Issue
Block a user