diff --git a/src/components/AckButton.tsx b/src/components/AckButton.tsx
index 32756916..a0ff4c55 100644
--- a/src/components/AckButton.tsx
+++ b/src/components/AckButton.tsx
@@ -36,7 +36,8 @@ export const AckButton = (props: AckButtonProps): JSX.Element | null => {
onMouseLeave={() => {
setIsHovered(false)
}}
- onClick={() => {
+ onClick={(e) => {
+ e.stopPropagation()
if (myAck) {
props.user.UnAck().then(() => {
forceUpdate()
diff --git a/src/components/AckList.tsx b/src/components/AckList.tsx
index 7a3bd782..75a040d6 100644
--- a/src/components/AckList.tsx
+++ b/src/components/AckList.tsx
@@ -1,8 +1,8 @@
import { type User } from '@concurrent-world/client'
import { useEffect, useState } from 'react'
-import { Box, Chip, Link, Tab, Tabs, Typography } from '@mui/material'
+import { Box, Chip, Tab, Tabs, Typography } from '@mui/material'
import { CCAvatar } from './ui/CCAvatar'
-import { Link as RouterLink } from 'react-router-dom'
+import { Link as NavLink } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { useClient } from '../context/ClientContext'
import { AckButton } from './AckButton'
@@ -78,13 +78,21 @@ export const AckList = (props: AckListProps): JSX.Element => {
gap: 1,
textDecoration: 'none'
}}
- component={RouterLink}
- to={`/${user.ccid}`}
- onClick={props.onNavigated}
>
-
- {user.profile?.username}
+
+ {user.profile?.username}
{client.ackers.find((ack) => ack.ccid === user.ccid) && (
{
<>
{
@{entity.id}@{client.host}
-
+
{
diff --git a/src/components/Settings/General.tsx b/src/components/Settings/General.tsx
index 70d58cc4..85766e94 100644
--- a/src/components/Settings/General.tsx
+++ b/src/components/Settings/General.tsx
@@ -6,11 +6,11 @@ import {
Box,
Button,
Checkbox,
- Divider,
FormControlLabel,
FormGroup,
MenuItem,
Select,
+ Slider,
Switch,
Typography
} from '@mui/material'
@@ -22,6 +22,9 @@ import { IssueJWT, Schemas } from '@concurrent-world/client'
import { useTranslation } from 'react-i18next'
import { type NotificationSubscription } from '../../model'
+import TextIncreaseIcon from '@mui/icons-material/TextIncrease'
+import TextDecreaseIcon from '@mui/icons-material/TextDecrease'
+
export const GeneralSettings = (): JSX.Element => {
const { client } = useClient()
const [invitationCode, setInvitationCode] = useState('')
@@ -32,6 +35,7 @@ export const GeneralSettings = (): JSX.Element => {
const [enableConcord, setEnableConcord] = usePreference('enableConcord')
const [autoSwitchMediaPostType, setAutoSwitchMediaPostType] = usePreference('autoSwitchMediaPostType')
const [tutorialCompleted, setTutorialCompleted] = usePreference('tutorialCompleted')
+ const [baseFontSize, setBaseFontSize] = usePreference('baseFontSize')
const tags = client?.user?.tag ? client.user.tag.split(',') : []
const { enqueueSnackbar } = useSnackbar()
@@ -72,7 +76,7 @@ export const GeneralSettings = (): JSX.Element => {
sx={{
display: 'flex',
flexDirection: 'column',
- gap: 1
+ gap: 2
}}
>
@@ -83,6 +87,9 @@ export const GeneralSettings = (): JSX.Element => {
i18n.changeLanguage(e.target.value)
setCurrentLanguage(e.target.value)
}}
+ sx={{
+ marginLeft: 2
+ }}
>
@@ -94,7 +101,11 @@ export const GeneralSettings = (): JSX.Element => {
{t('basic')}
-
+
{
{t('showTutorial')}
)}
-
- {t('notification.title')}
-
- {notification ? (
- <>
-
- {
- if (e.target.checked) {
- setSchemas((prev) => [...prev, Schemas.replyAssociation])
- } else {
- setSchemas((prev) => prev.filter((s) => s !== Schemas.replyAssociation))
- }
- }}
- />
- }
- label={t('notification.reply')}
- />
- {
- if (e.target.checked) {
- setSchemas((prev) => [...prev, Schemas.mentionAssociation])
- } else {
- setSchemas((prev) => prev.filter((s) => s !== Schemas.mentionAssociation))
- }
- }}
- />
- }
- label={t('notification.mention')}
- />
- {
- if (e.target.checked) {
- setSchemas((prev) => [...prev, Schemas.readAccessRequestAssociation])
- } else {
- setSchemas((prev) =>
- prev.filter((s) => s !== Schemas.readAccessRequestAssociation)
- )
- }
- }}
- />
- }
- label={t('notification.viewerRequest')}
- />
- {
- if (e.target.checked) {
- setSchemas((prev) => [...prev, Schemas.likeAssociation])
- } else {
- setSchemas((prev) => prev.filter((s) => s !== Schemas.likeAssociation))
- }
- }}
- />
- }
- label={t('notification.fav')}
- />
- {
- if (e.target.checked) {
- setSchemas((prev) => [...prev, Schemas.reactionAssociation])
- } else {
- setSchemas((prev) => prev.filter((s) => s !== Schemas.reactionAssociation))
- }
- }}
- />
- }
- label={t('notification.reaction')}
- />
- {
- if (e.target.checked) {
- setSchemas((prev) => [...prev, Schemas.rerouteAssociation])
- } else {
- setSchemas((prev) => prev.filter((s) => s !== Schemas.rerouteAssociation))
- }
- }}
- />
- }
- label={t('notification.reroute')}
- />
-
-
+ {'文字サイズ'}
+
+
-
+
- client.api
- .fetchWithCredential(
- client.host,
- `/api/v1/notification/${client.ccid}/concrnt.world`,
- {
- method: 'DELETE'
- }
- )
- .then((res) => {
- enqueueSnackbar(t('notification.disabled'), { variant: 'success' })
- setReload((prev) => prev + 1)
- })
- .catch((err) => {
- console.error(err)
- enqueueSnackbar(t('notification.failed'), { variant: 'error' })
- })
+
+
+ {t('notification.title')}
+
+ {notification ? (
+ <>
+
- {t('notification.disable')}
-
+ {
+ if (e.target.checked) {
+ setSchemas((prev) => [...prev, Schemas.replyAssociation])
+ } else {
+ setSchemas((prev) => prev.filter((s) => s !== Schemas.replyAssociation))
+ }
+ }}
+ />
+ }
+ label={t('notification.reply')}
+ />
+ {
+ if (e.target.checked) {
+ setSchemas((prev) => [...prev, Schemas.mentionAssociation])
+ } else {
+ setSchemas((prev) =>
+ prev.filter((s) => s !== Schemas.mentionAssociation)
+ )
+ }
+ }}
+ />
+ }
+ label={t('notification.mention')}
+ />
+ {
+ if (e.target.checked) {
+ setSchemas((prev) => [...prev, Schemas.readAccessRequestAssociation])
+ } else {
+ setSchemas((prev) =>
+ prev.filter((s) => s !== Schemas.readAccessRequestAssociation)
+ )
+ }
+ }}
+ />
+ }
+ label={t('notification.viewerRequest')}
+ />
+ {
+ if (e.target.checked) {
+ setSchemas((prev) => [...prev, Schemas.likeAssociation])
+ } else {
+ setSchemas((prev) => prev.filter((s) => s !== Schemas.likeAssociation))
+ }
+ }}
+ />
+ }
+ label={t('notification.fav')}
+ />
+ {
+ if (e.target.checked) {
+ setSchemas((prev) => [...prev, Schemas.reactionAssociation])
+ } else {
+ setSchemas((prev) =>
+ prev.filter((s) => s !== Schemas.reactionAssociation)
+ )
+ }
+ }}
+ />
+ }
+ label={t('notification.reaction')}
+ />
+ {
+ if (e.target.checked) {
+ setSchemas((prev) => [...prev, Schemas.rerouteAssociation])
+ } else {
+ setSchemas((prev) =>
+ prev.filter((s) => s !== Schemas.rerouteAssociation)
+ )
+ }
+ }}
+ />
+ }
+ label={t('notification.reroute')}
+ />
+
+
+
+
+
+
+ >
+ ) : (
+ <>
-
- >
- ) : (
- <>
-
- >
- )}
+ >
+ )}
+
{!enableConcord && (
diff --git a/src/context/PreferenceContext.tsx b/src/context/PreferenceContext.tsx
index 20df13bf..18b337e8 100644
--- a/src/context/PreferenceContext.tsx
+++ b/src/context/PreferenceContext.tsx
@@ -28,6 +28,7 @@ export interface Preference {
autoSwitchMediaPostType: boolean
tutorialProgress: number
tutorialCompleted: boolean
+ baseFontSize: number
}
export const defaultPreference: Preference = {
@@ -57,7 +58,8 @@ export const defaultPreference: Preference = {
enableConcord: false,
autoSwitchMediaPostType: true,
tutorialProgress: 0,
- tutorialCompleted: false
+ tutorialCompleted: false,
+ baseFontSize: 16
}
interface PreferenceState {
diff --git a/src/context/Theme.tsx b/src/context/Theme.tsx
index 560295a8..a00fbfd3 100644
--- a/src/context/Theme.tsx
+++ b/src/context/Theme.tsx
@@ -11,10 +11,13 @@ interface ConcrntThemeProps {
export const ConcrntThemeProvider = (props: ConcrntThemeProps): JSX.Element => {
const [themeName] = usePreference('themeName')
const [customThemes] = usePreference('customThemes')
+ const [baseFontSize] = usePreference('baseFontSize')
const [theme, setTheme] = useState(loadConcurrentTheme(themeName, customThemes))
useEffect(() => {
- const newtheme = loadConcurrentTheme(themeName, customThemes)
+ const newtheme = loadConcurrentTheme(themeName, customThemes, { fontSize: baseFontSize })
+ newtheme.typography.fontSize = baseFontSize
+ console.log('fontsize changed:', baseFontSize)
localStorage.setItem('theme', JSON.stringify(newtheme))
setTheme(newtheme)
let themeColorMetaTag: HTMLMetaElement = document.querySelector('meta[name="theme-color"]') as HTMLMetaElement
@@ -24,7 +27,7 @@ export const ConcrntThemeProvider = (props: ConcrntThemeProps): JSX.Element => {
document.head.appendChild(themeColorMetaTag)
}
themeColorMetaTag.content = newtheme.palette.background.default
- }, [themeName, customThemes])
+ }, [themeName, customThemes, baseFontSize])
return (
diff --git a/src/themes.ts b/src/themes.ts
index 148482e9..ecee964a 100644
--- a/src/themes.ts
+++ b/src/themes.ts
@@ -246,7 +246,7 @@ export const ConcurrentDefaultTheme = {
}
},
typography: {
- fontSize: 14,
+ fontSize: 16,
body1: {
fontSize: '1rem'
},
@@ -287,7 +287,7 @@ export const ConcurrentDefaultTheme = {
breakpoints: {
values: {
xs: 0,
- sm: 450,
+ sm: 550,
md: 960,
lg: 1280,
xl: 1920
@@ -316,7 +316,8 @@ export const ConcurrentDefaultTheme = {
},
html: {
overscrollBehaviorY: 'none',
- userSelect: 'none'
+ userSelect: 'none',
+ fontSize: '16px'
},
body: {
overflowX: 'hidden',
@@ -356,7 +357,7 @@ export function deepMerge(target: Record, source: Record {
+export const createConcurrentThemeFromObject = (base: any, options?: any): ConcurrentTheme => {
if (base.palette.text !== undefined) {
if (base.palette.text.hint === undefined) base.palette.text.hint = alpha(base.palette.text.primary, 0.5)
if (base.palette.text.disabled === undefined) base.palette.text.disabled = alpha(base.palette.text.primary, 0.5)
@@ -374,14 +375,20 @@ export const createConcurrentThemeFromObject = (base: any): ConcurrentTheme => {
}
}
- const theme: ConcurrentTheme = deepMerge(ConcurrentDefaultTheme, base)
+ const defaultTheme = ConcurrentDefaultTheme
+ if (options?.fontSize) {
+ defaultTheme.components.MuiCssBaseline.styleOverrides.html.fontSize = `${options.fontSize}px`
+ }
+
+ const theme: ConcurrentTheme = deepMerge(defaultTheme, base)
return createTheme(theme) as ConcurrentTheme
}
export const loadConcurrentTheme = (
name: string,
- customs: Record> = {}
+ customs: Record> = {},
+ options?: { fontSize?: number }
): ConcurrentTheme => {
const base = customs[name] ?? Themes[name] ?? Themes.blue
- return createConcurrentThemeFromObject(base)
+ return createConcurrentThemeFromObject(base, options)
}