wip
This commit is contained in:
parent
230e952c84
commit
ad366c122e
7 changed files with 68 additions and 42 deletions
|
@ -4,7 +4,7 @@ html
|
|||
meta(charset="UTF-8")
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1.0")
|
||||
block meta
|
||||
- const title = 'みす廃アラート'
|
||||
- const title = 'Misskey Tools'
|
||||
- const desc = '✨Misskey での1日のノート数、フォロー数、フォロワー数をカウントし、深夜0時にお知らせする便利サービスです。';
|
||||
title= title
|
||||
meta(name='description' content=desc)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import React from 'react';
|
||||
import { BrowserRouter, Link, Route, Switch, useLocation } from 'react-router-dom';
|
||||
import { Provider } from 'react-redux';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
@ -7,45 +7,17 @@ import { IndexPage } from './pages';
|
|||
import { RankingPage } from './pages/ranking';
|
||||
import { Header } from './components/Header';
|
||||
import { TermPage } from './pages/term';
|
||||
import { store, useSelector } from './store';
|
||||
import { store } from './store';
|
||||
import { ModalComponent } from './Modal';
|
||||
import { useTheme } from './misc/theme';
|
||||
|
||||
import 'xeltica-ui/dist/css/xeltica-ui.min.css';
|
||||
import './style.scss';
|
||||
import { ActualTheme } from './misc/theme';
|
||||
|
||||
const AppInner : React.VFC = () => {
|
||||
const $location = useLocation();
|
||||
|
||||
const theme = useSelector(state => state.screen.theme);
|
||||
|
||||
const [ osTheme, setOsTheme ] = useState<ActualTheme>('dark');
|
||||
|
||||
const applyTheme = useCallback(() => {
|
||||
const actualTheme = theme === 'system' ? osTheme : theme;
|
||||
if (actualTheme === 'dark') {
|
||||
document.body.classList.add('dark');
|
||||
} else {
|
||||
document.body.classList.remove('dark');
|
||||
}
|
||||
}, [theme, osTheme]);
|
||||
|
||||
// テーマ変更に追従する
|
||||
useEffect(() => {
|
||||
applyTheme();
|
||||
}, [theme, osTheme]);
|
||||
|
||||
// システムテーマ変更に追従する
|
||||
useEffect(() => {
|
||||
const q = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
setOsTheme(q.matches ? 'dark' : 'light');
|
||||
|
||||
const listener = () => setOsTheme(q.matches ? 'dark' : 'light');
|
||||
q.addEventListener('change', listener);
|
||||
return () => {
|
||||
q.removeEventListener('change', listener);
|
||||
};
|
||||
}, [osTheme, setOsTheme]);
|
||||
useTheme();
|
||||
|
||||
const {t} = useTranslation();
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { welcomeMessage } from '../misc/welcome-message';
|
||||
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
|
|
14
src/frontend/components/RankingPage.tsx
Normal file
14
src/frontend/components/RankingPage.tsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Ranking } from './Ranking';
|
||||
|
||||
export const RankingPage: React.VFC = () => {
|
||||
const [limit, setLimit] = useState<number | undefined>(10);
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
<div className="fade">
|
||||
<Ranking limit={limit} />
|
||||
{limit && <button className="btn link" onClick={() => setLimit(undefined)}>{t('_missHai.showAll')}</button>}
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -50,6 +50,7 @@ export const SettingPage: React.VFC = () => {
|
|||
];
|
||||
|
||||
const updateSetting = useCallback((obj: SettingDraftType) => {
|
||||
const previousDraft = draft;
|
||||
dispatchDraft(obj);
|
||||
return fetch(`${API_ENDPOINT}session`, {
|
||||
method: 'PUT',
|
||||
|
@ -58,8 +59,16 @@ export const SettingPage: React.VFC = () => {
|
|||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(obj),
|
||||
});
|
||||
}, []);
|
||||
})
|
||||
.catch(e => {
|
||||
dispatch(showModal({
|
||||
type: 'dialog',
|
||||
icon: 'error',
|
||||
message: 'エラー'
|
||||
}));
|
||||
dispatchDraft(previousDraft);
|
||||
});
|
||||
}, [draft]);
|
||||
|
||||
const updateSettingWithDialog = useCallback((obj: SettingDraftType) => {
|
||||
updateSetting(obj)
|
||||
|
@ -67,10 +76,7 @@ export const SettingPage: React.VFC = () => {
|
|||
type: 'dialog',
|
||||
icon: 'info',
|
||||
message: '保存しました。'
|
||||
})))
|
||||
.catch(e => {
|
||||
alert(e.message);
|
||||
});
|
||||
})));
|
||||
}, [updateSetting]);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { useSelector } from '../store';
|
||||
|
||||
export const actualThemes = [
|
||||
'light',
|
||||
'dark',
|
||||
|
@ -11,3 +14,35 @@ export const themes = [
|
|||
export type Theme = typeof themes[number];
|
||||
|
||||
export type ActualTheme = typeof actualThemes[number];
|
||||
|
||||
export const useTheme = () => {
|
||||
const theme = useSelector(state => state.screen.theme);
|
||||
|
||||
const [ osTheme, setOsTheme ] = useState<ActualTheme>('dark');
|
||||
|
||||
const applyTheme = useCallback(() => {
|
||||
const actualTheme = theme === 'system' ? osTheme : theme;
|
||||
if (actualTheme === 'dark') {
|
||||
document.body.classList.add('dark');
|
||||
} else {
|
||||
document.body.classList.remove('dark');
|
||||
}
|
||||
}, [theme, osTheme]);
|
||||
|
||||
// テーマ変更に追従する
|
||||
useEffect(() => {
|
||||
applyTheme();
|
||||
}, [theme, osTheme]);
|
||||
|
||||
// システムテーマ変更に追従する
|
||||
useEffect(() => {
|
||||
const q = window.matchMedia('(prefers-color-scheme: dark)');
|
||||
setOsTheme(q.matches ? 'dark' : 'light');
|
||||
|
||||
const listener = () => setOsTheme(q.matches ? 'dark' : 'light');
|
||||
q.addEventListener('change', listener);
|
||||
return () => {
|
||||
q.removeEventListener('change', listener);
|
||||
};
|
||||
}, [osTheme, setOsTheme]);
|
||||
};
|
||||
|
|
|
@ -2,10 +2,10 @@ import React, { useMemo, useState } from 'react';
|
|||
|
||||
import { Header } from '../components/Header';
|
||||
import { SessionDataPage } from '../components/SessionDataPage';
|
||||
import { Ranking } from '../components/Ranking';
|
||||
import { Tab, TabItem } from '../components/Tab';
|
||||
import { SettingPage } from '../components/SettingPage';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { RankingPage } from '../components/RankingPage';
|
||||
|
||||
export const IndexSessionPage: React.VFC = () => {
|
||||
const [selectedTab, setSelectedTab] = useState<number>(0);
|
||||
|
@ -20,7 +20,7 @@ export const IndexSessionPage: React.VFC = () => {
|
|||
const component = useMemo(() => {
|
||||
switch (selectedTab) {
|
||||
case 0: return <SessionDataPage />;
|
||||
case 1: return <Ranking limit={10}/>;
|
||||
case 1: return <RankingPage/>;
|
||||
case 2: return <SettingPage/>;
|
||||
default: return null;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue