デザイン調整
This commit is contained in:
parent
7c833c3568
commit
bc0eeb5461
@ -15,7 +15,7 @@ html
|
||||
meta(name='twitter:site' content='@Xeltica')
|
||||
meta(name='twitter:creator' content='@Xeltica')
|
||||
link(rel="stylesheet" href="https://koruri.chillout.chat/koruri.css")
|
||||
link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css")
|
||||
link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css")
|
||||
style.
|
||||
.loading {
|
||||
display: flex;
|
||||
|
@ -59,7 +59,7 @@ const AppInner : React.VFC = () => {
|
||||
</div>
|
||||
) : (
|
||||
<div className="container">
|
||||
{$location.pathname !== '/' && <Header hasTopLink />}
|
||||
{$location.pathname !== '/' && <Header hasTopLink className="xarticle mb-2" />}
|
||||
<Switch>
|
||||
<Route exact path="/" component={IndexPage} />
|
||||
<Route exact path="/ranking" component={RankingPage} />
|
||||
|
@ -30,32 +30,34 @@ export const AccountsPage: React.VFC = () => {
|
||||
<Skeleton />
|
||||
</div>
|
||||
) : (
|
||||
<article className="fade">
|
||||
<div>
|
||||
<strong>{t('_accounts.switchAccount')}</strong>
|
||||
</div>
|
||||
<div className="menu large fluid mb-2">
|
||||
{
|
||||
accounts.length === accountTokens.length ? (
|
||||
accounts.map(account => (
|
||||
<button className="item fluid" style={{display: 'flex', flexDirection: 'row', alignItems: 'center'}} onClick={() => switchAccount(account.misshaiToken)}>
|
||||
<i className="icon bi bi-chevron-right" />
|
||||
<article className="card fade">
|
||||
<div className="body">
|
||||
<div>
|
||||
<strong>{t('_accounts.switchAccount')}</strong>
|
||||
</div>
|
||||
<div className="menu large fluid mb-2">
|
||||
{
|
||||
accounts.length === accountTokens.length ? (
|
||||
accounts.map(account => (
|
||||
<button className="item fluid" style={{display: 'flex', flexDirection: 'row', alignItems: 'center'}} onClick={() => switchAccount(account.misshaiToken)}>
|
||||
<i className="icon bi bi-chevron-right" />
|
||||
@{account.username}@{account.host}
|
||||
<button className="btn flat text-danger" style={{marginLeft: 'auto'}} onClick={e => {
|
||||
const filteredAccounts = accounts.filter(ac => ac.id !== account.id);
|
||||
dispatch(setAccounts(filteredAccounts));
|
||||
e.stopPropagation();
|
||||
}}>
|
||||
<i className="bi bi-trash"/>
|
||||
<button className="btn flat text-danger" style={{marginLeft: 'auto'}} onClick={e => {
|
||||
const filteredAccounts = accounts.filter(ac => ac.id !== account.id);
|
||||
dispatch(setAccounts(filteredAccounts));
|
||||
e.stopPropagation();
|
||||
}}>
|
||||
<i className="bi bi-trash"/>
|
||||
</button>
|
||||
</button>
|
||||
</button>
|
||||
))
|
||||
) : (
|
||||
<div className="item">...</div>
|
||||
)
|
||||
}
|
||||
))
|
||||
) : (
|
||||
<div className="item">...</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
<LoginForm />
|
||||
</div>
|
||||
<LoginForm />
|
||||
</article>
|
||||
);
|
||||
};
|
||||
|
@ -24,7 +24,7 @@ export const AnnouncementList: React.VFC = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="mb-0">{t('announcements')}</h2>
|
||||
<h1 className="mb-0">{t('announcements')}</h1>
|
||||
<div className="large menu fade">
|
||||
{announcements.map(a => (
|
||||
<Link className="item fluid" key={a.id} to={`/announcements/${a.id}`}>
|
||||
|
17
src/frontend/components/MisshaiPage.scss
Normal file
17
src/frontend/components/MisshaiPage.scss
Normal file
@ -0,0 +1,17 @@
|
||||
.misshaiPageLayout {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--margin);
|
||||
> .misshaiData {
|
||||
flex: 1 0 300px;
|
||||
}
|
||||
> .misshaiRanking {
|
||||
flex: 5 0 300px;
|
||||
}
|
||||
> .alertModeSetting {
|
||||
flex: 1 0 300px;
|
||||
}
|
||||
> .templateSetting {
|
||||
flex: 5 0 300px;
|
||||
}
|
||||
}
|
@ -10,10 +10,11 @@ import { $post, $put } from '../misc/api';
|
||||
import { useGetScoreQuery, useGetSessionQuery } from '../services/session';
|
||||
import { showModal } from '../store/slices/screen';
|
||||
import { AnnouncementList } from './AnnouncementList';
|
||||
import { Card } from './Card';
|
||||
import { Ranking } from './Ranking';
|
||||
import { Skeleton } from './Skeleton';
|
||||
|
||||
import './MisshaiPage.scss';
|
||||
|
||||
const variables = [
|
||||
'notesCount',
|
||||
'followingCount',
|
||||
@ -174,7 +175,7 @@ export const MisshaiPage: React.VFC = () => {
|
||||
|
||||
const defaultTemplate = t('_template.default');
|
||||
|
||||
return session.isLoading || score.isLoading ? (
|
||||
return session.isLoading || score.isLoading || !session.data || !score.data ? (
|
||||
<div className="vstack">
|
||||
<Skeleton width="100%" height="1rem" />
|
||||
<Skeleton width="100%" height="1rem" />
|
||||
@ -182,23 +183,16 @@ export const MisshaiPage: React.VFC = () => {
|
||||
<Skeleton width="100%" height="160px" />
|
||||
</div>
|
||||
) : (
|
||||
<div className="fade vstack">
|
||||
{session.data && (
|
||||
<section>
|
||||
<p>{t('welcomeBack', {acct: `@${session.data.username}@${session.data.host}`})}</p>
|
||||
<p>
|
||||
<strong>
|
||||
{t('_missHai.rating')}{': '}
|
||||
</strong>
|
||||
{session.data.rating}
|
||||
</p>
|
||||
</section>
|
||||
)}
|
||||
<AnnouncementList />
|
||||
{score.data && (
|
||||
<>
|
||||
<section>
|
||||
<h2>{t('_missHai.data')}</h2>
|
||||
<div className="vstack">
|
||||
<section className="card announcement">
|
||||
<div className="body">
|
||||
<AnnouncementList />
|
||||
</div>
|
||||
</section>
|
||||
<div className="misshaiPageLayout">
|
||||
<section className="card misshaiData">
|
||||
<div className="body">
|
||||
<h1>{t('_missHai.data')}</h1>
|
||||
<table className="table fluid">
|
||||
<thead>
|
||||
<tr>
|
||||
@ -225,88 +219,104 @@ export const MisshaiPage: React.VFC = () => {
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</section>
|
||||
<section>
|
||||
<h2>{t('_missHai.ranking')}</h2>
|
||||
<p>
|
||||
<strong>
|
||||
{t('_missHai.rating')}{': '}
|
||||
</strong>
|
||||
{session.data.rating}
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<section className="card misshaiRanking">
|
||||
<div className="body">
|
||||
<h1>{t('_missHai.ranking')}</h1>
|
||||
<Ranking limit={limit} />
|
||||
{limit && <button className="btn link" onClick={() => setLimit(undefined)}>{t('_missHai.showAll')}</button>}
|
||||
</section>
|
||||
<section className="vstack mt-2">
|
||||
<Card bodyClassName="vstack">
|
||||
<h1>{t('alertMode')}</h1>
|
||||
<div>
|
||||
{
|
||||
alertModes.map((mode) => (
|
||||
<label key={mode} className="input-check">
|
||||
<input type="radio" checked={mode === draft.alertMode} onChange={() => {
|
||||
updateSetting({ alertMode: mode });
|
||||
}} />
|
||||
<span>{t(`_alertMode.${mode}`)}</span>
|
||||
</label>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
{ draft.alertMode === 'notification' && (
|
||||
<div className="alert bg-danger mt-2">
|
||||
<i className="icon bi bi-exclamation-circle"></i>
|
||||
{t('_alertMode.notificationWarning')}
|
||||
</div>
|
||||
)}
|
||||
{ draft.alertMode === 'note' && (
|
||||
<>
|
||||
<h2>{t('visibility')}</h2>
|
||||
<div>
|
||||
{
|
||||
availableVisibilities.map((visibility) => (
|
||||
<label key={visibility} className="input-check">
|
||||
<input type="radio" checked={visibility === draft.visibility} onChange={() => {
|
||||
updateSetting({ visibility });
|
||||
}} />
|
||||
<span>{t(`_visibility.${visibility}`)}</span>
|
||||
</label>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<label className="input-check mt-2">
|
||||
<input type="checkbox" checked={draft.localOnly} onChange={(e) => {
|
||||
updateSetting({ localOnly: e.target.checked });
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div className="misshaiPageLayout">
|
||||
<section className="card alertModeSetting">
|
||||
<div className="body">
|
||||
<h1 className="mb-2">{t('alertMode')}</h1>
|
||||
<div className="vstack">
|
||||
{
|
||||
alertModes.map((mode) => (
|
||||
<label key={mode} className="input-check">
|
||||
<input type="radio" checked={mode === draft.alertMode} onChange={() => {
|
||||
updateSetting({ alertMode: mode });
|
||||
}} />
|
||||
<span>{t('localOnly')}</span>
|
||||
<span>{t(`_alertMode.${mode}`)}</span>
|
||||
</label>
|
||||
</>
|
||||
)}
|
||||
</Card>
|
||||
<Card bodyClassName="vstack">
|
||||
<h1>{t('template')}</h1>
|
||||
<p>{t('_template.description')}</p>
|
||||
<div className="hstack dense">
|
||||
<button className="btn" onClick={onClickInsertVariables}>
|
||||
<i className="bi bi-braces" />
|
||||
{t('_template.insertVariables')}
|
||||
</button>
|
||||
<button className="btn link text-info" onClick={onClickInsertVariablesHelp}>
|
||||
<i className="bi bi-question-circle" />
|
||||
</button>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
{ draft.alertMode === 'notification' && (
|
||||
<div className="alert bg-danger mt-2">
|
||||
<i className="icon bi bi-exclamation-circle"></i>
|
||||
{t('_alertMode.notificationWarning')}
|
||||
</div>
|
||||
<textarea ref={templateTextarea} className="input-field" value={draft.template ?? defaultTemplate} placeholder={defaultTemplate} style={{height: 228}} onChange={(e) => {
|
||||
dispatchDraft({ template: e.target.value });
|
||||
}} />
|
||||
<small className="text-dimmed">{t('_template.description2')}</small>
|
||||
<div className="hstack" style={{justifyContent: 'flex-end'}}>
|
||||
<button className="btn danger" onClick={() => dispatchDraft({ template: null })}>{t('resetToDefault')}</button>
|
||||
<button className="btn primary" onClick={() => {
|
||||
updateSettingWithDialog({ template: draft.template === '' ? null : draft.template });
|
||||
}}>{t('save')}</button>
|
||||
</div>
|
||||
</Card>
|
||||
<Card bodyClassName="vstack">
|
||||
<button className="btn block" onClick={onClickSendAlert} disabled={draft.alertMode === 'nothing'}>{t('sendAlert')}</button>
|
||||
<p className="text-dimmed">{t(draft.alertMode === 'nothing' ? 'sendAlertDisabled' : 'sendAlertDescription')}</p>
|
||||
</Card>
|
||||
</section>
|
||||
</>
|
||||
)}
|
||||
)}
|
||||
{ draft.alertMode === 'note' && (
|
||||
<>
|
||||
<h2 className="mt-2 mb-1">{t('visibility')}</h2>
|
||||
<div className="vstack">
|
||||
{
|
||||
availableVisibilities.map((visibility) => (
|
||||
<label key={visibility} className="input-check">
|
||||
<input type="radio" checked={visibility === draft.visibility} onChange={() => {
|
||||
updateSetting({ visibility });
|
||||
}} />
|
||||
<span>{t(`_visibility.${visibility}`)}</span>
|
||||
</label>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<label className="input-check mt-2">
|
||||
<input type="checkbox" checked={draft.localOnly} onChange={(e) => {
|
||||
updateSetting({ localOnly: e.target.checked });
|
||||
}} />
|
||||
<span>{t('localOnly')}</span>
|
||||
</label>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
<section className="card templateSetting">
|
||||
<div className="body">
|
||||
<h1>{t('template')}</h1>
|
||||
<p>{t('_template.description')}</p>
|
||||
<div className="hstack dense mb-2">
|
||||
<button className="btn" onClick={onClickInsertVariables}>
|
||||
<i className="bi bi-braces" />
|
||||
{t('_template.insertVariables')}
|
||||
</button>
|
||||
<button className="btn link text-info" onClick={onClickInsertVariablesHelp}>
|
||||
<i className="bi bi-question-circle" />
|
||||
</button>
|
||||
</div>
|
||||
<textarea ref={templateTextarea} className="input-field" value={draft.template ?? defaultTemplate} placeholder={defaultTemplate} style={{height: 228}} onChange={(e) => {
|
||||
dispatchDraft({ template: e.target.value });
|
||||
}} />
|
||||
<small className="text-dimmed">{t('_template.description2')}</small>
|
||||
<div className="hstack mt-2" style={{justifyContent: 'flex-end'}}>
|
||||
<button className="btn danger" onClick={() => dispatchDraft({ template: null })}>{t('resetToDefault')}</button>
|
||||
<button className="btn primary" onClick={() => {
|
||||
updateSettingWithDialog({ template: draft.template === '' ? null : draft.template });
|
||||
}}>{t('save')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<section className="list-form mt-2">
|
||||
<button className="item" onClick={onClickSendAlert} disabled={draft.alertMode === 'nothing'}>
|
||||
<i className="icon bi bi-send" />
|
||||
<div className="body">
|
||||
<h1>{t('sendAlert')}</h1>
|
||||
<p className="desc">{t(draft.alertMode === 'nothing' ? 'sendAlertDisabled' : 'sendAlertDescription')}</p>
|
||||
</div>
|
||||
</button>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,11 +1,9 @@
|
||||
import React, { ChangeEventHandler, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ReactCrop, { Crop } from 'react-image-crop';
|
||||
|
||||
import 'react-image-crop/dist/ReactCrop.css';
|
||||
|
||||
export const NekomimiPage: React.VFC = () => {
|
||||
const {t} = useTranslation();
|
||||
const [blobUrl, setBlobUrl] = useState<string | null>(null);
|
||||
const [image, setImage] = useState<HTMLImageElement | null>(null);
|
||||
const [crop, setCrop] = useState<Partial<Crop>>({unit: '%', width: 100, aspect: 1 / 1});
|
||||
|
@ -129,7 +129,7 @@ export const SettingPage: React.VFC = () => {
|
||||
</div>
|
||||
</button>
|
||||
<button className="item text-danger" onClick={onClickDeleteAccount}>
|
||||
<i className="icon bi bi-trash-fill" />
|
||||
<i className="icon bi bi-trash" />
|
||||
<div className="body">
|
||||
<h1>{t('deleteAccount')}</h1>
|
||||
<p className="desc">{t('deleteAccountDescription')}</p>
|
||||
|
@ -54,15 +54,17 @@
|
||||
"title": "プロ仕様のツールキット",
|
||||
"description": "Misskey Toolsでは、Misskeyのために設計された、Misskeyをより楽しめるツールを取り揃えています。",
|
||||
"misshaiAlertTitle": "ミス廃アラート",
|
||||
"misshaiAlertDescription": "Misskeyにのめり込んでいませんか?ミス廃アラートを使えば、毎日のMisskeyでの活動量を以下のように定期投稿できます。",
|
||||
"misshaiAlertDescription": "Misskeyにのめり込んでいませんか?ミス廃アラートを使えば、毎日のMisskeyでの活動量を定期投稿できます。",
|
||||
"misshaiRankingDescription": "ミス廃ランキングでは、Misskeyでの活動を数値化し、ランキング表示します。",
|
||||
"catAdjusterDescription": "CATモードの猫耳がアイコンに合わなくてお悩みのあなたへ。かわいいアイコンを猫耳に合わせてトリミングできます。",
|
||||
"nextFeaturesTitle": "今後も追加予定。",
|
||||
"nextFeaturesDescription": "これだけではありません。今後もアップデートで様々な機能を追加します!"
|
||||
},
|
||||
"_nav": {
|
||||
"misshai": "ミス廃",
|
||||
"accounts": "アカウント",
|
||||
"settings": "設定"
|
||||
"settings": "設定",
|
||||
"catAdjuster": "ねこみみ"
|
||||
},
|
||||
"_missHai": {
|
||||
"ranking": "ミス廃ランキング",
|
||||
@ -157,5 +159,8 @@
|
||||
"no": "キャンセル",
|
||||
"success": "アカウントを解除しました。トップ画面に戻ります。",
|
||||
"failure": "アカウントを解除できませんでした。"
|
||||
},
|
||||
"_catAdjuster": {
|
||||
"title": "ねこみみアジャスター"
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,6 @@ import { useGetSessionQuery } from '../services/session';
|
||||
import { AdminPage } from '../components/AdminPage';
|
||||
import { $get } from '../misc/api';
|
||||
import { NekomimiPage } from '../components/NekomimiPage';
|
||||
import { CurrentUser } from '../components/CurrentUser';
|
||||
import { Card } from '../components/Card';
|
||||
|
||||
export const IndexSessionPage: React.VFC = () => {
|
||||
const [selectedTab, setSelectedTab] = useState<string>('misshai');
|
||||
@ -59,7 +57,7 @@ export const IndexSessionPage: React.VFC = () => {
|
||||
<Tab items={items} selected={selectedTab} onSelect={setSelectedTab}/>
|
||||
</div>
|
||||
</div>
|
||||
<article className="xarticle mt-2">
|
||||
<article className="xarticle mt-4">
|
||||
{component}
|
||||
</article>
|
||||
</>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
@ -8,49 +8,42 @@ import { AnnouncementList } from '../components/AnnouncementList';
|
||||
export const IndexWelcomePage: React.VFC = () => {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const example = useMemo(() => (
|
||||
t('_template.default')
|
||||
.replace('{notesCount}', '32000')
|
||||
.replace('{notesDelta}', '+190')
|
||||
.replace('{followingCount}', '510')
|
||||
.replace('{followingDelta}', '+3')
|
||||
.replace('{followersCount}', '1020')
|
||||
.replace('{followersDelta}', '-1')
|
||||
.replace('{url}', 'https://misskey.tools')
|
||||
), []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header>
|
||||
<Header className="xarticle mb-4">
|
||||
<article className="mt-4">
|
||||
<p>{t('description1')}</p>
|
||||
<p>{t('description2')}</p>
|
||||
</article>
|
||||
<LoginForm />
|
||||
</Header>
|
||||
<article className="xarticle">
|
||||
<AnnouncementList />
|
||||
<article className="xarticle card">
|
||||
<div className="body">
|
||||
<AnnouncementList />
|
||||
</div>
|
||||
</article>
|
||||
<hr />
|
||||
<article className="xarticle vstack pa-2">
|
||||
<header>
|
||||
<h2>{t('_welcome.title')}</h2>
|
||||
<p>{t('_welcome.description')}</p>
|
||||
</header>
|
||||
<article>
|
||||
<h3>{t('_welcome.misshaiAlertTitle')}</h3>
|
||||
<p>{t('_welcome.misshaiAlertDescription')}</p>
|
||||
<div className="card ma-2 shadow-2" style={{maxWidth: 360}}>
|
||||
<div className="body">
|
||||
<pre>{example}</pre>
|
||||
</div>
|
||||
<div className="row">
|
||||
<article className="col-4 col-12-sm">
|
||||
<h3><i className="bi bi-megaphone-fill"/> {t('_welcome.misshaiAlertTitle')}</h3>
|
||||
<p>{t('_welcome.misshaiAlertDescription')}</p>
|
||||
</article>
|
||||
<article className="col-4 col-12-sm">
|
||||
<h3><i className="bi bi-bar-chart-fill"/> {t('_missHai.ranking')}</h3>
|
||||
<p>{t('_welcome.misshaiRankingDescription')}</p>
|
||||
<Link to="/ranking">{t('_missHai.showRanking')}</Link>
|
||||
</article>
|
||||
<div className="col-4 col-12-sm">
|
||||
<h3><i className="bi bi-crop"/> {t('_catAdjuster.title')}</h3>
|
||||
<p>{t('_welcome.catAdjusterDescription')}</p>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<h3 className="mb-1">{t('_missHai.ranking')}</h3>
|
||||
<p>{t('_welcome.misshaiRankingDescription')}</p>
|
||||
<Link to="/ranking">{t('_missHai.showRanking')}</Link>
|
||||
</article>
|
||||
<article>
|
||||
</div>
|
||||
<article className="mt-5">
|
||||
<h3>{t('_welcome.nextFeaturesTitle')}</h3>
|
||||
<p>{t('_welcome.nextFeaturesDescription')}</p>
|
||||
</article>
|
||||
|
@ -1,12 +1,22 @@
|
||||
body {
|
||||
--primary: rgb(134, 179, 0);
|
||||
--max-width: 1024px;
|
||||
font-family: "Koruri", sans-serif;
|
||||
font-feature-settings: "pkna";
|
||||
}
|
||||
|
||||
hr {
|
||||
height: 4px;
|
||||
background: var(--dimmed);
|
||||
border: none;
|
||||
margin: 64px auto;
|
||||
width: 50%;
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.xarticle {
|
||||
margin: auto;
|
||||
max-width: 1024px;
|
||||
max-width: var(--max-width);
|
||||
}
|
||||
|
||||
.fade {
|
||||
|
Loading…
Reference in New Issue
Block a user