mirror of
https://github.com/blitzkit/blitzkit.git
synced 2026-10-23 11:39:50 +02:00
feat: migrated app store
This commit is contained in:
1 parent
5aa4b262f8
commit
cf841c9bb2
14 files changed
+156
-191
No files matched your search
@@ -4,7 +4,7 @@ import { Flex, Heading, Text } from '@radix-ui/themes';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useEffect } from 'react';
|
||||
import PageWrapper from '../../../components/PageWrapper';
|
||||
import { mutateApp } from '../../../stores/app';
|
||||
import * as App from '../../../stores/app';
|
||||
|
||||
export interface PatreonAuthResponse {
|
||||
access_token: string;
|
||||
@@ -23,6 +23,7 @@ export default function Page({
|
||||
searchParams: { [key: string]: string };
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const mutateApp = App.useMutation();
|
||||
|
||||
useEffect(() => {
|
||||
switch (params.provider) {
|
||||
|
||||
@@ -10,13 +10,21 @@ import {
|
||||
} from '@radix-ui/themes';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { extendAuthPatreon } from '../../core/blitz/extendAuthPatreon';
|
||||
import { extendAuthWargaming } from '../../core/blitz/extendAuthWargaming';
|
||||
import { logoutPatreon } from '../../core/blitz/logoutPatreon';
|
||||
import { logoutWargaming } from '../../core/blitz/logoutWargaming';
|
||||
import { WARGAMING_APPLICATION_ID } from '../../constants/wargamingApplicationID';
|
||||
import { idToRegion } from '../../core/blitz/idToRegion';
|
||||
import isDev from '../../core/blitzkit/isDev';
|
||||
import { isLocalhost } from '../../core/blitzkit/isLocalhost';
|
||||
import { CURRENT_POLICIES_AGREEMENT_INDEX, useApp } from '../../stores/app';
|
||||
import * as App from '../../stores/app';
|
||||
import { CURRENT_POLICIES_AGREEMENT_INDEX } from '../../stores/app/constants';
|
||||
import { PatreonAuthResponse } from '../auth/[provider]/page';
|
||||
|
||||
interface Extension {
|
||||
data: {
|
||||
access_token: string;
|
||||
account_id: number;
|
||||
expires_at: number;
|
||||
};
|
||||
}
|
||||
|
||||
const DEV_BUILD_AGREEMENT_COOLDOWN = 8 * 24 * 60 * 60 * 1000;
|
||||
|
||||
@@ -27,8 +35,10 @@ const DEV_BUILD_AGREEMENT_COOLDOWN = 8 * 24 * 60 * 60 * 1000;
|
||||
|
||||
export function Checks() {
|
||||
const [showDevBuildAlert, setShowDevBuildAlert] = useState(false);
|
||||
const logins = useApp((state) => state.logins);
|
||||
const policiesAgreementIndex = useApp(
|
||||
const mutateApp = App.useMutation();
|
||||
const logins = App.use((state) => state.logins);
|
||||
const appStore = App.useStore();
|
||||
const policiesAgreementIndex = App.use(
|
||||
(state) => state.policiesAgreementIndex,
|
||||
);
|
||||
const pathname = usePathname();
|
||||
@@ -39,7 +49,7 @@ export function Checks() {
|
||||
setShowDevBuildAlert(
|
||||
isDev() &&
|
||||
!isLocalhost() &&
|
||||
Date.now() - useApp.getState().devBuildAgreementTime >=
|
||||
Date.now() - appStore.getState().devBuildAgreementTime >=
|
||||
DEV_BUILD_AGREEMENT_COOLDOWN,
|
||||
);
|
||||
}, []);
|
||||
@@ -55,9 +65,31 @@ export function Checks() {
|
||||
const expiresInDays = expiresIn / 1000 / 60 / 60 / 24;
|
||||
|
||||
if (expiresInDays < 0) {
|
||||
logoutWargaming();
|
||||
mutateApp((draft) => {
|
||||
draft.logins.wargaming = undefined;
|
||||
});
|
||||
} else if (expiresInDays < 7) {
|
||||
extendAuthWargaming();
|
||||
const { wargaming } = appStore.getState().logins;
|
||||
|
||||
if (!wargaming) return;
|
||||
|
||||
fetch(
|
||||
`https://api.worldoftanks.${idToRegion(
|
||||
wargaming.id,
|
||||
)}/wot/auth/prolongate/?application_id=${WARGAMING_APPLICATION_ID}&access_token=${
|
||||
wargaming.token
|
||||
}`,
|
||||
)
|
||||
.then((response) => response.json() as Promise<Extension>)
|
||||
.then((json) => {
|
||||
mutateApp((draft) => {
|
||||
draft.logins.wargaming = {
|
||||
id: wargaming.id,
|
||||
token: json.data.access_token,
|
||||
expires: json.data.expires_at * 1000,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,9 +98,25 @@ export function Checks() {
|
||||
const expiresInDays = expiresIn / 1000 / 60 / 60 / 24;
|
||||
|
||||
if (expiresInDays < 0) {
|
||||
logoutPatreon();
|
||||
mutateApp((draft) => {
|
||||
draft.logins.patreon = undefined;
|
||||
});
|
||||
} else if (expiresInDays < 15) {
|
||||
extendAuthPatreon();
|
||||
const { patreon } = appStore.getState().logins;
|
||||
|
||||
if (!patreon) return;
|
||||
|
||||
fetch(`/api/patreon/refresh/${patreon.refreshToken}`)
|
||||
.then((response) => response.json() as Promise<PatreonAuthResponse>)
|
||||
.then((data) => {
|
||||
mutateApp((draft) => {
|
||||
draft.logins.patreon = {
|
||||
token: data.access_token,
|
||||
refreshToken: data.refresh_token,
|
||||
expires: Date.now() + data.expires_in * 1000,
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -93,7 +141,7 @@ export function Checks() {
|
||||
variant="solid"
|
||||
onClick={() => {
|
||||
setShowDevBuildAlert(false);
|
||||
useApp.setState({ devBuildAgreementTime: Date.now() });
|
||||
appStore.setState({ devBuildAgreementTime: Date.now() });
|
||||
}}
|
||||
>
|
||||
Continue
|
||||
@@ -158,7 +206,7 @@ export function Checks() {
|
||||
|
||||
<Button
|
||||
onClick={() => {
|
||||
useApp.setState({
|
||||
appStore.setState({
|
||||
policiesAgreementIndex: CURRENT_POLICIES_AGREEMENT_INDEX,
|
||||
});
|
||||
}}
|
||||
|
||||
@@ -5,10 +5,10 @@ import { Button, Flex, Link, Text } from '@radix-ui/themes';
|
||||
import { patreonLoginUrl } from '../../core/blitzkit/patreonLoginUrl';
|
||||
import { useAdExempt } from '../../hooks/useAdExempt';
|
||||
import { PatreonIcon } from '../../icons/Patreon';
|
||||
import { useApp } from '../../stores/app';
|
||||
import * as App from '../../stores/app';
|
||||
|
||||
export function PatreonPlug() {
|
||||
const patreon = useApp((state) => state.logins.patreon);
|
||||
const patreon = App.use((state) => state.logins.patreon);
|
||||
const exempt = useAdExempt();
|
||||
|
||||
return (
|
||||
|
||||
+54
-51
@@ -10,6 +10,7 @@ import { Footer } from '../components/Footer';
|
||||
import { Loader } from '../components/Loader';
|
||||
import Navbar, { NAVBAR_HEIGHT } from '../components/Navbar';
|
||||
import { Party3 } from '../components/Party3';
|
||||
import * as App from '../stores/app';
|
||||
import { Checks } from './components/Checks';
|
||||
import './layout.css';
|
||||
|
||||
@@ -31,62 +32,64 @@ export default function RootLayout({ children }: RootLayoutProps) {
|
||||
const isRoot = pathname === '/';
|
||||
|
||||
return (
|
||||
<html lang="en" className={robotoFlex.className}>
|
||||
<head>
|
||||
{isRoot && (
|
||||
<>
|
||||
<title>BlitzKit</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="🎉 Tools for everything World of Tanks Blitz"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<meta property="og:site_name" content="BlitzKit" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
<App.Provider>
|
||||
<html lang="en" className={robotoFlex.className}>
|
||||
<head>
|
||||
{isRoot && (
|
||||
<>
|
||||
<title>BlitzKit</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="🎉 Tools for everything World of Tanks Blitz"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<meta property="og:site_name" content="BlitzKit" />
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
||||
|
||||
<Party3 />
|
||||
</head>
|
||||
<Party3 />
|
||||
</head>
|
||||
|
||||
<body
|
||||
style={{
|
||||
margin: 0,
|
||||
backgroundColor: isEmbed ? 'transparent' : undefined,
|
||||
}}
|
||||
>
|
||||
<Theme
|
||||
appearance="dark"
|
||||
panelBackground="solid"
|
||||
radius="full"
|
||||
accentColor="amber"
|
||||
suppressHydrationWarning
|
||||
suppressContentEditableWarning
|
||||
<body
|
||||
style={{
|
||||
margin: 0,
|
||||
backgroundColor: isEmbed ? 'transparent' : undefined,
|
||||
}}
|
||||
>
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
minHeight: '100vh',
|
||||
paddingTop: isEmbed ? undefined : NAVBAR_HEIGHT,
|
||||
}}
|
||||
<Theme
|
||||
appearance="dark"
|
||||
panelBackground="solid"
|
||||
radius="full"
|
||||
accentColor="amber"
|
||||
suppressHydrationWarning
|
||||
suppressContentEditableWarning
|
||||
>
|
||||
{!isEmbed && <Navbar />}
|
||||
|
||||
<Checks />
|
||||
|
||||
<Suspense
|
||||
fallback={
|
||||
<div style={{ flex: 1 }}>
|
||||
<Loader />
|
||||
</div>
|
||||
}
|
||||
<Flex
|
||||
direction="column"
|
||||
style={{
|
||||
minHeight: '100vh',
|
||||
paddingTop: isEmbed ? undefined : NAVBAR_HEIGHT,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Suspense>
|
||||
{!isEmbed && <Navbar />}
|
||||
|
||||
{!isEmbed && <Footer />}
|
||||
</Flex>
|
||||
</Theme>
|
||||
</body>
|
||||
</html>
|
||||
<Checks />
|
||||
|
||||
<Suspense
|
||||
fallback={
|
||||
<div style={{ flex: 1 }}>
|
||||
<Loader />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</Suspense>
|
||||
|
||||
{!isEmbed && <Footer />}
|
||||
</Flex>
|
||||
</Theme>
|
||||
</body>
|
||||
</html>
|
||||
</App.Provider>
|
||||
);
|
||||
}
|
||||
@@ -2,10 +2,11 @@
|
||||
|
||||
import { Flex, Heading, Switch, Text } from '@radix-ui/themes';
|
||||
import PageWrapper from '../../components/PageWrapper';
|
||||
import { useApp } from '../../stores/app';
|
||||
import * as App from '../../stores/app';
|
||||
|
||||
export default function Page() {
|
||||
const developerMode = useApp((state) => state.developerMode);
|
||||
const developerMode = App.use((state) => state.developerMode);
|
||||
const appStore = App.useStore();
|
||||
|
||||
return (
|
||||
<PageWrapper justify="center" align="center">
|
||||
@@ -18,7 +19,7 @@ export default function Page() {
|
||||
<Switch
|
||||
checked={developerMode}
|
||||
onCheckedChange={(checked) =>
|
||||
useApp.setState({ developerMode: checked })
|
||||
appStore.setState({ developerMode: checked })
|
||||
}
|
||||
/>
|
||||
</Flex>
|
||||
|
||||
@@ -31,7 +31,7 @@ import {
|
||||
} from '../../../../../../../core/blitzkit/tankDefinitions/constants';
|
||||
import { useEquipment } from '../../../../../../../hooks/useEquipment';
|
||||
import { useFullScreen } from '../../../../../../../hooks/useFullScreen';
|
||||
import { useApp } from '../../../../../../../stores/app';
|
||||
import * as App from '../../../../../../../stores/app';
|
||||
import { mutateDuel, useDuel } from '../../../../../../../stores/duel';
|
||||
import * as TankopediaEphemeral from '../../../../../../../stores/tankopediaEphemeral';
|
||||
import * as TankopediaPersistent from '../../../../../../../stores/tankopediaPersistent';
|
||||
@@ -65,7 +65,7 @@ export function Options() {
|
||||
const environment = TankopediaPersistent.use(
|
||||
(state) => state.model.visual.environment,
|
||||
);
|
||||
const developerMode = useApp((state) => state.developerMode);
|
||||
const developerMode = App.use((state) => state.developerMode);
|
||||
const antagonistGun = useDuel((state) => state.antagonist!.gun);
|
||||
const antagonistShell = useDuel((state) => state.antagonist!.shell);
|
||||
const [antagonistSelectorOpen, setAntagonistSelectorOpen] = useState(false);
|
||||
|
||||
Reference in new issue
Block a user