diff --git a/Website/src/activitys/FetchTextActivity.tsx b/Website/src/activitys/FetchTextActivity.tsx index b73a9e97..da3eb67e 100644 --- a/Website/src/activitys/FetchTextActivity.tsx +++ b/Website/src/activitys/FetchTextActivity.tsx @@ -4,8 +4,11 @@ import { useActivity } from "@Hooks/useActivity"; import React from "react"; import { Toolbar } from "@Components/onsenui/Toolbar"; import { Page } from "@Components/onsenui/Page"; -import { useStrings } from "@Hooks/useStrings"; -import { useTheme } from "@Hooks/useTheme"; +import Stack from "@mui/material/Stack"; +import Box from "@mui/material/Box"; +import Icon from "@Components/Icon"; +import { useNetwork } from "@Hooks/useNetwork"; +import { MissingInternet } from "@Components/MissingInternet"; type FetchTextActivityExtra = { title: string; @@ -22,8 +25,7 @@ type Action = { type: "loading" } | { type: "fetched"; payload: T } | { type: function FetchTextActivity() { const { context, extra } = useActivity(); - const { strings } = useStrings(); - const { theme } = useTheme(); + const { isNetworkAvailable } = useNetwork(); const { title, url } = extra; const initialState: State = { @@ -54,7 +56,7 @@ function FetchTextActivity() { React.useEffect(() => { // Do nothing if the url is not given - if (!url) return; + if (!url || !isNetworkAvailable) return; cancelRequest.current = false; @@ -107,34 +109,35 @@ function FetchTextActivity() { ); }; + if (!isNetworkAvailable) { + return ( + + + + ); + } + + if (!state.data) { + return ( + + + + ); + } + return ( - - {!state.data ? ( - - ) : ( - <> - - - )} + + ); diff --git a/Website/src/activitys/MainActivity.tsx b/Website/src/activitys/MainActivity.tsx index aef3002f..5f9a40f2 100644 --- a/Website/src/activitys/MainActivity.tsx +++ b/Website/src/activitys/MainActivity.tsx @@ -111,7 +111,7 @@ const MainActivity = (): JSX.Element => { const route = { component: props.component, props: { - key: props.component.name || props.key, + key: props.key || props.component.name, }, }; diff --git a/Website/src/activitys/MainApplication.tsx b/Website/src/activitys/MainApplication.tsx index 508616c4..eabdb1d3 100644 --- a/Website/src/activitys/MainApplication.tsx +++ b/Website/src/activitys/MainApplication.tsx @@ -8,10 +8,12 @@ import { Page } from "@Components/onsenui/Page"; import { useStrings } from "@Hooks/useStrings"; import { Tabbar, TabbarRenderTab } from "@Components/onsenui/Tabbar"; import { useRepos } from "@Hooks/useRepos"; +import React from "react"; const MainApplication = () => { const { strings } = useStrings(); const { context } = useActivity(); + const [index, setIndex] = React.useState(0); const filteredModules = (modules: Module[], search: string) => modules.filter( @@ -57,7 +59,19 @@ const MainApplication = () => { return ( - + { + if (event.index != index) { + setIndex(event.index); + } + }} + renderTabs={renderTabs} + /> ); }; diff --git a/Website/src/activitys/RepoActivity/index.tsx b/Website/src/activitys/RepoActivity/index.tsx index 94825715..aceca8cd 100644 --- a/Website/src/activitys/RepoActivity/index.tsx +++ b/Website/src/activitys/RepoActivity/index.tsx @@ -22,12 +22,12 @@ import ArrowBackIcon from "@mui/icons-material/ArrowBack"; import { os } from "@Native/Os"; import { useStrings } from "@Hooks/useStrings"; import { Page } from "@Components/onsenui/Page"; -import { For } from "@Components/For"; import { RecommendedRepo } from "./components/RecommendedRepo"; import { LocalRepository } from "./components/LocalRepository"; +import { useNetwork } from "@Hooks/useNetwork"; const RepoActivity = () => { - const MAX_REPO_LENGTH: number = 5; + const { isNetworkAvailable } = useNetwork(); const { context } = useActivity(); const { strings } = useStrings(); @@ -38,7 +38,11 @@ const RepoActivity = () => { const [open, setOpen] = React.useState(false); const handleClickOpen = () => { - setOpen(true); + if (isNetworkAvailable) { + setOpen(true); + } else { + os.toast("Please chack your internet connection", Toast.LENGTH_SHORT); + } }; const handleClose = () => { @@ -92,18 +96,23 @@ const RepoActivity = () => { ))} - - - {filteredRepos.length !== 0 && } - ({ bgcolor: theme.palette.background.default })}>{strings.explore_repositories} - } - > - {recommended_repos.map((repo) => ( - - ))} - + + {isNetworkAvailable && ( + <> + {filteredRepos.length !== 0 && } + ({ bgcolor: theme.palette.background.default })}> + {strings.explore_repositories} + + } + > + {recommended_repos.map((repo) => ( + + ))} + + + )} diff --git a/Website/src/activitys/fragments/ExploreModuleFragment.tsx b/Website/src/activitys/fragments/ExploreModuleFragment.tsx index a154d9b9..ee9a797d 100644 --- a/Website/src/activitys/fragments/ExploreModuleFragment.tsx +++ b/Website/src/activitys/fragments/ExploreModuleFragment.tsx @@ -3,17 +3,18 @@ import { Searchbar } from "@Components/Searchbar"; import React from "react"; import { useActivity } from "@Hooks/useActivity"; import { useRepos } from "@Hooks/useRepos"; -import { Pagination, Stack } from "@mui/material"; +import { Box, Pagination, Stack, Typography } from "@mui/material"; import { useStrings } from "@Hooks/useStrings"; import { usePagination } from "@Hooks/usePagination"; import RepoActivity from "@Activitys/RepoActivity"; import { useSettings } from "@Hooks/useSettings"; -import DescriptonActivity from "@Activitys/DescriptonActivity"; -import { Properties } from "properties-file"; -import { useStateCallback } from "@Hooks/useStateCallback"; +import NorthEastRoundedIcon from "@mui/icons-material/NorthEastRounded"; import { useTheme } from "@Hooks/useTheme"; import { Page, RenderFunction } from "@Components/onsenui/Page"; import { BottomToolbar } from "@Components/onsenui/BottomToolbar"; +import Icon from "@Components/Icon"; +import { MissingInternet } from "@Components/MissingInternet"; +import { useNetwork } from "@Hooks/useNetwork"; export interface ExploreModuleProps { renderToolbar?: RenderFunction; @@ -26,6 +27,7 @@ const ExploreModuleFragment = (props: ExploreModuleProps) => { const { settings } = useSettings(); const { scheme, theme } = useTheme(); const { modules, repos } = useRepos(); + const { isNetworkAvailable } = useNetwork(); const [search, setSearch] = React.useState(""); const applyFilter = props.applyFilter(modules, search); @@ -36,35 +38,60 @@ const ExploreModuleFragment = (props: ExploreModuleProps) => { const count = Math.ceil(applyFilter.length / PER_PAGE); const _DATA = usePagination(applyFilter, PER_PAGE); + if (!isNetworkAvailable) { + return ( + + + + ); + } + if (repos.length === 0) { return ( -

- - Looks empty here... Add an{" "} - + + Looks empty here... Add an + { context.pushPage({ component: RepoActivity, key: "repos", + extra: {}, }); }} > - {strings.repository} - - -

+ {strings.repository} + + + + ); } diff --git a/Website/src/components/ExploreModule.tsx b/Website/src/components/ExploreModule.tsx index 9993d25e..151e240e 100644 --- a/Website/src/components/ExploreModule.tsx +++ b/Website/src/components/ExploreModule.tsx @@ -120,7 +120,7 @@ export const ExploreModule = (props: Props) => { ({ - bgcolor: `${settings.darkmode ? shade(scheme[100], -36) : theme.palette.secondary.light}46`, + bgcolor: `${settings.darkmode ? shade(scheme[200], -24.5) : shade(scheme[300], 49)}46`, })} label={formatLastUpdate} /> diff --git a/Website/src/components/Icon.tsx b/Website/src/components/Icon.tsx index 97bae0be..89e9832e 100644 --- a/Website/src/components/Icon.tsx +++ b/Website/src/components/Icon.tsx @@ -16,9 +16,9 @@ interface IProps extends SvgIconProps { const Icon = (props: IProps) => { const { settings } = useSettings(); - const { keepLight, ...rest } = props; + const { keepLight, icon: WarpperIcon, ...rest } = props; return ( - { + return ( + ({ + color: theme.palette.secondary.dark, + width: "100%", + height: "100%", + m: "unset", + })} + direction="column" + justifyContent="center" + alignItems="center" + spacing={2} + > + + Please check your internet connection + + ); +}; diff --git a/Website/src/components/onsenui/Page.tsx b/Website/src/components/onsenui/Page.tsx index 9ff9c8de..cefc46d9 100644 --- a/Website/src/components/onsenui/Page.tsx +++ b/Website/src/components/onsenui/Page.tsx @@ -83,6 +83,7 @@ const RelativeContent = styled(Content)((props: ContentProps) => { return { boxSizing: "border-box", + height: "100%", minWidth: props.minWidth ? props.minWidth : 200, maxWidth: props.maxWidth ? props.maxWidth : 980, margin: "0 auto", diff --git a/Website/src/hooks/useNetwork.ts b/Website/src/hooks/useNetwork.ts new file mode 100644 index 00000000..621e3cd5 --- /dev/null +++ b/Website/src/hooks/useNetwork.ts @@ -0,0 +1,20 @@ +import React from "react"; + +export const useNetwork = () => { + const [isOnline, setNetwork] = React.useState(window.navigator.onLine); + + const updateNetwork = () => { + setNetwork(window.navigator.onLine); + }; + + React.useEffect(() => { + window.addEventListener("offline", updateNetwork); + window.addEventListener("online", updateNetwork); + return () => { + window.removeEventListener("offline", updateNetwork); + window.removeEventListener("online", updateNetwork); + }; + }, [isOnline]); + + return { isNetworkAvailable: isOnline }; +}; diff --git a/Website/src/hooks/useRepos.tsx b/Website/src/hooks/useRepos.tsx index 8c6f92aa..3492d981 100644 --- a/Website/src/hooks/useRepos.tsx +++ b/Website/src/hooks/useRepos.tsx @@ -129,45 +129,49 @@ export const RepoProvider = (props: React.PropsWithChildren) => { }, []); const addRepo = (data: AddRepoData) => { - if (link.validURL(data.url)) { - fetch(data.url) - .then((response) => response.json()) - .then((response) => { - const ajv = new Ajv(); // options can be passed, e.g. {allErrors: true} - const validate = ajv.compile(repo_schema); - const valid = validate(response) as boolean; + if (repos.length <= 5) { + if (link.validURL(data.url)) { + fetch(data.url) + .then((response) => response.json()) + .then((response) => { + const ajv = new Ajv(); // options can be passed, e.g. {allErrors: true} + const validate = ajv.compile(repo_schema); + const valid = validate(response) as boolean; - if (valid) { - setRepos( - (prev) => [ - ...prev, - { - id: "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { - var r = (Math.random() * 16) | 0, - v = c == "x" ? r : (r & 0x3) | 0x8; - return v.toString(16); - }), - name: response.name || "Unknown Repository", - mmrlOwner: response.mmrlOwner || null, - website: response.website || null, - support: response.support || null, - donate: response.donate || null, - submitModule: response.submitModules || null, - last_update: response.last_update || 0, - modules: data.url, - isOn: false, - }, - ], - data.callback - ); - } else { - log.e(JSON.stringify(validate.errors, null, 4)); - os.toast("Repository schema does not match", Toast.LENGTH_SHORT); - } - }) - .catch((e) => (data.callback ? data.callback(e) : log.e(e))); + if (valid) { + setRepos( + (prev) => [ + ...prev, + { + id: "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { + var r = (Math.random() * 16) | 0, + v = c == "x" ? r : (r & 0x3) | 0x8; + return v.toString(16); + }), + name: response.name || "Unknown Repository", + mmrlOwner: response.mmrlOwner || null, + website: response.website || null, + support: response.support || null, + donate: response.donate || null, + submitModule: response.submitModules || null, + last_update: response.last_update || 0, + modules: data.url, + isOn: false, + }, + ], + data.callback + ); + } else { + log.e(JSON.stringify(validate.errors, null, 4)); + os.toast("Repository schema does not match", Toast.LENGTH_SHORT); + } + }) + .catch((e) => (data.callback ? data.callback(e) : log.e(e))); + } else { + os.toast("The given link isn't valid", Toast.LENGTH_SHORT); + } } else { - os.toast("The given link isn't valid.", Toast.LENGTH_SHORT); + os.toast("You can't add more than five repos", Toast.LENGTH_SHORT); } };