mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-15 06:22:25 +03:00
feat(core): init editor setting ui (#7878)
- init editor setting ui https://github.com/user-attachments/assets/c54f5816-ef05-4ac0-b11a-8ab7159f928c
This commit is contained in:
parent
03c4d56a91
commit
b333cde336
@ -91,6 +91,13 @@ export const AFFINE_FLAGS = {
|
||||
configurable: true,
|
||||
defaultState: false,
|
||||
},
|
||||
enable_editor_settings: {
|
||||
category: 'affine',
|
||||
displayName: 'Editor Settings',
|
||||
description: 'Enables editor settings.',
|
||||
configurable: isCanaryBuild,
|
||||
defaultState: false,
|
||||
},
|
||||
} satisfies { [key in string]: FlagInfo };
|
||||
|
||||
export type AFFINE_FLAGS = typeof AFFINE_FLAGS;
|
||||
|
@ -0,0 +1,183 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuTrigger,
|
||||
RadioGroup,
|
||||
type RadioItem,
|
||||
Slider,
|
||||
} from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { menuTrigger, settingWrapper } from '../style.css';
|
||||
import { EdgelessSnapshot } from './snapshot';
|
||||
|
||||
export const ConnecterSettings = () => {
|
||||
const t = useI18n();
|
||||
|
||||
const [connecterStyle, setConnecterStyle] = useState<'general' | 'scribbled'>(
|
||||
'general'
|
||||
);
|
||||
const [connectorShape, setConnectorShape] = useState<
|
||||
'elbowed' | 'curve' | 'straight'
|
||||
>('elbowed');
|
||||
const [borderStyle, setBorderStyle] = useState<'solid' | 'dash'>('solid');
|
||||
const [borderThickness, setBorderThickness] = useState<number[]>([3]);
|
||||
|
||||
const connecterStyleItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'general',
|
||||
label: t['com.affine.settings.editorSettings.edgeless.style.general'](),
|
||||
},
|
||||
{
|
||||
value: 'scribbled',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.style.scribbled'](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
const connecterShapeItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'elbowed',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.connector-shape.elbowed'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'curve',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.connector-shape.curve'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'straight',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.connector-shape.straight'
|
||||
](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
const borderStyleItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'solid',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.note.border.solid'](),
|
||||
},
|
||||
{
|
||||
value: 'dash',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.note.border.dash'](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<EdgelessSnapshot
|
||||
title={t['com.affine.settings.editorSettings.edgeless.connecter']()}
|
||||
option={['mock-option']}
|
||||
type="mock-type"
|
||||
/>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.color'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Grey</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Grey
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.style']()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={connecterStyleItems}
|
||||
value={connecterStyle}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setConnecterStyle}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.connector-shape'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={connecterShapeItems}
|
||||
value={connectorShape}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setConnectorShape}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.border-style'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={borderStyleItems}
|
||||
value={borderStyle}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setBorderStyle}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.border-thickness'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Slider
|
||||
value={borderThickness}
|
||||
onValueChange={setBorderThickness}
|
||||
min={1}
|
||||
max={5}
|
||||
step={1}
|
||||
nodes={[1, 2, 3, 4, 5]}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.start-endpoint'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>None</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
None
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.connecter.end-endpoint'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Arrow</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Arrow
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,23 @@
|
||||
import { SettingWrapper } from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
import { ConnecterSettings } from './connecter';
|
||||
import { MindMapSettings } from './mind-map';
|
||||
import { NoteSettings } from './note';
|
||||
import { PenSettings } from './pen';
|
||||
import { ShapeSettings } from './shape';
|
||||
import { TextSettings } from './text';
|
||||
|
||||
export const Edgeless = () => {
|
||||
const t = useI18n();
|
||||
return (
|
||||
<SettingWrapper title={t['com.affine.settings.editorSettings.edgeless']()}>
|
||||
<NoteSettings />
|
||||
<TextSettings />
|
||||
<ShapeSettings />
|
||||
<ConnecterSettings />
|
||||
<PenSettings />
|
||||
<MindMapSettings />
|
||||
</SettingWrapper>
|
||||
);
|
||||
};
|
@ -0,0 +1 @@
|
||||
export * from './edgeless';
|
@ -0,0 +1,79 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuTrigger,
|
||||
RadioGroup,
|
||||
type RadioItem,
|
||||
} from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { menuTrigger, settingWrapper } from '../style.css';
|
||||
import { EdgelessSnapshot } from './snapshot';
|
||||
|
||||
export const MindMapSettings = () => {
|
||||
const t = useI18n();
|
||||
const [layoutValue, setLayoutValue] = useState<'left' | 'radial' | 'right'>(
|
||||
'right'
|
||||
);
|
||||
const layoutValueItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'left',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.mind-map.layout.left'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'radial',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.mind-map.layout.radial'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'right',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.mind-map.layout.right'
|
||||
](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<EdgelessSnapshot
|
||||
title={t['com.affine.settings.editorSettings.edgeless.mind-map']()}
|
||||
option={['mock-option']}
|
||||
type="mock-type"
|
||||
/>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.style']()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Style 1</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Style 1
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.mind-map.layout'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={layoutValueItems}
|
||||
value={layoutValue}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setLayoutValue}
|
||||
/>
|
||||
</SettingRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,111 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuTrigger,
|
||||
RadioGroup,
|
||||
type RadioItem,
|
||||
Slider,
|
||||
} from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { menuTrigger, settingWrapper } from '../style.css';
|
||||
import { EdgelessSnapshot } from './snapshot';
|
||||
|
||||
export const NoteSettings = () => {
|
||||
const t = useI18n();
|
||||
const [borderStyle, setBorderStyle] = useState<'solid' | 'dash' | 'none'>(
|
||||
'solid'
|
||||
);
|
||||
const [borderThickness, setBorderThickness] = useState<number[]>([3]);
|
||||
|
||||
const borderStyleItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'solid',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.note.border.solid'](),
|
||||
},
|
||||
{
|
||||
value: 'dash',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.note.border.dash'](),
|
||||
},
|
||||
{
|
||||
value: 'none',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.note.border.none'](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<EdgelessSnapshot
|
||||
title={t['com.affine.settings.editorSettings.edgeless.note']()}
|
||||
option={['mock-option']}
|
||||
type="mock-type"
|
||||
/>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.note.background'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Yellow</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Yellow
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.note.corners']()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Small</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Small
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.note.shadow']()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Box shadow</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Box shadow
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.note.border']()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={borderStyleItems}
|
||||
value={borderStyle}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setBorderStyle}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.note.border-thickness'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Slider
|
||||
value={borderThickness}
|
||||
onValueChange={setBorderThickness}
|
||||
min={1}
|
||||
max={5}
|
||||
step={1}
|
||||
nodes={[1, 2, 3, 4, 5]}
|
||||
/>
|
||||
</SettingRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,44 @@
|
||||
import { Menu, MenuItem, MenuTrigger, Slider } from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { menuTrigger } from '../style.css';
|
||||
import { EdgelessSnapshot } from './snapshot';
|
||||
|
||||
export const PenSettings = () => {
|
||||
const t = useI18n();
|
||||
const [borderThickness, setBorderThickness] = useState<number[]>([3]);
|
||||
return (
|
||||
<>
|
||||
<EdgelessSnapshot
|
||||
title={t['com.affine.settings.editorSettings.edgeless.pen']()}
|
||||
option={['mock-option']}
|
||||
type="mock-type"
|
||||
/>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.pen.color']()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Yellow</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Yellow
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.pen.thickness']()}
|
||||
desc={''}
|
||||
>
|
||||
<Slider
|
||||
value={borderThickness}
|
||||
onValueChange={setBorderThickness}
|
||||
min={1}
|
||||
max={5}
|
||||
step={1}
|
||||
nodes={[1, 2, 3, 4, 5]}
|
||||
/>
|
||||
</SettingRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,276 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuTrigger,
|
||||
RadioGroup,
|
||||
type RadioItem,
|
||||
Slider,
|
||||
} from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { menuTrigger, settingWrapper, shapeIndicator } from '../style.css';
|
||||
import { EdgelessSnapshot } from './snapshot';
|
||||
|
||||
type Shape =
|
||||
| 'square'
|
||||
| 'ellipse'
|
||||
| 'diamond'
|
||||
| 'triangle'
|
||||
| 'rounded-rectangle';
|
||||
|
||||
export const ShapeSettings = () => {
|
||||
const t = useI18n();
|
||||
const [currentShape, setCurrentShape] = useState<Shape>('square');
|
||||
const [shapeStyle, setShapeStyle] = useState<'general' | 'scribbled'>(
|
||||
'general'
|
||||
);
|
||||
const [borderStyle, setBorderStyle] = useState<'solid' | 'dash' | 'none'>(
|
||||
'solid'
|
||||
);
|
||||
const [borderThickness, setBorderThickness] = useState<number[]>([3]);
|
||||
const [textAlignment, setTextAlignment] = useState<
|
||||
'left' | 'center' | 'right'
|
||||
>('left');
|
||||
|
||||
const shapeStyleItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'general',
|
||||
label: t['com.affine.settings.editorSettings.edgeless.style.general'](),
|
||||
},
|
||||
{
|
||||
value: 'scribbled',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.style.scribbled'](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
const borderStyleItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'solid',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.note.border.solid'](),
|
||||
},
|
||||
{
|
||||
value: 'dash',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.note.border.dash'](),
|
||||
},
|
||||
{
|
||||
value: 'none',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.note.border.none'](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
const alignItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'left',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.left'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'center',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.center'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'right',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.right'
|
||||
](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
const shapes = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'square',
|
||||
label: t['com.affine.settings.editorSettings.edgeless.shape.square'](),
|
||||
},
|
||||
{
|
||||
value: 'ellipse',
|
||||
label: t['com.affine.settings.editorSettings.edgeless.shape.ellipse'](),
|
||||
},
|
||||
{
|
||||
value: 'diamond',
|
||||
label: t['com.affine.settings.editorSettings.edgeless.shape.diamond'](),
|
||||
},
|
||||
{
|
||||
value: 'triangle',
|
||||
label:
|
||||
t['com.affine.settings.editorSettings.edgeless.shape.triangle'](),
|
||||
},
|
||||
{
|
||||
value: 'rounded-rectangle',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.rounded-rectangle'
|
||||
](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EdgelessSnapshot
|
||||
title={t['com.affine.settings.editorSettings.edgeless.shape']()}
|
||||
option={['mock-option']}
|
||||
type="mock-type"
|
||||
/>
|
||||
|
||||
<RadioGroup
|
||||
padding={0}
|
||||
gap={4}
|
||||
itemHeight={28}
|
||||
borderRadius={8}
|
||||
value={currentShape}
|
||||
items={shapes}
|
||||
onChange={setCurrentShape}
|
||||
style={{ background: 'transparent', marginBottom: '16px' }}
|
||||
indicatorClassName={shapeIndicator}
|
||||
/>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.style']()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={shapeStyleItems}
|
||||
value={shapeStyle}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setShapeStyle}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.fill-color'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Yellow</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Yellow
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.border-color'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Yellow</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Yellow
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.border-style'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={borderStyleItems}
|
||||
value={borderStyle}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setBorderStyle}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.border-thickness'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Slider
|
||||
value={borderThickness}
|
||||
onValueChange={setBorderThickness}
|
||||
min={1}
|
||||
max={5}
|
||||
step={1}
|
||||
nodes={[1, 2, 3, 4, 5]}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.text-color'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Yellow</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Yellow
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.shape.font']()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Inter</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Inter
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.font-size'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>15px</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
15px
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.font-style'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Regular</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Regular
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.shape.text-alignment'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={alignItems}
|
||||
value={textAlignment}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setTextAlignment}
|
||||
/>
|
||||
</SettingRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
import { snapshot, snapshotContainer, snapshotTitle } from '../style.css';
|
||||
|
||||
export const EdgelessSnapshot = ({
|
||||
title,
|
||||
option,
|
||||
type,
|
||||
}: {
|
||||
title: string;
|
||||
option: string[];
|
||||
type: string;
|
||||
}) => {
|
||||
return (
|
||||
<div className={snapshotContainer}>
|
||||
<div className={snapshotTitle}>{title}</div>
|
||||
<div
|
||||
className={snapshot}
|
||||
data-editor-option={option}
|
||||
data-editor-type={type}
|
||||
>
|
||||
Mock Preview
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
@ -0,0 +1,112 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuTrigger,
|
||||
RadioGroup,
|
||||
type RadioItem,
|
||||
} from '@affine/component';
|
||||
import { SettingRow } from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import { useMemo, useState } from 'react';
|
||||
|
||||
import { menuTrigger, settingWrapper } from '../style.css';
|
||||
import { EdgelessSnapshot } from './snapshot';
|
||||
|
||||
export const TextSettings = () => {
|
||||
const t = useI18n();
|
||||
|
||||
const [textAlignment, setTextAlignment] = useState<
|
||||
'left' | 'center' | 'right'
|
||||
>('left');
|
||||
|
||||
const alignItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'left',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.left'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'center',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.center'
|
||||
](),
|
||||
},
|
||||
{
|
||||
value: 'right',
|
||||
label:
|
||||
t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.alignment.right'
|
||||
](),
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<EdgelessSnapshot
|
||||
title={t['com.affine.settings.editorSettings.edgeless.text']()}
|
||||
option={['mock-option']}
|
||||
type="mock-type"
|
||||
/>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.text.color']()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Blue</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Blue
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.text.font']()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Inter</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Inter
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.text.font-size']()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>15px</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
15px
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.edgeless.text.font-weight'
|
||||
]()}
|
||||
desc={''}
|
||||
>
|
||||
<Menu items={<MenuItem>Regular</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Regular
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.edgeless.text.alignment']()}
|
||||
desc={''}
|
||||
>
|
||||
<RadioGroup
|
||||
items={alignItems}
|
||||
value={textAlignment}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setTextAlignment}
|
||||
/>
|
||||
</SettingRow>
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,199 @@
|
||||
import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
MenuTrigger,
|
||||
RadioGroup,
|
||||
type RadioItem,
|
||||
Switch,
|
||||
} from '@affine/component';
|
||||
import {
|
||||
SettingRow,
|
||||
SettingWrapper,
|
||||
} from '@affine/component/setting-components';
|
||||
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import {
|
||||
type AppSetting,
|
||||
type DocMode,
|
||||
fontStyleOptions,
|
||||
} from '@toeverything/infra';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
|
||||
import { menu, menuTrigger, settingWrapper } from './style.css';
|
||||
|
||||
const FontFamilySettings = () => {
|
||||
const t = useI18n();
|
||||
const { appSettings, updateSettings } = useAppSettingHelper();
|
||||
|
||||
const radioItems = useMemo(() => {
|
||||
return fontStyleOptions.map(({ key, value }) => {
|
||||
const label =
|
||||
key === 'Mono'
|
||||
? t[`com.affine.appearanceSettings.fontStyle.mono`]()
|
||||
: key === 'Sans'
|
||||
? t['com.affine.appearanceSettings.fontStyle.sans']()
|
||||
: key === 'Serif'
|
||||
? t['com.affine.appearanceSettings.fontStyle.serif']()
|
||||
: '';
|
||||
return {
|
||||
value: key,
|
||||
label,
|
||||
testId: 'system-font-style-trigger',
|
||||
style: { fontFamily: value },
|
||||
} satisfies RadioItem;
|
||||
});
|
||||
}, [t]);
|
||||
|
||||
return (
|
||||
<RadioGroup
|
||||
items={radioItems}
|
||||
value={appSettings.fontStyle}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={useCallback(
|
||||
(value: AppSetting['fontStyle']) => {
|
||||
updateSettings('fontStyle', value);
|
||||
},
|
||||
[updateSettings]
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const NewDocDefaultModeSettings = () => {
|
||||
const t = useI18n();
|
||||
const [value, setValue] = useState<DocMode>('page');
|
||||
const radioItems = useMemo<RadioItem[]>(
|
||||
() => [
|
||||
{
|
||||
value: 'page',
|
||||
label: t['Page'](),
|
||||
testId: 'page-mode-trigger',
|
||||
},
|
||||
{
|
||||
value: 'edgeless',
|
||||
label: t['Edgeless'](),
|
||||
testId: 'edgeless-mode-trigger',
|
||||
},
|
||||
],
|
||||
[t]
|
||||
);
|
||||
return (
|
||||
<RadioGroup
|
||||
items={radioItems}
|
||||
value={value}
|
||||
width={250}
|
||||
className={settingWrapper}
|
||||
onChange={setValue}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const General = () => {
|
||||
const t = useI18n();
|
||||
return (
|
||||
<SettingWrapper title={t['com.affine.settings.editorSettings.general']()}>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.general.ai.title']()}
|
||||
desc={t['com.affine.settings.editorSettings.general.ai.description']()}
|
||||
>
|
||||
<Switch />
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.appearanceSettings.font.title']()}
|
||||
desc={t['com.affine.appearanceSettings.font.description']()}
|
||||
>
|
||||
<FontFamilySettings />
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.general.font-family.custom.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.general.font-family.custom.description'
|
||||
]()}
|
||||
>
|
||||
<Switch />
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.general.font-family.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.general.font-family.description'
|
||||
]()}
|
||||
>
|
||||
<Menu items={<MenuItem>inter</MenuItem>}>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
inter
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.general.font-size.title']()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.general.font-size.description'
|
||||
]()}
|
||||
>
|
||||
<Menu
|
||||
contentOptions={{
|
||||
className: menu,
|
||||
}}
|
||||
items={<MenuItem>15</MenuItem>}
|
||||
>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
15
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.general.default-new-doc.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.general.default-new-doc.description'
|
||||
]()}
|
||||
>
|
||||
<NewDocDefaultModeSettings />
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.general.default-code-block.language.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.general.default-code-block.language.description'
|
||||
]()}
|
||||
>
|
||||
<Menu
|
||||
contentOptions={{
|
||||
className: menu,
|
||||
}}
|
||||
items={<MenuItem>Plain Text</MenuItem>}
|
||||
>
|
||||
<MenuTrigger className={menuTrigger} disabled>
|
||||
Plain Text
|
||||
</MenuTrigger>
|
||||
</Menu>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.general.default-code-block.wrap.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.general.default-code-block.wrap.description'
|
||||
]()}
|
||||
>
|
||||
<Switch />
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.general.spell-check.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.general.spell-check.description'
|
||||
]()}
|
||||
>
|
||||
<Switch />
|
||||
</SettingRow>
|
||||
</SettingWrapper>
|
||||
);
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
import { SettingHeader } from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
import { Edgeless } from './edgeless';
|
||||
import { General } from './general';
|
||||
import { Page } from './page';
|
||||
import { Preferences } from './preferences';
|
||||
|
||||
export const EditorSettings = () => {
|
||||
const t = useI18n();
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingHeader
|
||||
title={t['com.affine.settings.editorSettings.title']()}
|
||||
subtitle={t['com.affine.settings.editorSettings.subtitle']()}
|
||||
/>
|
||||
<General />
|
||||
<Page />
|
||||
<Edgeless />
|
||||
<Preferences />
|
||||
</>
|
||||
);
|
||||
};
|
@ -0,0 +1,38 @@
|
||||
import { Switch } from '@affine/component';
|
||||
import {
|
||||
SettingRow,
|
||||
SettingWrapper,
|
||||
} from '@affine/component/setting-components';
|
||||
import { useAppSettingHelper } from '@affine/core/hooks/affine/use-app-setting-helper';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
export const Page = () => {
|
||||
const t = useI18n();
|
||||
const { appSettings, updateSettings } = useAppSettingHelper();
|
||||
return (
|
||||
<SettingWrapper title={t['com.affine.settings.editorSettings.page']()}>
|
||||
<SettingRow
|
||||
name={t['com.affine.settings.editorSettings.page.full-width.title']()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.page.full-width.description'
|
||||
]()}
|
||||
>
|
||||
<Switch
|
||||
data-testid="full-width-layout-trigger"
|
||||
checked={appSettings.fullWidthLayout}
|
||||
onChange={checked => updateSettings('fullWidthLayout', checked)}
|
||||
/>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.page.display-doc-info.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.page.display-doc-info.description'
|
||||
]()}
|
||||
>
|
||||
<Switch />
|
||||
</SettingRow>
|
||||
</SettingWrapper>
|
||||
);
|
||||
};
|
@ -0,0 +1,36 @@
|
||||
import { Button } from '@affine/component';
|
||||
import {
|
||||
SettingRow,
|
||||
SettingWrapper,
|
||||
} from '@affine/component/setting-components';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
|
||||
export const Preferences = () => {
|
||||
const t = useI18n();
|
||||
return (
|
||||
<SettingWrapper
|
||||
title={t['com.affine.settings.editorSettings.preferences']()}
|
||||
>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.preferences.export.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.preferences.export.description'
|
||||
]()}
|
||||
>
|
||||
<Button>Export</Button>
|
||||
</SettingRow>
|
||||
<SettingRow
|
||||
name={t[
|
||||
'com.affine.settings.editorSettings.preferences.import.title'
|
||||
]()}
|
||||
desc={t[
|
||||
'com.affine.settings.editorSettings.preferences.import.description'
|
||||
]()}
|
||||
>
|
||||
<Button>Import</Button>
|
||||
</SettingRow>
|
||||
</SettingWrapper>
|
||||
);
|
||||
};
|
@ -0,0 +1,51 @@
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { style } from '@vanilla-extract/css';
|
||||
export const settingWrapper = style({
|
||||
flexGrow: 1,
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end',
|
||||
minWidth: '150px',
|
||||
maxWidth: '250px',
|
||||
});
|
||||
|
||||
export const menu = style({
|
||||
background: 'white',
|
||||
width: '250px',
|
||||
maxHeight: '30vh',
|
||||
overflowY: 'auto',
|
||||
});
|
||||
|
||||
export const menuTrigger = style({
|
||||
textTransform: 'capitalize',
|
||||
fontWeight: 600,
|
||||
width: '250px',
|
||||
});
|
||||
|
||||
export const snapshotContainer = style({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
marginBottom: '24px',
|
||||
});
|
||||
|
||||
export const snapshotTitle = style({
|
||||
marginBottom: '8px',
|
||||
fontSize: cssVar('fontSm'),
|
||||
fontWeight: 500,
|
||||
color: cssVarV2('text/secondary'),
|
||||
});
|
||||
|
||||
export const snapshot = style({
|
||||
width: '100%',
|
||||
height: '180px',
|
||||
border: `1px solid ${cssVarV2('layer/insideBorder/border')}`,
|
||||
borderRadius: '4px',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
});
|
||||
|
||||
export const shapeIndicator = style({
|
||||
boxShadow: 'none',
|
||||
backgroundColor: cssVarV2('layer/background/tertiary'),
|
||||
});
|
@ -2,11 +2,16 @@ import { UserFeatureService } from '@affine/core/modules/cloud/services/user-fea
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import {
|
||||
AppearanceIcon,
|
||||
BlocksuiteIcon,
|
||||
ExperimentIcon,
|
||||
InformationIcon,
|
||||
KeyboardIcon,
|
||||
} from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useServices } from '@toeverything/infra';
|
||||
import {
|
||||
FeatureFlagService,
|
||||
useLiveData,
|
||||
useServices,
|
||||
} from '@toeverything/infra';
|
||||
import type { ReactElement, SVGProps } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
@ -15,6 +20,7 @@ import type { GeneralSettingKey } from '../types';
|
||||
import { AboutAffine } from './about';
|
||||
import { AppearanceSettings } from './appearance';
|
||||
import { BillingSettings } from './billing';
|
||||
import { EditorSettings } from './editor';
|
||||
import { ExperimentalFeatures } from './experimental-features';
|
||||
import { PaymentIcon, UpgradeIcon } from './icons';
|
||||
import { AFFiNEPricingPlans } from './plans';
|
||||
@ -31,15 +37,24 @@ export type GeneralSettingList = GeneralSettingListItem[];
|
||||
|
||||
export const useGeneralSettingList = (): GeneralSettingList => {
|
||||
const t = useI18n();
|
||||
const { authService, serverConfigService, userFeatureService } = useServices({
|
||||
const {
|
||||
authService,
|
||||
serverConfigService,
|
||||
userFeatureService,
|
||||
featureFlagService,
|
||||
} = useServices({
|
||||
AuthService,
|
||||
ServerConfigService,
|
||||
UserFeatureService,
|
||||
FeatureFlagService,
|
||||
});
|
||||
const status = useLiveData(authService.session.status$);
|
||||
const hasPaymentFeature = useLiveData(
|
||||
serverConfigService.serverConfig.features$.map(f => f?.payment)
|
||||
);
|
||||
const enableEditorSettings = useLiveData(
|
||||
featureFlagService.flags.enable_editor_settings.$
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
userFeatureService.userFeature.revalidate();
|
||||
@ -65,6 +80,15 @@ export const useGeneralSettingList = (): GeneralSettingList => {
|
||||
testId: 'about-panel-trigger',
|
||||
},
|
||||
];
|
||||
if (enableEditorSettings) {
|
||||
// add editor settings to second position
|
||||
settings.splice(1, 0, {
|
||||
key: 'editor',
|
||||
title: t['com.affine.settings.editorSettings.title'](),
|
||||
icon: BlocksuiteIcon,
|
||||
testId: 'editor-panel-trigger',
|
||||
});
|
||||
}
|
||||
|
||||
if (hasPaymentFeature) {
|
||||
settings.splice(3, 0, {
|
||||
@ -103,6 +127,8 @@ export const GeneralSetting = ({ generalKey }: GeneralSettingProps) => {
|
||||
switch (generalKey) {
|
||||
case 'shortcuts':
|
||||
return <Shortcuts />;
|
||||
case 'editor':
|
||||
return <EditorSettings />;
|
||||
case 'appearance':
|
||||
return <AppearanceSettings />;
|
||||
case 'about':
|
||||
|
@ -5,6 +5,7 @@ export const GeneralSettingKeys = [
|
||||
'plans',
|
||||
'billing',
|
||||
'experimental-features',
|
||||
'editor',
|
||||
] as const;
|
||||
|
||||
export const WorkspaceSubTabs = ['preference', 'properties'] as const;
|
||||
|
@ -1217,6 +1217,94 @@
|
||||
"com.affine.settings.appearance.window-frame-description": "Customise appearance of Windows Client.",
|
||||
"com.affine.settings.auto-check-description": "If enabled, it will automatically check for new versions at regular intervals.",
|
||||
"com.affine.settings.auto-download-description": "If enabled, new versions will be automatically downloaded to the current device.",
|
||||
"com.affine.settings.editorSettings": "Editor",
|
||||
"com.affine.settings.editorSettings.title": "Editor Settings",
|
||||
"com.affine.settings.editorSettings.subtitle": "Configure your own editor.",
|
||||
"com.affine.settings.editorSettings.general": "General",
|
||||
"com.affine.settings.editorSettings.general.ai.title": "AFFiNE AI",
|
||||
"com.affine.settings.editorSettings.general.ai.description": "Enable the powerful AI assistant, AFFiNE AI.",
|
||||
"com.affine.settings.editorSettings.general.font-style.title": "Font style",
|
||||
"com.affine.settings.editorSettings.general.font-style.description": "Choose your editor’s font style.",
|
||||
"com.affine.settings.editorSettings.general.font-family.title": "Font family",
|
||||
"com.affine.settings.editorSettings.general.font-family.description": "Choose your editor’s font family.",
|
||||
"com.affine.settings.editorSettings.general.font-family.custom.title": "Custom font family",
|
||||
"com.affine.settings.editorSettings.general.font-family.custom.description": "Customize your text experience.",
|
||||
"com.affine.settings.editorSettings.general.font-size.title": "Font size",
|
||||
"com.affine.settings.editorSettings.general.font-size.description": "Choose your editor’s base font size.",
|
||||
"com.affine.settings.editorSettings.general.default-new-doc.title": "New doc default mode",
|
||||
"com.affine.settings.editorSettings.general.default-new-doc.description": "Default mode for new doc.",
|
||||
"com.affine.settings.editorSettings.general.default-code-block.language.title": "Code blocks default language",
|
||||
"com.affine.settings.editorSettings.general.default-code-block.language.description": "Set a default programming language.",
|
||||
"com.affine.settings.editorSettings.general.default-code-block.wrap.title": "Wrap code in code blocks",
|
||||
"com.affine.settings.editorSettings.general.default-code-block.wrap.description": "Encapsulate code snippets for better readability.",
|
||||
"com.affine.settings.editorSettings.general.spell-check.title": "Spell check",
|
||||
"com.affine.settings.editorSettings.general.spell-check.description": "Automatically detect and correct spelling errors.",
|
||||
"com.affine.settings.editorSettings.page": "Page",
|
||||
"com.affine.settings.editorSettings.page.full-width.title": "Full width layout",
|
||||
"com.affine.settings.editorSettings.page.full-width.description": "Maximise display of content within a page.",
|
||||
"com.affine.settings.editorSettings.page.display-doc-info.title": "Display doc info",
|
||||
"com.affine.settings.editorSettings.page.display-doc-info.description": "Display document information on the doc.",
|
||||
"com.affine.settings.editorSettings.edgeless": "Edgeless",
|
||||
"com.affine.settings.editorSettings.edgeless.style": "Style",
|
||||
"com.affine.settings.editorSettings.edgeless.style.general": "General",
|
||||
"com.affine.settings.editorSettings.edgeless.style.scribbled": "Scribbled",
|
||||
"com.affine.settings.editorSettings.edgeless.custom": "Custom",
|
||||
"com.affine.settings.editorSettings.edgeless.note": "Note",
|
||||
"com.affine.settings.editorSettings.edgeless.note.background": "Background",
|
||||
"com.affine.settings.editorSettings.edgeless.note.corners": "Corners",
|
||||
"com.affine.settings.editorSettings.edgeless.note.shadow": "Shadow style",
|
||||
"com.affine.settings.editorSettings.edgeless.note.border": "Border style",
|
||||
"com.affine.settings.editorSettings.edgeless.note.border.solid": "Solid",
|
||||
"com.affine.settings.editorSettings.edgeless.note.border.dash": "Dash",
|
||||
"com.affine.settings.editorSettings.edgeless.note.border.none": "None",
|
||||
"com.affine.settings.editorSettings.edgeless.note.border-thickness": "Border thickness",
|
||||
"com.affine.settings.editorSettings.edgeless.text": "Text",
|
||||
"com.affine.settings.editorSettings.edgeless.text.color": "Text color",
|
||||
"com.affine.settings.editorSettings.edgeless.text.font": "Font",
|
||||
"com.affine.settings.editorSettings.edgeless.text.font-size": "Font size",
|
||||
"com.affine.settings.editorSettings.edgeless.text.font-weight": "Font weight",
|
||||
"com.affine.settings.editorSettings.edgeless.text.alignment": "Alignment",
|
||||
"com.affine.settings.editorSettings.edgeless.text.alignment.left": "Left",
|
||||
"com.affine.settings.editorSettings.edgeless.text.alignment.center": "Center",
|
||||
"com.affine.settings.editorSettings.edgeless.text.alignment.right": "Right",
|
||||
"com.affine.settings.editorSettings.edgeless.shape": "Shape",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.square": "Square",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.ellipse": "Ellipse",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.diamond": "Diamond",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.triangle": "Triangle",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.rounded-rectangle": "Rounded Rectangle",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.fill-color": "Fill color",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.border-color": "Border color",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.border-style": "Border style",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.border-thickness": "Border thickness",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.text-color": "Text color",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.font": "Font",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.font-size": "Font size",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.font-style": "Font style",
|
||||
"com.affine.settings.editorSettings.edgeless.shape.text-alignment": "Text alignment",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter": "Connecter",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.color": "Color",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.connector-shape": "Connector Shape",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.connector-shape.elbowed": "Elbowed",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.connector-shape.curve": "Curve",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.connector-shape.straight": "Straight",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.border-style": "Border style",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.border-thickness": "Border thickness",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.start-endpoint": "Start endpoint",
|
||||
"com.affine.settings.editorSettings.edgeless.connecter.end-endpoint": "End endpoint",
|
||||
"com.affine.settings.editorSettings.edgeless.pen": "Pen",
|
||||
"com.affine.settings.editorSettings.edgeless.pen.color": "Color",
|
||||
"com.affine.settings.editorSettings.edgeless.pen.thickness": "Thickness",
|
||||
"com.affine.settings.editorSettings.edgeless.mind-map": "Mind Map",
|
||||
"com.affine.settings.editorSettings.edgeless.mind-map.layout": "Layout",
|
||||
"com.affine.settings.editorSettings.edgeless.mind-map.layout.left": "Left",
|
||||
"com.affine.settings.editorSettings.edgeless.mind-map.layout.radial": "Radial",
|
||||
"com.affine.settings.editorSettings.edgeless.mind-map.layout.right": "Right",
|
||||
"com.affine.settings.editorSettings.preferences": "Preferences",
|
||||
"com.affine.settings.editorSettings.preferences.export.title": "Export Settings",
|
||||
"com.affine.settings.editorSettings.preferences.export.description": "You can export the entire preferences data for backup, and the exported data can be re-imported.",
|
||||
"com.affine.settings.editorSettings.preferences.import.title": "Import Settings",
|
||||
"com.affine.settings.editorSettings.preferences.import.description": "You can import previously exported preferences data for restoration.",
|
||||
"com.affine.settings.email": "Email",
|
||||
"com.affine.settings.email.action": "Change email",
|
||||
"com.affine.settings.email.action.change": "Change email",
|
||||
|
Loading…
Reference in New Issue
Block a user