wip
This commit is contained in:
parent
440268a24a
commit
dc6a53e38c
4 changed files with 140 additions and 44 deletions
16
src/frontend/components/Card.tsx
Normal file
16
src/frontend/components/Card.tsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import React from 'react';
|
||||
|
||||
export type CardProps = {
|
||||
className?: string;
|
||||
bodyClassName?: string;
|
||||
};
|
||||
|
||||
export const Card: React.FC<CardProps> = ({children, className, bodyClassName}) => {
|
||||
return (
|
||||
<div className={`card ${className}`}>
|
||||
<div className={`body ${bodyClassName}`}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
|
@ -1,9 +1,11 @@
|
|||
import React, { useEffect, useMemo, useReducer } from 'react';
|
||||
import React, { useEffect, useMemo, useReducer, useState } from 'react';
|
||||
import { AlertMode } from '../../common/types/alert-mode';
|
||||
import { IUser } from '../../common/types/user';
|
||||
import { Visibility } from '../../common/types/visibility';
|
||||
import { useGetSessionQuery } from '../services/session';
|
||||
import { defaultTemplate } from '../../common/default-template';
|
||||
import { Card } from './Card';
|
||||
import { Theme } from '../misc/theme';
|
||||
|
||||
type SettingDraftType = Pick<IUser,
|
||||
| 'alertMode'
|
||||
|
@ -30,6 +32,24 @@ export const SettingPage: React.VFC = () => {
|
|||
template: data?.template ?? null,
|
||||
});
|
||||
|
||||
const themes: Array<{ theme: Theme, name: string }> = [
|
||||
{
|
||||
theme: 'light',
|
||||
name: 'ライトテーマ'
|
||||
},
|
||||
{
|
||||
theme: 'dark',
|
||||
name: 'ダークテーマ'
|
||||
},
|
||||
{
|
||||
theme: 'system',
|
||||
name: 'システム設定に準じる'
|
||||
},
|
||||
];
|
||||
|
||||
const [currentTheme, setCurrentTheme] = useState<Theme>('light');
|
||||
const [currentLang, setCurrentLang] = useState<string>('ja-JP');
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
dispatchDraft({
|
||||
|
@ -52,53 +72,98 @@ export const SettingPage: React.VFC = () => {
|
|||
<div className="skeleton" style={{width: '100%', height: '128px'}}></div>
|
||||
) : (
|
||||
<div className="vstack fade">
|
||||
<div className="card">
|
||||
<div className="body vstack">
|
||||
<h1>スコア通知方法</h1>
|
||||
<div>
|
||||
<select name="alertMode" className="input-field" value={draft.alertMode} onChange={(e) => {
|
||||
dispatchDraft({ alertMode: e.target.value as AlertMode });
|
||||
}}>
|
||||
<option value="note">自動的にノートを投稿</option>
|
||||
<option value="notification">Misskeyに通知(標準)</option>
|
||||
<option value="nothing">通知しない</option>
|
||||
</select>
|
||||
{draft.alertMode === 'notification' && (
|
||||
<div className="alert bg-danger mt-2">
|
||||
<i className="icon bi bi-exclamation-circle"></i>
|
||||
「Misskey に通知」オプションは古いMisskeyでは動作しません。
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{ draft.alertMode === 'note' && (
|
||||
<div>
|
||||
<label htmlFor="visibility" className="input-field">公開範囲</label>
|
||||
<select name="visibility" className="input-field" value={draft.visibility} onChange={(e) => {
|
||||
dispatchDraft({ visibility: e.target.value as Visibility });
|
||||
}}>
|
||||
<option value="public">パブリック</option>
|
||||
<option value="home">ホーム</option>
|
||||
<option value="followers">フォロワー</option>
|
||||
</select>
|
||||
<label className="input-switch mt-2">
|
||||
<input type="checkbox" />
|
||||
<div className="switch"></div>
|
||||
<span>ローカル限定</span>
|
||||
</label>
|
||||
<Card bodyClassName="vstack">
|
||||
<h1>スコア通知方法</h1>
|
||||
<div>
|
||||
<select name="alertMode" className="input-field" value={draft.alertMode} onChange={(e) => {
|
||||
dispatchDraft({ alertMode: e.target.value as AlertMode });
|
||||
}}>
|
||||
<option value="note">自動的にノートを投稿</option>
|
||||
<option value="notification">Misskeyに通知(標準)</option>
|
||||
<option value="nothing">通知しない</option>
|
||||
</select>
|
||||
{draft.alertMode === 'notification' && (
|
||||
<div className="alert bg-danger mt-2">
|
||||
<i className="icon bi bi-exclamation-circle"></i>
|
||||
「Misskey に通知」オプションは古いMisskeyでは動作しません。
|
||||
</div>
|
||||
)}
|
||||
{saveButton}
|
||||
</div>
|
||||
</div>
|
||||
<div className="card">
|
||||
<div className="body vstack">
|
||||
<h1>テンプレート</h1>
|
||||
<textarea className="input-field" value={draft.template ?? defaultTemplate} style={{height: 228}} onChange={(e) => {
|
||||
dispatchDraft({ template: e.target.value });
|
||||
}} />
|
||||
{saveButton}
|
||||
{ draft.alertMode === 'note' && (
|
||||
<div>
|
||||
<label htmlFor="visibility" className="input-field">公開範囲</label>
|
||||
<select name="visibility" className="input-field" value={draft.visibility} onChange={(e) => {
|
||||
dispatchDraft({ visibility: e.target.value as Visibility });
|
||||
}}>
|
||||
<option value="public">パブリック</option>
|
||||
<option value="home">ホーム</option>
|
||||
<option value="followers">フォロワー</option>
|
||||
</select>
|
||||
<label className="input-switch mt-2">
|
||||
<input type="checkbox" />
|
||||
<div className="switch"></div>
|
||||
<span>ローカル限定</span>
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
{saveButton}
|
||||
</Card>
|
||||
<Card bodyClassName="vstack">
|
||||
<h1>表示設定</h1>
|
||||
<h2>テーマ</h2>
|
||||
<div>
|
||||
{
|
||||
themes.map(({ theme, name }) => (
|
||||
<label key={theme} className="input-check">
|
||||
<input type="radio" name={theme} value={theme} checked={theme === currentTheme} onChange={(e) => setCurrentTheme(e.target.value as Theme)} />
|
||||
<span>{name}</span>
|
||||
</label>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2>言語設定</h2>
|
||||
<select name="currentLang" className="input-field" value={currentLang} onChange={e => setCurrentLang(e.target.value)}>
|
||||
<option value="ja-JP">日本語</option>
|
||||
<option value="en-US">英語</option>
|
||||
</select>
|
||||
</Card>
|
||||
|
||||
<Card bodyClassName="vstack">
|
||||
<h1>テンプレート</h1>
|
||||
<p>アラートの自動投稿をカスタマイズできます。テンプレートに使える文字数は280文字です。空欄にすると、デフォルト値にリセットされます。</p>
|
||||
<textarea className="input-field" value={draft.template ?? defaultTemplate} style={{height: 228}} onChange={(e) => {
|
||||
dispatchDraft({ template: e.target.value });
|
||||
}} />
|
||||
<small className="text-dimmed">
|
||||
ハッシュタグ #misshaialert は、テンプレートに関わらず自動付与されます。
|
||||
</small>
|
||||
<details>
|
||||
<summary>ヘルプ</summary>
|
||||
<ul className="fade">
|
||||
<li><code>{'{'}notesCount{'}'}</code>といった形式のテキストは変数として扱われ、これを含めると投稿時に自動的に値が埋め込まれます。</li>
|
||||
</ul>
|
||||
</details>
|
||||
{saveButton}
|
||||
</Card>
|
||||
<Card bodyClassName="vstack">
|
||||
<button className="btn block">アラートをテスト送信する</button>
|
||||
<p className="text-dimmed">
|
||||
このボタンを押すと、現在の設定でアラートを送信するテストを行います。
|
||||
</p>
|
||||
</Card>
|
||||
<Card bodyClassName="vstack">
|
||||
<button className="btn block">ログアウトする</button>
|
||||
<p className="text-dimmed">
|
||||
ログアウトしても、アラートは送信されます。
|
||||
</p>
|
||||
</Card>
|
||||
<Card bodyClassName="vstack">
|
||||
<button className="btn danger block">アカウント連携を解除する</button>
|
||||
<p className="text-dimmed">
|
||||
これを実行すると、Misskeyとの連携設定を含むみす廃アラートのアカウントを削除します。
|
||||
</p>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
3
src/frontend/misc/theme.ts
Normal file
3
src/frontend/misc/theme.ts
Normal file
|
@ -0,0 +1,3 @@
|
|||
export type Theme = ActualTheme | 'system';
|
||||
|
||||
export type ActualTheme = 'light' | 'dark';
|
|
@ -21,3 +21,15 @@ body {
|
|||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block !important;
|
||||
}
|
||||
|
||||
.inline {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue