mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-07-23 04:36:52 +00:00
added apps to dev mode
This commit is contained in:
@@ -332,7 +332,7 @@ export const AppsDevMode = ({ mode, setMode, show , myName, goToHome, setDesktop
|
||||
isSelected={tab?.tabId === selectedTab?.tabId}
|
||||
app={tab}
|
||||
ref={iframeRefs.current[tab.tabId]}
|
||||
isDevMode={true}
|
||||
isDevMode={tab?.service ? false : true}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
@@ -7,7 +7,7 @@ import {
|
||||
AppsContainer,
|
||||
AppsParent,
|
||||
} from "./Apps-styles";
|
||||
import {Buffer} from 'buffer'
|
||||
import { Buffer } from "buffer";
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
@@ -29,249 +29,239 @@ import { Spacer } from "../../common/Spacer";
|
||||
import { useModal } from "../../common/useModal";
|
||||
import { createEndpoint, isUsingLocal } from "../../background";
|
||||
import { Label } from "../Group/AddGroup";
|
||||
import ShortUniqueId from "short-unique-id";
|
||||
import swaggerSVG from '../../assets/svgs/swagger.svg'
|
||||
const uid = new ShortUniqueId({ length: 8 });
|
||||
|
||||
export const AppsDevModeHome = ({
|
||||
setMode,
|
||||
myApp,
|
||||
myWebsite,
|
||||
availableQapps,
|
||||
myName
|
||||
myName,
|
||||
}) => {
|
||||
const [domain, setDomain] = useState("127.0.0.1");
|
||||
const [port, setPort] = useState("");
|
||||
const [selectedPreviewFile, setSelectedPreviewFile] = useState(null);
|
||||
|
||||
const [domain, setDomain] = useState("127.0.0.1");
|
||||
const [port, setPort] = useState("");
|
||||
const [selectedPreviewFile, setSelectedPreviewFile] = useState(null);
|
||||
const { isShow, onCancel, onOk, show, message } = useModal();
|
||||
const {
|
||||
openSnackGlobal,
|
||||
setOpenSnackGlobal,
|
||||
infoSnackCustom,
|
||||
setInfoSnackCustom,
|
||||
} = useContext(MyContext);
|
||||
|
||||
const { isShow, onCancel, onOk, show, message } = useModal();
|
||||
const {
|
||||
openSnackGlobal,
|
||||
setOpenSnackGlobal,
|
||||
infoSnackCustom,
|
||||
setInfoSnackCustom,
|
||||
} = useContext(MyContext);
|
||||
const handleSelectFile = async (existingFilePath) => {
|
||||
const filePath = existingFilePath || (await window.electron.selectFile());
|
||||
if (filePath) {
|
||||
const content = await window.electron.readFile(filePath);
|
||||
return { buffer: content, filePath };
|
||||
} else {
|
||||
console.log("No file selected.");
|
||||
}
|
||||
};
|
||||
const handleSelectDirectry = async (existingDirectoryPath) => {
|
||||
const { buffer, directoryPath } =
|
||||
await window.electron.selectAndZipDirectory(existingDirectoryPath);
|
||||
if (buffer) {
|
||||
return { buffer, directoryPath };
|
||||
} else {
|
||||
console.log("No file selected.");
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectFile = async (existingFilePath) => {
|
||||
const filePath = existingFilePath || await window.electron.selectFile();
|
||||
if (filePath) {
|
||||
|
||||
const content = await window.electron.readFile(filePath);
|
||||
return {buffer: content, filePath}
|
||||
} else {
|
||||
console.log('No file selected.');
|
||||
}
|
||||
};
|
||||
const handleSelectDirectry = async (existingDirectoryPath) => {
|
||||
const {buffer, directoryPath} = await window.electron.selectAndZipDirectory(existingDirectoryPath);
|
||||
if (buffer) {
|
||||
|
||||
|
||||
return {buffer, directoryPath}
|
||||
} else {
|
||||
console.log('No file selected.');
|
||||
}
|
||||
};
|
||||
const addDevModeApp = async () => {
|
||||
try {
|
||||
const usingLocal = await isUsingLocal();
|
||||
if (!usingLocal) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
const addDevModeApp = async () => {
|
||||
try {
|
||||
const usingLocal = await isUsingLocal();
|
||||
if (!usingLocal) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"Please use your local node for dev mode! Logout and use Local node.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const {portVal, domainVal} = await show({
|
||||
message: "",
|
||||
publishFee: "",
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"Please use your local node for dev mode! Logout and use Local node.",
|
||||
});
|
||||
const framework = domainVal + ":" + portVal;
|
||||
const response = await fetch(
|
||||
`${getBaseApiReact()}/developer/proxy/start`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
body: framework,
|
||||
}
|
||||
);
|
||||
const responseData = await response.text();
|
||||
executeEvent("appsDevModeAddTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:" + responseData,
|
||||
return;
|
||||
}
|
||||
const { portVal, domainVal } = await show({
|
||||
message: "",
|
||||
publishFee: "",
|
||||
});
|
||||
const framework = domainVal + ":" + portVal;
|
||||
const response = await fetch(
|
||||
`${getBaseApiReact()}/developer/proxy/start`,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
body: framework,
|
||||
}
|
||||
);
|
||||
const responseData = await response.text();
|
||||
executeEvent("appsDevModeAddTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:" + responseData,
|
||||
},
|
||||
});
|
||||
} catch (error) {}
|
||||
};
|
||||
|
||||
const addPreviewApp = async (isRefresh, existingFilePath, tabId) => {
|
||||
try {
|
||||
const usingLocal = await isUsingLocal();
|
||||
if (!usingLocal) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"Please use your local node for dev mode! Logout and use Local node.",
|
||||
});
|
||||
} catch (error) {}
|
||||
};
|
||||
return;
|
||||
}
|
||||
if (!myName) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
const addPreviewApp = async (isRefresh, existingFilePath, tabId) => {
|
||||
try {
|
||||
const usingLocal = await isUsingLocal();
|
||||
if (!usingLocal) {
|
||||
setOpenSnackGlobal(true);
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message: "You need a name to use preview",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"Please use your local node for dev mode! Logout and use Local node.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!myName) {
|
||||
setOpenSnackGlobal(true);
|
||||
const { buffer, filePath } = await handleSelectFile(existingFilePath);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"You need a name to use preview",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!buffer) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
|
||||
const {buffer, filePath} = await handleSelectFile(existingFilePath)
|
||||
|
||||
if (!buffer) {
|
||||
setOpenSnackGlobal(true);
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message: "Please select a file",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const postBody = Buffer.from(buffer).toString("base64");
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"Please select a file",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const postBody = Buffer.from(buffer).toString('base64')
|
||||
|
||||
const endpoint = await createEndpoint(`/arbitrary/APP/${myName}/zip?preview=true`)
|
||||
const response = await fetch(
|
||||
endpoint
|
||||
,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
body: postBody,
|
||||
}
|
||||
);
|
||||
if(!response?.ok) throw new Error('Invalid zip')
|
||||
const previewPath = await response.text();
|
||||
if(tabId){
|
||||
const endpoint = await createEndpoint(
|
||||
`/arbitrary/APP/${myName}/zip?preview=true`
|
||||
);
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
body: postBody,
|
||||
});
|
||||
if (!response?.ok) throw new Error("Invalid zip");
|
||||
const previewPath = await response.text();
|
||||
if (tabId) {
|
||||
executeEvent("appsDevModeUpdateTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:12391" + previewPath,
|
||||
url: "http://127.0.0.1:12391" + previewPath,
|
||||
isPreview: true,
|
||||
filePath,
|
||||
refreshFunc: (tabId)=> {
|
||||
addPreviewApp(true, filePath, tabId)
|
||||
refreshFunc: (tabId) => {
|
||||
addPreviewApp(true, filePath, tabId);
|
||||
},
|
||||
tabId
|
||||
tabId,
|
||||
},
|
||||
});
|
||||
return
|
||||
return;
|
||||
}
|
||||
executeEvent("appsDevModeAddTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:12391" + previewPath,
|
||||
isPreview: true,
|
||||
filePath,
|
||||
refreshFunc: (tabId)=> {
|
||||
addPreviewApp(true, filePath, tabId)
|
||||
}
|
||||
executeEvent("appsDevModeAddTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:12391" + previewPath,
|
||||
isPreview: true,
|
||||
filePath,
|
||||
refreshFunc: (tabId) => {
|
||||
addPreviewApp(true, filePath, tabId);
|
||||
},
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
const addPreviewAppWithDirectory = async (isRefresh, existingDir, tabId) => {
|
||||
try {
|
||||
const usingLocal = await isUsingLocal();
|
||||
if (!usingLocal) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"Please use your local node for dev mode! Logout and use Local node.",
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return;
|
||||
}
|
||||
};
|
||||
if (!myName) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
const addPreviewAppWithDirectory = async (isRefresh, existingDir, tabId) => {
|
||||
try {
|
||||
const usingLocal = await isUsingLocal();
|
||||
if (!usingLocal) {
|
||||
setOpenSnackGlobal(true);
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message: "You need a name to use preview",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"Please use your local node for dev mode! Logout and use Local node.",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!myName) {
|
||||
setOpenSnackGlobal(true);
|
||||
const { buffer, directoryPath } = await handleSelectDirectry(existingDir);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"You need a name to use preview",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!buffer) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
|
||||
const {buffer, directoryPath} = await handleSelectDirectry(existingDir)
|
||||
|
||||
if (!buffer) {
|
||||
setOpenSnackGlobal(true);
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message: "Please select a file",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const postBody = Buffer.from(buffer).toString("base64");
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: "error",
|
||||
message:
|
||||
"Please select a file",
|
||||
});
|
||||
return;
|
||||
}
|
||||
const postBody = Buffer.from(buffer).toString('base64')
|
||||
|
||||
const endpoint = await createEndpoint(`/arbitrary/APP/${myName}/zip?preview=true`)
|
||||
const response = await fetch(
|
||||
endpoint
|
||||
,
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
body: postBody,
|
||||
}
|
||||
);
|
||||
if(!response?.ok) throw new Error('Invalid zip')
|
||||
const previewPath = await response.text();
|
||||
if(tabId){
|
||||
const endpoint = await createEndpoint(
|
||||
`/arbitrary/APP/${myName}/zip?preview=true`
|
||||
);
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "text/plain",
|
||||
},
|
||||
body: postBody,
|
||||
});
|
||||
if (!response?.ok) throw new Error("Invalid zip");
|
||||
const previewPath = await response.text();
|
||||
if (tabId) {
|
||||
executeEvent("appsDevModeUpdateTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:12391" + previewPath,
|
||||
url: "http://127.0.0.1:12391" + previewPath,
|
||||
isPreview: true,
|
||||
directoryPath,
|
||||
refreshFunc: (tabId)=> {
|
||||
addPreviewAppWithDirectory(true, directoryPath, tabId)
|
||||
refreshFunc: (tabId) => {
|
||||
addPreviewAppWithDirectory(true, directoryPath, tabId);
|
||||
},
|
||||
tabId
|
||||
tabId,
|
||||
},
|
||||
});
|
||||
return
|
||||
return;
|
||||
}
|
||||
executeEvent("appsDevModeAddTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:12391" + previewPath,
|
||||
isPreview: true,
|
||||
directoryPath,
|
||||
refreshFunc: (tabId)=> {
|
||||
addPreviewAppWithDirectory(true, directoryPath, tabId)
|
||||
}
|
||||
executeEvent("appsDevModeAddTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:12391" + previewPath,
|
||||
isPreview: true,
|
||||
directoryPath,
|
||||
refreshFunc: (tabId) => {
|
||||
addPreviewAppWithDirectory(true, directoryPath, tabId);
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
};
|
||||
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppsContainer
|
||||
@@ -342,67 +332,146 @@ export const AppsDevModeHome = ({
|
||||
<AppCircleLabel>Directory</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
executeEvent("appsDevModeAddTab", {
|
||||
data: {
|
||||
service: "APP",
|
||||
name: "Q-Sandbox",
|
||||
tabId: uid.rnd(),
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<AppCircleContainer
|
||||
sx={{
|
||||
gap: !isMobile ? "10px" : "5px",
|
||||
}}
|
||||
>
|
||||
<AppCircle>
|
||||
<Avatar
|
||||
sx={{
|
||||
height: "42px",
|
||||
width: "42px",
|
||||
"& img": {
|
||||
objectFit: "fill",
|
||||
},
|
||||
}}
|
||||
alt="Q-Sandbox"
|
||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/Q-Sandbox/qortal_avatar?async=true`}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
width: "31px",
|
||||
height: "auto",
|
||||
}}
|
||||
alt="center-icon"
|
||||
/>
|
||||
</Avatar>
|
||||
</AppCircle>
|
||||
<AppCircleLabel>Q-Sandbox</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
executeEvent("appsDevModeAddTab", {
|
||||
data: {
|
||||
url: "http://127.0.0.1:12391",
|
||||
isPreview: false,
|
||||
customIcon: swaggerSVG
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
<AppCircleContainer
|
||||
sx={{
|
||||
gap: !isMobile ? "10px" : "5px",
|
||||
}}
|
||||
>
|
||||
<AppCircle>
|
||||
<Avatar
|
||||
sx={{
|
||||
height: "42px",
|
||||
width: "42px",
|
||||
"& img": {
|
||||
objectFit: "fill",
|
||||
},
|
||||
}}
|
||||
alt="API"
|
||||
src={swaggerSVG}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
width: "31px",
|
||||
height: "auto",
|
||||
}}
|
||||
alt="center-icon"
|
||||
/>
|
||||
</Avatar>
|
||||
</AppCircle>
|
||||
<AppCircleLabel>API</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
</AppsContainer>
|
||||
{isShow && (
|
||||
<Dialog
|
||||
open={isShow}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' && domain && port) {
|
||||
onOk({ portVal: port, domainVal: domain });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
{"Add custom framework"}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "5px",
|
||||
}}
|
||||
>
|
||||
<Label>Domain</Label>
|
||||
<Input
|
||||
placeholder="Domain"
|
||||
value={domain}
|
||||
onChange={(e) => setDomain(e.target.value)}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "5px",
|
||||
marginTop: '15px'
|
||||
}}
|
||||
>
|
||||
<Label>Port</Label>
|
||||
<Input
|
||||
placeholder="Port"
|
||||
value={port}
|
||||
onChange={(e) => setPort(e.target.value)}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button variant="contained" onClick={onCancel}>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!domain || !port}
|
||||
variant="contained"
|
||||
onClick={() => onOk({ portVal: port, domainVal: domain })}
|
||||
autoFocus
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
||||
<Dialog
|
||||
open={isShow}
|
||||
aria-labelledby="alert-dialog-title"
|
||||
aria-describedby="alert-dialog-description"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && domain && port) {
|
||||
onOk({ portVal: port, domainVal: domain });
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
{"Add custom framework"}
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "5px",
|
||||
}}
|
||||
>
|
||||
<Label>Domain</Label>
|
||||
<Input
|
||||
placeholder="Domain"
|
||||
value={domain}
|
||||
onChange={(e) => setDomain(e.target.value)}
|
||||
/>
|
||||
</Box>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "5px",
|
||||
marginTop: "15px",
|
||||
}}
|
||||
>
|
||||
<Label>Port</Label>
|
||||
<Input
|
||||
placeholder="Port"
|
||||
value={port}
|
||||
onChange={(e) => setPort(e.target.value)}
|
||||
/>
|
||||
</Box>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button variant="contained" onClick={onCancel}>
|
||||
Close
|
||||
</Button>
|
||||
<Button
|
||||
disabled={!domain || !port}
|
||||
variant="contained"
|
||||
onClick={() => onOk({ portVal: port, domainVal: domain })}
|
||||
autoFocus
|
||||
>
|
||||
Add
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
@@ -1,59 +1,67 @@
|
||||
import React from 'react'
|
||||
import { TabParent } from './Apps-styles'
|
||||
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 { getBaseApiReact } from "../../App";
|
||||
import { Avatar, ButtonBase } from "@mui/material";
|
||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { executeEvent } from "../../utils/events";
|
||||
|
||||
export const AppsDevModeTabComponent = ({isSelected, app}) => {
|
||||
export const AppsDevModeTabComponent = ({ isSelected, app }) => {
|
||||
return (
|
||||
<ButtonBase onClick={()=> {
|
||||
if(isSelected){
|
||||
executeEvent('removeTabDevMode', {
|
||||
data: app
|
||||
})
|
||||
return
|
||||
}
|
||||
executeEvent('setSelectedTabDevMode', {
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
if (isSelected) {
|
||||
executeEvent("removeTabDevMode", {
|
||||
data: app,
|
||||
isDevMode: true
|
||||
})
|
||||
}}>
|
||||
<TabParent sx={{
|
||||
border: isSelected && '1px solid #FFFFFF'
|
||||
}}>
|
||||
});
|
||||
return;
|
||||
}
|
||||
executeEvent("setSelectedTabDevMode", {
|
||||
data: app,
|
||||
isDevMode: true,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<TabParent
|
||||
sx={{
|
||||
border: isSelected && "1px solid #FFFFFF",
|
||||
}}
|
||||
>
|
||||
{isSelected && (
|
||||
|
||||
<img style={
|
||||
{
|
||||
position: 'absolute',
|
||||
top: '-5px',
|
||||
right: '-5px',
|
||||
zIndex: 1
|
||||
}
|
||||
} src={NavCloseTab}/>
|
||||
|
||||
) }
|
||||
<Avatar
|
||||
sx={{
|
||||
height: "28px",
|
||||
width: "28px",
|
||||
}}
|
||||
alt=''
|
||||
src={``}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
width: "28px",
|
||||
height: "auto",
|
||||
}}
|
||||
src={LogoSelected}
|
||||
alt="center-icon"
|
||||
/>
|
||||
</Avatar>
|
||||
</TabParent>
|
||||
<img
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: "-5px",
|
||||
right: "-5px",
|
||||
zIndex: 1,
|
||||
}}
|
||||
src={NavCloseTab}
|
||||
/>
|
||||
)}
|
||||
<Avatar
|
||||
sx={{
|
||||
height: "28px",
|
||||
width: "28px",
|
||||
}}
|
||||
alt=""
|
||||
src={``}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
width: "28px",
|
||||
height: "auto",
|
||||
}}
|
||||
src={ app?.customIcon ? app?.customIcon :
|
||||
app?.service
|
||||
? `${getBaseApiReact()}/arbitrary/THUMBNAIL/${
|
||||
app?.name
|
||||
}/qortal_avatar?async=true`
|
||||
: LogoSelected
|
||||
}
|
||||
alt="center-icon"
|
||||
/>
|
||||
</Avatar>
|
||||
</TabParent>
|
||||
</ButtonBase>
|
||||
)
|
||||
}
|
||||
|
||||
);
|
||||
};
|
||||
|
Reference in New Issue
Block a user