diff --git a/capacitor.config.ts b/capacitor.config.ts
index 5ea50ad..178591e 100644
--- a/capacitor.config.ts
+++ b/capacitor.config.ts
@@ -1,9 +1,9 @@
-import type { CapacitorConfig } from '@capacitor/cli';
+import type { CapacitorConfig } from "@capacitor/cli";
const config: CapacitorConfig = {
- appId: 'io.ionic.starter',
- appName: 'game-node-mobile',
- webDir: 'dist'
+ appId: "app.gamenode",
+ appName: "GameNode",
+ webDir: "dist",
};
export default config;
diff --git a/src/App.test.tsx b/src/App.test.tsx
deleted file mode 100644
index 8c927a8..0000000
--- a/src/App.test.tsx
+++ /dev/null
@@ -1,8 +0,0 @@
-import React from 'react';
-import { render } from '@testing-library/react';
-import App from './App';
-
-test('renders without crashing', () => {
- const { baseElement } = render();
- expect(baseElement).toBeDefined();
-});
diff --git a/src/App.tsx b/src/App.tsx
index 7f532d3..70937bd 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -2,7 +2,16 @@ import React, { useState } from "react";
import { Redirect, Route } from "react-router-dom";
import * as reactRouterDom from "react-router-dom";
-import { IonApp, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs, setupIonicReact } from "@ionic/react";
+import {
+ IonApp,
+ IonLabel,
+ IonPage,
+ IonRouterOutlet,
+ IonTabBar,
+ IonTabButton,
+ IonTabs,
+ setupIonicReact,
+} from "@ionic/react";
import { IonReactRouter } from "@ionic/react-router";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { MantineProvider } from "@mantine/core";
@@ -40,7 +49,7 @@ import "@ionic/react/css/palettes/dark.always.css";
/* Theme variables */
import "./theme/variables.css";
-import { getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
+import { AuthPage, getSuperTokensRoutesForReactRouterDom } from "supertokens-auth-react/ui";
import { ThirdPartyPreBuiltUI } from "supertokens-auth-react/recipe/thirdparty/prebuiltui";
import { PasswordlessPreBuiltUI } from "supertokens-auth-react/recipe/passwordless/prebuiltui";
import SuperTokensProvider from "./components/auth/SuperTokensProvider";
@@ -49,9 +58,8 @@ import { OpenAPI as ServerOpenAPI } from "@/wrapper/server";
import { OpenAPI as SearchOpenAPI } from "@/wrapper/search";
import ExplorePage from "@/pages/explore";
import SearchResultsPage from "@/pages/search_results";
-import GamePage from "@/pages/game";
import HomePage from "./pages/home";
-import ProfilePage from "@/pages/profile";
+import ProfilePage from "@/pages/profile/profile";
import { getCommonRoutes } from "./pages/routes/getCommonRoutes";
import LibraryPage from "./pages/library";
import NotificationsManager from "./components/general/NotificationsManager";
@@ -72,11 +80,6 @@ const App: React.FC = () => {
defaultOptions: {
queries: {
refetchOnWindowFocus: false,
- refetchInterval: false,
- refetchOnMount: false,
- refetchIntervalInBackground: false,
- refetchOnReconnect: false,
- staleTime: Infinity,
retry: 2,
},
},
@@ -92,11 +95,6 @@ const App: React.FC = () => {
- {/*This renders the login UI on the /auth route*/}
- {getSuperTokensRoutesForReactRouterDom(reactRouterDom, [
- ThirdPartyPreBuiltUI,
- PasswordlessPreBuiltUI,
- ])}
{/* ---- HOME ROUTES ---- */}
@@ -135,14 +133,15 @@ const App: React.FC = () => {
Explore
-
-
- Profile
-
+
Library
+
+
+ Profile
+
diff --git a/src/components/achievement/AchievementsScreen.tsx b/src/components/achievement/AchievementsScreen.tsx
index 2202bfb..119cce3 100644
--- a/src/components/achievement/AchievementsScreen.tsx
+++ b/src/components/achievement/AchievementsScreen.tsx
@@ -1,16 +1,5 @@
import React, { useState } from "react";
-import {
- Box,
- Button,
- Center,
- Divider,
- Group,
- Pagination,
- Paper,
- Progress,
- SimpleGrid,
- Stack,
-} from "@mantine/core";
+import { Box, Button, Center, Divider, Group, Pagination, Paper, Progress, SimpleGrid, Stack } from "@mantine/core";
import { SessionAuth } from "supertokens-auth-react/recipe/session";
import useUserId from "@/components/auth/hooks/useUserId";
import { useAchievements } from "@/components/achievement/hooks/useAchievements";
@@ -33,62 +22,49 @@ const AchievementsScreen = ({ targetUserId }: Props) => {
const isOwnUserId = userId != undefined && userId === targetUserId;
if (!targetUserId) return null;
return (
-
-
-
-
-
-
+
+
+
+
+
- {isOwnUserId && (
-
- )}
-
-
-
- {achievements.isError && (
-
- Something happened while loading achievements. Please
- try again.
-
+ {isOwnUserId && (
+
)}
- {achievements.isLoading && }
-
+
+
+ {achievements.isError && (
+ Something happened while loading achievements. Please try again.
+ )}
+ {achievements.isLoading && }
+
+ {achievements.data?.data?.map((achievement) => {
+ return (
+
+ );
+ })}
+
+
+ {
+ const pageAsOffset = paginationData.limit * (page - 1);
+ setPaginationData({
+ offset: pageAsOffset,
+ limit: paginationData.limit,
+ });
}}
- >
- {achievements.data?.data?.map((achievement) => {
- return (
-
- );
- })}
-
-
- {
- const pageAsOffset =
- paginationData.limit * (page - 1);
- setPaginationData({
- offset: pageAsOffset,
- limit: paginationData.limit,
- });
- }}
- />
-
-
-
+ />
+
+
);
};
diff --git a/src/components/activity/item/CollectionEntryActivityItem.tsx b/src/components/activity/item/CollectionEntryActivityItem.tsx
index c5ccb3b..695b6fd 100644
--- a/src/components/activity/item/CollectionEntryActivityItem.tsx
+++ b/src/components/activity/item/CollectionEntryActivityItem.tsx
@@ -85,7 +85,11 @@ const CollectionEntryActivityItem = ({ activity }: Props) => {
-
+
{collectionQuery.data?.name}
diff --git a/src/components/auth/SuperTokensProvider.tsx b/src/components/auth/SuperTokensProvider.tsx
index 7ae601d..072577b 100755
--- a/src/components/auth/SuperTokensProvider.tsx
+++ b/src/components/auth/SuperTokensProvider.tsx
@@ -5,20 +5,20 @@ import Passwordless from "supertokens-auth-react/recipe/passwordless";
import ThirdParty from "supertokens-auth-react/recipe/thirdparty";
import { SuperTokensConfig } from "supertokens-auth-react/lib/build/types";
import { Capacitor } from "@capacitor/core";
+import { getTabAwareHref } from "@/util/getTabAwareHref";
export const frontendConfig = (): SuperTokensConfig => {
- const location = window.location;
- const websiteDomain = Capacitor.isNativePlatform()
- ? `${location.protocol}//${location.host}`
+ const PARSED_WEBSITE_DOMAIN = Capacitor.isNativePlatform()
+ ? `${window.location.protocol}//${window.location.host}`
: import.meta.env.VITE_PUBLIC_DOMAIN_WEBSITE;
return {
appInfo: {
appName: "GameNode",
apiDomain: import.meta.env.VITE_PUBLIC_DOMAIN_SERVER as string,
- websiteDomain: websiteDomain,
+ websiteDomain: PARSED_WEBSITE_DOMAIN,
apiBasePath: "/v1/auth",
- websiteBasePath: "/auth",
+ websiteBasePath: "/profile/auth",
},
getRedirectionURL: async (context) => {
if (context.action === "SUCCESS" && context.newSessionCreated) {
@@ -33,6 +33,8 @@ export const frontendConfig = (): SuperTokensConfig => {
// user signed in
}
return "/";
+ } else if (context.action === "TO_AUTH") {
+ return getTabAwareHref("/auth");
}
return undefined;
},
diff --git a/src/components/collection/collection-entry/form/modal/CollectionEntryAddOrUpdateModal.tsx b/src/components/collection/collection-entry/form/modal/CollectionEntryAddOrUpdateModal.tsx
index 50d7612..19ce98c 100755
--- a/src/components/collection/collection-entry/form/modal/CollectionEntryAddOrUpdateModal.tsx
+++ b/src/components/collection/collection-entry/form/modal/CollectionEntryAddOrUpdateModal.tsx
@@ -13,7 +13,7 @@ interface IGameAddModalProps extends BaseModalProps {
const CollectionEntryAddOrUpdateModal = ({ opened, onClose, id }: IGameAddModalProps) => {
const userId = useUserId();
- const collectionEntryQuery = useOwnCollectionEntryForGameId(id);
+ const collectionEntryQuery = useOwnCollectionEntryForGameId(id, opened);
const [isExpanded, setIsExpanded] = useState(false);
const isInLibrary = collectionEntryQuery.data != undefined;
diff --git a/src/components/collection/collection-entry/hooks/useOwnCollectionEntryForGameId.ts b/src/components/collection/collection-entry/hooks/useOwnCollectionEntryForGameId.ts
index b30ed87..036adf6 100644
--- a/src/components/collection/collection-entry/hooks/useOwnCollectionEntryForGameId.ts
+++ b/src/components/collection/collection-entry/hooks/useOwnCollectionEntryForGameId.ts
@@ -7,29 +7,29 @@ import { ExtendedUseQueryResult } from "@/util/types/ExtendedUseQueryResult";
* Returns a collection entry for the current user based on a game ID.
* The collection entry will be undefined if the user doesn't have the game in their library.
* @param gameId
+ * @param enabled
*/
export function useOwnCollectionEntryForGameId(
gameId: number | undefined,
+ enabled = true,
): ExtendedUseQueryResult {
const queryClient = useQueryClient();
const queryKey = ["collection-entries", "own", gameId];
- const invalidate = () =>
- queryClient.invalidateQueries({ queryKey: queryKey.slice(0, 2) });
+ const invalidate = () => queryClient.invalidateQueries({ queryKey: queryKey.slice(0, 2) });
return {
...useQuery({
queryKey,
queryFn: async () => {
if (!gameId) return null;
try {
- const collectionEntry =
- await getOwnCollectionEntryByGameId(gameId);
+ const collectionEntry = await getOwnCollectionEntryByGameId(gameId);
if (!collectionEntry) return null;
return collectionEntry;
} catch (e) {
return null;
}
},
- enabled: gameId != undefined,
+ enabled: enabled && gameId != undefined,
}),
queryKey,
invalidate,
diff --git a/src/components/follow/input/UserFollowGroup.tsx b/src/components/follow/input/UserAvatarWithFollowActions.tsx
similarity index 65%
rename from src/components/follow/input/UserFollowGroup.tsx
rename to src/components/follow/input/UserAvatarWithFollowActions.tsx
index 23dee05..66ae1d2 100644
--- a/src/components/follow/input/UserFollowGroup.tsx
+++ b/src/components/follow/input/UserAvatarWithFollowActions.tsx
@@ -1,14 +1,13 @@
import React from "react";
import { Group, GroupProps } from "@mantine/core";
import { UserAvatarGroup } from "@/components/general/avatar/UserAvatarGroup";
-import ProfileFollowActions from "@/components/profile/view/ProfileFollowActions";
import UserFollowActions from "@/components/follow/input/UserFollowActions";
interface Props extends GroupProps {
userId: string;
}
-const UserFollowGroup = ({ userId, ...groupProps }: Props) => {
+const UserAvatarWithFollowActions = ({ userId, ...groupProps }: Props) => {
return (
{
wrap: "nowrap",
}}
/>
-
+
);
};
-export default UserFollowGroup;
+export default UserAvatarWithFollowActions;
diff --git a/src/components/follow/input/UserFollowActions.tsx b/src/components/follow/input/UserFollowActions.tsx
index 36f8f25..95e903e 100644
--- a/src/components/follow/input/UserFollowActions.tsx
+++ b/src/components/follow/input/UserFollowActions.tsx
@@ -7,16 +7,14 @@ import { useInfiniteFollowInfo } from "@/components/follow/hooks/useInfiniteFoll
import criteria = FollowInfoRequestDto.criteria;
import { ActionIcon, Button, Group, Tooltip } from "@mantine/core";
import { IconX } from "@tabler/icons-react";
+import { redirectToAuth } from "supertokens-auth-react";
interface Props {
targetUserId: string;
withUnfollowButton?: boolean;
}
-const UserFollowActions = ({
- targetUserId,
- withUnfollowButton = true,
-}: Props) => {
+const UserFollowActions = ({ targetUserId, withUnfollowButton = true }: Props) => {
const ownUserId = useUserId();
/*
Checks if current logged-in user is following target user
@@ -24,8 +22,7 @@ const UserFollowActions = ({
const ownToTargetFollowStatus = useFollowStatus(ownUserId, targetUserId);
const isFollowing = ownToTargetFollowStatus.data?.isFollowing ?? false;
- const shouldShowFollowButton =
- ownUserId != undefined && ownUserId !== targetUserId;
+ const shouldEnableFollowButton = ownUserId != undefined && ownUserId !== targetUserId && !isFollowing;
const followMutation = useMutation({
mutationFn: async (action: "register" | "remove") => {
@@ -53,9 +50,13 @@ const UserFollowActions = ({
return (