diff --git a/package.json b/package.json
index 347a4fc..f935433 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
- "name": "misshaialert",
- "version": "1.5.1",
+ "name": "misskey-tools",
+ "version": "2.0.0",
"description": "",
"main": "built/app.js",
"author": "Xeltica",
diff --git a/src/backend/const.ts b/src/backend/const.ts
index 6b172b1..3674531 100644
--- a/src/backend/const.ts
+++ b/src/backend/const.ts
@@ -1,5 +1,5 @@
export default {
- version: '1.5.1',
+ version: '2.0.0',
changelog: [
'インスタンスの接続エラーにより後続処理が行えなくなる重大な不具合を修正',
'全員分の算出が終わるまで、ランキングを非表示に',
diff --git a/src/backend/views/frontend.pug b/src/backend/views/frontend.pug
index 44d0f42..41e9108 100644
--- a/src/backend/views/frontend.pug
+++ b/src/backend/views/frontend.pug
@@ -31,7 +31,14 @@ html
if token
script.
- localStorage.setItem('token', '#{token}');
+ const token = '#{token}';
+ const previousToken = localStorage.getItem('token');
+ const accounts = JSON.parse(localStorage.getItem('accounts') && '[]');
+ if (previousToken && !accounts.includes(previousToken)) {
+ accounts.push(previousToken);
+ }
+ localStorage.setItem('accounts', JSON.stringify(accounts));
+ localStorage.setItem('token', token);
history.replaceState(null, null, '/');
if error
diff --git a/src/frontend/components/AccountsPage.tsx b/src/frontend/components/AccountsPage.tsx
new file mode 100644
index 0000000..ccd9ff3
--- /dev/null
+++ b/src/frontend/components/AccountsPage.tsx
@@ -0,0 +1,67 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useDispatch } from 'react-redux';
+import { LOCALSTORAGE_KEY_ACCOUNTS, LOCALSTORAGE_KEY_TOKEN } from '../const';
+import { useGetSessionQuery } from '../services/session';
+import { useSelector } from '../store';
+import { setAccounts } from '../store/slices/screen';
+import { LoginForm } from './LoginForm';
+import { Skeleton } from './Skeleton';
+
+export const AccountsPage: React.VFC = () => {
+ const {data} = useGetSessionQuery(undefined);
+ const {t} = useTranslation();
+ const dispatch = useDispatch();
+
+ const {accounts, accountTokens} = useSelector(state => state.screen);
+
+ const switchAccount = (token: string) => {
+ const newAccounts = accountTokens.filter(a => a !== token);
+ newAccounts.push(localStorage.getItem(LOCALSTORAGE_KEY_TOKEN) ?? '');
+ localStorage.setItem(LOCALSTORAGE_KEY_ACCOUNTS, JSON.stringify(newAccounts));
+ localStorage.setItem(LOCALSTORAGE_KEY_TOKEN, token);
+ location.reload();
+ };
+
+ return !data ? (
+
+
+
+
+
+ ) : (
+
+
+
+
{t('_accounts.currentAccount')}
+
@{data.username}@{data.host}
+
+
+
+ {t('_accounts.switchAccount')}
+
+ {
+ accounts.length === accountTokens.length ? (
+ accounts.map(account => (
+
+ ))
+ ) : (
+
...
+ )
+ }
+
+
+
+
+ );
+};
diff --git a/src/frontend/components/LoginForm.tsx b/src/frontend/components/LoginForm.tsx
index 5638e8c..7a3aed2 100644
--- a/src/frontend/components/LoginForm.tsx
+++ b/src/frontend/components/LoginForm.tsx
@@ -10,7 +10,7 @@ export const LoginForm: React.VFC = () => {
{t('instanceUrl')}
-
+
{
+ return fetch(`${API_ENDPOINT}session`, {
+ method: 'GET',
+ headers: {
+ 'Authorization': `Bearer ${token}`,
+ 'Content-Type': 'application/json',
+ },
+ }).then(r => r.json()).then(r => r as IUser);
+};
export const IndexSessionPage: React.VFC = () => {
const [selectedTab, setSelectedTab] = useState
(0);
const {t, i18n} = useTranslation();
+ const dispatch = useDispatch();
+
+ useEffect(() => {
+ const accounts = JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY_ACCOUNTS) || '[]') as string[];
+ Promise.all(accounts.map(getSession)).then(a => dispatch(setAccounts(a)));
+ }, [dispatch]);
const items = useMemo(() => ([
{ label: t('_nav.misshai') },
+ { label: t('_nav.accounts') },
{ label: t('_nav.settings') },
]), [i18n.language]);
const component = useMemo(() => {
switch (selectedTab) {
case 0: return ;
- case 1: return ;
+ case 1: return ;
+ case 2: return ;
default: return null;
}
}, [selectedTab]);
diff --git a/src/frontend/pages/index.welcome.tsx b/src/frontend/pages/index.welcome.tsx
index aa0a739..2fcdeb5 100644
--- a/src/frontend/pages/index.welcome.tsx
+++ b/src/frontend/pages/index.welcome.tsx
@@ -35,7 +35,7 @@ export const IndexWelcomePage: React.VFC = () => {
{t('_welcome.misshaiAlertTitle')}
{t('_welcome.misshaiAlertDescription')}
-
+
diff --git a/src/frontend/store/slices/screen.ts b/src/frontend/store/slices/screen.ts
index ec37d69..ed2db3d 100644
--- a/src/frontend/store/slices/screen.ts
+++ b/src/frontend/store/slices/screen.ts
@@ -1,7 +1,8 @@
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import i18n from 'i18next';
+import { IUser } from '../../../common/types/user';
-import { LOCALSTORAGE_KEY_LANG, LOCALSTORAGE_KEY_THEME } from '../../const';
+import { LOCALSTORAGE_KEY_ACCOUNTS, LOCALSTORAGE_KEY_LANG, LOCALSTORAGE_KEY_THEME } from '../../const';
import { Theme } from '../../misc/theme';
import { Modal } from '../../modal/modal';
@@ -10,6 +11,8 @@ interface ScreenState {
modalShown: boolean;
theme: Theme;
language: string;
+ accounts: IUser[];
+ accountTokens: string[];
}
const initialState: ScreenState = {
@@ -17,6 +20,8 @@ const initialState: ScreenState = {
modalShown: false,
theme: localStorage[LOCALSTORAGE_KEY_THEME] ?? 'system',
language: localStorage[LOCALSTORAGE_KEY_LANG] ?? i18n.language ?? 'ja_JP',
+ accounts: [],
+ accountTokens: JSON.parse(localStorage.getItem(LOCALSTORAGE_KEY_ACCOUNTS) || '[]') as string[],
};
export const screenSlice = createSlice({
@@ -40,9 +45,14 @@ export const screenSlice = createSlice({
localStorage[LOCALSTORAGE_KEY_LANG] = action.payload;
i18n.changeLanguage(action.payload);
},
+ setAccounts: (state, action: PayloadAction
) => {
+ state.accounts = action.payload;
+ state.accountTokens = action.payload.map(a => a.misshaiToken);
+ localStorage[LOCALSTORAGE_KEY_ACCOUNTS] = JSON.stringify(state.accountTokens);
+ },
},
});
-export const { showModal, hideModal, changeTheme, changeLang } = screenSlice.actions;
+export const { showModal, hideModal, changeTheme, changeLang, setAccounts } = screenSlice.actions;
export default screenSlice.reducer;
diff --git a/src/frontend/style.scss b/src/frontend/style.scss
index 8b0efd5..9fa9156 100644
--- a/src/frontend/style.scss
+++ b/src/frontend/style.scss
@@ -92,3 +92,8 @@ small {
padding: calc(var(--margin) / 2);
background: var(--panel);
}
+
+.login-form {
+ background: var(--panel);
+ border-radius: var(--radius);
+}