import React, { useCallback, useEffect, useReducer, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { useDispatch } from 'react-redux'; import { alertModes } from '../../common/types/alert-mode'; import { IUser } from '../../common/types/user'; import { Visibility } from '../../common/types/visibility'; import { useGetSessionQuery } from '../services/session'; import { Card } from './Card'; import { Theme, themes } from '../misc/theme'; import { API_ENDPOINT, LOCALSTORAGE_KEY_TOKEN } from '../const'; import { changeLang, changeTheme, showModal } from '../store/slices/screen'; import { useSelector } from '../store'; import { languageName } from '../langs'; import insertTextAtCursor from 'insert-text-at-cursor'; const variables = [ 'notesCount', 'followingCount', 'followersCount', 'notesDelta', 'followingDelta', 'followersDelta', 'url', 'username', 'host', 'rating', ] as const; type SettingDraftType = Partial>; type DraftReducer = React.Reducer>; export const SettingPage: React.VFC = () => { const session = useGetSessionQuery(undefined); const dispatch = useDispatch(); const data = session.data; const {t} = useTranslation(); const [draft, dispatchDraft] = useReducer((state, action) => { return { ...state, ...action }; }, { alertMode: data?.alertMode ?? 'note', visibility: data?.visibility ?? 'public', localOnly: data?.localOnly ?? false, remoteFollowersOnly: data?.remoteFollowersOnly ?? false, template: data?.template ?? null, }); const currentTheme = useSelector(state => state.screen.theme); const currentLang = useSelector(state => state.screen.language); const templateTextarea = useRef(null); const availableVisibilities: Visibility[] = [ 'public', 'home', 'followers' ]; const updateSetting = useCallback((obj: SettingDraftType) => { const previousDraft = draft; dispatchDraft(obj); return fetch(`${API_ENDPOINT}session`, { method: 'PUT', headers: { 'Authorization': `Bearer ${localStorage[LOCALSTORAGE_KEY_TOKEN]}`, '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) .then(() => dispatch(showModal({ type: 'dialog', icon: 'info', message: '保存しました。' }))); }, [updateSetting]); useEffect(() => { if (data) { dispatchDraft({ alertMode: data.alertMode, visibility: data.visibility, localOnly: data.localOnly, remoteFollowersOnly: data.remoteFollowersOnly, template: data.template, }); } }, [data]); const onClickInsertVariables = useCallback((e) => { dispatch(showModal({ type: 'menu', screenX: e.clientX, screenY: e.clientY, items: variables.map(key => ({ name: t('_template._variables.' + key), onClick: () => { if (templateTextarea.current) { insertTextAtCursor(templateTextarea.current, `{${key}}`); } }, })), })); }, [dispatch, t, variables, templateTextarea.current]); const onClickInsertVariablesHelp = useCallback(() => { dispatch(showModal({ type: 'dialog', icon: 'info', message: t('_template.insertVariablesHelp'), })); }, [dispatch, t]); const onClickSendAlert = useCallback(() => { dispatch(showModal({ type: 'dialog', title: t('_sendTest.title'), message: t('_sendTest.message'), icon: 'question', buttons: [ { text: t('_sendTest.yes'), style: 'primary', }, { text: t('_sendTest.no'), }, ], onSelect(i) { if (i === 0) { fetch(`${API_ENDPOINT}session/alert`, { method: 'POST', headers: { 'Authorization': `Bearer ${localStorage[LOCALSTORAGE_KEY_TOKEN]}`, }, }).then(() => { dispatch(showModal({ type: 'dialog', message: t('_sendTest.success'), icon: 'info', })); }).catch((e) => { console.error(e); dispatch(showModal({ type: 'dialog', message: t('_sendTest.failure'), icon: 'error', })); }); } }, })); }, [dispatch, t]); const onClickLogout = useCallback(() => { dispatch(showModal({ type: 'dialog', title: t('_logout.title'), message: t('_logout.message'), icon: 'question', buttons: [ { text: t('_logout.yes'), style: 'primary', }, { text: t('_logout.no'), }, ], onSelect(i) { if (i === 0) { localStorage.removeItem(LOCALSTORAGE_KEY_TOKEN); location.reload(); } }, })); }, [dispatch, t]); const onClickDeleteAccount = useCallback(() => { dispatch(showModal({ type: 'dialog', title: t('_deactivate.title'), message: t('_deactivate.message'), icon: 'question', buttons: [ { text: t('_deactivate.yes'), style: 'danger', }, { text: t('_deactivate.no'), }, ], primaryClassName: 'danger', onSelect(i) { if (i === 0) { fetch(`${API_ENDPOINT}session`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${localStorage[LOCALSTORAGE_KEY_TOKEN]}`, }, }).then(() => { dispatch(showModal({ type: 'dialog', message: t('_deactivate.success'), icon: 'info', onSelect() { location.reload(); } })); }).catch((e) => { console.error(e); dispatch(showModal({ type: 'dialog', message: t('_deactivate.failure'), icon: 'error', })); }); } }, })); }, [dispatch, t]); const defaultTemplate = t('_template.default'); return session.isLoading || !data ? (
) : (

{t('alertMode')}

{ alertModes.map((mode) => ( )) }
{ draft.alertMode === 'notification' && (
{t('_alertMode.notificationWarning')}
)} { draft.alertMode === 'note' && ( <>

{t('visibility')}

{ availableVisibilities.map((visibility) => ( )) }
)}

{t('appearance')}

{t('theme')}

{ themes.map(theme => ( )) }

{t('language')}

{t('translatedByTheCommunity')}  {t('helpTranslation')}

{t('template')}

{t('_template.description')}