mirror of
https://github.com/Qortal/chrome-extension.git
synced 2025-02-11 17:55:49 +00:00
finished desktop view
This commit is contained in:
parent
6b3a1f51ba
commit
bec51a07bb
9
public/appsBg.svg
Normal file
9
public/appsBg.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 1.2 MiB |
19
src/App.tsx
19
src/App.tsx
@ -146,7 +146,7 @@ const defaultValues: MyContextInterface = {
|
|||||||
message: "",
|
message: "",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
export let isMobile = true;
|
export let isMobile = false;
|
||||||
|
|
||||||
const isMobileDevice = () => {
|
const isMobileDevice = () => {
|
||||||
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
const userAgent = navigator.userAgent || navigator.vendor || window.opera;
|
||||||
@ -240,7 +240,7 @@ export const getBaseApiReact = (customApi?: string) => {
|
|||||||
// };
|
// };
|
||||||
export const getArbitraryEndpointReact = () => {
|
export const getArbitraryEndpointReact = () => {
|
||||||
if (globalApiKey) {
|
if (globalApiKey) {
|
||||||
return `/arbitrary/resources/search`;
|
return `/arbitrary/resources/searchsimple`;
|
||||||
} else {
|
} else {
|
||||||
return `/arbitrary/resources/searchsimple`;
|
return `/arbitrary/resources/searchsimple`;
|
||||||
}
|
}
|
||||||
@ -259,6 +259,8 @@ export const getBaseApiReactSocket = (customApi?: string) => {
|
|||||||
export const isMainWindow = window?.location?.href?.includes("?main=true");
|
export const isMainWindow = window?.location?.href?.includes("?main=true");
|
||||||
function App() {
|
function App() {
|
||||||
const [extState, setExtstate] = useState<extStates>("not-authenticated");
|
const [extState, setExtstate] = useState<extStates>("not-authenticated");
|
||||||
|
const [desktopViewMode, setDesktopViewMode] = useState('home')
|
||||||
|
|
||||||
const [backupjson, setBackupjson] = useState<any>(null);
|
const [backupjson, setBackupjson] = useState<any>(null);
|
||||||
const [rawWallet, setRawWallet] = useState<any>(null);
|
const [rawWallet, setRawWallet] = useState<any>(null);
|
||||||
const [ltcBalanceLoading, setLtcBalanceLoading] = useState<boolean>(false);
|
const [ltcBalanceLoading, setLtcBalanceLoading] = useState<boolean>(false);
|
||||||
@ -1554,12 +1556,13 @@ function App() {
|
|||||||
<AppContainer
|
<AppContainer
|
||||||
sx={{
|
sx={{
|
||||||
height: isMobile ? "100%" : "100vh",
|
height: isMobile ? "100%" : "100vh",
|
||||||
|
backgroundImage: desktopViewMode === 'apps' && 'url("appsBg.svg")',
|
||||||
|
backgroundSize: desktopViewMode === 'apps' && 'cover',
|
||||||
|
backgroundPosition: desktopViewMode === 'apps' && 'center',
|
||||||
|
backgroundRepeat: desktopViewMode === 'apps' && 'no-repeat',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* {extState === 'group' && (
|
|
||||||
<Group myAddress={userInfo?.address} />
|
|
||||||
)} */}
|
|
||||||
|
|
||||||
{extState === "not-authenticated" && (
|
{extState === "not-authenticated" && (
|
||||||
<>
|
<>
|
||||||
<Spacer height="48px" />
|
<Spacer height="48px" />
|
||||||
@ -1780,8 +1783,10 @@ function App() {
|
|||||||
isMain={isMain}
|
isMain={isMain}
|
||||||
isOpenDrawerProfile={isOpenDrawerProfile}
|
isOpenDrawerProfile={isOpenDrawerProfile}
|
||||||
setIsOpenDrawerProfile={setIsOpenDrawerProfile}
|
setIsOpenDrawerProfile={setIsOpenDrawerProfile}
|
||||||
|
desktopViewMode={desktopViewMode}
|
||||||
|
setDesktopViewMode={setDesktopViewMode}
|
||||||
/>
|
/>
|
||||||
{!isMobile && renderProfile()}
|
{(!isMobile && desktopViewMode !== 'apps') && renderProfile()}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
|
11
src/assets/svgs/AppIcon.svg
Normal file
11
src/assets/svgs/AppIcon.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3.76596 7.53192C5.84584 7.53192 7.53192 5.84584 7.53192 3.76596C7.53192 1.68608 5.84584 0 3.76596 0C1.68608 0 0 1.68608 0 3.76596C0 5.84584 1.68608 7.53192 3.76596 7.53192Z" fill="#919193"/>
|
||||||
|
<path d="M15 7.53192C17.0799 7.53192 18.766 5.84584 18.766 3.76596C18.766 1.68608 17.0799 0 15 0C12.9201 0 11.2341 1.68608 11.2341 3.76596C11.2341 5.84584 12.9201 7.53192 15 7.53192Z" fill="#919193"/>
|
||||||
|
<path d="M26.234 7.53192C28.3139 7.53192 30 5.84584 30 3.76596C30 1.68608 28.3139 0 26.234 0C24.1542 0 22.4681 1.68608 22.4681 3.76596C22.4681 5.84584 24.1542 7.53192 26.234 7.53192Z" fill="#919193"/>
|
||||||
|
<path d="M3.76596 30.0001C5.84584 30.0001 7.53192 28.314 7.53192 26.2341C7.53192 24.1542 5.84584 22.4681 3.76596 22.4681C1.68608 22.4681 0 24.1542 0 26.2341C0 28.314 1.68608 30.0001 3.76596 30.0001Z" fill="#919193"/>
|
||||||
|
<path d="M15 30.0002C17.0799 30.0002 18.766 28.3141 18.766 26.2342C18.766 24.1543 17.0799 22.4683 15 22.4683C12.9201 22.4683 11.2341 24.1543 11.2341 26.2342C11.2341 28.3141 12.9201 30.0002 15 30.0002Z" fill="#919193"/>
|
||||||
|
<path d="M26.234 30.0002C28.3139 30.0002 30 28.3141 30 26.2342C30 24.1543 28.3139 22.4683 26.234 22.4683C24.1542 22.4683 22.4681 24.1543 22.4681 26.2342C22.4681 28.3141 24.1542 30.0002 26.234 30.0002Z" fill="#919193"/>
|
||||||
|
<path d="M3.76596 18.766C5.84584 18.766 7.53192 17.08 7.53192 15.0001C7.53192 12.9202 5.84584 11.2341 3.76596 11.2341C1.68608 11.2341 0 12.9202 0 15.0001C0 17.08 1.68608 18.766 3.76596 18.766Z" fill="#919193"/>
|
||||||
|
<path d="M15 18.766C17.0799 18.766 18.766 17.08 18.766 15.0001C18.766 12.9202 17.0799 11.2341 15 11.2341C12.9201 11.2341 11.2341 12.9202 11.2341 15.0001C11.2341 17.08 12.9201 18.766 15 18.766Z" fill="#919193"/>
|
||||||
|
<path d="M26.234 18.766C28.3139 18.766 30 17.08 30 15.0001C30 12.9202 28.3139 11.2341 26.234 11.2341C24.1542 11.2341 22.4681 12.9202 22.4681 15.0001C22.4681 17.08 24.1542 18.766 26.234 18.766Z" fill="#919193"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
4
src/assets/svgs/qappLibraryText.svg
Normal file
4
src/assets/svgs/qappLibraryText.svg
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<svg width="301" height="26" viewBox="0 0 301 26" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M9.5 15.3636H14.4091L16.1818 17.5909L19.1818 21L23.0909 25.7273H17.5L14.7273 22.5L12.8636 19.8182L9.5 15.3636ZM23.0455 12.3636C23.0455 14.9545 22.5417 17.1402 21.5341 18.9205C20.5265 20.6932 19.1667 22.0379 17.4545 22.9545C15.7424 23.8636 13.8333 24.3182 11.7273 24.3182C9.60606 24.3182 7.68939 23.8598 5.97727 22.9432C4.27273 22.0189 2.91667 20.6705 1.90909 18.8977C0.909091 17.1174 0.409091 14.9394 0.409091 12.3636C0.409091 9.77273 0.909091 7.59091 1.90909 5.81818C2.91667 4.03788 4.27273 2.69318 5.97727 1.78409C7.68939 0.867423 9.60606 0.40909 11.7273 0.40909C13.8333 0.40909 15.7424 0.867423 17.4545 1.78409C19.1667 2.69318 20.5265 4.03788 21.5341 5.81818C22.5417 7.59091 23.0455 9.77273 23.0455 12.3636ZM16.5455 12.3636C16.5455 10.9697 16.3598 9.79545 15.9886 8.84091C15.625 7.87879 15.0833 7.15151 14.3636 6.65909C13.6515 6.15909 12.7727 5.90909 11.7273 5.90909C10.6818 5.90909 9.79924 6.15909 9.07955 6.65909C8.36742 7.15151 7.82576 7.87879 7.45455 8.84091C7.09091 9.79545 6.90909 10.9697 6.90909 12.3636C6.90909 13.7576 7.09091 14.9356 7.45455 15.8977C7.82576 16.8523 8.36742 17.5795 9.07955 18.0795C9.79924 18.572 10.6818 18.8182 11.7273 18.8182C12.7727 18.8182 13.6515 18.572 14.3636 18.0795C15.0833 17.5795 15.625 16.8523 15.9886 15.8977C16.3598 14.9356 16.5455 13.7576 16.5455 12.3636ZM39.5455 10V14.7273H28.6364V10H39.5455ZM51.233 24H44.4148L52.0966 0.727272H60.733L68.4148 24H61.5966L56.5057 7.13636H56.3239L51.233 24ZM49.9602 14.8182H62.7784V19.5455H49.9602V14.8182ZM72.6562 24V0.727272H82.7017C84.429 0.727272 85.9403 1.06818 87.2358 1.75C88.5313 2.43182 89.5388 3.39015 90.2585 4.625C90.9782 5.85985 91.3381 7.30303 91.3381 8.95455C91.3381 10.6212 90.9669 12.0644 90.2244 13.2841C89.4896 14.5038 88.4555 15.4432 87.1222 16.1023C85.7964 16.7614 84.2472 17.0909 82.4744 17.0909H76.4744V12.1818H81.2017C81.9441 12.1818 82.5767 12.053 83.0994 11.7955C83.6297 11.5303 84.035 11.1553 84.3153 10.6705C84.6032 10.1856 84.7472 9.61364 84.7472 8.95455C84.7472 8.28788 84.6032 7.7197 84.3153 7.25C84.035 6.77273 83.6297 6.40909 83.0994 6.15909C82.5767 5.90151 81.9441 5.77273 81.2017 5.77273H78.9744V24H72.6562ZM95.6562 24V0.727272H105.702C107.429 0.727272 108.94 1.06818 110.236 1.75C111.531 2.43182 112.539 3.39015 113.259 4.625C113.978 5.85985 114.338 7.30303 114.338 8.95455C114.338 10.6212 113.967 12.0644 113.224 13.2841C112.49 14.5038 111.455 15.4432 110.122 16.1023C108.796 16.7614 107.247 17.0909 105.474 17.0909H99.4744V12.1818H104.202C104.944 12.1818 105.577 12.053 106.099 11.7955C106.63 11.5303 107.035 11.1553 107.315 10.6705C107.603 10.1856 107.747 9.61364 107.747 8.95455C107.747 8.28788 107.603 7.7197 107.315 7.25C107.035 6.77273 106.63 6.40909 106.099 6.15909C105.577 5.90151 104.944 5.77273 104.202 5.77273H101.974V24H95.6562ZM131.202 8C131.141 7.24242 130.857 6.65151 130.349 6.22727C129.849 5.80303 129.088 5.59091 128.065 5.59091C127.414 5.59091 126.88 5.67045 126.463 5.82954C126.054 5.98106 125.751 6.18939 125.554 6.45454C125.357 6.7197 125.255 7.02273 125.247 7.36364C125.232 7.64394 125.281 7.89773 125.395 8.125C125.516 8.3447 125.705 8.54545 125.963 8.72727C126.221 8.90151 126.55 9.06061 126.952 9.20455C127.353 9.34848 127.83 9.47727 128.384 9.59091L130.293 10C131.58 10.2727 132.683 10.6326 133.599 11.0795C134.516 11.5265 135.266 12.053 135.849 12.6591C136.433 13.2576 136.861 13.9318 137.134 14.6818C137.414 15.4318 137.558 16.25 137.565 17.1364C137.558 18.6667 137.175 19.9621 136.418 21.0227C135.66 22.0833 134.577 22.8902 133.168 23.4432C131.766 23.9962 130.08 24.2727 128.111 24.2727C126.088 24.2727 124.323 23.9735 122.815 23.375C121.315 22.7765 120.149 21.8561 119.315 20.6136C118.49 19.3636 118.073 17.7652 118.065 15.8182H124.065C124.103 16.5303 124.281 17.1288 124.599 17.6136C124.918 18.0985 125.365 18.4659 125.94 18.7159C126.524 18.9659 127.217 19.0909 128.02 19.0909C128.694 19.0909 129.259 19.0076 129.713 18.8409C130.168 18.6742 130.512 18.4432 130.747 18.1477C130.982 17.8523 131.103 17.5152 131.111 17.1364C131.103 16.7803 130.986 16.4697 130.759 16.2045C130.539 15.9318 130.175 15.6894 129.668 15.4773C129.16 15.2576 128.474 15.053 127.611 14.8636L125.293 14.3636C123.232 13.9167 121.607 13.1705 120.418 12.125C119.236 11.072 118.649 9.63636 118.656 7.81818C118.649 6.34091 119.043 5.04924 119.838 3.94318C120.641 2.82954 121.751 1.96212 123.168 1.34091C124.592 0.719696 126.224 0.40909 128.065 0.40909C129.944 0.40909 131.569 0.723484 132.94 1.35227C134.312 1.98106 135.368 2.86742 136.111 4.01136C136.861 5.14773 137.24 6.47727 137.247 8H131.202Z" fill="white"/>
|
||||||
|
<path d="M150.344 24V0.727272H156.662V18.9091H166.071V24H150.344ZM176.943 0.727272V24H170.625V0.727272H176.943ZM181.938 24V0.727272H192.028C193.801 0.727272 195.29 0.965909 196.494 1.44318C197.706 1.92045 198.619 2.5947 199.233 3.46591C199.854 4.33712 200.165 5.36364 200.165 6.54545C200.165 7.40151 199.975 8.18182 199.597 8.88636C199.225 9.59091 198.703 10.1818 198.028 10.6591C197.354 11.1288 196.566 11.4545 195.665 11.6364V11.8636C196.665 11.9015 197.574 12.1553 198.392 12.625C199.21 13.0871 199.862 13.7273 200.347 14.5455C200.831 15.3561 201.074 16.3106 201.074 17.4091C201.074 18.6818 200.741 19.8144 200.074 20.8068C199.415 21.7992 198.475 22.5795 197.256 23.1477C196.036 23.7159 194.581 24 192.892 24H181.938ZM188.256 18.9545H191.21C192.271 18.9545 193.066 18.7576 193.597 18.3636C194.127 17.9621 194.392 17.3712 194.392 16.5909C194.392 16.0455 194.267 15.5833 194.017 15.2045C193.767 14.8258 193.411 14.5379 192.949 14.3409C192.494 14.1439 191.945 14.0455 191.301 14.0455H188.256V18.9545ZM188.256 10.1364H190.847C191.4 10.1364 191.888 10.0492 192.312 9.875C192.737 9.70076 193.066 9.45076 193.301 9.125C193.544 8.79167 193.665 8.38636 193.665 7.90909C193.665 7.18939 193.407 6.64015 192.892 6.26136C192.377 5.875 191.725 5.68182 190.938 5.68182H188.256V10.1364ZM205.312 24V0.727272H215.358C217.085 0.727272 218.597 1.04167 219.892 1.67045C221.188 2.29924 222.195 3.20455 222.915 4.38636C223.634 5.56818 223.994 6.98485 223.994 8.63636C223.994 10.303 223.623 11.7083 222.881 12.8523C222.146 13.9962 221.112 14.8598 219.778 15.4432C218.453 16.0265 216.903 16.3182 215.131 16.3182H209.131V11.4091H213.858C214.6 11.4091 215.233 11.3182 215.756 11.1364C216.286 10.947 216.691 10.6477 216.972 10.2386C217.259 9.82955 217.403 9.29545 217.403 8.63636C217.403 7.9697 217.259 7.42803 216.972 7.01136C216.691 6.58712 216.286 6.27651 215.756 6.07954C215.233 5.875 214.6 5.77273 213.858 5.77273H211.631V24H205.312ZM218.949 13.3182L224.767 24H217.903L212.222 13.3182H218.949ZM234.733 24H227.915L235.597 0.727272H244.233L251.915 24H245.097L240.006 7.13636H239.824L234.733 24ZM233.46 14.8182H246.278V19.5455H233.46V14.8182ZM256.156 24V0.727272H266.202C267.929 0.727272 269.44 1.04167 270.736 1.67045C272.031 2.29924 273.039 3.20455 273.759 4.38636C274.478 5.56818 274.838 6.98485 274.838 8.63636C274.838 10.303 274.467 11.7083 273.724 12.8523C272.99 13.9962 271.955 14.8598 270.622 15.4432C269.296 16.0265 267.747 16.3182 265.974 16.3182H259.974V11.4091H264.702C265.444 11.4091 266.077 11.3182 266.599 11.1364C267.13 10.947 267.535 10.6477 267.815 10.2386C268.103 9.82955 268.247 9.29545 268.247 8.63636C268.247 7.9697 268.103 7.42803 267.815 7.01136C267.535 6.58712 267.13 6.27651 266.599 6.07954C266.077 5.875 265.444 5.77273 264.702 5.77273H262.474V24H256.156ZM269.793 13.3182L275.611 24H268.747L263.065 13.3182H269.793ZM277.483 0.727272H284.528L289.074 10.1818H289.256L293.801 0.727272H300.847L292.301 16.6818V24H286.028V16.6818L277.483 0.727272Z" fill="#0091E1"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 7.4 KiB |
@ -117,7 +117,7 @@ const getApiKeyFromStorage = async () => {
|
|||||||
const getArbitraryEndpoint = async () => {
|
const getArbitraryEndpoint = async () => {
|
||||||
const apiKey = await getApiKeyFromStorage(); // Retrieve apiKey asynchronously
|
const apiKey = await getApiKeyFromStorage(); // Retrieve apiKey asynchronously
|
||||||
if (apiKey) {
|
if (apiKey) {
|
||||||
return `/arbitrary/resources/search`;
|
return `/arbitrary/resources/searchsimple`;
|
||||||
} else {
|
} else {
|
||||||
return `/arbitrary/resources/searchsimple`;
|
return `/arbitrary/resources/searchsimple`;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ import {
|
|||||||
} from "./Apps-styles";
|
} from "./Apps-styles";
|
||||||
import { Avatar, Box, ButtonBase, InputBase } from "@mui/material";
|
import { Avatar, Box, ButtonBase, InputBase } from "@mui/material";
|
||||||
import { Add } from "@mui/icons-material";
|
import { Add } from "@mui/icons-material";
|
||||||
import { getBaseApiReact } from "../../App";
|
import { getBaseApiReact, isMobile } from "../../App";
|
||||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||||
|
|
||||||
import { Spacer } from "../../common/Spacer";
|
import { Spacer } from "../../common/Spacer";
|
||||||
@ -32,7 +32,21 @@ import { AppRating } from "./AppRating";
|
|||||||
export const AppInfo = ({ app, myName }) => {
|
export const AppInfo = ({ app, myName }) => {
|
||||||
const isInstalled = app?.status?.status === "READY";
|
const isInstalled = app?.status?.status === "READY";
|
||||||
return (
|
return (
|
||||||
<AppsLibraryContainer>
|
<AppsLibraryContainer
|
||||||
|
sx={{
|
||||||
|
height: !isMobile && "100%",
|
||||||
|
justifyContent: !isMobile && "flex-start",
|
||||||
|
alignItems: isMobile && 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
maxWidth: "500px",
|
||||||
|
}}>
|
||||||
|
|
||||||
|
|
||||||
|
{!isMobile && <Spacer height="30px" />}
|
||||||
<AppsWidthLimiter>
|
<AppsWidthLimiter>
|
||||||
<AppInfoSnippetContainer>
|
<AppInfoSnippetContainer>
|
||||||
<AppInfoSnippetLeft
|
<AppInfoSnippetLeft
|
||||||
@ -108,30 +122,28 @@ export const AppInfo = ({ app, myName }) => {
|
|||||||
</AppDownloadButton>
|
</AppDownloadButton>
|
||||||
</AppsWidthLimiter>
|
</AppsWidthLimiter>
|
||||||
<Spacer height="20px" />
|
<Spacer height="20px" />
|
||||||
<AppsWidthLimiter>
|
<AppsWidthLimiter>
|
||||||
|
<AppsCategoryInfo>
|
||||||
<AppsCategoryInfo>
|
<AppRating ratingCountPosition="top" myName={myName} app={app} />
|
||||||
<AppRating ratingCountPosition="top" myName={myName} app={app} />
|
<Spacer width="16px" />
|
||||||
<Spacer width="16px" />
|
<Spacer height="40px" width="1px" backgroundColor="white" />
|
||||||
<Spacer height="40px" width="1px" backgroundColor="white" />
|
<Spacer width="16px" />
|
||||||
<Spacer width="16px" />
|
<AppsCategoryInfoSub>
|
||||||
<AppsCategoryInfoSub>
|
<AppsCategoryInfoLabel>Category:</AppsCategoryInfoLabel>
|
||||||
<AppsCategoryInfoLabel>Category:</AppsCategoryInfoLabel>
|
<Spacer height="4px" />
|
||||||
<Spacer height="4px" />
|
<AppsCategoryInfoValue>
|
||||||
<AppsCategoryInfoValue>
|
{app?.metadata?.categoryName || "none"}
|
||||||
{app?.metadata?.categoryName || "none"}
|
</AppsCategoryInfoValue>
|
||||||
</AppsCategoryInfoValue>
|
</AppsCategoryInfoSub>
|
||||||
</AppsCategoryInfoSub>
|
</AppsCategoryInfo>
|
||||||
</AppsCategoryInfo>
|
<Spacer height="30px" />
|
||||||
<Spacer height="30px" />
|
<AppInfoAppName>About this Q-App</AppInfoAppName>
|
||||||
<AppInfoAppName>
|
|
||||||
About this Q-App
|
|
||||||
</AppInfoAppName>
|
|
||||||
</AppsWidthLimiter>
|
</AppsWidthLimiter>
|
||||||
<Spacer height="20px" />
|
<Spacer height="20px" />
|
||||||
<AppsInfoDescription>
|
<AppsInfoDescription>
|
||||||
{app?.metadata?.description || "No description"}
|
{app?.metadata?.description || "No description"}
|
||||||
</AppsInfoDescription>
|
</AppsInfoDescription>
|
||||||
|
</Box>
|
||||||
</AppsLibraryContainer>
|
</AppsLibraryContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -39,7 +39,7 @@ import { Option as BaseOption, optionClasses } from "@mui/base/Option";
|
|||||||
import { styled } from "@mui/system";
|
import { styled } from "@mui/system";
|
||||||
import UnfoldMoreRoundedIcon from "@mui/icons-material/UnfoldMoreRounded";
|
import UnfoldMoreRoundedIcon from "@mui/icons-material/UnfoldMoreRounded";
|
||||||
import { Add } from "@mui/icons-material";
|
import { Add } from "@mui/icons-material";
|
||||||
import { MyContext, getBaseApiReact } from "../../App";
|
import { MyContext, getBaseApiReact, isMobile } from "../../App";
|
||||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||||
|
|
||||||
import { Spacer } from "../../common/Spacer";
|
import { Spacer } from "../../common/Spacer";
|
||||||
@ -257,8 +257,14 @@ export const AppPublish = ({ names, categories }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<AppsLibraryContainer>
|
<AppsLibraryContainer sx={{
|
||||||
<AppsWidthLimiter>
|
height: !isMobile && '100%',
|
||||||
|
paddingTop: !isMobile && '30px',
|
||||||
|
alignItems: !isMobile && 'center'
|
||||||
|
}}>
|
||||||
|
<AppsWidthLimiter sx={{
|
||||||
|
width: !isMobile && 'auto'
|
||||||
|
}}>
|
||||||
<AppLibrarySubTitle>Create Apps!</AppLibrarySubTitle>
|
<AppLibrarySubTitle>Create Apps!</AppLibrarySubTitle>
|
||||||
<Spacer height="18px" />
|
<Spacer height="18px" />
|
||||||
<PublishQAppInfo>
|
<PublishQAppInfo>
|
||||||
|
@ -16,7 +16,7 @@ import {
|
|||||||
} from "./Apps-styles";
|
} from "./Apps-styles";
|
||||||
import { Avatar, Box, ButtonBase, InputBase } from "@mui/material";
|
import { Avatar, Box, ButtonBase, InputBase } from "@mui/material";
|
||||||
import { Add } from "@mui/icons-material";
|
import { Add } from "@mui/icons-material";
|
||||||
import { MyContext, getBaseApiReact } from "../../App";
|
import { MyContext, getBaseApiReact, isMobile } from "../../App";
|
||||||
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||||
|
|
||||||
import { Spacer } from "../../common/Spacer";
|
import { Spacer } from "../../common/Spacer";
|
||||||
@ -61,7 +61,7 @@ export const AppViewer = ({ app }) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<iframe ref={iframeRef} style={{
|
<iframe ref={iframeRef} style={{
|
||||||
height: `calc(${rootHeight} - 60px - 45px - 20px)`,
|
height: !isMobile ? '100vh' : `calc(${rootHeight} - 60px - 45px - 20px)`,
|
||||||
border: 'none',
|
border: 'none',
|
||||||
width: '100%'
|
width: '100%'
|
||||||
}} id="browser-iframe" src={defaultUrl} sandbox="allow-scripts allow-same-origin allow-forms allow-downloads allow-modals" allow="fullscreen">
|
}} id="browser-iframe" src={defaultUrl} sandbox="allow-scripts allow-same-origin allow-forms allow-downloads allow-modals" allow="fullscreen">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React, { useContext, useEffect, useRef } from 'react'
|
import React, { useContext, useEffect, useRef } from 'react'
|
||||||
import { AppViewer } from './AppViewer'
|
import { AppViewer } from './AppViewer'
|
||||||
import Frame from 'react-frame-component';
|
import Frame from 'react-frame-component';
|
||||||
import { MyContext } from '../../App';
|
import { MyContext, isMobile } from '../../App';
|
||||||
import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
|
import { subscribeToEvent, unsubscribeFromEvent } from '../../utils/events';
|
||||||
|
|
||||||
const AppViewerContainer = ({app, isSelected, hide}) => {
|
const AppViewerContainer = ({app, isSelected, hide}) => {
|
||||||
@ -32,7 +32,7 @@ const AppViewerContainer = ({app, isSelected, hide}) => {
|
|||||||
</style>
|
</style>
|
||||||
</>
|
</>
|
||||||
} style={{
|
} style={{
|
||||||
height: `calc(${rootHeight} - 60px - 45px - 20px)`,
|
height: !isMobile ? '100vh' : `calc(${rootHeight} - 60px - 45px - 20px)`,
|
||||||
border: 'none',
|
border: 'none',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
display: (!isSelected || hide) && 'none'
|
display: (!isSelected || hide) && 'none'
|
||||||
|
223
src/components/Apps/AppsCategoryDesktop.tsx
Normal file
223
src/components/Apps/AppsCategoryDesktop.tsx
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
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";
|
||||||
|
import { AppsDesktopLibraryBody, AppsDesktopLibraryHeader } from "./AppsDesktop-styles";
|
||||||
|
const officialAppList = [
|
||||||
|
"q-tube",
|
||||||
|
"q-blog",
|
||||||
|
"q-share",
|
||||||
|
"q-support",
|
||||||
|
"q-mail",
|
||||||
|
"qombo",
|
||||||
|
"q-fund",
|
||||||
|
"q-shop",
|
||||||
|
];
|
||||||
|
|
||||||
|
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
|
||||||
|
"-ms-overflow-style": "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
|
||||||
|
"-ms-overflow-style": "none",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const AppsCategoryDesktop = ({
|
||||||
|
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",
|
||||||
|
padding: "0px",
|
||||||
|
height: "100vh",
|
||||||
|
overflow: "hidden",
|
||||||
|
paddingTop: "30px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppsDesktopLibraryHeader
|
||||||
|
sx={{
|
||||||
|
maxWidth: "1500px",
|
||||||
|
width: "90%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppsWidthLimiter
|
||||||
|
sx={{
|
||||||
|
alignItems: "flex-end",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppsSearchContainer sx={{
|
||||||
|
width: "412px",
|
||||||
|
}}>
|
||||||
|
<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>
|
||||||
|
</AppsWidthLimiter>
|
||||||
|
</AppsDesktopLibraryHeader>
|
||||||
|
<AppsDesktopLibraryBody
|
||||||
|
sx={{
|
||||||
|
height: `calc(100vh - 36px)`,
|
||||||
|
overflow: "auto",
|
||||||
|
padding: "0px",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</AppsDesktopLibraryBody>
|
||||||
|
</AppsLibraryContainer>
|
||||||
|
);
|
||||||
|
};
|
24
src/components/Apps/AppsDesktop-styles.tsx
Normal file
24
src/components/Apps/AppsDesktop-styles.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import {
|
||||||
|
AppBar,
|
||||||
|
Button,
|
||||||
|
Toolbar,
|
||||||
|
Typography,
|
||||||
|
Box,
|
||||||
|
TextField,
|
||||||
|
InputLabel,
|
||||||
|
ButtonBase,
|
||||||
|
} from "@mui/material";
|
||||||
|
import { styled } from "@mui/system";
|
||||||
|
|
||||||
|
export const AppsDesktopLibraryHeader = styled(Box)(({ theme }) => ({
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: 'column',
|
||||||
|
flexShrink: 0,
|
||||||
|
width: '100%'
|
||||||
|
}));
|
||||||
|
export const AppsDesktopLibraryBody = styled(Box)(({ theme }) => ({
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: 'column',
|
||||||
|
flexGrow: 1,
|
||||||
|
width: '100%'
|
||||||
|
}));
|
429
src/components/Apps/AppsDesktop.tsx
Normal file
429
src/components/Apps/AppsDesktop.tsx
Normal file
@ -0,0 +1,429 @@
|
|||||||
|
import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
||||||
|
import { AppsHomeDesktop } from "./AppsHomeDesktop";
|
||||||
|
import { Spacer } from "../../common/Spacer";
|
||||||
|
import { MyContext, getBaseApiReact } from "../../App";
|
||||||
|
import { AppInfo } from "./AppInfo";
|
||||||
|
import {
|
||||||
|
executeEvent,
|
||||||
|
subscribeToEvent,
|
||||||
|
unsubscribeFromEvent,
|
||||||
|
} from "../../utils/events";
|
||||||
|
import { AppsNavBar } from "./AppsNavBar";
|
||||||
|
import { AppsParent } from "./Apps-styles";
|
||||||
|
import { AppViewer } from "./AppViewer";
|
||||||
|
import AppViewerContainer from "./AppViewerContainer";
|
||||||
|
import ShortUniqueId from "short-unique-id";
|
||||||
|
import { AppPublish } from "./AppPublish";
|
||||||
|
import { useRecoilState } from "recoil";
|
||||||
|
import { AppsCategory } from "./AppsCategory";
|
||||||
|
import { AppsLibrary } from "./AppsLibrary";
|
||||||
|
import { AppsLibraryDesktop } from "./AppsLibraryDesktop";
|
||||||
|
import { AppsCategoryDesktop } from "./AppsCategoryDesktop";
|
||||||
|
import { AppsNavBarDesktop } from "./AppsNavBarDesktop";
|
||||||
|
import { Box, ButtonBase } from "@mui/material";
|
||||||
|
import { HomeIcon } from "../../assets/Icons/HomeIcon";
|
||||||
|
import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
|
||||||
|
import { Save } from "../Save/Save";
|
||||||
|
import { HubsIcon } from "../../assets/Icons/HubsIcon";
|
||||||
|
|
||||||
|
const uid = new ShortUniqueId({ length: 8 });
|
||||||
|
|
||||||
|
export const AppsDesktop = ({ mode, setMode, show , myName, goToHome, setDesktopSideView, hasUnreadDirects, isDirects, isGroups, hasUnreadGroups, toggleSideViewGroups, toggleSideViewDirects}) => {
|
||||||
|
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 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) {
|
||||||
|
} 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) {
|
||||||
|
} 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(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 {
|
||||||
|
const iframeId = `browser-iframe-${selectedTab?.tabId}`;
|
||||||
|
const iframe = document.getElementById(iframeId);
|
||||||
|
// Go Back in the iframe's history
|
||||||
|
if (iframe) {
|
||||||
|
if (iframe && iframe.contentWindow) {
|
||||||
|
const iframeWindow = iframe.contentWindow;
|
||||||
|
if (iframeWindow && iframeWindow.history) {
|
||||||
|
iframeWindow.history.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
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",
|
||||||
|
flexDirection: 'row'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
<Box sx={{
|
||||||
|
width: '60px',
|
||||||
|
flexDirection: 'column',
|
||||||
|
height: '100vh',
|
||||||
|
alignItems: 'center',
|
||||||
|
display: 'flex',
|
||||||
|
gap: '30px'
|
||||||
|
}}>
|
||||||
|
<ButtonBase
|
||||||
|
sx={{
|
||||||
|
width: '60px',
|
||||||
|
height: '60px',
|
||||||
|
paddingTop: '23px'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
goToHome();
|
||||||
|
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
<HomeIcon
|
||||||
|
height={34}
|
||||||
|
color="rgba(250, 250, 250, 0.5)"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
setDesktopSideView("directs");
|
||||||
|
toggleSideViewDirects()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
<MessagingIcon
|
||||||
|
height={30}
|
||||||
|
color={
|
||||||
|
hasUnreadDirects
|
||||||
|
? "var(--unread)"
|
||||||
|
: isDirects
|
||||||
|
? "white"
|
||||||
|
: "rgba(250, 250, 250, 0.5)"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
setDesktopSideView("groups");
|
||||||
|
toggleSideViewGroups()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<HubsIcon
|
||||||
|
height={30}
|
||||||
|
color={
|
||||||
|
hasUnreadGroups
|
||||||
|
? "var(--unread)"
|
||||||
|
: isGroups
|
||||||
|
? "white"
|
||||||
|
: "rgba(250, 250, 250, 0.5)"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
</ButtonBase>
|
||||||
|
<Save isDesktop />
|
||||||
|
{mode !== 'home' && (
|
||||||
|
<AppsNavBarDesktop />
|
||||||
|
|
||||||
|
)}
|
||||||
|
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
|
{mode === "home" && (
|
||||||
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
flexDirection: 'column',
|
||||||
|
height: '100vh',
|
||||||
|
overflow: 'auto'
|
||||||
|
}}>
|
||||||
|
|
||||||
|
<Spacer height="30px" />
|
||||||
|
<AppsHomeDesktop availableQapps={availableQapps} setMode={setMode} myApp={myApp} myWebsite={myWebsite} />
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<AppsLibraryDesktop
|
||||||
|
isShow={mode === "library" && !selectedTab}
|
||||||
|
availableQapps={availableQapps}
|
||||||
|
setMode={setMode}
|
||||||
|
myName={myName}
|
||||||
|
hasPublishApp={!!(myApp || myWebsite)}
|
||||||
|
categories={categories}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{mode === "appInfo" && <AppInfo app={selectedAppInfo} myName={myName} />}
|
||||||
|
{mode === "appInfo-from-category" && <AppInfo app={selectedAppInfo} myName={myName} />}
|
||||||
|
<AppsCategoryDesktop availableQapps={availableQapps} isShow={mode === 'category' && !selectedTab} category={selectedCategory} myName={myName} />
|
||||||
|
{mode === "publish" && <AppPublish names={myName ? [myName] : []} categories={categories} />}
|
||||||
|
|
||||||
|
{tabs.map((tab) => {
|
||||||
|
return (
|
||||||
|
<AppViewerContainer
|
||||||
|
hide={isNewTabWindow}
|
||||||
|
isSelected={tab?.tabId === selectedTab?.tabId}
|
||||||
|
app={tab}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
{isNewTabWindow && mode === "viewer" && (
|
||||||
|
<>
|
||||||
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
width: '100%',
|
||||||
|
flexDirection: 'column',
|
||||||
|
height: '100vh',
|
||||||
|
overflow: 'auto'
|
||||||
|
}}>
|
||||||
|
|
||||||
|
<Spacer height="30px" />
|
||||||
|
<AppsHomeDesktop availableQapps={availableQapps} setMode={setMode} myApp={myApp} myWebsite={myWebsite} />
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</AppsParent>
|
||||||
|
);
|
||||||
|
};
|
39
src/components/Apps/AppsHomeDesktop.tsx
Normal file
39
src/components/Apps/AppsHomeDesktop.tsx
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import React, { useMemo, useState } from "react";
|
||||||
|
import {
|
||||||
|
AppCircle,
|
||||||
|
AppCircleContainer,
|
||||||
|
AppCircleLabel,
|
||||||
|
AppsContainer,
|
||||||
|
AppsParent,
|
||||||
|
} from "./Apps-styles";
|
||||||
|
import { Avatar, ButtonBase } from "@mui/material";
|
||||||
|
import { Add } from "@mui/icons-material";
|
||||||
|
import { getBaseApiReact } from "../../App";
|
||||||
|
import LogoSelected from "../../assets/svgs/LogoSelected.svg";
|
||||||
|
import { executeEvent } from "../../utils/events";
|
||||||
|
import { SortablePinnedApps } from "./SortablePinnedApps";
|
||||||
|
|
||||||
|
export const AppsHomeDesktop = ({ setMode, myApp, myWebsite, availableQapps }) => {
|
||||||
|
return (
|
||||||
|
<AppsContainer sx={{
|
||||||
|
gap: '75px',
|
||||||
|
justifyContent: 'flex-start'
|
||||||
|
}}>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
setMode("library");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppCircleContainer>
|
||||||
|
<AppCircle>
|
||||||
|
<Add>+</Add>
|
||||||
|
</AppCircle>
|
||||||
|
<AppCircleLabel>Add</AppCircleLabel>
|
||||||
|
</AppCircleContainer>
|
||||||
|
</ButtonBase>
|
||||||
|
|
||||||
|
<SortablePinnedApps isDesktop={true} availableQapps={availableQapps} myWebsite={myWebsite} myApp={myApp} />
|
||||||
|
|
||||||
|
</AppsContainer>
|
||||||
|
);
|
||||||
|
};
|
411
src/components/Apps/AppsLibraryDesktop.tsx
Normal file
411
src/components/Apps/AppsLibraryDesktop.tsx
Normal file
@ -0,0 +1,411 @@
|
|||||||
|
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 qappLibraryText from "../../assets/svgs/qappLibraryText.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";
|
||||||
|
import {
|
||||||
|
AppsDesktopLibraryBody,
|
||||||
|
AppsDesktopLibraryHeader,
|
||||||
|
} from "./AppsDesktop-styles";
|
||||||
|
import { AppsNavBarDesktop } from "./AppsNavBarDesktop";
|
||||||
|
const officialAppList = [
|
||||||
|
"q-tube",
|
||||||
|
"q-blog",
|
||||||
|
"q-share",
|
||||||
|
"q-support",
|
||||||
|
"q-mail",
|
||||||
|
"qombo",
|
||||||
|
"q-fund",
|
||||||
|
"q-shop",
|
||||||
|
];
|
||||||
|
|
||||||
|
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
|
||||||
|
"-ms-overflow-style": "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
|
||||||
|
"-ms-overflow-style": "none",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const AppsLibraryDesktop = ({
|
||||||
|
availableQapps,
|
||||||
|
setMode,
|
||||||
|
myName,
|
||||||
|
hasPublishApp,
|
||||||
|
isShow,
|
||||||
|
categories = { categories },
|
||||||
|
}) => {
|
||||||
|
const [searchValue, setSearchValue] = useState("");
|
||||||
|
const virtuosoRef = useRef();
|
||||||
|
|
||||||
|
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}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AppsLibraryContainer
|
||||||
|
sx={{
|
||||||
|
display: !isShow && "none",
|
||||||
|
padding: "0px",
|
||||||
|
height: "100vh",
|
||||||
|
overflow: "hidden",
|
||||||
|
paddingTop: '30px'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
|
||||||
|
<AppsDesktopLibraryHeader
|
||||||
|
sx={{
|
||||||
|
maxWidth: "1500px",
|
||||||
|
width: "90%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppsWidthLimiter>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
width: "100%",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img src={qappLibraryText} />
|
||||||
|
<AppsSearchContainer
|
||||||
|
sx={{
|
||||||
|
width: "412px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</AppsDesktopLibraryHeader>
|
||||||
|
<AppsDesktopLibraryBody
|
||||||
|
sx={{
|
||||||
|
height: `calc(100vh - 36px)`,
|
||||||
|
overflow: "auto",
|
||||||
|
padding: "0px",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppsDesktopLibraryBody
|
||||||
|
sx={{
|
||||||
|
height: `calc(100vh - 36px)`,
|
||||||
|
flexGrow: "unset",
|
||||||
|
maxWidth: "1500px",
|
||||||
|
width: "90%",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Spacer height="90px" />
|
||||||
|
{searchedList?.length > 0 ? (
|
||||||
|
<AppsWidthLimiter>
|
||||||
|
<StyledVirtuosoContainer
|
||||||
|
sx={{
|
||||||
|
height: `calc(100vh - 36px - 90px)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Virtuoso
|
||||||
|
ref={virtuosoRef}
|
||||||
|
data={searchedList}
|
||||||
|
itemContent={rowRenderer}
|
||||||
|
atBottomThreshold={50}
|
||||||
|
followOutput="smooth"
|
||||||
|
components={{
|
||||||
|
Scroller: ScrollerStyled, // Use the styled scroller component
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</StyledVirtuosoContainer>
|
||||||
|
</AppsWidthLimiter>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<AppLibrarySubTitle
|
||||||
|
sx={{
|
||||||
|
fontSize: "30px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Official Apps
|
||||||
|
</AppLibrarySubTitle>
|
||||||
|
<Spacer height="45px" />
|
||||||
|
<AppsContainer>
|
||||||
|
{officialApps?.map((qapp) => {
|
||||||
|
return (
|
||||||
|
<ButtonBase
|
||||||
|
sx={{
|
||||||
|
height: "80px",
|
||||||
|
width: "60px",
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
// executeEvent("addTab", {
|
||||||
|
// data: qapp
|
||||||
|
// })
|
||||||
|
executeEvent("selectedAppInfo", {
|
||||||
|
data: qapp,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppCircleContainer
|
||||||
|
sx={{
|
||||||
|
gap: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<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="80px" />
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
gap: "250px",
|
||||||
|
display: "flex",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppLibrarySubTitle
|
||||||
|
sx={{
|
||||||
|
fontSize: "30px",
|
||||||
|
width: "100%",
|
||||||
|
textAlign: "start",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{hasPublishApp ? "Update Apps!" : "Create Apps!"}
|
||||||
|
</AppLibrarySubTitle>
|
||||||
|
<Spacer height="18px" />
|
||||||
|
<PublishQAppCTAParent
|
||||||
|
sx={{
|
||||||
|
gap: "25px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<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>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppLibrarySubTitle
|
||||||
|
sx={{
|
||||||
|
fontSize: "30px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Categories
|
||||||
|
</AppLibrarySubTitle>
|
||||||
|
<Spacer height="18px" />
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
width: "100%",
|
||||||
|
display: "flex",
|
||||||
|
gap: "20px",
|
||||||
|
flexWrap: "wrap",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{categories?.map((category) => {
|
||||||
|
return (
|
||||||
|
<ButtonBase
|
||||||
|
key={category?.id}
|
||||||
|
onClick={() => {
|
||||||
|
executeEvent("selectedCategory", {
|
||||||
|
data: category,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
sx={{
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
height: "60px",
|
||||||
|
padding: "0px 24px",
|
||||||
|
border: "4px solid #10242F",
|
||||||
|
borderRadius: "6px",
|
||||||
|
boxShadow: "2px 4px 0px 0px #000000",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{category?.name}
|
||||||
|
</Box>
|
||||||
|
</ButtonBase>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</AppsDesktopLibraryBody>
|
||||||
|
</AppsDesktopLibraryBody>
|
||||||
|
</AppsLibraryContainer>
|
||||||
|
);
|
||||||
|
};
|
347
src/components/Apps/AppsNavBarDesktop.tsx
Normal file
347
src/components/Apps/AppsNavBarDesktop.tsx
Normal file
@ -0,0 +1,347 @@
|
|||||||
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
|
import {
|
||||||
|
AppsNavBarLeft,
|
||||||
|
AppsNavBarParent,
|
||||||
|
AppsNavBarRight,
|
||||||
|
} from "./Apps-styles";
|
||||||
|
import NavBack from "../../assets/svgs/NavBack.svg";
|
||||||
|
import NavAdd from "../../assets/svgs/NavAdd.svg";
|
||||||
|
import NavMoreMenu from "../../assets/svgs/NavMoreMenu.svg";
|
||||||
|
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 {
|
||||||
|
settingsLocalLastUpdatedAtom,
|
||||||
|
sortablePinnedAppsAtom,
|
||||||
|
} from "../../atoms/global";
|
||||||
|
|
||||||
|
export function saveToLocalStorage(key, subKey, newValue) {
|
||||||
|
try {
|
||||||
|
// 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,
|
||||||
|
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 = {
|
||||||
|
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 AppsNavBarDesktop = () => {
|
||||||
|
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 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 ? nulll : { ...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
|
||||||
|
sx={{
|
||||||
|
position: "relative",
|
||||||
|
flexDirection: "column",
|
||||||
|
width: "60px",
|
||||||
|
height: "unset",
|
||||||
|
maxHeight: "70vh",
|
||||||
|
borderRadius: "0px 30px 30px 0px",
|
||||||
|
padding: "10px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AppsNavBarLeft
|
||||||
|
sx={{
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
executeEvent("navigateBack", {});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img src={NavBack} />
|
||||||
|
</ButtonBase>
|
||||||
|
<Tabs
|
||||||
|
orientation="vertical"
|
||||||
|
ref={tabsRef}
|
||||||
|
aria-label="basic tabs example"
|
||||||
|
variant="scrollable" // Make tabs scrollable
|
||||||
|
scrollButtons={true}
|
||||||
|
sx={{
|
||||||
|
"& .MuiTabs-indicator": {
|
||||||
|
backgroundColor: "white",
|
||||||
|
},
|
||||||
|
maxHeight: `320px`, // 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>
|
||||||
|
<AppsNavBarRight
|
||||||
|
sx={{
|
||||||
|
gap: "10px",
|
||||||
|
flexDirection: "column",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedTab(null);
|
||||||
|
executeEvent("newTabWindow", {});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
height: "40px",
|
||||||
|
width: "40px",
|
||||||
|
}}
|
||||||
|
src={NavAdd}
|
||||||
|
/>
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={(e) => {
|
||||||
|
if (!selectedTab) return;
|
||||||
|
handleClick(e);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
style={{
|
||||||
|
height: "34px",
|
||||||
|
width: "34px",
|
||||||
|
}}
|
||||||
|
src={NavMoreMenu}
|
||||||
|
/>
|
||||||
|
</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>
|
||||||
|
);
|
||||||
|
};
|
@ -12,7 +12,7 @@ import { useRecoilState, useSetRecoilState } from 'recoil';
|
|||||||
import { saveToLocalStorage } from './AppsNavBar';
|
import { saveToLocalStorage } from './AppsNavBar';
|
||||||
import { ContextMenuPinnedApps } from '../ContextMenuPinnedApps';
|
import { ContextMenuPinnedApps } from '../ContextMenuPinnedApps';
|
||||||
|
|
||||||
const SortableItem = ({ id, name, app }) => {
|
const SortableItem = ({ id, name, app, isDesktop }) => {
|
||||||
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
|
const { attributes, listeners, setNodeRef, transform, transition } = useSortable({ id });
|
||||||
const style = {
|
const style = {
|
||||||
transform: CSS.Transform.toString(transform),
|
transform: CSS.Transform.toString(transform),
|
||||||
@ -42,7 +42,10 @@ const SortableItem = ({ id, name, app }) => {
|
|||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AppCircleContainer>
|
<AppCircleContainer sx={{
|
||||||
|
border: "none",
|
||||||
|
gap: isDesktop ? '10px': '5px'
|
||||||
|
}}>
|
||||||
<AppCircle
|
<AppCircle
|
||||||
sx={{
|
sx={{
|
||||||
border: "none",
|
border: "none",
|
||||||
@ -80,7 +83,7 @@ const SortableItem = ({ id, name, app }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SortablePinnedApps = ({ myWebsite, myApp, availableQapps = [] }) => {
|
export const SortablePinnedApps = ({ isDesktop, myWebsite, myApp, availableQapps = [] }) => {
|
||||||
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
||||||
const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom);
|
const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom);
|
||||||
|
|
||||||
@ -164,7 +167,7 @@ export const SortablePinnedApps = ({ myWebsite, myApp, availableQapps = [] }) =
|
|||||||
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
|
||||||
<SortableContext items={transformPinnedApps.map((app) => `${app?.service}-${app?.name}`)}>
|
<SortableContext items={transformPinnedApps.map((app) => `${app?.service}-${app?.name}`)}>
|
||||||
{transformPinnedApps.map((app) => (
|
{transformPinnedApps.map((app) => (
|
||||||
<SortableItem key={`${app?.service}-${app?.name}`} id={`${app?.service}-${app?.name}`} name={app?.name} app={app} />
|
<SortableItem isDesktop={isDesktop} key={`${app?.service}-${app?.name}`} id={`${app?.service}-${app?.name}`} name={app?.name} app={app} />
|
||||||
))}
|
))}
|
||||||
</SortableContext>
|
</SortableContext>
|
||||||
</DndContext>
|
</DndContext>
|
||||||
|
@ -13,21 +13,24 @@ import { WalletIcon } from "../../assets/Icons/WalletIcon";
|
|||||||
import { HubsIcon } from "../../assets/Icons/HubsIcon";
|
import { HubsIcon } from "../../assets/Icons/HubsIcon";
|
||||||
import { TradingIcon } from "../../assets/Icons/TradingIcon";
|
import { TradingIcon } from "../../assets/Icons/TradingIcon";
|
||||||
import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
|
import { MessagingIcon } from "../../assets/Icons/MessagingIcon";
|
||||||
import { HomeIcon } from "../../assets/Icons/HomeIcon";
|
import AppIcon from "../../assets/svgs/AppIcon.svg";
|
||||||
|
|
||||||
const IconWrapper = ({ children, label, color, selected }) => {
|
import { HomeIcon } from "../../assets/Icons/HomeIcon";
|
||||||
|
import { Save } from "../Save/Save";
|
||||||
|
|
||||||
|
export const IconWrapper = ({ children, label, color, selected }) => {
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
gap: "5px",
|
gap: "5px",
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
height: '89px',
|
height: "89px",
|
||||||
width: '89px',
|
width: "89px",
|
||||||
borderRadius: '50%',
|
borderRadius: "50%",
|
||||||
backgroundColor: selected ? 'rgba(28, 29, 32, 1)' : 'transparent'
|
backgroundColor: selected ? "rgba(28, 29, 32, 1)" : "transparent",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
@ -69,9 +72,17 @@ export const DesktopFooter = ({
|
|||||||
isHome,
|
isHome,
|
||||||
isGroups,
|
isGroups,
|
||||||
isDirects,
|
isDirects,
|
||||||
setDesktopSideView
|
setDesktopSideView,
|
||||||
|
isApps,
|
||||||
|
setDesktopViewMode,
|
||||||
|
desktopViewMode,
|
||||||
|
hide,
|
||||||
|
setIsOpenSideViewDirects,
|
||||||
|
setisOpenSideViewDirects
|
||||||
|
|
||||||
}) => {
|
}) => {
|
||||||
const [value, setValue] = React.useState(0);
|
|
||||||
|
if(hide) return
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -82,37 +93,93 @@ export const DesktopFooter = ({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
height: "100px", // Footer height
|
height: "100px", // Footer height
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
justifyContent: 'center'
|
justifyContent: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box sx={{
|
<Box
|
||||||
display: 'flex',
|
sx={{
|
||||||
gap: '20px'
|
display: "flex",
|
||||||
}}>
|
gap: "20px",
|
||||||
<ButtonBase onClick={()=> {
|
}}
|
||||||
goToHome()
|
>
|
||||||
}}>
|
<ButtonBase
|
||||||
<IconWrapper color="rgba(250, 250, 250, 0.5)" label="Home" selected={isHome}>
|
onClick={() => {
|
||||||
<HomeIcon height={30} color={isHome ? "white" : "rgba(250, 250, 250, 0.5)"} />
|
goToHome();
|
||||||
</IconWrapper>
|
}}
|
||||||
</ButtonBase>
|
>
|
||||||
<ButtonBase onClick={()=> {
|
<IconWrapper
|
||||||
setDesktopSideView('groups')
|
color="rgba(250, 250, 250, 0.5)"
|
||||||
}}>
|
label="Home"
|
||||||
<IconWrapper color="rgba(250, 250, 250, 0.5)" label="Hubs" selected={isGroups}>
|
selected={isHome}
|
||||||
<HubsIcon height={30} color={hasUnreadGroups ? "var(--unread)" : isGroups ? 'white' : "rgba(250, 250, 250, 0.5)"} />
|
>
|
||||||
</IconWrapper>
|
<HomeIcon
|
||||||
</ButtonBase>
|
height={30}
|
||||||
<ButtonBase onClick={()=> {
|
color={isHome ? "white" : "rgba(250, 250, 250, 0.5)"}
|
||||||
setDesktopSideView('directs')
|
/>
|
||||||
}}>
|
</IconWrapper>
|
||||||
|
</ButtonBase>
|
||||||
<IconWrapper color="rgba(250, 250, 250, 0.5)" label="Messaging" selected={isDirects}>
|
<ButtonBase
|
||||||
<MessagingIcon height={30} color={hasUnreadDirects ? "var(--unread)" : isDirects ? 'white' : "rgba(250, 250, 250, 0.5)"} />
|
onClick={() => {
|
||||||
</IconWrapper>
|
setDesktopViewMode('apps')
|
||||||
</ButtonBase>
|
setIsOpenSideViewDirects(false)
|
||||||
|
setIsOpenSideViewGroups(false)
|
||||||
</Box>
|
}}
|
||||||
|
>
|
||||||
|
<IconWrapper
|
||||||
|
color="rgba(250, 250, 250, 0.5)"
|
||||||
|
label="Apps"
|
||||||
|
selected={isApps}
|
||||||
|
>
|
||||||
|
<img src={AppIcon} />
|
||||||
|
</IconWrapper>
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
setDesktopSideView("groups");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconWrapper
|
||||||
|
color="rgba(250, 250, 250, 0.5)"
|
||||||
|
label="Hubs"
|
||||||
|
selected={isGroups}
|
||||||
|
>
|
||||||
|
<HubsIcon
|
||||||
|
height={30}
|
||||||
|
color={
|
||||||
|
hasUnreadGroups
|
||||||
|
? "var(--unread)"
|
||||||
|
: isGroups
|
||||||
|
? "white"
|
||||||
|
: "rgba(250, 250, 250, 0.5)"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</IconWrapper>
|
||||||
|
</ButtonBase>
|
||||||
|
<ButtonBase
|
||||||
|
onClick={() => {
|
||||||
|
setDesktopSideView("directs");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconWrapper
|
||||||
|
color="rgba(250, 250, 250, 0.5)"
|
||||||
|
label="Messaging"
|
||||||
|
selected={isDirects}
|
||||||
|
>
|
||||||
|
<MessagingIcon
|
||||||
|
height={30}
|
||||||
|
color={
|
||||||
|
hasUnreadDirects
|
||||||
|
? "var(--unread)"
|
||||||
|
: isDirects
|
||||||
|
? "white"
|
||||||
|
: "rgba(250, 250, 250, 0.5)"
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</IconWrapper>
|
||||||
|
</ButtonBase>
|
||||||
|
|
||||||
|
<Save isDesktop />
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -90,6 +90,7 @@ import { DesktopFooter } from "../Desktop/DesktopFooter";
|
|||||||
import { DesktopHeader } from "../Desktop/DesktopHeader";
|
import { DesktopHeader } from "../Desktop/DesktopHeader";
|
||||||
import { Apps } from "../Apps/Apps";
|
import { Apps } from "../Apps/Apps";
|
||||||
import { AppsNavBar } from "../Apps/AppsNavBar";
|
import { AppsNavBar } from "../Apps/AppsNavBar";
|
||||||
|
import { AppsDesktop } from "../Apps/AppsDesktop";
|
||||||
|
|
||||||
// let touchStartY = 0;
|
// let touchStartY = 0;
|
||||||
// let disablePullToRefresh = false;
|
// let disablePullToRefresh = false;
|
||||||
@ -375,7 +376,11 @@ export const Group = ({
|
|||||||
isOpenDrawerProfile,
|
isOpenDrawerProfile,
|
||||||
setIsOpenDrawerProfile,
|
setIsOpenDrawerProfile,
|
||||||
logoutFunc,
|
logoutFunc,
|
||||||
|
setDesktopViewMode,
|
||||||
|
desktopViewMode
|
||||||
}: GroupProps) => {
|
}: GroupProps) => {
|
||||||
|
const [desktopSideView, setDesktopSideView] = useState('groups')
|
||||||
|
|
||||||
const [secretKey, setSecretKey] = useState(null);
|
const [secretKey, setSecretKey] = useState(null);
|
||||||
const [secretKeyPublishDate, setSecretKeyPublishDate] = useState(null);
|
const [secretKeyPublishDate, setSecretKeyPublishDate] = useState(null);
|
||||||
const lastFetchedSecretKey = useRef(null);
|
const lastFetchedSecretKey = useRef(null);
|
||||||
@ -420,7 +425,6 @@ export const Group = ({
|
|||||||
const [mutedGroups, setMutedGroups] = useState([]);
|
const [mutedGroups, setMutedGroups] = useState([]);
|
||||||
const [mobileViewMode, setMobileViewMode] = useState("home");
|
const [mobileViewMode, setMobileViewMode] = useState("home");
|
||||||
const [mobileViewModeKeepOpen, setMobileViewModeKeepOpen] = useState("");
|
const [mobileViewModeKeepOpen, setMobileViewModeKeepOpen] = useState("");
|
||||||
const [desktopSideView, setDesktopSideView] = useState('groups')
|
|
||||||
const isFocusedRef = useRef(true);
|
const isFocusedRef = useRef(true);
|
||||||
const timestampEnterDataRef = useRef({});
|
const timestampEnterDataRef = useRef({});
|
||||||
const selectedGroupRef = useRef(null);
|
const selectedGroupRef = useRef(null);
|
||||||
@ -434,7 +438,21 @@ export const Group = ({
|
|||||||
const initiatedGetMembers = useRef(false);
|
const initiatedGetMembers = useRef(false);
|
||||||
const [groupChatTimestamps, setGroupChatTimestamps] = React.useState({});
|
const [groupChatTimestamps, setGroupChatTimestamps] = React.useState({});
|
||||||
const [appsMode, setAppsMode] = useState('home')
|
const [appsMode, setAppsMode] = useState('home')
|
||||||
|
const [isOpenSideViewDirects, setIsOpenSideViewDirects] = useState(false)
|
||||||
|
const [isOpenSideViewGroups, setIsOpenSideViewGroups] = useState(false)
|
||||||
|
|
||||||
|
const toggleSideViewDirects = ()=> {
|
||||||
|
if(isOpenSideViewGroups){
|
||||||
|
setIsOpenSideViewGroups(false)
|
||||||
|
}
|
||||||
|
setIsOpenSideViewDirects((prev)=> !prev)
|
||||||
|
}
|
||||||
|
const toggleSideViewGroups = ()=> {
|
||||||
|
if(isOpenSideViewDirects){
|
||||||
|
setIsOpenSideViewDirects(false)
|
||||||
|
}
|
||||||
|
setIsOpenSideViewGroups((prev)=> !prev)
|
||||||
|
}
|
||||||
useEffect(()=> {
|
useEffect(()=> {
|
||||||
timestampEnterDataRef.current = timestampEnterData
|
timestampEnterDataRef.current = timestampEnterData
|
||||||
}, [timestampEnterData])
|
}, [timestampEnterData])
|
||||||
@ -501,6 +519,7 @@ export const Group = ({
|
|||||||
});
|
});
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
};
|
};
|
||||||
|
console.log('desktopViewMode', desktopViewMode)
|
||||||
const getGroupDataSingle = async (groupId) => {
|
const getGroupDataSingle = async (groupId) => {
|
||||||
try {
|
try {
|
||||||
return new Promise((res, rej) => {
|
return new Promise((res, rej) => {
|
||||||
@ -1314,6 +1333,7 @@ export const Group = ({
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setSelectedGroup(findGroup);
|
setSelectedGroup(findGroup);
|
||||||
setMobileViewMode("group");
|
setMobileViewMode("group");
|
||||||
|
setDesktopSideView('home')
|
||||||
getTimestampEnterChat();
|
getTimestampEnterChat();
|
||||||
isLoadingOpenSectionFromNotification.current = false;
|
isLoadingOpenSectionFromNotification.current = false;
|
||||||
}, 200);
|
}, 200);
|
||||||
@ -1361,7 +1381,7 @@ export const Group = ({
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setSelectedGroup(findGroup);
|
setSelectedGroup(findGroup);
|
||||||
setMobileViewMode("group");
|
setMobileViewMode("group");
|
||||||
|
setDesktopSideView('home')
|
||||||
getGroupAnnouncements();
|
getGroupAnnouncements();
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
@ -1416,6 +1436,7 @@ export const Group = ({
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setSelectedGroup(findGroup);
|
setSelectedGroup(findGroup);
|
||||||
setMobileViewMode("group");
|
setMobileViewMode("group");
|
||||||
|
setDesktopSideView('home')
|
||||||
getGroupAnnouncements();
|
getGroupAnnouncements();
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
@ -1439,6 +1460,8 @@ export const Group = ({
|
|||||||
}
|
}
|
||||||
if (!isMobile) {
|
if (!isMobile) {
|
||||||
}
|
}
|
||||||
|
setDesktopViewMode('home')
|
||||||
|
|
||||||
setGroupSection("default");
|
setGroupSection("default");
|
||||||
clearAllQueues();
|
clearAllQueues();
|
||||||
await new Promise((res) => {
|
await new Promise((res) => {
|
||||||
@ -1462,6 +1485,8 @@ export const Group = ({
|
|||||||
setMemberCountFromSecretKeyData(null);
|
setMemberCountFromSecretKeyData(null);
|
||||||
setTriedToFetchSecretKey(false);
|
setTriedToFetchSecretKey(false);
|
||||||
setFirstSecretKeyInCreation(false);
|
setFirstSecretKeyInCreation(false);
|
||||||
|
setIsOpenSideViewDirects(false)
|
||||||
|
setIsOpenSideViewGroups(false)
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToAnnouncements = async () => {
|
const goToAnnouncements = async () => {
|
||||||
@ -1937,6 +1962,7 @@ export const Group = ({
|
|||||||
// }
|
// }
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setMobileViewMode("group");
|
setMobileViewMode("group");
|
||||||
|
setDesktopSideView('home')
|
||||||
initiatedGetMembers.current = false;
|
initiatedGetMembers.current = false;
|
||||||
clearAllQueues();
|
clearAllQueues();
|
||||||
setSelectedDirect(null);
|
setSelectedDirect(null);
|
||||||
@ -2165,8 +2191,8 @@ export const Group = ({
|
|||||||
alignItems: "flex-start",
|
alignItems: "flex-start",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!isMobile && desktopSideView === 'groups' && renderGroups()}
|
{!isMobile && ((desktopSideView === 'groups' && desktopViewMode !== 'apps') || isOpenSideViewGroups) && renderGroups()}
|
||||||
{!isMobile && desktopSideView === 'directs' && renderDirects()}
|
{!isMobile && ((desktopSideView === 'directs' && desktopViewMode !== 'apps') || isOpenSideViewDirects) && renderDirects()}
|
||||||
|
|
||||||
<Box
|
<Box
|
||||||
sx={{
|
sx={{
|
||||||
@ -2623,10 +2649,16 @@ export const Group = ({
|
|||||||
groupsAnnHasUnread}
|
groupsAnnHasUnread}
|
||||||
hasUnreadDirects={directChatHasUnread}
|
hasUnreadDirects={directChatHasUnread}
|
||||||
myName={userInfo?.name || null}
|
myName={userInfo?.name || null}
|
||||||
isHome={groupSection === "home"}
|
isHome={groupSection === "home" && desktopViewMode === 'home'}
|
||||||
isGroups={desktopSideView === 'groups'}
|
isGroups={desktopSideView === 'groups' && desktopViewMode !== 'apps'}
|
||||||
isDirects={desktopSideView === 'directs'}
|
isDirects={desktopSideView === 'directs' && desktopViewMode !== 'apps'}
|
||||||
|
setDesktopViewMode={setDesktopViewMode}
|
||||||
|
isApps={desktopViewMode === 'apps'}
|
||||||
setDesktopSideView={setDesktopSideView}
|
setDesktopSideView={setDesktopSideView}
|
||||||
|
desktopViewMode={desktopViewMode}
|
||||||
|
hide={desktopViewMode === 'apps'}
|
||||||
|
setIsOpenSideViewDirects={setIsOpenSideViewDirects}
|
||||||
|
setIsOpenSideViewGroups={setIsOpenSideViewGroups}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{isMobile && mobileViewMode === "home" && (
|
{isMobile && mobileViewMode === "home" && (
|
||||||
@ -2648,11 +2680,16 @@ export const Group = ({
|
|||||||
{isMobile && (
|
{isMobile && (
|
||||||
<Apps mode={appsMode} setMode={setAppsMode} show={mobileViewMode === "apps"} myName={userInfo?.name} />
|
<Apps mode={appsMode} setMode={setAppsMode} show={mobileViewMode === "apps"} myName={userInfo?.name} />
|
||||||
)}
|
)}
|
||||||
{
|
{!isMobile && (
|
||||||
!isMobile && !selectedGroup &&
|
<AppsDesktop toggleSideViewGroups={toggleSideViewGroups} toggleSideViewDirects={toggleSideViewDirects} goToHome={goToHome} mode={appsMode} setMode={setAppsMode} setDesktopSideView={setDesktopSideView} hasUnreadDirects={directChatHasUnread} show={desktopViewMode === "apps"} myName={userInfo?.name} isGroups={isOpenSideViewGroups}
|
||||||
groupSection === "home" && (
|
isDirects={isOpenSideViewDirects} hasUnreadGroups={groupChatHasUnread ||
|
||||||
|
groupsAnnHasUnread} />
|
||||||
<HomeDesktop
|
)}
|
||||||
|
|
||||||
|
|
||||||
|
{!isMobile && !selectedGroup &&
|
||||||
|
groupSection === "home" && desktopViewMode !== "apps" && (
|
||||||
|
<HomeDesktop
|
||||||
refreshHomeDataFunc={refreshHomeDataFunc}
|
refreshHomeDataFunc={refreshHomeDataFunc}
|
||||||
myAddress={myAddress}
|
myAddress={myAddress}
|
||||||
isLoadingGroups={isLoadingGroups}
|
isLoadingGroups={isLoadingGroups}
|
||||||
@ -2666,7 +2703,9 @@ export const Group = ({
|
|||||||
setOpenAddGroup={setOpenAddGroup}
|
setOpenAddGroup={setOpenAddGroup}
|
||||||
setMobileViewMode={setMobileViewMode}
|
setMobileViewMode={setMobileViewMode}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
||||||
</Box>
|
</Box>
|
||||||
<AuthenticatedContainerInnerRight
|
<AuthenticatedContainerInnerRight
|
||||||
sx={{
|
sx={{
|
||||||
@ -2674,188 +2713,10 @@ export const Group = ({
|
|||||||
width: "31px",
|
width: "31px",
|
||||||
// minWidth: "135px",
|
// minWidth: "135px",
|
||||||
padding: "5px",
|
padding: "5px",
|
||||||
display: isMobile ? "none" : "flex",
|
display: (isMobile || desktopViewMode === 'apps') ? "none" : "flex",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* <Spacer height="20px" />
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
gap: "3px",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
width: "100%",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
onClick={goToHome}
|
|
||||||
>
|
|
||||||
<HomeIcon
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
color: groupSection === "home" ? "#1444c7" : "white",
|
|
||||||
opacity: groupSection === "home" ? 1 : 0.4,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: "12px",
|
|
||||||
color: groupSection === "home" ? "#1444c7" : "white",
|
|
||||||
opacity: groupSection === "home" ? 1 : 0.4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Home
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
{selectedGroup && (
|
|
||||||
<>
|
|
||||||
<Spacer height="20px" />
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
gap: "3px",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
width: "100%",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
onClick={goToAnnouncements}
|
|
||||||
>
|
|
||||||
<CampaignIcon
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
color: isUnread
|
|
||||||
? "red"
|
|
||||||
: groupSection === "announcement"
|
|
||||||
? "#1444c7"
|
|
||||||
: "white",
|
|
||||||
opacity: groupSection === "announcement" ? 1 : 0.4,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: "12px",
|
|
||||||
color: isUnread
|
|
||||||
? "red"
|
|
||||||
: groupSection === "announcement"
|
|
||||||
? "#1444c7"
|
|
||||||
: "white",
|
|
||||||
opacity: groupSection === "announcement" ? 1 : 0.4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Announcements
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Spacer height="20px" />
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
gap: "3px",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
width: "100%",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
onClick={goToChat}
|
|
||||||
>
|
|
||||||
<ChatIcon
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
color: isUnreadChat
|
|
||||||
? "red"
|
|
||||||
: groupSection === "chat"
|
|
||||||
? "#1444c7"
|
|
||||||
: "white",
|
|
||||||
opacity: groupSection === "chat" ? 1 : 0.4,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: "12px",
|
|
||||||
color: isUnreadChat
|
|
||||||
? "red"
|
|
||||||
: groupSection === "chat"
|
|
||||||
? "#1444c7"
|
|
||||||
: "white",
|
|
||||||
opacity: groupSection === "chat" ? 1 : 0.4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Chat
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Spacer height="20px" />
|
|
||||||
<Box
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
gap: "3px",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
width: "100%",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
onClick={() => {
|
|
||||||
setGroupSection("forum");
|
|
||||||
setSelectedDirect(null);
|
|
||||||
setNewChat(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ForumIcon
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
color: groupSection === "forum" ? "#1444c7" : "white",
|
|
||||||
opacity: groupSection === "forum" ? 1 : 0.4,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: "12px",
|
|
||||||
color: groupSection === "forum" ? "#1444c7" : "white",
|
|
||||||
opacity: groupSection === "forum" ? 1 : 0.4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Forum
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Spacer height="20px" />
|
|
||||||
<Box
|
|
||||||
onClick={() => setOpenManageMembers(true)}
|
|
||||||
sx={{
|
|
||||||
display: "flex",
|
|
||||||
gap: "3px",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
width: "100%",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<PeopleIcon
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
color: "white",
|
|
||||||
opacity: 0.4,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Typography
|
|
||||||
sx={{
|
|
||||||
fontSize: "12px",
|
|
||||||
color: "white",
|
|
||||||
opacity: 0.4,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Members
|
|
||||||
</Typography>
|
|
||||||
</Box>
|
|
||||||
<Spacer height="20px" />
|
|
||||||
</>
|
|
||||||
)} */}
|
|
||||||
|
|
||||||
{/* <SettingsIcon
|
|
||||||
sx={{
|
|
||||||
cursor: "pointer",
|
|
||||||
color: "white",
|
|
||||||
}}
|
|
||||||
/> */}
|
|
||||||
</AuthenticatedContainerInnerRight>
|
</AuthenticatedContainerInnerRight>
|
||||||
<LoadingSnackbar
|
<LoadingSnackbar
|
||||||
open={isLoadingGroup}
|
open={isLoadingGroup}
|
||||||
@ -2915,7 +2776,7 @@ export const Group = ({
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{(isMobile && isMobile && mobileViewMode === "apps" && appsMode !== 'home') && !mobileViewModeKeepOpen && (
|
{(isMobile && mobileViewMode === "apps" && appsMode !== 'home') && !mobileViewModeKeepOpen && (
|
||||||
<>
|
<>
|
||||||
<AppsNavBar />
|
<AppsNavBar />
|
||||||
</>
|
</>
|
||||||
@ -2924,236 +2785,4 @@ export const Group = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// {isMobile && (
|
|
||||||
// <Box
|
|
||||||
// sx={{
|
|
||||||
// display: "flex",
|
|
||||||
// alignItems: "center",
|
|
||||||
// justifyContent: "center",
|
|
||||||
// flexDirection: "column",
|
|
||||||
// width: "100%",
|
|
||||||
// height: "75px", // Keep the height at 75px
|
|
||||||
// background: "rgba(0, 0, 0, 0.1)",
|
|
||||||
// padding: "0px", // Remove unnecessary padding
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// <Grid
|
|
||||||
// container
|
|
||||||
// spacing={0.5}
|
|
||||||
// sx={{ width: "100%", justifyContent: "space-around" }}
|
|
||||||
// >
|
|
||||||
// {selectedGroup && (
|
|
||||||
// <>
|
|
||||||
// <Grid item xs={4} sx={{
|
|
||||||
// display: 'flex'
|
|
||||||
// }}>
|
|
||||||
// <Button
|
|
||||||
// fullWidth
|
|
||||||
// size="small"
|
|
||||||
// variant="contained"
|
|
||||||
// startIcon={<AnnouncementsIcon />}
|
|
||||||
// sx={{
|
|
||||||
// padding: "4px 6px",
|
|
||||||
// color:
|
|
||||||
// groupSection === "announcement" ? "black" : "white",
|
|
||||||
// backgroundColor: isUnread
|
|
||||||
// ? "red"
|
|
||||||
// : groupSection === "announcement"
|
|
||||||
// ? "white"
|
|
||||||
// : "black",
|
|
||||||
// "&:hover": {
|
|
||||||
// backgroundColor: isUnread
|
|
||||||
// ? "red"
|
|
||||||
// : groupSection === "announcement"
|
|
||||||
// ? "white"
|
|
||||||
// : "black",
|
|
||||||
// },
|
|
||||||
// "&:active": {
|
|
||||||
// backgroundColor: isUnread
|
|
||||||
// ? "red"
|
|
||||||
// : groupSection === "announcement"
|
|
||||||
// ? "white"
|
|
||||||
// : "black",
|
|
||||||
// },
|
|
||||||
// "&:focus": {
|
|
||||||
// backgroundColor: isUnread
|
|
||||||
// ? "red"
|
|
||||||
// : groupSection === "announcement"
|
|
||||||
// ? "white"
|
|
||||||
// : "black",
|
|
||||||
// },
|
|
||||||
// }}
|
|
||||||
// onClick={goToAnnouncements}
|
|
||||||
// >
|
|
||||||
// ANN
|
|
||||||
// </Button>
|
|
||||||
// </Grid>
|
|
||||||
// <Grid item xs={4} sx={{
|
|
||||||
// display: 'flex'
|
|
||||||
// }}>
|
|
||||||
// <Button
|
|
||||||
// fullWidth
|
|
||||||
// size="small"
|
|
||||||
// variant="contained"
|
|
||||||
// startIcon={<ChatIcon />}
|
|
||||||
// sx={{
|
|
||||||
// padding: "4px 6px",
|
|
||||||
// color: groupSection === "chat" ? "black" : "white",
|
|
||||||
// backgroundColor: isUnreadChat
|
|
||||||
// ? "red"
|
|
||||||
// : groupSection === "chat"
|
|
||||||
// ? "white"
|
|
||||||
// : "black",
|
|
||||||
// "&:hover": {
|
|
||||||
// backgroundColor: isUnreadChat
|
|
||||||
// ? "red"
|
|
||||||
// : groupSection === "chat"
|
|
||||||
// ? "white"
|
|
||||||
// : "black", // Same logic for hover
|
|
||||||
// },
|
|
||||||
// "&:active": {
|
|
||||||
// backgroundColor: isUnreadChat
|
|
||||||
// ? "red"
|
|
||||||
// : groupSection === "chat"
|
|
||||||
// ? "white"
|
|
||||||
// : "black", // Same logic for active
|
|
||||||
// },
|
|
||||||
// "&:focus": {
|
|
||||||
// backgroundColor: isUnreadChat
|
|
||||||
// ? "red"
|
|
||||||
// : groupSection === "chat"
|
|
||||||
// ? "white"
|
|
||||||
// : "black", // Same logic for focus
|
|
||||||
// },
|
|
||||||
// }}
|
|
||||||
// onClick={goToChat}
|
|
||||||
// >
|
|
||||||
// Chat
|
|
||||||
// </Button>
|
|
||||||
// </Grid>
|
|
||||||
// <Grid item xs={4} sx={{
|
|
||||||
// display: 'flex'
|
|
||||||
// }}>
|
|
||||||
// <Button
|
|
||||||
// fullWidth
|
|
||||||
// size="small"
|
|
||||||
// variant="contained"
|
|
||||||
// startIcon={<ForumIcon />}
|
|
||||||
// sx={{
|
|
||||||
// padding: "4px 6px",
|
|
||||||
// color: groupSection === "forum" ? "black" : "white",
|
|
||||||
// backgroundColor:
|
|
||||||
// groupSection === "forum" ? "white" : "black",
|
|
||||||
// "&:hover": {
|
|
||||||
// backgroundColor: groupSection === "forum" ? "white" : "black", // Hover state
|
|
||||||
// },
|
|
||||||
// "&:active": {
|
|
||||||
// backgroundColor: groupSection === "forum" ? "white" : "black", // Active state
|
|
||||||
// },
|
|
||||||
// "&:focus": {
|
|
||||||
// backgroundColor: groupSection === "forum" ? "white" : "black", // Focus state
|
|
||||||
// },
|
|
||||||
// }}
|
|
||||||
// onClick={() => {
|
|
||||||
// setSelectedDirect(null);
|
|
||||||
// setNewChat(false)
|
|
||||||
// setGroupSection("forum")
|
|
||||||
// } }
|
|
||||||
// >
|
|
||||||
// Forum
|
|
||||||
// </Button>
|
|
||||||
// </Grid>
|
|
||||||
// <Grid item xs={4} sx={{
|
|
||||||
// display: 'flex'
|
|
||||||
// }}>
|
|
||||||
// <Button
|
|
||||||
// fullWidth
|
|
||||||
// size="small"
|
|
||||||
// variant="contained"
|
|
||||||
// startIcon={<GroupIcon />}
|
|
||||||
// sx={{ padding: "4px 6px", backgroundColor: "black", "&:hover": {
|
|
||||||
// backgroundColor: "black", // Hover state
|
|
||||||
// },
|
|
||||||
// "&:active": {
|
|
||||||
// backgroundColor: "black", // Active state
|
|
||||||
// },
|
|
||||||
// "&:focus": {
|
|
||||||
// backgroundColor: "black", // Focus state
|
|
||||||
// }, }}
|
|
||||||
// onClick={() => setOpenManageMembers(true)}
|
|
||||||
// >
|
|
||||||
// Members
|
|
||||||
// </Button>
|
|
||||||
// </Grid>
|
|
||||||
// </>
|
|
||||||
// )}
|
|
||||||
|
|
||||||
// {/* Second row: Groups, Home, Profile */}
|
|
||||||
// <Grid item xs={4} sx={{
|
|
||||||
// display: 'flex',
|
|
||||||
// }}>
|
|
||||||
// <Button
|
|
||||||
// fullWidth
|
|
||||||
// size="small"
|
|
||||||
// variant="contained"
|
|
||||||
// startIcon={<GroupIcon />}
|
|
||||||
// sx={{
|
|
||||||
// padding: "2px 4px",
|
|
||||||
// backgroundColor:
|
|
||||||
// groupChatHasUnread ||
|
|
||||||
// groupsAnnHasUnread ||
|
|
||||||
// directChatHasUnread
|
|
||||||
// ? "red"
|
|
||||||
// : "black",
|
|
||||||
// "&:hover": {
|
|
||||||
// backgroundColor:
|
|
||||||
// groupChatHasUnread || groupsAnnHasUnread || directChatHasUnread
|
|
||||||
// ? "red"
|
|
||||||
// : "black", // Hover state follows the same logic
|
|
||||||
// },
|
|
||||||
// "&:active": {
|
|
||||||
// backgroundColor:
|
|
||||||
// groupChatHasUnread || groupsAnnHasUnread || directChatHasUnread
|
|
||||||
// ? "red"
|
|
||||||
// : "black", // Active state follows the same logic
|
|
||||||
// },
|
|
||||||
// "&:focus": {
|
|
||||||
// backgroundColor:
|
|
||||||
// groupChatHasUnread || groupsAnnHasUnread || directChatHasUnread
|
|
||||||
// ? "red"
|
|
||||||
// : "black", // Focus state follows the same logic
|
|
||||||
// },
|
|
||||||
// }}
|
|
||||||
// onClick={() => {
|
|
||||||
// setIsOpenDrawer(true);
|
|
||||||
// setDrawerMode("groups");
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// {chatMode === "groups" ? "Groups" : "Direct"}
|
|
||||||
// </Button>
|
|
||||||
// </Grid>
|
|
||||||
// <Grid item xs={2} sx={{
|
|
||||||
// display: 'flex',
|
|
||||||
// justifyContent: 'center'
|
|
||||||
// }}>
|
|
||||||
// <IconButton
|
|
||||||
// sx={{ padding: "0", color: "white" }} // Reduce padding for icons
|
|
||||||
// onClick={goToHome}
|
|
||||||
// >
|
|
||||||
// <HomeIcon />
|
|
||||||
// </IconButton>
|
|
||||||
// </Grid>
|
|
||||||
// <Grid item xs={2} sx={{
|
|
||||||
// display: 'flex',
|
|
||||||
// justifyContent: 'center'
|
|
||||||
// }}>
|
|
||||||
// <IconButton
|
|
||||||
// sx={{ padding: "0", color: "white" }} // Reduce padding for icons
|
|
||||||
// onClick={() => setIsOpenDrawerProfile(true)}
|
|
||||||
// >
|
|
||||||
// <PersonIcon />
|
|
||||||
// </IconButton>
|
|
||||||
// </Grid>
|
|
||||||
// </Grid>
|
|
||||||
// </Box>
|
|
||||||
// )}
|
|
||||||
|
@ -8,7 +8,8 @@ import { MyContext } from '../../App';
|
|||||||
import { getFee } from '../../background';
|
import { getFee } from '../../background';
|
||||||
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
import { CustomizedSnackbars } from '../Snackbar/Snackbar';
|
||||||
import { SaveIcon } from '../../assets/svgs/SaveIcon';
|
import { SaveIcon } from '../../assets/svgs/SaveIcon';
|
||||||
export const Save = () => {
|
import { IconWrapper } from '../Desktop/DesktopFooter';
|
||||||
|
export const Save = ({isDesktop}) => {
|
||||||
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
const [pinnedApps, setPinnedApps] = useRecoilState(sortablePinnedAppsAtom);
|
||||||
const [settingsQdnLastUpdated, setSettingsQdnLastUpdated] = useRecoilState(settingsQDNLastUpdatedAtom);
|
const [settingsQdnLastUpdated, setSettingsQdnLastUpdated] = useRecoilState(settingsQDNLastUpdatedAtom);
|
||||||
const [settingsLocalLastUpdated] = useRecoilState(settingsLocalLastUpdatedAtom);
|
const [settingsLocalLastUpdated] = useRecoilState(settingsLocalLastUpdatedAtom);
|
||||||
@ -130,9 +131,22 @@ export const Save = () => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ButtonBase onClick={saveToQdn} disabled={!hasChanged || !canSave || isLoading || settingsQdnLastUpdated === -100}>
|
<ButtonBase onClick={saveToQdn} disabled={!hasChanged || !canSave || isLoading || settingsQdnLastUpdated === -100}>
|
||||||
<SaveIcon
|
{isDesktop ? (
|
||||||
|
<IconWrapper
|
||||||
|
color="rgba(250, 250, 250, 0.5)"
|
||||||
|
label="Save"
|
||||||
|
selected={false}
|
||||||
|
>
|
||||||
|
<SaveIcon
|
||||||
color={settingsQdnLastUpdated === -100 ? '#8F8F91' : (hasChanged && !isLoading) ? '#5EB049' : '#8F8F91'}
|
color={settingsQdnLastUpdated === -100 ? '#8F8F91' : (hasChanged && !isLoading) ? '#5EB049' : '#8F8F91'}
|
||||||
/>
|
/>
|
||||||
|
</IconWrapper>
|
||||||
|
) : (
|
||||||
|
<SaveIcon
|
||||||
|
color={settingsQdnLastUpdated === -100 ? '#8F8F91' : (hasChanged && !isLoading) ? '#5EB049' : '#8F8F91'}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
</ButtonBase>
|
</ButtonBase>
|
||||||
<CustomizedSnackbars
|
<CustomizedSnackbars
|
||||||
duration={3500}
|
duration={3500}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
--bg-primary : rgba(31, 32, 35, 1);
|
--bg-primary : rgba(31, 32, 35, 1);
|
||||||
--bg-2: #27282c;
|
--bg-2: #27282c;
|
||||||
--bg-3: rgba(0, 0, 0, 0.1);
|
--bg-3: rgba(0, 0, 0, 0.1);
|
||||||
--unread: rgba(255, 0, 0, 1);
|
--unread: #B14646;
|
||||||
--apps-circle: #1F2023
|
--apps-circle: #1F2023
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,4 +103,8 @@ body {
|
|||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
overscroll-behavior:none !important;
|
overscroll-behavior:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.swiper {
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { useCallback, useEffect } from 'react';
|
import { useCallback, useEffect } from 'react';
|
||||||
|
import { isMobile } from './App';
|
||||||
|
|
||||||
export const useAppFullScreen = (setFullScreen) => {
|
export const useAppFullScreen = (setFullScreen) => {
|
||||||
const enterFullScreen = useCallback(() => {
|
const enterFullScreen = useCallback(() => {
|
||||||
@ -27,6 +28,7 @@ export const useAppFullScreen = (setFullScreen) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const toggleFullScreen = useCallback(() => {
|
const toggleFullScreen = useCallback(() => {
|
||||||
|
if(!isMobile) return
|
||||||
if (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement) {
|
if (document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement || document.msFullscreenElement) {
|
||||||
exitFullScreen();
|
exitFullScreen();
|
||||||
setFullScreen(false)
|
setFullScreen(false)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user