mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-04-20 10:05:56 +00:00
added tabs
This commit is contained in:
parent
28c2dfbb7a
commit
54b1725585
@ -3,7 +3,7 @@ import { AppViewer } from './AppViewer'
|
||||
import Frame from 'react-frame-component';
|
||||
import { MyContext } from '../../App';
|
||||
|
||||
const AppViewerContainer = ({app, isSelected}) => {
|
||||
const AppViewerContainer = ({app, isSelected, hide}) => {
|
||||
const { rootHeight } = useContext(MyContext);
|
||||
const frameRef = useRef(null);
|
||||
|
||||
@ -32,7 +32,7 @@ const AppViewerContainer = ({app, isSelected}) => {
|
||||
height: `calc(${rootHeight} - 60px - 45px)`,
|
||||
border: 'none',
|
||||
width: '100%',
|
||||
display: !isSelected && 'none'
|
||||
display: (!isSelected || hide) && 'none'
|
||||
}} ><AppViewer app={app} /></Frame>
|
||||
)
|
||||
}
|
||||
|
@ -186,9 +186,23 @@ import {
|
||||
display: "flex",
|
||||
justifyContent: 'flex-start',
|
||||
alignItems: 'center',
|
||||
flexGrow: 1
|
||||
}));
|
||||
export const AppsNavBarRight = styled(Box)(({ theme }) => ({
|
||||
display: "flex",
|
||||
justifyContent: 'flex-end',
|
||||
alignItems: 'center',
|
||||
}));
|
||||
}));
|
||||
|
||||
export const TabParent = styled(Box)(({ theme }) => ({
|
||||
height: '36px',
|
||||
width: '36px',
|
||||
backgroundColor: '#434343',
|
||||
position: 'relative',
|
||||
borderRadius: '50%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}));
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { Spacer } from '../../common/Spacer'
|
||||
import { MyContext, getBaseApiReact } from '../../App'
|
||||
import { AppsLibrary } from './AppsLibrary'
|
||||
import { AppInfo } from './AppInfo'
|
||||
import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events'
|
||||
import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from '../../utils/events'
|
||||
import { AppsNavBar } from './AppsNavBar'
|
||||
import { AppsParent } from './Apps-styles'
|
||||
import { AppViewer } from './AppViewer'
|
||||
@ -14,13 +14,24 @@ import ShortUniqueId from "short-unique-id";
|
||||
const uid = new ShortUniqueId({ length: 8 });
|
||||
|
||||
|
||||
export const Apps = ({mode, setMode}) => {
|
||||
export const Apps = ({mode, setMode, show}) => {
|
||||
const [availableQapps, setAvailableQapps] = useState([])
|
||||
const [downloadedQapps, setDownloadedQapps] = useState([])
|
||||
const [selectedAppInfo, setSelectedAppInfo] = useState(null)
|
||||
const [tabs, setTabs] = useState([])
|
||||
const [selectedTab, setSelectedTab] = useState(null)
|
||||
|
||||
const [isNewTabWindow, setIsNewTabWindow] = useState(false)
|
||||
|
||||
useEffect(()=> {
|
||||
setTimeout(() => {
|
||||
executeEvent('setTabsToNav', {
|
||||
data: {
|
||||
tabs: tabs,
|
||||
selectedTab: selectedTab
|
||||
}
|
||||
})
|
||||
}, 100);
|
||||
}, [show, tabs, selectedTab])
|
||||
|
||||
const getQapps = React.useCallback(
|
||||
async () => {
|
||||
@ -85,8 +96,8 @@ export const Apps = ({mode, setMode}) => {
|
||||
} else if(mode === 'library'){
|
||||
setMode('home')
|
||||
} else {
|
||||
|
||||
const iframe = document.getElementById('browser-iframe2');
|
||||
const iframeId = `browser-iframe-${selectedTab?.tabId}`
|
||||
const iframe = document.getElementById(iframeId);
|
||||
console.log('iframe', iframe)
|
||||
// Go Back in the iframe's history
|
||||
if (iframe) {
|
||||
@ -108,7 +119,7 @@ if (iframe) {
|
||||
return () => {
|
||||
unsubscribeFromEvent("navigateBack", navigateBackFunc);
|
||||
};
|
||||
}, [mode]);
|
||||
}, [mode, selectedTab]);
|
||||
|
||||
|
||||
const addTabFunc = (e) => {
|
||||
@ -119,6 +130,9 @@ if (iframe) {
|
||||
}
|
||||
setTabs((prev)=> [...prev, newTab])
|
||||
setSelectedTab(newTab)
|
||||
setMode('viewer')
|
||||
|
||||
setIsNewTabWindow(false)
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@ -127,10 +141,76 @@ if (iframe) {
|
||||
return () => {
|
||||
unsubscribeFromEvent("addTab", addTabFunc);
|
||||
};
|
||||
}, [mode]);
|
||||
|
||||
}, [tabs]);
|
||||
|
||||
const setSelectedTabFunc = (e) => {
|
||||
const data = e.detail?.data;
|
||||
|
||||
|
||||
setSelectedTab(data)
|
||||
setTimeout(() => {
|
||||
executeEvent('setTabsToNav', {
|
||||
data: {
|
||||
tabs: tabs,
|
||||
selectedTab: data
|
||||
}
|
||||
})
|
||||
}, 100);
|
||||
setIsNewTabWindow(false)
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
subscribeToEvent("setSelectedTab", setSelectedTabFunc);
|
||||
|
||||
return () => {
|
||||
unsubscribeFromEvent("setSelectedTab", setSelectedTabFunc);
|
||||
};
|
||||
}, [tabs]);
|
||||
|
||||
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)
|
||||
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
subscribeToEvent("newTabWindow", setNewTabWindowFunc);
|
||||
|
||||
return () => {
|
||||
unsubscribeFromEvent("newTabWindow", setNewTabWindowFunc);
|
||||
};
|
||||
}, [tabs]);
|
||||
|
||||
if(!show) return null
|
||||
|
||||
return (
|
||||
<AppsParent>
|
||||
@ -141,14 +221,14 @@ if (iframe) {
|
||||
{mode === 'home' && <AppsHome downloadedQapps={downloadedQapps} setMode={setMode} />}
|
||||
{mode === 'library' && <AppsLibrary downloadedQapps={downloadedQapps} availableQapps={availableQapps} />}
|
||||
{mode === 'appInfo' && <AppInfo app={selectedAppInfo} />}
|
||||
{mode === 'viewer' && (
|
||||
<>
|
||||
|
||||
{tabs.map((tab)=> {
|
||||
return <AppViewerContainer isSelected={tab?.tabId === selectedTab?.tabId} app={tab} />
|
||||
return <AppViewerContainer hide={isNewTabWindow} isSelected={tab?.tabId === selectedTab?.tabId} app={tab} />
|
||||
})}
|
||||
</>
|
||||
) }
|
||||
|
||||
|
||||
{isNewTabWindow && (
|
||||
<AppsHome downloadedQapps={downloadedQapps} setMode={setMode} />
|
||||
)}
|
||||
{mode !== 'viewer' && (
|
||||
<Spacer height="180px" />
|
||||
|
||||
|
@ -1,17 +1,48 @@
|
||||
import React from "react";
|
||||
import React, { useEffect, useRef, useState } from "react";
|
||||
import {
|
||||
AppsNavBarLeft,
|
||||
AppsNavBarParent,
|
||||
AppsNavBarRight,
|
||||
} from "./Apps-styles";
|
||||
import NavBack from "../../assets/svgs/NavBack.svg";
|
||||
import NavCloseTab from "../../assets/svgs/NavCloseTab.svg";
|
||||
import NavAdd from "../../assets/svgs/NavAdd.svg";
|
||||
import NavMoreMenu from "../../assets/svgs/NavMoreMenu.svg";
|
||||
import { ButtonBase } from "@mui/material";
|
||||
import { executeEvent } from "../../utils/events";
|
||||
import { ButtonBase, Tab, Tabs } from "@mui/material";
|
||||
import { executeEvent, subscribeToEvent, unsubscribeFromEvent } from "../../utils/events";
|
||||
import TabComponent from "./TabComponent";
|
||||
|
||||
export const AppsNavBar = () => {
|
||||
const [tabs, setTabs] = useState([])
|
||||
const [selectedTab, setSelectedTab] = useState([])
|
||||
|
||||
const tabsRef = useRef(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');
|
||||
console.log('tabElements', tabElements)
|
||||
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} = e.detail?.data;
|
||||
|
||||
setTabs([...tabs])
|
||||
setSelectedTab({...selectedTab})
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
subscribeToEvent("setTabsToNav", setTabsToNav);
|
||||
|
||||
return () => {
|
||||
unsubscribeFromEvent("setTabsToNav", setTabsToNav);
|
||||
};
|
||||
}, []);
|
||||
return (
|
||||
<AppsNavBarParent>
|
||||
<AppsNavBarLeft>
|
||||
@ -21,11 +52,43 @@ export const AppsNavBar = () => {
|
||||
}}>
|
||||
<img src={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} app={tab} />} // Pass custom component
|
||||
sx={{
|
||||
"&.Mui-selected": {
|
||||
color: "white",
|
||||
},
|
||||
padding: '0px',
|
||||
margin: '0px',
|
||||
minWidth: '0px',
|
||||
width: '50px'
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</Tabs>
|
||||
</AppsNavBarLeft>
|
||||
<AppsNavBarRight sx={{
|
||||
gap: '10px'
|
||||
}}>
|
||||
<ButtonBase>
|
||||
<ButtonBase onClick={()=> {
|
||||
executeEvent("newTabWindow", {
|
||||
});
|
||||
}}>
|
||||
<img style={{
|
||||
height: '40px',
|
||||
width: '40px'
|
||||
|
61
src/components/Apps/TabComponent.tsx
Normal file
61
src/components/Apps/TabComponent.tsx
Normal file
@ -0,0 +1,61 @@
|
||||
import React from 'react'
|
||||
import { TabParent } from './Apps-styles'
|
||||
import NavCloseTab from "../../assets/svgs/NavCloseTab.svg";
|
||||
import { getBaseApiReact } from '../../App';
|
||||
import { Avatar, ButtonBase } from '@mui/material';
|
||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||
import { executeEvent } from '../../utils/events';
|
||||
|
||||
const TabComponent = ({isSelected, app}) => {
|
||||
return (
|
||||
<ButtonBase onClick={()=> {
|
||||
if(isSelected){
|
||||
executeEvent('removeTab', {
|
||||
data: app
|
||||
})
|
||||
return
|
||||
}
|
||||
executeEvent('setSelectedTab', {
|
||||
data: app
|
||||
})
|
||||
}}>
|
||||
<TabParent sx={{
|
||||
border: isSelected && '1px solid #FFFFFF'
|
||||
}}>
|
||||
{isSelected && (
|
||||
|
||||
<img style={
|
||||
{
|
||||
position: 'absolute',
|
||||
top: '-5px',
|
||||
right: '-5px',
|
||||
zIndex: 1
|
||||
}
|
||||
} src={NavCloseTab}/>
|
||||
|
||||
) }
|
||||
<Avatar
|
||||
sx={{
|
||||
height: "31px",
|
||||
width: "31px",
|
||||
}}
|
||||
alt={app?.name}
|
||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
|
||||
app?.name
|
||||
}/qortal_avatar?async=true`}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
width: "31px",
|
||||
height: "auto",
|
||||
}}
|
||||
src={LogoSelected}
|
||||
alt="center-icon"
|
||||
/>
|
||||
</Avatar>
|
||||
</TabParent>
|
||||
</ButtonBase>
|
||||
)
|
||||
}
|
||||
|
||||
export default TabComponent
|
@ -433,7 +433,7 @@ export const Group = ({
|
||||
const { clearStatesMessageQueueProvider } = useMessageQueue();
|
||||
const initiatedGetMembers = useRef(false);
|
||||
const [groupChatTimestamps, setGroupChatTimestamps] = React.useState({});
|
||||
const [appsMode, setAppsMode] = useState('viewer')
|
||||
const [appsMode, setAppsMode] = useState('home')
|
||||
|
||||
useEffect(()=> {
|
||||
timestampEnterDataRef.current = timestampEnterData
|
||||
@ -2736,8 +2736,8 @@ export const Group = ({
|
||||
setMobileViewMode={setMobileViewMode}
|
||||
/>
|
||||
)}
|
||||
{isMobile && mobileViewMode === "apps" && (
|
||||
<Apps mode={appsMode} setMode={setAppsMode} />
|
||||
{isMobile && (
|
||||
<Apps mode={appsMode} setMode={setAppsMode} show={mobileViewMode === "apps"} />
|
||||
)}
|
||||
{
|
||||
!isMobile && !selectedGroup &&
|
||||
|
Loading…
x
Reference in New Issue
Block a user