feat: add custom note title format pref (#1678)
This commit is contained in:
@@ -13,6 +13,7 @@ import PreferencesPane from '../PreferencesComponents/PreferencesPane'
|
||||
import PreferencesGroup from '../PreferencesComponents/PreferencesGroup'
|
||||
import PreferencesSegment from '../PreferencesComponents/PreferencesSegment'
|
||||
import { PremiumFeatureIconName } from '@/Components/Icon/PremiumFeatureIcon'
|
||||
import { PrefDefaults } from '@/Constants/PrefDefaults'
|
||||
|
||||
type Props = {
|
||||
application: WebApplication
|
||||
@@ -24,18 +25,17 @@ const Appearance: FunctionComponent<Props> = ({ application }) => {
|
||||
application.features.getFeatureStatus(FeatureIdentifier.MidnightTheme) === FeatureStatus.Entitled
|
||||
|
||||
const [themeItems, setThemeItems] = useState<DropdownItem[]>([])
|
||||
const [autoLightTheme, setAutoLightTheme] = useState<string>(
|
||||
() => application.getPreference(PrefKey.AutoLightThemeIdentifier, 'Default') as string,
|
||||
const [autoLightTheme, setAutoLightTheme] = useState<string>(() =>
|
||||
application.getPreference(PrefKey.AutoLightThemeIdentifier, PrefDefaults[PrefKey.AutoLightThemeIdentifier]),
|
||||
)
|
||||
const [autoDarkTheme, setAutoDarkTheme] = useState<string>(
|
||||
() =>
|
||||
application.getPreference(
|
||||
PrefKey.AutoDarkThemeIdentifier,
|
||||
isEntitledToMidnightTheme ? FeatureIdentifier.MidnightTheme : 'Default',
|
||||
) as string,
|
||||
const [autoDarkTheme, setAutoDarkTheme] = useState<string>(() =>
|
||||
application.getPreference(
|
||||
PrefKey.AutoDarkThemeIdentifier,
|
||||
isEntitledToMidnightTheme ? FeatureIdentifier.MidnightTheme : PrefDefaults[PrefKey.AutoDarkThemeIdentifier],
|
||||
),
|
||||
)
|
||||
const [useDeviceSettings, setUseDeviceSettings] = useState(
|
||||
() => application.getPreference(PrefKey.UseSystemColorScheme, false) as boolean,
|
||||
const [useDeviceSettings, setUseDeviceSettings] = useState(() =>
|
||||
application.getPreference(PrefKey.UseSystemColorScheme, PrefDefaults[PrefKey.UseSystemColorScheme]),
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -11,13 +11,15 @@ import {
|
||||
} from '@standardnotes/snjs'
|
||||
import { Subtitle, Text, Title } from '@/Components/Preferences/PreferencesComponents/Content'
|
||||
import { WebApplication } from '@/Application/Application'
|
||||
import { FunctionComponent, useEffect, useState } from 'react'
|
||||
import { FunctionComponent, useEffect, useMemo, useState } from 'react'
|
||||
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
|
||||
import Switch from '@/Components/Switch/Switch'
|
||||
import { PLAIN_EDITOR_NAME } from '@/Constants/Constants'
|
||||
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
|
||||
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
|
||||
import Button from '@/Components/Button/Button'
|
||||
import CustomNoteTitleFormat from './Defaults/CustomNoteTitleFormat'
|
||||
import { PrefDefaults } from '@/Constants/PrefDefaults'
|
||||
|
||||
type Props = {
|
||||
application: WebApplication
|
||||
@@ -60,10 +62,12 @@ const Defaults: FunctionComponent<Props> = ({ application }) => {
|
||||
() => getDefaultEditor(application)?.package_info?.identifier || 'plain-editor',
|
||||
)
|
||||
|
||||
const [spellcheck, setSpellcheck] = useState(() => application.getPreference(PrefKey.EditorSpellcheck, true))
|
||||
const [spellcheck, setSpellcheck] = useState(() =>
|
||||
application.getPreference(PrefKey.EditorSpellcheck, PrefDefaults[PrefKey.EditorSpellcheck]),
|
||||
)
|
||||
|
||||
const [newNoteTitleFormat, setNewNoteTitleFormat] = useState(() =>
|
||||
application.getPreference(PrefKey.NewNoteTitleFormat, NewNoteTitleFormat.CurrentDateAndTime),
|
||||
application.getPreference(PrefKey.NewNoteTitleFormat, PrefDefaults[PrefKey.NewNoteTitleFormat]),
|
||||
)
|
||||
const handleNewNoteTitleFormatChange = (value: string) => {
|
||||
setNewNoteTitleFormat(value as NewNoteTitleFormat)
|
||||
@@ -71,7 +75,7 @@ const Defaults: FunctionComponent<Props> = ({ application }) => {
|
||||
}
|
||||
|
||||
const [addNoteToParentFolders, setAddNoteToParentFolders] = useState(() =>
|
||||
application.getPreference(PrefKey.NoteAddToParentFolders, true),
|
||||
application.getPreference(PrefKey.NoteAddToParentFolders, PrefDefaults[PrefKey.NoteAddToParentFolders]),
|
||||
)
|
||||
|
||||
const toggleSpellcheck = () => {
|
||||
@@ -128,6 +132,28 @@ const Defaults: FunctionComponent<Props> = ({ application }) => {
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const noteTitleFormatOptions = useMemo(
|
||||
() => [
|
||||
{
|
||||
label: 'Current date and time',
|
||||
value: NewNoteTitleFormat.CurrentDateAndTime,
|
||||
},
|
||||
{
|
||||
label: 'Current note count',
|
||||
value: NewNoteTitleFormat.CurrentNoteCount,
|
||||
},
|
||||
{
|
||||
label: 'Custom format',
|
||||
value: NewNoteTitleFormat.CustomFormat,
|
||||
},
|
||||
{
|
||||
label: 'Empty',
|
||||
value: NewNoteTitleFormat.Empty,
|
||||
},
|
||||
],
|
||||
[],
|
||||
)
|
||||
|
||||
return (
|
||||
<PreferencesGroup>
|
||||
<PreferencesSegment>
|
||||
@@ -166,25 +192,13 @@ const Defaults: FunctionComponent<Props> = ({ application }) => {
|
||||
<Dropdown
|
||||
id="def-new-note-title-format"
|
||||
label="Select the default note type"
|
||||
items={[
|
||||
{
|
||||
label: 'Current date and time',
|
||||
value: NewNoteTitleFormat.CurrentDateAndTime,
|
||||
},
|
||||
{
|
||||
label: 'Current note count',
|
||||
value: NewNoteTitleFormat.CurrentNoteCount,
|
||||
},
|
||||
{
|
||||
label: 'Empty',
|
||||
value: NewNoteTitleFormat.Empty,
|
||||
},
|
||||
]}
|
||||
items={noteTitleFormatOptions}
|
||||
value={newNoteTitleFormat}
|
||||
onChange={handleNewNoteTitleFormatChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{newNoteTitleFormat === NewNoteTitleFormat.CustomFormat && <CustomNoteTitleFormat application={application} />}
|
||||
<HorizontalSeparator classes="my-4" />
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col">
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { WebApplication } from '@/Application/Application'
|
||||
import { Text, Subtitle } from '@/Components/Preferences/PreferencesComponents/Content'
|
||||
import HorizontalSeparator from '@/Components/Shared/HorizontalSeparator'
|
||||
import { PrefDefaults } from '@/Constants/PrefDefaults'
|
||||
import { PrefKey } from '@standardnotes/snjs'
|
||||
import { ChangeEventHandler, useRef, useState } from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
type Props = {
|
||||
application: WebApplication
|
||||
}
|
||||
|
||||
const PrefChangeDebounceTimeInMs = 25
|
||||
|
||||
const CustomNoteTitleFormat = ({ application }: Props) => {
|
||||
const [customNoteTitleFormat, setCustomNoteTitleFormat] = useState(() =>
|
||||
application.getPreference(PrefKey.CustomNoteTitleFormat, PrefDefaults[PrefKey.CustomNoteTitleFormat]),
|
||||
)
|
||||
|
||||
const setCustomNoteTitleFormatPreference = () => {
|
||||
application.setPreference(PrefKey.CustomNoteTitleFormat, customNoteTitleFormat)
|
||||
}
|
||||
|
||||
const debounceTimeoutRef = useRef<number>()
|
||||
|
||||
const handleInputChange: ChangeEventHandler<HTMLInputElement> = (event) => {
|
||||
setCustomNoteTitleFormat(event.currentTarget.value)
|
||||
|
||||
if (debounceTimeoutRef.current) {
|
||||
clearTimeout(debounceTimeoutRef.current)
|
||||
}
|
||||
|
||||
debounceTimeoutRef.current = window.setTimeout(async () => {
|
||||
setCustomNoteTitleFormatPreference()
|
||||
}, PrefChangeDebounceTimeInMs)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<HorizontalSeparator classes="my-4" />
|
||||
<div>
|
||||
<Subtitle>Custom Note Title Format</Subtitle>
|
||||
<Text>
|
||||
All available date-time formatting options can be found{' '}
|
||||
<a className="underline" href="https://day.js.org/docs/en/display/format#list-of-all-available-formats">
|
||||
here
|
||||
</a>
|
||||
. Use square brackets (<code>[]</code>) to escape date-time formatting.
|
||||
</Text>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
className="min-w-55 rounded border border-solid border-passive-3 bg-default px-2 py-1.5 text-sm focus-within:ring-2 focus-within:ring-info"
|
||||
placeholder="e.g. YYYY-MM-DD"
|
||||
value={customNoteTitleFormat}
|
||||
onChange={handleInputChange}
|
||||
onBlur={setCustomNoteTitleFormatPreference}
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<span className="font-bold">Preview:</span> {dayjs().format(customNoteTitleFormat)}
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomNoteTitleFormat
|
||||
@@ -7,6 +7,7 @@ import { observer } from 'mobx-react-lite'
|
||||
import { FunctionComponent, useState } from 'react'
|
||||
import PreferencesGroup from '../../PreferencesComponents/PreferencesGroup'
|
||||
import PreferencesSegment from '../../PreferencesComponents/PreferencesSegment'
|
||||
import { PrefDefaults } from '@/Constants/PrefDefaults'
|
||||
|
||||
type Props = {
|
||||
application: WebApplication
|
||||
@@ -14,10 +15,10 @@ type Props = {
|
||||
|
||||
const Tools: FunctionComponent<Props> = ({ application }: Props) => {
|
||||
const [monospaceFont, setMonospaceFont] = useState(() =>
|
||||
application.getPreference(PrefKey.EditorMonospaceEnabled, true),
|
||||
application.getPreference(PrefKey.EditorMonospaceEnabled, PrefDefaults[PrefKey.EditorMonospaceEnabled]),
|
||||
)
|
||||
const [marginResizers, setMarginResizers] = useState(() =>
|
||||
application.getPreference(PrefKey.EditorResizersEnabled, true),
|
||||
application.getPreference(PrefKey.EditorResizersEnabled, PrefDefaults[PrefKey.EditorResizersEnabled]),
|
||||
)
|
||||
|
||||
const toggleMonospaceFont = () => {
|
||||
|
||||
Reference in New Issue
Block a user