feat: refetch token before open splatnet
parent
4c458861c6
commit
3fdc66c384
|
|
@ -57,7 +57,7 @@ document.addEventListener("DOMContentLoaded", () => {{
|
||||||
const style = document.createElement('style');
|
const style = document.createElement('style');
|
||||||
style.innerHTML = `
|
style.innerHTML = `
|
||||||
[class^="App_App_"] , [class^="InAppContent_children_"] , [class^="SwipableView_swipableViewItem_"] ,
|
[class^="App_App_"] , [class^="InAppContent_children_"] , [class^="SwipableView_swipableViewItem_"] ,
|
||||||
[class^="MainWrapper_wrapper_"] {{
|
[class^="MainWrapper_wrapper_"] , [class^="FriendList_wrapper_"] {{
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}}
|
}}
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
import { invoke } from '@tauri-apps/api';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { usePromise } from 'hooks/usePromise';
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import { getConfig, getProfile, setProfile } from 'services/config';
|
||||||
|
import { ensureTokenValid } from 'services/s3si';
|
||||||
|
import { composeLoadable } from 'utils/composeLoadable';
|
||||||
|
import { ErrorContent } from './ErrorContent';
|
||||||
|
|
||||||
|
type OpenSplatnetProps = {
|
||||||
|
children?: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OpenSplatnet: React.FC<OpenSplatnetProps> = ({ children }) => {
|
||||||
|
let { loading, error, retry, result } = composeLoadable({
|
||||||
|
config: usePromise(getConfig),
|
||||||
|
profile: usePromise(() => getProfile(0)),
|
||||||
|
});
|
||||||
|
const [doing, setDoing] = useState(false);
|
||||||
|
const [err, setError] = useState<any>();
|
||||||
|
|
||||||
|
const onClick = async () => {
|
||||||
|
setDoing(true);
|
||||||
|
try {
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const state = result.profile.state;
|
||||||
|
const newState = await ensureTokenValid(state);
|
||||||
|
await setProfile(0, {
|
||||||
|
...result.profile,
|
||||||
|
state: newState,
|
||||||
|
});
|
||||||
|
retry?.();
|
||||||
|
const gtoken = newState.loginState?.gToken;
|
||||||
|
await invoke('open_splatnet', {
|
||||||
|
gtoken,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
setError(e);
|
||||||
|
} finally {
|
||||||
|
setDoing(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (error || err) {
|
||||||
|
return <>
|
||||||
|
<ErrorContent error={error || err} retry={retry} />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
||||||
|
return <>
|
||||||
|
<button className={classNames('btn', {
|
||||||
|
'btn-disabled': !result?.profile.state.loginState?.sessionToken,
|
||||||
|
'loading': loading || doing,
|
||||||
|
})} onClick={onClick}>{children}</button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
|
@ -1,41 +1,13 @@
|
||||||
import { invoke } from '@tauri-apps/api';
|
import { OpenSplatnet } from 'components/OpenSplatnet';
|
||||||
import { ErrorContent } from 'components/ErrorContent';
|
|
||||||
import { Loading } from 'components/Loading';
|
|
||||||
import { LogPanel, RunPanel } from 'components/RunPanel';
|
import { LogPanel, RunPanel } from 'components/RunPanel';
|
||||||
import { STAT_INK } from 'constant';
|
import { STAT_INK } from 'constant';
|
||||||
import { usePromise } from 'hooks/usePromise';
|
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { getConfig, getProfile } from 'services/config';
|
|
||||||
import { composeLoadable } from 'utils/composeLoadable';
|
|
||||||
|
|
||||||
export const Home: React.FC = () => {
|
export const Home: React.FC = () => {
|
||||||
let { loading, error, retry, result } = composeLoadable({
|
|
||||||
config: usePromise(getConfig),
|
|
||||||
profile: usePromise(() => getProfile(0)),
|
|
||||||
});
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return <>
|
|
||||||
<div className='h-full flex items-center justify-center'><Loading /></div>
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return <>
|
|
||||||
<ErrorContent error={error} retry={retry} />
|
|
||||||
</>
|
|
||||||
}
|
|
||||||
const gtoken = result?.profile.state.loginState?.gToken
|
|
||||||
const onOpenSplatnet3 = async () => {
|
|
||||||
await invoke('open_splatnet', {
|
|
||||||
gtoken,
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return <div className='flex p-2 w-full h-full gap-2'>
|
return <div className='flex p-2 w-full h-full gap-2'>
|
||||||
<div className='max-w-full h-full md:max-w-sm flex-auto'>
|
<div className='max-w-full h-full md:max-w-sm flex-auto'>
|
||||||
<div className='flex flex-col gap-2 h-full'>
|
<div className='flex flex-col gap-2 h-full'>
|
||||||
|
|
@ -43,7 +15,7 @@ export const Home: React.FC = () => {
|
||||||
<RunPanel />
|
<RunPanel />
|
||||||
<Link to='/settings' className='btn'>{t('设置')}</Link>
|
<Link to='/settings' className='btn'>{t('设置')}</Link>
|
||||||
<div className='flex gap-2 flex-auto-all'>
|
<div className='flex gap-2 flex-auto-all'>
|
||||||
<button className='btn' onClick={onOpenSplatnet3}>{t('打开鱿鱼圈3')}</button>
|
<OpenSplatnet>{t('打开鱿鱼圈3')}</OpenSplatnet>
|
||||||
<a className='btn' href={STAT_INK} target='_blank' rel='noreferrer'>{t('前往 stat.ink')}</a>
|
<a className='btn' href={STAT_INK} target='_blank' rel='noreferrer'>{t('前往 stat.ink')}</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -140,3 +140,11 @@ export async function run(state: State, opts: ExportOpts) {
|
||||||
}
|
}
|
||||||
return r.result;
|
return r.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function ensureTokenValid(state: State) {
|
||||||
|
const r = await client.ensureTokenValid(state);
|
||||||
|
if (r.error) {
|
||||||
|
throw new Error(r.error.message);
|
||||||
|
}
|
||||||
|
return r.result;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ import { DEFAULT_ENV, Env } from "./env.ts";
|
||||||
import { Queue } from "./jsonrpc/channel.ts";
|
import { Queue } from "./jsonrpc/channel.ts";
|
||||||
import { ExportOpts, Log } from "./jsonrpc/types.ts";
|
import { ExportOpts, Log } from "./jsonrpc/types.ts";
|
||||||
import { App } from "./app.ts";
|
import { App } from "./app.ts";
|
||||||
import { InMemoryStateBackend, State } from "./state.ts";
|
import { InMemoryStateBackend, Profile, State } from "./state.ts";
|
||||||
import { MemoryCache } from "./cache.ts";
|
import { MemoryCache } from "./cache.ts";
|
||||||
|
import { Splatnet3 } from "./splatnet3.ts";
|
||||||
|
|
||||||
class S3SIServiceImplement implements S3SIService, Service {
|
class S3SIServiceImplement implements S3SIService, Service {
|
||||||
loginMap: Map<string, {
|
loginMap: Map<string, {
|
||||||
|
|
@ -71,6 +72,25 @@ class S3SIServiceImplement implements S3SIService, Service {
|
||||||
result: await loginSteps(this.env, step2),
|
result: await loginSteps(this.env, step2),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
async ensureTokenValid(state: State): Promise<
|
||||||
|
RPCResult<State>
|
||||||
|
> {
|
||||||
|
const stateBackend = new InMemoryStateBackend(state);
|
||||||
|
const profile = new Profile({ stateBackend, env: this.env });
|
||||||
|
await profile.readState();
|
||||||
|
const splatnet3 = new Splatnet3({ profile, env: this.env });
|
||||||
|
if (!await splatnet3.checkToken()) {
|
||||||
|
return {
|
||||||
|
error: {
|
||||||
|
code: 101,
|
||||||
|
message: "SessionToken is invalid",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
result: stateBackend.state,
|
||||||
|
};
|
||||||
|
}
|
||||||
async getLogs(): Promise<RPCResult<Log[]>> {
|
async getLogs(): Promise<RPCResult<Log[]>> {
|
||||||
const log = await this.loggerQueue.pop();
|
const log = await this.loggerQueue.pop();
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,7 @@ export interface S3SIService {
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
>;
|
>;
|
||||||
|
ensureTokenValid(state: State): Promise<RPCResult<State>>;
|
||||||
getLogs(): Promise<RPCResult<Log[]>>;
|
getLogs(): Promise<RPCResult<Log[]>>;
|
||||||
run(state: State, opts: ExportOpts): Promise<RPCResult<State>>;
|
run(state: State, opts: ExportOpts): Promise<RPCResult<State>>;
|
||||||
// deno-lint-ignore no-explicit-any
|
// deno-lint-ignore no-explicit-any
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ export class Splatnet3 {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.request(Queries.HomeQuery);
|
await this.request(Queries.ConfigureAnalyticsQuery);
|
||||||
return true;
|
return true;
|
||||||
} catch (_e) {
|
} catch (_e) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue