mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-06-07 17:06:58 +00:00
Use desktop file
This commit is contained in:
parent
bf4e58bcfa
commit
c4f7d150de
@ -1,4 +1,4 @@
|
||||
import React, { useEffect, useMemo, useState } from "react";
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import {
|
||||
AppCircle,
|
||||
AppCircleContainer,
|
||||
@ -19,191 +19,211 @@ import {
|
||||
AppsLibraryContainer,
|
||||
AppsParent,
|
||||
AppsWidthLimiter,
|
||||
} from "./Apps-styles";
|
||||
import { Avatar, Box, ButtonBase, InputBase } from "@mui/material";
|
||||
import { Add } from "@mui/icons-material";
|
||||
import { getBaseApiReact, isMobile } from "../../App";
|
||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||
} from './Apps-styles';
|
||||
import { Avatar, Box, ButtonBase, InputBase } from '@mui/material';
|
||||
import { Add } from '@mui/icons-material';
|
||||
import { getBaseApiReact, isMobile } from '../../App';
|
||||
import LogoSelected from '../../assets/svgs/LogoSelected.svg';
|
||||
|
||||
import { Spacer } from "../../common/Spacer";
|
||||
import { executeEvent } from "../../utils/events";
|
||||
import { AppRating } from "./AppRating";
|
||||
import { settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom } from "../../atoms/global";
|
||||
import { saveToLocalStorage } from "./AppsNavBar";
|
||||
import { useRecoilState, useSetRecoilState } from "recoil";
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { AppRating } from './AppRating';
|
||||
import {
|
||||
settingsLocalLastUpdatedAtom,
|
||||
sortablePinnedAppsAtom,
|
||||
} from '../../atoms/global';
|
||||
import { saveToLocalStorage } from './AppsNavBarDesktop';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
|
||||
export const AppInfo = ({ app, myName }) => {
|
||||
const isInstalled = app?.status?.status === "READY";
|
||||
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
||||
const isInstalled = app?.status?.status === 'READY';
|
||||
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(
|
||||
sortablePinnedAppsAtom
|
||||
);
|
||||
|
||||
const isSelectedAppPinned = !!sortablePinnedApps?.find((item)=> item?.name === app?.name && item?.service === app?.service)
|
||||
const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom);
|
||||
const isSelectedAppPinned = !!sortablePinnedApps?.find(
|
||||
(item) => item?.name === app?.name && item?.service === app?.service
|
||||
);
|
||||
const setSettingsLocalLastUpdated = useSetRecoilState(
|
||||
settingsLocalLastUpdatedAtom
|
||||
);
|
||||
|
||||
return (
|
||||
<AppsLibraryContainer
|
||||
sx={{
|
||||
height: !isMobile && "100%",
|
||||
justifyContent: !isMobile && "flex-start",
|
||||
alignItems: isMobile && 'center'
|
||||
height: !isMobile && '100%',
|
||||
justifyContent: !isMobile && 'flex-start',
|
||||
alignItems: isMobile && 'center',
|
||||
}}
|
||||
>
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
maxWidth: "500px",
|
||||
width: '90%'
|
||||
}}>
|
||||
|
||||
|
||||
{!isMobile && <Spacer height="30px" />}
|
||||
<AppsWidthLimiter>
|
||||
<AppInfoSnippetContainer>
|
||||
<AppInfoSnippetLeft
|
||||
sx={{
|
||||
flexGrow: 1,
|
||||
gap: "18px",
|
||||
}}
|
||||
>
|
||||
<AppCircleContainer
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
maxWidth: '500px',
|
||||
width: '90%',
|
||||
}}
|
||||
>
|
||||
{!isMobile && <Spacer height="30px" />}
|
||||
<AppsWidthLimiter>
|
||||
<AppInfoSnippetContainer>
|
||||
<AppInfoSnippetLeft
|
||||
sx={{
|
||||
width: "auto",
|
||||
flexGrow: 1,
|
||||
gap: '18px',
|
||||
}}
|
||||
>
|
||||
<AppCircle
|
||||
<AppCircleContainer
|
||||
sx={{
|
||||
border: "none",
|
||||
height: "100px",
|
||||
width: "100px",
|
||||
width: 'auto',
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
<AppCircle
|
||||
sx={{
|
||||
height: "43px",
|
||||
width: "43px",
|
||||
"& img": {
|
||||
objectFit: "fill",
|
||||
},
|
||||
border: 'none',
|
||||
height: '100px',
|
||||
width: '100px',
|
||||
}}
|
||||
alt={app?.name}
|
||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
|
||||
app?.name
|
||||
}/qortal_avatar?async=true`}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
width: "43px",
|
||||
height: "auto",
|
||||
<Avatar
|
||||
sx={{
|
||||
height: '43px',
|
||||
width: '43px',
|
||||
'& img': {
|
||||
objectFit: 'fill',
|
||||
},
|
||||
}}
|
||||
src={LogoSelected}
|
||||
alt="center-icon"
|
||||
/>
|
||||
</Avatar>
|
||||
</AppCircle>
|
||||
</AppCircleContainer>
|
||||
<AppInfoSnippetMiddle>
|
||||
<AppInfoAppName>
|
||||
{app?.metadata?.title || app?.name}
|
||||
</AppInfoAppName>
|
||||
<Spacer height="6px" />
|
||||
<AppInfoUserName>{app?.name}</AppInfoUserName>
|
||||
<Spacer height="3px" />
|
||||
</AppInfoSnippetMiddle>
|
||||
</AppInfoSnippetLeft>
|
||||
<AppInfoSnippetRight></AppInfoSnippetRight>
|
||||
</AppInfoSnippetContainer>
|
||||
<Spacer height="11px" />
|
||||
<Box sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '20px'
|
||||
}}>
|
||||
<AppDownloadButton
|
||||
onClick={() => {
|
||||
setSortablePinnedApps((prev) => {
|
||||
let updatedApps;
|
||||
|
||||
if (isSelectedAppPinned) {
|
||||
// Remove the selected app if it is pinned
|
||||
updatedApps = prev.filter(
|
||||
(item) => !(item?.name === app?.name && item?.service === app?.service)
|
||||
alt={app?.name}
|
||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/${
|
||||
app?.name
|
||||
}/qortal_avatar?async=true`}
|
||||
>
|
||||
<img
|
||||
style={{
|
||||
width: '43px',
|
||||
height: 'auto',
|
||||
}}
|
||||
src={LogoSelected}
|
||||
alt="center-icon"
|
||||
/>
|
||||
</Avatar>
|
||||
</AppCircle>
|
||||
</AppCircleContainer>
|
||||
<AppInfoSnippetMiddle>
|
||||
<AppInfoAppName>
|
||||
{app?.metadata?.title || app?.name}
|
||||
</AppInfoAppName>
|
||||
<Spacer height="6px" />
|
||||
<AppInfoUserName>{app?.name}</AppInfoUserName>
|
||||
<Spacer height="3px" />
|
||||
</AppInfoSnippetMiddle>
|
||||
</AppInfoSnippetLeft>
|
||||
<AppInfoSnippetRight></AppInfoSnippetRight>
|
||||
</AppInfoSnippetContainer>
|
||||
<Spacer height="11px" />
|
||||
<Box
|
||||
sx={{
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: '20px',
|
||||
}}
|
||||
>
|
||||
<AppDownloadButton
|
||||
onClick={() => {
|
||||
setSortablePinnedApps((prev) => {
|
||||
let updatedApps;
|
||||
|
||||
if (isSelectedAppPinned) {
|
||||
// Remove the selected app if it is pinned
|
||||
updatedApps = prev.filter(
|
||||
(item) =>
|
||||
!(
|
||||
item?.name === app?.name &&
|
||||
item?.service === app?.service
|
||||
)
|
||||
);
|
||||
} else {
|
||||
// Add the selected app if it is not pinned
|
||||
updatedApps = [
|
||||
...prev,
|
||||
{
|
||||
name: app?.name,
|
||||
service: app?.service,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
saveToLocalStorage(
|
||||
'ext_saved_settings',
|
||||
'sortablePinnedApps',
|
||||
updatedApps
|
||||
);
|
||||
} else {
|
||||
// Add the selected app if it is not pinned
|
||||
updatedApps = [...prev, {
|
||||
name: app?.name,
|
||||
service: app?.service,
|
||||
}];
|
||||
}
|
||||
|
||||
saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', updatedApps)
|
||||
return updatedApps;
|
||||
});
|
||||
setSettingsLocalLastUpdated(Date.now())
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: "#359ff7ff",
|
||||
width: "100%",
|
||||
maxWidth: "320px",
|
||||
height: "29px",
|
||||
opacity: isSelectedAppPinned ? 0.6 : 1
|
||||
}}
|
||||
>
|
||||
<AppDownloadButtonText>
|
||||
{!isMobile ? (
|
||||
<>
|
||||
{isSelectedAppPinned ? 'Unpin from dashboard' : 'Pin to dashboard'}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
{isSelectedAppPinned ? 'Unpin' : 'Pin'}
|
||||
</>
|
||||
)}
|
||||
|
||||
</AppDownloadButtonText>
|
||||
</AppDownloadButton>
|
||||
<AppDownloadButton
|
||||
onClick={() => {
|
||||
executeEvent("addTab", {
|
||||
data: app,
|
||||
});
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: isInstalled ? "#0091E1" : "#247C0E",
|
||||
width: "100%",
|
||||
maxWidth: "320px",
|
||||
height: "29px",
|
||||
}}
|
||||
>
|
||||
<AppDownloadButtonText>
|
||||
{isInstalled ? "Open" : "Download"}
|
||||
</AppDownloadButtonText>
|
||||
</AppDownloadButton>
|
||||
</Box>
|
||||
|
||||
</AppsWidthLimiter>
|
||||
<Spacer height="20px" />
|
||||
<AppsWidthLimiter>
|
||||
<AppsCategoryInfo>
|
||||
<AppRating ratingCountPosition="top" myName={myName} app={app} />
|
||||
<Spacer width="16px" />
|
||||
<Spacer height="40px" width="1px" backgroundColor="white" />
|
||||
<Spacer width="16px" />
|
||||
<AppsCategoryInfoSub>
|
||||
<AppsCategoryInfoLabel>Category:</AppsCategoryInfoLabel>
|
||||
<Spacer height="4px" />
|
||||
<AppsCategoryInfoValue>
|
||||
{app?.metadata?.categoryName || "none"}
|
||||
</AppsCategoryInfoValue>
|
||||
</AppsCategoryInfoSub>
|
||||
</AppsCategoryInfo>
|
||||
<Spacer height="30px" />
|
||||
<AppInfoAppName>About this Q-App</AppInfoAppName>
|
||||
</AppsWidthLimiter>
|
||||
<Spacer height="20px" />
|
||||
<AppsInfoDescription>
|
||||
{app?.metadata?.description || "No description"}
|
||||
</AppsInfoDescription>
|
||||
return updatedApps;
|
||||
});
|
||||
setSettingsLocalLastUpdated(Date.now());
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: '#359ff7ff',
|
||||
width: '100%',
|
||||
maxWidth: '320px',
|
||||
height: '29px',
|
||||
opacity: isSelectedAppPinned ? 0.6 : 1,
|
||||
}}
|
||||
>
|
||||
<AppDownloadButtonText>
|
||||
{!isMobile ? (
|
||||
<>
|
||||
{isSelectedAppPinned
|
||||
? 'Unpin from dashboard'
|
||||
: 'Pin to dashboard'}
|
||||
</>
|
||||
) : (
|
||||
<>{isSelectedAppPinned ? 'Unpin' : 'Pin'}</>
|
||||
)}
|
||||
</AppDownloadButtonText>
|
||||
</AppDownloadButton>
|
||||
<AppDownloadButton
|
||||
onClick={() => {
|
||||
executeEvent('addTab', {
|
||||
data: app,
|
||||
});
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: isInstalled ? '#0091E1' : '#247C0E',
|
||||
width: '100%',
|
||||
maxWidth: '320px',
|
||||
height: '29px',
|
||||
}}
|
||||
>
|
||||
<AppDownloadButtonText>
|
||||
{isInstalled ? 'Open' : 'Download'}
|
||||
</AppDownloadButtonText>
|
||||
</AppDownloadButton>
|
||||
</Box>
|
||||
</AppsWidthLimiter>
|
||||
<Spacer height="20px" />
|
||||
<AppsWidthLimiter>
|
||||
<AppsCategoryInfo>
|
||||
<AppRating ratingCountPosition="top" myName={myName} app={app} />
|
||||
<Spacer width="16px" />
|
||||
<Spacer height="40px" width="1px" backgroundColor="white" />
|
||||
<Spacer width="16px" />
|
||||
<AppsCategoryInfoSub>
|
||||
<AppsCategoryInfoLabel>Category:</AppsCategoryInfoLabel>
|
||||
<Spacer height="4px" />
|
||||
<AppsCategoryInfoValue>
|
||||
{app?.metadata?.categoryName || 'none'}
|
||||
</AppsCategoryInfoValue>
|
||||
</AppsCategoryInfoSub>
|
||||
</AppsCategoryInfo>
|
||||
<Spacer height="30px" />
|
||||
<AppInfoAppName>About this Q-App</AppInfoAppName>
|
||||
</AppsWidthLimiter>
|
||||
<Spacer height="20px" />
|
||||
<AppsInfoDescription>
|
||||
{app?.metadata?.description || 'No description'}
|
||||
</AppsInfoDescription>
|
||||
</Box>
|
||||
</AppsLibraryContainer>
|
||||
);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
import {
|
||||
AppCircle,
|
||||
AppCircleContainer,
|
||||
@ -10,148 +10,180 @@ import {
|
||||
AppInfoSnippetMiddle,
|
||||
AppInfoSnippetRight,
|
||||
AppInfoUserName,
|
||||
} from "./Apps-styles";
|
||||
import { Avatar, ButtonBase } from "@mui/material";
|
||||
import { getBaseApiReact, isMobile } from "../../App";
|
||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||
} from './Apps-styles';
|
||||
import { Avatar, ButtonBase } from '@mui/material';
|
||||
import { getBaseApiReact, isMobile } from '../../App';
|
||||
import LogoSelected from '../../assets/svgs/LogoSelected.svg';
|
||||
|
||||
import { Spacer } from "../../common/Spacer";
|
||||
import { executeEvent } from "../../utils/events";
|
||||
import { AppRating } from "./AppRating";
|
||||
import { useRecoilState, useSetRecoilState } from "recoil";
|
||||
import { settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom } from "../../atoms/global";
|
||||
import { saveToLocalStorage } from "./AppsNavBar";
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { AppRating } from './AppRating';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
import {
|
||||
settingsLocalLastUpdatedAtom,
|
||||
sortablePinnedAppsAtom,
|
||||
} from '../../atoms/global';
|
||||
import { saveToLocalStorage } from './AppsNavBarDesktop';
|
||||
|
||||
export const AppInfoSnippet = ({ app, myName, isFromCategory, parentStyles = {} }) => {
|
||||
export const AppInfoSnippet = ({
|
||||
app,
|
||||
myName,
|
||||
isFromCategory,
|
||||
parentStyles = {},
|
||||
}) => {
|
||||
const isInstalled = app?.status?.status === 'READY';
|
||||
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(
|
||||
sortablePinnedAppsAtom
|
||||
);
|
||||
|
||||
const isInstalled = app?.status?.status === 'READY'
|
||||
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
||||
|
||||
const isSelectedAppPinned = !!sortablePinnedApps?.find((item)=> item?.name === app?.name && item?.service === app?.service)
|
||||
const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom);
|
||||
const isSelectedAppPinned = !!sortablePinnedApps?.find(
|
||||
(item) => item?.name === app?.name && item?.service === app?.service
|
||||
);
|
||||
const setSettingsLocalLastUpdated = useSetRecoilState(
|
||||
settingsLocalLastUpdatedAtom
|
||||
);
|
||||
return (
|
||||
<AppInfoSnippetContainer sx={{
|
||||
...parentStyles
|
||||
}}>
|
||||
<AppInfoSnippetContainer
|
||||
sx={{
|
||||
...parentStyles,
|
||||
}}
|
||||
>
|
||||
<AppInfoSnippetLeft>
|
||||
<ButtonBase
|
||||
sx={{
|
||||
height: "80px",
|
||||
width: "60px",
|
||||
}}
|
||||
onClick={()=> {
|
||||
if(isFromCategory){
|
||||
executeEvent("selectedAppInfoCategory", {
|
||||
<ButtonBase
|
||||
sx={{
|
||||
height: '80px',
|
||||
width: '60px',
|
||||
}}
|
||||
onClick={() => {
|
||||
if (isFromCategory) {
|
||||
executeEvent('selectedAppInfoCategory', {
|
||||
data: app,
|
||||
});
|
||||
return;
|
||||
}
|
||||
executeEvent('selectedAppInfo', {
|
||||
data: app,
|
||||
});
|
||||
return
|
||||
}
|
||||
executeEvent("selectedAppInfo", {
|
||||
data: app,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<AppCircleContainer>
|
||||
<AppCircle
|
||||
sx={{
|
||||
border: "none",
|
||||
}}
|
||||
>
|
||||
<AppCircleContainer>
|
||||
<AppCircle
|
||||
sx={{
|
||||
border: 'none',
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
sx={{
|
||||
height: '42px',
|
||||
width: '42px',
|
||||
'& img': {
|
||||
objectFit: 'fill',
|
||||
},
|
||||
}}
|
||||
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>
|
||||
</AppCircle>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
<AppInfoSnippetMiddle>
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
if (isFromCategory) {
|
||||
executeEvent('selectedAppInfoCategory', {
|
||||
data: app,
|
||||
});
|
||||
return;
|
||||
}
|
||||
executeEvent('selectedAppInfo', {
|
||||
data: app,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Avatar
|
||||
sx={{
|
||||
height: "42px",
|
||||
width: "42px",
|
||||
'& img': {
|
||||
objectFit: 'fill',
|
||||
}
|
||||
}}
|
||||
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>
|
||||
</AppCircle>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
<AppInfoSnippetMiddle>
|
||||
|
||||
<ButtonBase onClick={()=> {
|
||||
if(isFromCategory){
|
||||
executeEvent("selectedAppInfoCategory", {
|
||||
data: app,
|
||||
});
|
||||
return
|
||||
}
|
||||
executeEvent("selectedAppInfo", {
|
||||
data: app,
|
||||
});
|
||||
}}>
|
||||
<AppInfoAppName >
|
||||
{app?.metadata?.title || app?.name}
|
||||
</AppInfoAppName>
|
||||
</ButtonBase>
|
||||
<Spacer height="6px" />
|
||||
<AppInfoUserName>
|
||||
{ app?.name}
|
||||
</AppInfoUserName>
|
||||
<AppInfoAppName>{app?.metadata?.title || app?.name}</AppInfoAppName>
|
||||
</ButtonBase>
|
||||
<Spacer height="6px" />
|
||||
<AppInfoUserName>{app?.name}</AppInfoUserName>
|
||||
<Spacer height="3px" />
|
||||
<AppRating app={app} myName={myName} />
|
||||
</AppInfoSnippetMiddle>
|
||||
</AppInfoSnippetMiddle>
|
||||
</AppInfoSnippetLeft>
|
||||
<AppInfoSnippetRight sx={{
|
||||
gap: '10px'
|
||||
}}>
|
||||
<AppInfoSnippetRight
|
||||
sx={{
|
||||
gap: '10px',
|
||||
}}
|
||||
>
|
||||
{!isMobile && (
|
||||
<AppDownloadButton onClick={()=> {
|
||||
|
||||
setSortablePinnedApps((prev) => {
|
||||
let updatedApps;
|
||||
|
||||
if (isSelectedAppPinned) {
|
||||
// Remove the selected app if it is pinned
|
||||
updatedApps = prev.filter(
|
||||
(item) => !(item?.name === app?.name && item?.service === app?.service)
|
||||
);
|
||||
} else {
|
||||
// Add the selected app if it is not pinned
|
||||
updatedApps = [...prev, {
|
||||
name: app?.name,
|
||||
service: app?.service,
|
||||
}];
|
||||
}
|
||||
|
||||
saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', updatedApps)
|
||||
return updatedApps;
|
||||
});
|
||||
setSettingsLocalLastUpdated(Date.now())
|
||||
}} sx={{
|
||||
backgroundColor: '#359ff7ff',
|
||||
opacity: isSelectedAppPinned ? 0.6 : 1
|
||||
|
||||
}}>
|
||||
<AppDownloadButtonText> {isSelectedAppPinned ? 'Unpin' : 'Pin'}</AppDownloadButtonText>
|
||||
</AppDownloadButton>
|
||||
)}
|
||||
|
||||
<AppDownloadButton onClick={()=> {
|
||||
|
||||
executeEvent("addTab", {
|
||||
data: app
|
||||
})
|
||||
}} sx={{
|
||||
backgroundColor: isInstalled ? '#0091E1' : '#247C0E',
|
||||
|
||||
}}>
|
||||
<AppDownloadButtonText>{isInstalled ? 'Open' : 'Download'}</AppDownloadButtonText>
|
||||
<AppDownloadButton
|
||||
onClick={() => {
|
||||
setSortablePinnedApps((prev) => {
|
||||
let updatedApps;
|
||||
|
||||
if (isSelectedAppPinned) {
|
||||
// Remove the selected app if it is pinned
|
||||
updatedApps = prev.filter(
|
||||
(item) =>
|
||||
!(
|
||||
item?.name === app?.name &&
|
||||
item?.service === app?.service
|
||||
)
|
||||
);
|
||||
} else {
|
||||
// Add the selected app if it is not pinned
|
||||
updatedApps = [
|
||||
...prev,
|
||||
{
|
||||
name: app?.name,
|
||||
service: app?.service,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
saveToLocalStorage(
|
||||
'ext_saved_settings',
|
||||
'sortablePinnedApps',
|
||||
updatedApps
|
||||
);
|
||||
return updatedApps;
|
||||
});
|
||||
setSettingsLocalLastUpdated(Date.now());
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: '#359ff7ff',
|
||||
opacity: isSelectedAppPinned ? 0.6 : 1,
|
||||
}}
|
||||
>
|
||||
<AppDownloadButtonText>
|
||||
{' '}
|
||||
{isSelectedAppPinned ? 'Unpin' : 'Pin'}
|
||||
</AppDownloadButtonText>
|
||||
</AppDownloadButton>
|
||||
)}
|
||||
|
||||
<AppDownloadButton
|
||||
onClick={() => {
|
||||
executeEvent('addTab', {
|
||||
data: app,
|
||||
});
|
||||
}}
|
||||
sx={{
|
||||
backgroundColor: isInstalled ? '#0091E1' : '#247C0E',
|
||||
}}
|
||||
>
|
||||
<AppDownloadButtonText>
|
||||
{isInstalled ? 'Open' : 'Download'}
|
||||
</AppDownloadButtonText>
|
||||
</AppDownloadButton>
|
||||
</AppInfoSnippetRight>
|
||||
</AppInfoSnippetContainer>
|
||||
|
@ -23,7 +23,7 @@ import {
|
||||
sortablePinnedAppsAtom,
|
||||
} from '../../atoms/global';
|
||||
import { useRecoilState, useSetRecoilState } from 'recoil';
|
||||
import { saveToLocalStorage } from './AppsNavBar';
|
||||
import { saveToLocalStorage } from './AppsNavBarDesktop';
|
||||
import { ContextMenuPinnedApps } from '../ContextMenuPinnedApps';
|
||||
import LockIcon from '@mui/icons-material/Lock';
|
||||
import { useHandlePrivateApps } from './useHandlePrivateApps';
|
||||
|
@ -1,152 +1,182 @@
|
||||
import React, { useState, useRef } from 'react';
|
||||
import { ListItemIcon, Menu, MenuItem, Typography, styled } from '@mui/material';
|
||||
import {
|
||||
ListItemIcon,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Typography,
|
||||
styled,
|
||||
} from '@mui/material';
|
||||
import PushPinIcon from '@mui/icons-material/PushPin';
|
||||
import { saveToLocalStorage } from './Apps/AppsNavBar';
|
||||
import { saveToLocalStorage } from './Apps/AppsNavBarDesktop';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { sortablePinnedAppsAtom } from '../atoms/global';
|
||||
|
||||
const CustomStyledMenu = styled(Menu)(({ theme }) => ({
|
||||
'& .MuiPaper-root': {
|
||||
backgroundColor: '#f9f9f9',
|
||||
borderRadius: '12px',
|
||||
padding: theme.spacing(1),
|
||||
boxShadow: '0 5px 15px rgba(0, 0, 0, 0.2)',
|
||||
},
|
||||
'& .MuiMenuItem-root': {
|
||||
fontSize: '14px',
|
||||
color: '#444',
|
||||
transition: '0.3s background-color',
|
||||
'&:hover': {
|
||||
backgroundColor: '#f0f0f0',
|
||||
},
|
||||
'& .MuiPaper-root': {
|
||||
backgroundColor: '#f9f9f9',
|
||||
borderRadius: '12px',
|
||||
padding: theme.spacing(1),
|
||||
boxShadow: '0 5px 15px rgba(0, 0, 0, 0.2)',
|
||||
},
|
||||
'& .MuiMenuItem-root': {
|
||||
fontSize: '14px',
|
||||
color: '#444',
|
||||
transition: '0.3s background-color',
|
||||
'&:hover': {
|
||||
backgroundColor: '#f0f0f0',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export const ContextMenuPinnedApps = ({ children, app, isMine }) => {
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const longPressTimeout = useRef(null);
|
||||
const maxHoldTimeout = useRef(null);
|
||||
const preventClick = useRef(false);
|
||||
const startTouchPosition = useRef({ x: 0, y: 0 }); // Track initial touch position
|
||||
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const longPressTimeout = useRef(null);
|
||||
const maxHoldTimeout = useRef(null);
|
||||
const preventClick = useRef(false);
|
||||
const startTouchPosition = useRef({ x: 0, y: 0 }); // Track initial touch position
|
||||
const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(
|
||||
sortablePinnedAppsAtom
|
||||
);
|
||||
|
||||
const handleContextMenu = (event) => {
|
||||
if(isMine) return
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
preventClick.current = true;
|
||||
setMenuPosition({
|
||||
mouseX: event.clientX,
|
||||
mouseY: event.clientY,
|
||||
});
|
||||
};
|
||||
const handleContextMenu = (event) => {
|
||||
if (isMine) return;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
preventClick.current = true;
|
||||
setMenuPosition({
|
||||
mouseX: event.clientX,
|
||||
mouseY: event.clientY,
|
||||
});
|
||||
};
|
||||
|
||||
const handleTouchStart = (event) => {
|
||||
if(isMine) return
|
||||
const handleTouchStart = (event) => {
|
||||
if (isMine) return;
|
||||
|
||||
const { clientX, clientY } = event.touches[0];
|
||||
startTouchPosition.current = { x: clientX, y: clientY };
|
||||
const { clientX, clientY } = event.touches[0];
|
||||
startTouchPosition.current = { x: clientX, y: clientY };
|
||||
|
||||
longPressTimeout.current = setTimeout(() => {
|
||||
preventClick.current = true;
|
||||
|
||||
event.stopPropagation();
|
||||
setMenuPosition({
|
||||
mouseX: clientX,
|
||||
mouseY: clientY,
|
||||
longPressTimeout.current = setTimeout(() => {
|
||||
preventClick.current = true;
|
||||
|
||||
event.stopPropagation();
|
||||
setMenuPosition({
|
||||
mouseX: clientX,
|
||||
mouseY: clientY,
|
||||
});
|
||||
}, 500);
|
||||
|
||||
// Set a maximum hold duration (e.g., 1.5 seconds)
|
||||
maxHoldTimeout.current = setTimeout(() => {
|
||||
clearTimeout(longPressTimeout.current);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
const handleTouchMove = (event) => {
|
||||
if (isMine) return;
|
||||
|
||||
const { clientX, clientY } = event.touches[0];
|
||||
const { x, y } = startTouchPosition.current;
|
||||
|
||||
// Determine if the touch has moved beyond a small threshold (e.g., 10px)
|
||||
const movedEnough =
|
||||
Math.abs(clientX - x) > 10 || Math.abs(clientY - y) > 10;
|
||||
|
||||
if (movedEnough) {
|
||||
clearTimeout(longPressTimeout.current);
|
||||
clearTimeout(maxHoldTimeout.current);
|
||||
}
|
||||
};
|
||||
|
||||
const handleTouchEnd = (event) => {
|
||||
if (isMine) return;
|
||||
|
||||
clearTimeout(longPressTimeout.current);
|
||||
clearTimeout(maxHoldTimeout.current);
|
||||
if (preventClick.current) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
preventClick.current = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = (e) => {
|
||||
if (isMine) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setMenuPosition(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onContextMenu={handleContextMenu}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchMove={handleTouchMove}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
style={{ touchAction: 'none' }}
|
||||
>
|
||||
{children}
|
||||
<CustomStyledMenu
|
||||
disableAutoFocusItem
|
||||
open={!!menuPosition}
|
||||
onClose={handleClose}
|
||||
anchorReference="anchorPosition"
|
||||
anchorPosition={
|
||||
menuPosition
|
||||
? { top: menuPosition.mouseY, left: menuPosition.mouseX }
|
||||
: undefined
|
||||
}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MenuItem
|
||||
onClick={(e) => {
|
||||
handleClose(e);
|
||||
setSortablePinnedApps((prev) => {
|
||||
if (app?.isPrivate) {
|
||||
const updatedApps = prev.filter(
|
||||
(item) =>
|
||||
!(
|
||||
item?.privateAppProperties?.name ===
|
||||
app?.privateAppProperties?.name &&
|
||||
item?.privateAppProperties?.service ===
|
||||
app?.privateAppProperties?.service &&
|
||||
item?.privateAppProperties?.identifier ===
|
||||
app?.privateAppProperties?.identifier
|
||||
)
|
||||
);
|
||||
saveToLocalStorage(
|
||||
'ext_saved_settings',
|
||||
'sortablePinnedApps',
|
||||
updatedApps
|
||||
);
|
||||
return updatedApps;
|
||||
} else {
|
||||
const updatedApps = prev.filter(
|
||||
(item) =>
|
||||
!(
|
||||
item?.name === app?.name && item?.service === app?.service
|
||||
)
|
||||
);
|
||||
saveToLocalStorage(
|
||||
'ext_saved_settings',
|
||||
'sortablePinnedApps',
|
||||
updatedApps
|
||||
);
|
||||
return updatedApps;
|
||||
}
|
||||
});
|
||||
}, 500);
|
||||
|
||||
// Set a maximum hold duration (e.g., 1.5 seconds)
|
||||
maxHoldTimeout.current = setTimeout(() => {
|
||||
clearTimeout(longPressTimeout.current);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
const handleTouchMove = (event) => {
|
||||
if(isMine) return
|
||||
|
||||
const { clientX, clientY } = event.touches[0];
|
||||
const { x, y } = startTouchPosition.current;
|
||||
|
||||
// Determine if the touch has moved beyond a small threshold (e.g., 10px)
|
||||
const movedEnough = Math.abs(clientX - x) > 10 || Math.abs(clientY - y) > 10;
|
||||
|
||||
if (movedEnough) {
|
||||
clearTimeout(longPressTimeout.current);
|
||||
clearTimeout(maxHoldTimeout.current);
|
||||
}
|
||||
};
|
||||
|
||||
const handleTouchEnd = (event) => {
|
||||
if(isMine) return
|
||||
|
||||
clearTimeout(longPressTimeout.current);
|
||||
clearTimeout(maxHoldTimeout.current);
|
||||
if (preventClick.current) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
preventClick.current = false;
|
||||
}
|
||||
};
|
||||
|
||||
const handleClose = (e) => {
|
||||
if(isMine) return
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
setMenuPosition(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
onContextMenu={handleContextMenu}
|
||||
onTouchStart={handleTouchStart}
|
||||
onTouchMove={handleTouchMove}
|
||||
onTouchEnd={handleTouchEnd}
|
||||
style={{ touchAction: 'none' }}
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
<CustomStyledMenu
|
||||
disableAutoFocusItem
|
||||
open={!!menuPosition}
|
||||
onClose={handleClose}
|
||||
anchorReference="anchorPosition"
|
||||
anchorPosition={
|
||||
menuPosition
|
||||
? { top: menuPosition.mouseY, left: menuPosition.mouseX }
|
||||
: undefined
|
||||
}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<MenuItem onClick={(e) => {
|
||||
handleClose(e);
|
||||
setSortablePinnedApps((prev) => {
|
||||
if(app?.isPrivate){
|
||||
const updatedApps = prev.filter(
|
||||
(item) => !(item?.privateAppProperties?.name === app?.privateAppProperties?.name && item?.privateAppProperties?.service === app?.privateAppProperties?.service && item?.privateAppProperties?.identifier === app?.privateAppProperties?.identifier)
|
||||
);
|
||||
saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', updatedApps);
|
||||
return updatedApps;
|
||||
} else {
|
||||
const updatedApps = prev.filter(
|
||||
(item) => !(item?.name === app?.name && item?.service === app?.service)
|
||||
);
|
||||
saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', updatedApps);
|
||||
return updatedApps;
|
||||
}
|
||||
});
|
||||
}}>
|
||||
<ListItemIcon sx={{ minWidth: '32px' }}>
|
||||
<PushPinIcon fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<Typography variant="inherit" sx={{ fontSize: '14px' }}>
|
||||
Unpin app
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
</CustomStyledMenu>
|
||||
</div>
|
||||
);
|
||||
<ListItemIcon sx={{ minWidth: '32px' }}>
|
||||
<PushPinIcon fontSize="small" />
|
||||
</ListItemIcon>
|
||||
<Typography variant="inherit" sx={{ fontSize: '14px' }}>
|
||||
Unpin app
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
</CustomStyledMenu>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -19,7 +19,7 @@ import { SaveIcon } from '../../assets/Icons/SaveIcon';
|
||||
import { IconWrapper } from '../Desktop/DesktopFooter';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { LoadingButton } from '@mui/lab';
|
||||
import { saveToLocalStorage } from '../Apps/AppsNavBar';
|
||||
import { saveToLocalStorage } from '../Apps/AppsNavBarDesktop';
|
||||
import { decryptData, encryptData } from '../../qortalRequests/get';
|
||||
import { saveFileToDiskGeneric } from '../../utils/generateWallet/generateWallet';
|
||||
import {
|
||||
|
@ -1,192 +1,194 @@
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
import { saveToLocalStorage } from "../Apps/AppsNavBar";
|
||||
import creationImg from './img/creation.webp'
|
||||
import dashboardImg from './img/dashboard.webp'
|
||||
import groupsImg from './img/groups.webp'
|
||||
import importantImg from './img/important.webp'
|
||||
import navigationImg from './img/navigation.webp'
|
||||
import overviewImg from './img/overview.webp'
|
||||
import startedImg from './img/started.webp'
|
||||
import obtainingImg from './img/obtaining-qort.jpg'
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { saveToLocalStorage } from '../Apps/AppsNavBarDesktop';
|
||||
import creationImg from './img/creation.webp';
|
||||
import dashboardImg from './img/dashboard.webp';
|
||||
import groupsImg from './img/groups.webp';
|
||||
import importantImg from './img/important.webp';
|
||||
import navigationImg from './img/navigation.webp';
|
||||
import overviewImg from './img/overview.webp';
|
||||
import startedImg from './img/started.webp';
|
||||
import obtainingImg from './img/obtaining-qort.jpg';
|
||||
|
||||
const checkIfGatewayIsOnline = async () => {
|
||||
try {
|
||||
const url = `https://ext-node.qortal.link/admin/status`;
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data?.height) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
} catch (error) {
|
||||
return false
|
||||
|
||||
}
|
||||
try {
|
||||
const url = `https://ext-node.qortal.link/admin/status`;
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data?.height) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
export const useHandleTutorials = () => {
|
||||
const [openTutorialModal, setOpenTutorialModal] = useState<any>(null);
|
||||
const [shownTutorials, setShowTutorials] = useState(null)
|
||||
const [shownTutorials, setShowTutorials] = useState(null);
|
||||
|
||||
useEffect(()=> {
|
||||
useEffect(() => {
|
||||
try {
|
||||
const storedData = localStorage.getItem('shown-tutorials');
|
||||
const storedData = localStorage.getItem('shown-tutorials');
|
||||
|
||||
|
||||
if (storedData) {
|
||||
setShowTutorials(JSON.parse(storedData));
|
||||
} else {
|
||||
setShowTutorials({})
|
||||
}
|
||||
if (storedData) {
|
||||
setShowTutorials(JSON.parse(storedData));
|
||||
} else {
|
||||
setShowTutorials({});
|
||||
}
|
||||
} catch (error) {
|
||||
//error
|
||||
//error
|
||||
}
|
||||
}, [])
|
||||
}, []);
|
||||
|
||||
const saveShowTutorial = useCallback((type)=> {
|
||||
const saveShowTutorial = useCallback((type) => {
|
||||
try {
|
||||
|
||||
setShowTutorials((prev)=> {
|
||||
return {
|
||||
...(prev || {}),
|
||||
[type]: true
|
||||
}
|
||||
})
|
||||
saveToLocalStorage('shown-tutorials', type, true)
|
||||
setShowTutorials((prev) => {
|
||||
return {
|
||||
...(prev || {}),
|
||||
[type]: true,
|
||||
};
|
||||
});
|
||||
saveToLocalStorage('shown-tutorials', type, true);
|
||||
} catch (error) {
|
||||
//error
|
||||
//error
|
||||
}
|
||||
}, [])
|
||||
const showTutorial = useCallback(async (type, isForce) => {
|
||||
try {
|
||||
const isOnline = await checkIfGatewayIsOnline()
|
||||
if(!isOnline) return
|
||||
}, []);
|
||||
const showTutorial = useCallback(
|
||||
async (type, isForce) => {
|
||||
try {
|
||||
const isOnline = await checkIfGatewayIsOnline();
|
||||
if (!isOnline) return;
|
||||
switch (type) {
|
||||
case "create-account":
|
||||
{
|
||||
if((shownTutorials || {})['create-account'] && !isForce) return
|
||||
saveShowTutorial('create-account')
|
||||
setOpenTutorialModal({
|
||||
title: "Account Creation",
|
||||
resource: {
|
||||
name: "a-test",
|
||||
service: "VIDEO",
|
||||
identifier: "account-creation-hub",
|
||||
poster: creationImg
|
||||
},
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "important-information":
|
||||
{
|
||||
if((shownTutorials || {})['important-information'] && !isForce) return
|
||||
saveShowTutorial('important-information')
|
||||
case 'create-account':
|
||||
{
|
||||
if ((shownTutorials || {})['create-account'] && !isForce) return;
|
||||
saveShowTutorial('create-account');
|
||||
setOpenTutorialModal({
|
||||
title: 'Account Creation',
|
||||
resource: {
|
||||
name: 'a-test',
|
||||
service: 'VIDEO',
|
||||
identifier: 'account-creation-hub',
|
||||
poster: creationImg,
|
||||
},
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'important-information':
|
||||
{
|
||||
if ((shownTutorials || {})['important-information'] && !isForce)
|
||||
return;
|
||||
saveShowTutorial('important-information');
|
||||
|
||||
setOpenTutorialModal({
|
||||
title: "Important Information!",
|
||||
resource: {
|
||||
name: "a-test",
|
||||
service: "VIDEO",
|
||||
identifier: "important-information-hub",
|
||||
poster: importantImg
|
||||
},
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "getting-started":
|
||||
{
|
||||
if((shownTutorials || {})['getting-started'] && !isForce) return
|
||||
saveShowTutorial('getting-started')
|
||||
setOpenTutorialModal({
|
||||
title: 'Important Information!',
|
||||
resource: {
|
||||
name: 'a-test',
|
||||
service: 'VIDEO',
|
||||
identifier: 'important-information-hub',
|
||||
poster: importantImg,
|
||||
},
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'getting-started':
|
||||
{
|
||||
if ((shownTutorials || {})['getting-started'] && !isForce) return;
|
||||
saveShowTutorial('getting-started');
|
||||
|
||||
setOpenTutorialModal({
|
||||
multi: [
|
||||
|
||||
{
|
||||
title: "1. Getting Started",
|
||||
resource: {
|
||||
name: "a-test",
|
||||
service: "VIDEO",
|
||||
identifier: "getting-started-hub",
|
||||
poster: startedImg
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "2. Overview",
|
||||
resource: {
|
||||
name: "a-test",
|
||||
service: "VIDEO",
|
||||
identifier: "overview-hub",
|
||||
poster: overviewImg
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "3. Qortal Groups",
|
||||
resource: {
|
||||
name: "a-test",
|
||||
service: "VIDEO",
|
||||
identifier: "groups-hub",
|
||||
poster: groupsImg
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "4. Obtaining Qort",
|
||||
resource: {
|
||||
name: "a-test",
|
||||
service: "VIDEO",
|
||||
identifier: "obtaining-qort",
|
||||
poster: obtainingImg
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
break;
|
||||
case "qapps":
|
||||
setOpenTutorialModal({
|
||||
multi: [
|
||||
{
|
||||
if((shownTutorials || {})['qapps'] && !isForce) return
|
||||
saveShowTutorial('qapps')
|
||||
title: '1. Getting Started',
|
||||
resource: {
|
||||
name: 'a-test',
|
||||
service: 'VIDEO',
|
||||
identifier: 'getting-started-hub',
|
||||
poster: startedImg,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '2. Overview',
|
||||
resource: {
|
||||
name: 'a-test',
|
||||
service: 'VIDEO',
|
||||
identifier: 'overview-hub',
|
||||
poster: overviewImg,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '3. Qortal Groups',
|
||||
resource: {
|
||||
name: 'a-test',
|
||||
service: 'VIDEO',
|
||||
identifier: 'groups-hub',
|
||||
poster: groupsImg,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '4. Obtaining Qort',
|
||||
resource: {
|
||||
name: 'a-test',
|
||||
service: 'VIDEO',
|
||||
identifier: 'obtaining-qort',
|
||||
poster: obtainingImg,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'qapps':
|
||||
{
|
||||
if ((shownTutorials || {})['qapps'] && !isForce) return;
|
||||
saveShowTutorial('qapps');
|
||||
|
||||
setOpenTutorialModal({
|
||||
multi: [
|
||||
{
|
||||
title: "1. Apps Dashboard",
|
||||
resource: {
|
||||
name: "a-test",
|
||||
service: "VIDEO",
|
||||
identifier: "apps-dashboard-hub",
|
||||
poster: dashboardImg
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "2. Apps Navigation",
|
||||
resource: {
|
||||
name: "a-test",
|
||||
service: "VIDEO",
|
||||
identifier: "apps-navigation-hub",
|
||||
poster: navigationImg
|
||||
},
|
||||
}
|
||||
],
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
setOpenTutorialModal({
|
||||
multi: [
|
||||
{
|
||||
title: '1. Apps Dashboard',
|
||||
resource: {
|
||||
name: 'a-test',
|
||||
service: 'VIDEO',
|
||||
identifier: 'apps-dashboard-hub',
|
||||
poster: dashboardImg,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '2. Apps Navigation',
|
||||
resource: {
|
||||
name: 'a-test',
|
||||
service: 'VIDEO',
|
||||
identifier: 'apps-navigation-hub',
|
||||
poster: navigationImg,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
//error
|
||||
}
|
||||
}, [shownTutorials]);
|
||||
}
|
||||
},
|
||||
[shownTutorials]
|
||||
);
|
||||
return {
|
||||
showTutorial,
|
||||
hasSeenGettingStarted: shownTutorials === null ? null : !!(shownTutorials || {})['getting-started'],
|
||||
hasSeenGettingStarted:
|
||||
shownTutorials === null
|
||||
? null
|
||||
: !!(shownTutorials || {})['getting-started'],
|
||||
openTutorialModal,
|
||||
setOpenTutorialModal,
|
||||
shownTutorialsInitiated: !!shownTutorials
|
||||
shownTutorialsInitiated: !!shownTutorials,
|
||||
};
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user