diff --git a/src/App.tsx b/src/App.tsx index ab48b87..557e90b 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -149,7 +149,7 @@ const defaultValues: MyContextInterface = { message: "", }, }; -export let isMobile = false; +export let isMobile = true; const isMobileDevice = () => { const userAgent = navigator.userAgent || navigator.vendor || window.opera; diff --git a/src/atoms/global.ts b/src/atoms/global.ts index 05b615a..cc1f02f 100644 --- a/src/atoms/global.ts +++ b/src/atoms/global.ts @@ -5,7 +5,7 @@ export const sortablePinnedAppsAtom = atom({ key: 'sortablePinnedAppsFromAtom', default: [{ name: 'Q-Tube', - servic: 'APP' + service: 'APP' }, { name: 'Q-Mail', service: 'APP' diff --git a/src/components/Apps/AppInfo.tsx b/src/components/Apps/AppInfo.tsx index b99c4bd..ad36163 100644 --- a/src/components/Apps/AppInfo.tsx +++ b/src/components/Apps/AppInfo.tsx @@ -28,9 +28,17 @@ import LogoSelected from "../../assets/svgs/LogoSelected.svg"; import { Spacer } from "../../common/Spacer"; import { executeEvent } from "../../utils/events"; import { AppRating } from "./AppRating"; +import { settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom } from "../../atoms/global"; +import { saveToLocalStorage } from "./AppsNavBar"; +import { useRecoilState, useSetRecoilState } from "recoil"; export const AppInfo = ({ app, myName }) => { const isInstalled = app?.status?.status === "READY"; + const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(sortablePinnedAppsAtom); + + const isSelectedAppPinned = !!sortablePinnedApps?.find((item)=> item?.name === app?.name && item?.service === app?.service) + const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom); + return ( { + + { + setSortablePinnedApps((prev) => { + let updatedApps; + + if (isSelectedAppPinned) { + // Remove the selected app if it is pinned + updatedApps = prev.filter( + (item) => !(item?.name === app?.name && item?.service === app?.service) + ); + } else { + // Add the selected app if it is not pinned + updatedApps = [...prev, { + name: app?.name, + service: app?.service, + }]; + } + + saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', updatedApps) + return updatedApps; + }); + setSettingsLocalLastUpdated(Date.now()) + }} + sx={{ + backgroundColor: "#359ff7ff", + width: "100%", + maxWidth: "320px", + height: "29px", + opacity: isSelectedAppPinned ? 0.6 : 1 + }} + > + + {!isMobile ? ( + <> + {isSelectedAppPinned ? 'Unpin from dashboard' : 'Pin to dashboard'} + + ) : ( + <> + {isSelectedAppPinned ? 'Unpin' : 'Pin'} + + )} + + + { executeEvent("addTab", { @@ -121,6 +179,8 @@ export const AppInfo = ({ app, myName }) => { {isInstalled ? "Open" : "Download"} + + diff --git a/src/components/Apps/AppInfoSnippet.tsx b/src/components/Apps/AppInfoSnippet.tsx index 34e7bb5..01a7083 100644 --- a/src/components/Apps/AppInfoSnippet.tsx +++ b/src/components/Apps/AppInfoSnippet.tsx @@ -12,16 +12,23 @@ import { AppInfoUserName, } from "./Apps-styles"; import { Avatar, ButtonBase } from "@mui/material"; -import { getBaseApiReact } from "../../App"; +import { getBaseApiReact, isMobile } from "../../App"; import LogoSelected from "../../assets/svgs/LogoSelected.svg"; import { Spacer } from "../../common/Spacer"; import { executeEvent } from "../../utils/events"; import { AppRating } from "./AppRating"; +import { useRecoilState, useSetRecoilState } from "recoil"; +import { settingsLocalLastUpdatedAtom, sortablePinnedAppsAtom } from "../../atoms/global"; +import { saveToLocalStorage } from "./AppsNavBar"; export const AppInfoSnippet = ({ app, myName, isFromCategory }) => { const isInstalled = app?.status?.status === 'READY' + const [sortablePinnedApps, setSortablePinnedApps] = useRecoilState(sortablePinnedAppsAtom); + + const isSelectedAppPinned = !!sortablePinnedApps?.find((item)=> item?.name === app?.name && item?.service === app?.service) + const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom); return ( @@ -74,6 +81,7 @@ export const AppInfoSnippet = ({ app, myName, isFromCategory }) => { + { if(isFromCategory){ executeEvent("selectedAppInfoCategory", { @@ -97,7 +105,41 @@ export const AppInfoSnippet = ({ app, myName, isFromCategory }) => { - + + {!isMobile && ( + { + + setSortablePinnedApps((prev) => { + let updatedApps; + + if (isSelectedAppPinned) { + // Remove the selected app if it is pinned + updatedApps = prev.filter( + (item) => !(item?.name === app?.name && item?.service === app?.service) + ); + } else { + // Add the selected app if it is not pinned + updatedApps = [...prev, { + name: app?.name, + service: app?.service, + }]; + } + + saveToLocalStorage('ext_saved_settings', 'sortablePinnedApps', updatedApps) + return updatedApps; + }); + setSettingsLocalLastUpdated(Date.now()) + }} sx={{ + backgroundColor: '#359ff7ff', + opacity: isSelectedAppPinned ? 0.6 : 1 + + }}> + {isSelectedAppPinned ? 'Unpin' : 'Pin'} + + )} + { executeEvent("addTab", { diff --git a/src/components/Apps/AppsHome.tsx b/src/components/Apps/AppsHome.tsx index 2927694..218ad07 100644 --- a/src/components/Apps/AppsHome.tsx +++ b/src/components/Apps/AppsHome.tsx @@ -3,6 +3,7 @@ import { AppCircle, AppCircleContainer, AppCircleLabel, + AppLibrarySubTitle, AppsContainer, AppsParent, } from "./Apps-styles"; @@ -12,9 +13,26 @@ import { getBaseApiReact } from "../../App"; import LogoSelected from "../../assets/svgs/LogoSelected.svg"; import { executeEvent } from "../../utils/events"; import { SortablePinnedApps } from "./SortablePinnedApps"; +import { Spacer } from "../../common/Spacer"; export const AppsHome = ({ setMode, myApp, myWebsite, availableQapps }) => { return ( + <> + + + Apps Dashboard + + + + + { @@ -32,5 +50,6 @@ export const AppsHome = ({ setMode, myApp, myWebsite, availableQapps }) => { + ); }; diff --git a/src/components/Apps/AppsHomeDesktop.tsx b/src/components/Apps/AppsHomeDesktop.tsx index 0f3e958..e7346ff 100644 --- a/src/components/Apps/AppsHomeDesktop.tsx +++ b/src/components/Apps/AppsHomeDesktop.tsx @@ -3,6 +3,7 @@ import { AppCircle, AppCircleContainer, AppCircleLabel, + AppLibrarySubTitle, AppsContainer, AppsParent, } from "./Apps-styles"; @@ -12,30 +13,61 @@ import { getBaseApiReact, isMobile } from "../../App"; import LogoSelected from "../../assets/svgs/LogoSelected.svg"; import { executeEvent } from "../../utils/events"; import { SortablePinnedApps } from "./SortablePinnedApps"; +import { Spacer } from "../../common/Spacer"; -export const AppsHomeDesktop = ({ setMode, myApp, myWebsite, availableQapps }) => { +export const AppsHomeDesktop = ({ + setMode, + myApp, + myWebsite, + availableQapps, +}) => { return ( - + <> + + + Apps Dashboard + + + + { setMode("library"); }} > - + + Library - - - + + + ); }; diff --git a/src/components/Apps/AppsLibrary.tsx b/src/components/Apps/AppsLibrary.tsx index d719db8..f3bd7c1 100644 --- a/src/components/Apps/AppsLibrary.tsx +++ b/src/components/Apps/AppsLibrary.tsx @@ -25,11 +25,13 @@ 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 ReturnSVG from '../../assets/svgs/Return.svg' import { Spacer } from "../../common/Spacer"; import { AppInfoSnippet } from "./AppInfoSnippet"; import { Virtuoso } from "react-virtuoso"; import { executeEvent } from "../../utils/events"; +import { ComposeP, MailIconImg, ShowMessageReturnButton } from "../Group/Forum/Mail-styles"; const officialAppList = [ "q-tube", "q-blog", @@ -160,6 +162,15 @@ export const AppsLibrary = ({ availableQapps, setMode, myName, hasPublishApp, i + { + setMode('home') + }}> + + Return to Apps Dashboard + + {searchedList?.length > 0 ? ( - + + + { + setMode('home') + }}> + + Return to Apps Dashboard + + {searchedList?.length > 0 ? ( { - const [tabs, setTabs] = useState([]) - const [selectedTab, setSelectedTab] = useState(null) - const [isNewTabWindow, setIsNewTabWindow] = useState(false) + 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 [sortablePinnedApps, setSortablePinnedApps] = useRecoilState( + sortablePinnedAppsAtom + ); - const setSettingsLocalLastUpdated = useSetRecoilState(settingsLocalLastUpdatedAtom); + const setSettingsLocalLastUpdated = useSetRecoilState( + settingsLocalLastUpdatedAtom + ); const handleClick = (event) => { setAnchorEl(event.currentTarget); @@ -70,20 +87,24 @@ export const AppsNavBar = () => { 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'); + 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' }); + 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) + const { tabs, selectedTab, isNewTabWindow } = e.detail?.data; + + setTabs([...tabs]); + setSelectedTab(!selectedTab ? nulll : { ...selectedTab }); + setIsNewTabWindow(isNewTabWindow); }; useEffect(() => { @@ -94,70 +115,94 @@ export const AppsNavBar = () => { }; }, []); - - const isSelectedAppPinned = !!sortablePinnedApps?.find((item)=> item?.name === selectedTab?.name && item?.service === selectedTab?.service) + const isSelectedAppPinned = !!sortablePinnedApps?.find( + (item) => + item?.name === selectedTab?.name && item?.service === selectedTab?.service + ); return ( - { - executeEvent("navigateBack", { - }); - }}> + { + executeEvent("navigateBack", {}); + }} + > - {tabs?.map((tab) => ( - } // Pass custom component + ref={tabsRef} + aria-label="basic tabs example" + variant="scrollable" // Make tabs scrollable + scrollButtons={false} sx={{ - "&.Mui-selected": { - color: "white", + "& .MuiTabs-indicator": { + backgroundColor: "white", }, - padding: '0px', - margin: '0px', - minWidth: '0px', - width: '50px' + maxWidth: `calc(100vw - 150px)`, // Ensure the tabs container fits within the available space + overflow: "hidden", // Prevents overflow on small screens }} - /> - ))} - + > + {tabs?.map((tab) => ( + + } // Pass custom component + sx={{ + "&.Mui-selected": { + color: "white", + }, + padding: "0px", + margin: "0px", + minWidth: "0px", + width: "50px", + }} + /> + ))} + - - { - setSelectedTab(null) - executeEvent("newTabWindow", { - }); - }}> - - - { - if(!selectedTab) return - handleClick(e) - }}> - - - + {selectedTab && ( + + { + setSelectedTab(null); + executeEvent("newTabWindow", {}); + }} + > + + + { + if (!selectedTab) return; + handleClick(e); + }} + > + + + + )} + { "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' - }, + 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' - }} - + }, + }} + sx={{ + marginTop: "10px", + }} > { 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(); - }} - > - - - - { + 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, }, - }} primary={`${isSelectedAppPinned ? 'Unpin app' : 'Pin app'}`} /> - - { - executeEvent('refreshApp', { - tabId: selectedTab?.tabId - }) + ]; + } + + saveToLocalStorage( + "ext_saved_settings", + "sortablePinnedApps", + updatedApps + ); + return updatedApps; + }); + setSettingsLocalLastUpdated(Date.now()); + handleClose(); }} > - - + + - + - + { + executeEvent("refreshApp", { + tabId: selectedTab?.tabId, + }); + handleClose(); + }} + > + + + + + + ); };