Skip to content

Commit 54fae49

Browse files
authored
feat: Add editor width setting (#91)
1 parent 1328719 commit 54fae49

File tree

17 files changed

+223
-234
lines changed

17 files changed

+223
-234
lines changed

components/container/edit-container.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export const EditContainer = () => {
105105
<NoteNav />
106106
<DeleteAlert />
107107
<section className="h-full">
108-
<MainEditor />
108+
<MainEditor note={note} />
109109
</section>
110110
</>
111111
)

components/editor/main-editor.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import EditTitle from './edit-title'
22
import Editor, { EditorProps } from './editor'
33
import Backlinks from './backlinks'
44
import EditorState from 'libs/web/state/editor'
5+
import UIState from 'libs/web/state/ui'
56
import { FC } from 'react'
67
import { NoteModel } from 'libs/shared/note'
78

@@ -12,14 +13,18 @@ const MainEditor: FC<
1213
className?: string
1314
}
1415
> = ({
15-
className = 'pt-40 px-6 m-auto h-full max-w-prose',
16+
className,
1617
note,
1718
small,
1819
...props
1920
}) => {
21+
const { settings: { settings } } = UIState.useContainer()
22+
const editorWidthClass = (note?.editorsize ?? settings.editorsize) > 0 ? "max-w-4xl" : "max-w-prose"
23+
const articleClassName = className || `pt-40 px-6 m-auto h-full ${editorWidthClass}`
24+
2025
return (
2126
<EditorState.Provider initialState={note}>
22-
<article className={className}>
27+
<article className={articleClassName}>
2328
<EditTitle readOnly={props.readOnly} />
2429
<Editor {...props} />
2530
{!small && <Backlinks />}

components/portal/sidebar-menu/sidebar-menu-item.tsx

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1-
import { NOTE_PINNED } from 'libs/shared/meta'
1+
import { EDITOR_SIZE, NOTE_PINNED } from 'libs/shared/meta'
22
import { NoteModel } from 'libs/shared/note'
33
import NoteState from 'libs/web/state/note'
44
import PortalState from 'libs/web/state/portal'
55
import { forwardRef, useCallback, useMemo } from 'react'
66
import { MenuItem } from '@material-ui/core'
7+
import UIState from 'libs/web/state/ui'
78

89
export enum MENU_HANDLER_NAME {
910
REMOVE_NOTE,
1011
COPY_LINK,
1112
ADD_TO_FAVORITES,
1213
REMOVE_FROM_FAVORITES,
14+
TOGGLE_WIDTH,
1315
}
1416

1517
export interface Item {
@@ -25,6 +27,7 @@ interface ItemProps {
2527

2628
export const SidebarMenuItem = forwardRef<HTMLLIElement, ItemProps>(
2729
({ item }, ref) => {
30+
const { settings: { settings } } = UIState.useContainer()
2831
const { removeNote, mutateNote } = NoteState.useContainer()
2932
const {
3033
menu: { close, data },
@@ -63,15 +66,28 @@ export const SidebarMenuItem = forwardRef<HTMLLIElement, ItemProps>(
6366
})
6467
}
6568
}, [close, data, mutateNote])
69+
70+
const toggleWidth = useCallback(() => {
71+
close()
72+
if (data?.id) {
73+
const resolvedNoteWidth = data.editorsize ?? settings.editorsize
74+
const editorSizesCount = Object.values(EDITOR_SIZE).length / 2 // contains both string & int values
75+
76+
mutateNote(data.id, {
77+
editorsize: (resolvedNoteWidth + 1) % editorSizesCount,
78+
})
79+
}
80+
}, [close, data, mutateNote, settings.editorsize])
6681

6782
const MENU_HANDLER = useMemo(
6883
() => ({
6984
[MENU_HANDLER_NAME.REMOVE_NOTE]: doRemoveNote,
7085
[MENU_HANDLER_NAME.COPY_LINK]: doCopyLink,
7186
[MENU_HANDLER_NAME.ADD_TO_FAVORITES]: doPinned,
7287
[MENU_HANDLER_NAME.REMOVE_FROM_FAVORITES]: doUnpinned,
88+
[MENU_HANDLER_NAME.TOGGLE_WIDTH]: toggleWidth,
7389
}),
74-
[doCopyLink, doPinned, doRemoveNote, doUnpinned]
90+
[doCopyLink, doPinned, doRemoveNote, doUnpinned, toggleWidth]
7591
)
7692

7793
return (

components/portal/sidebar-menu/sidebar-menu.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Menu } from '@material-ui/core'
22
import { FC, useMemo } from 'react'
33
import {
44
ClipboardCopyIcon,
5+
SelectorIcon,
56
StarIcon,
67
TrashIcon,
78
} from '@heroicons/react/outline'
@@ -45,6 +46,12 @@ const SidebarMenu: FC = () => {
4546
return item?.pinned === NOTE_PINNED.PINNED
4647
},
4748
},
49+
{
50+
text: t('Toggle width'),
51+
// TODO: or SwitchHorizontal?
52+
icon: <SelectorIcon style={{ transform: "rotate(90deg)" }} />,
53+
handler: MENU_HANDLER_NAME.TOGGLE_WIDTH,
54+
},
4855
],
4956
[t]
5057
)

components/settings/editor-width.tsx

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { FC, useCallback, ChangeEvent } from 'react'
2+
import { MenuItem, TextField } from '@material-ui/core'
3+
import router from 'next/router'
4+
import { defaultFieldConfig } from './settings-container'
5+
import useI18n from 'libs/web/hooks/use-i18n'
6+
import UIState from 'libs/web/state/ui'
7+
import { EDITOR_SIZE } from 'libs/shared/meta'
8+
9+
export const EditorWidth: FC = () => {
10+
const { t } = useI18n()
11+
const {
12+
settings: { settings, updateSettings },
13+
} = UIState.useContainer()
14+
15+
const handleChange = useCallback(
16+
async (event: ChangeEvent<HTMLInputElement>) => {
17+
await updateSettings({ editorsize: parseInt(event.target.value) })
18+
router.reload()
19+
},
20+
[updateSettings]
21+
)
22+
23+
return (
24+
<TextField
25+
{...defaultFieldConfig}
26+
label={t('Default editor width')}
27+
value={settings.editorsize ?? EDITOR_SIZE.SMALL}
28+
onChange={handleChange}
29+
select
30+
>
31+
<MenuItem value={EDITOR_SIZE.SMALL}>{t('Small (default)')}</MenuItem>
32+
<MenuItem value={EDITOR_SIZE.LARGE}>{t('Large')}</MenuItem>
33+
</TextField>
34+
)
35+
}

components/settings/settings-container.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { FC } from 'react'
33
import { DailyNotes } from './daily-notes'
44
import { Language } from './language'
55
import { Theme } from './theme'
6+
import { EditorWidth } from './editor-width'
67
import { ImportOrExport } from './import-or-export'
78
import { SnippetInjection } from './snippet-injection'
89
import useI18n from 'libs/web/hooks/use-i18n'
@@ -34,6 +35,7 @@ export const SettingsContainer: FC = () => {
3435
<DailyNotes></DailyNotes>
3536
<Language></Language>
3637
<Theme></Theme>
38+
<EditorWidth></EditorWidth>
3739
<HR />
3840
<SettingsHeader
3941
id="import-and-export"

libs/server/meta.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ export function metaToJson(metaData?: Record<string, any>) {
4545
meta[key] = value ? strDecompress(value) : NOTE_SHARED.PRIVATE
4646
} else if (key === 'pinned') {
4747
meta[key] = value ? strDecompress(value) : NOTE_PINNED.UNPINNED
48+
} else if (key === 'editorsize') {
49+
meta[key] = value ? strDecompress(value) : null
4850
}
4951
})
5052
}

libs/shared/meta.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ export enum NOTE_PINNED {
1313
PINNED,
1414
}
1515

16+
export enum EDITOR_SIZE {
17+
SMALL,
18+
LARGE,
19+
}
20+
1621
export const PAGE_META_KEY = <const>[
1722
'title',
1823
'pid',
@@ -22,8 +27,9 @@ export const PAGE_META_KEY = <const>[
2227
'date',
2328
'deleted',
2429
'pinned',
30+
'editorsize',
2531
]
2632

2733
export type metaKey = typeof PAGE_META_KEY[number]
2834

29-
export const NUMBER_KEYS: metaKey[] = ['deleted', 'shared', 'pinned']
35+
export const NUMBER_KEYS: metaKey[] = ['deleted', 'shared', 'pinned', 'editorsize']

libs/shared/note.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { NOTE_DELETED, NOTE_PINNED, NOTE_SHARED } from './meta'
1+
import { EDITOR_SIZE, NOTE_DELETED, NOTE_PINNED, NOTE_SHARED } from './meta'
22

33
export interface NoteModel {
44
id: string
@@ -10,6 +10,7 @@ export interface NoteModel {
1010
deleted: NOTE_DELETED
1111
shared: NOTE_SHARED
1212
pinned: NOTE_PINNED
13+
editorsize: EDITOR_SIZE | null
1314
}
1415

1516
/**

libs/shared/settings.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Locale } from 'locales'
22
import { isArray, isBoolean, isNumber, isString, values } from 'lodash'
3+
import { EDITOR_SIZE } from './meta'
34
import { ROOT_ID } from './tree'
45

56
export interface Settings {
@@ -9,13 +10,15 @@ export interface Settings {
910
last_visit?: string
1011
locale: Locale
1112
injection?: string
13+
editorsize: EDITOR_SIZE;
1214
}
1315

1416
export const DEFAULT_SETTINGS: Settings = Object.freeze({
1517
split_sizes: [30, 70],
1618
daily_root_id: ROOT_ID,
1719
sidebar_is_fold: false,
1820
locale: Locale.EN,
21+
editorsize: EDITOR_SIZE.SMALL,
1922
})
2023

2124
export function formatSettings(body: Record<string, any> = {}) {
@@ -53,5 +56,9 @@ export function formatSettings(body: Record<string, any> = {}) {
5356
settings.injection = body.injection
5457
}
5558

59+
if (isNumber(body.editorsize)) {
60+
settings.editorsize = body.editorsize
61+
}
62+
5663
return settings
5764
}

libs/web/state/note.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ const useNote = (initData?: NoteModel) => {
171171
deleted: NOTE_DELETED.NORMAL,
172172
shared: NOTE_SHARED.PRIVATE,
173173
pinned: NOTE_PINNED.UNPINNED,
174+
editorsize: null,
174175
id: '-1',
175176
title: '',
176177
...note,

0 commit comments

Comments
 (0)