feat: add custom note title format pref (#1678)

This commit is contained in:
Aman Harwara
2022-09-29 20:10:05 +05:30
committed by GitHub
parent d7a90c4d91
commit 11dd39c126
16 changed files with 252 additions and 62 deletions

View File

@@ -7,6 +7,7 @@ import MenuItem from '@/Components/Menu/MenuItem'
import MenuItemSeparator from '@/Components/Menu/MenuItemSeparator'
import { MenuItemType } from '@/Components/Menu/MenuItemType'
import { DisplayOptionsMenuProps } from './DisplayOptionsMenuProps'
import { PrefDefaults } from '@/Constants/PrefDefaults'
const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
closeDisplayOptionsMenu,
@@ -14,17 +15,35 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
isOpen,
isFilesSmartView,
}) => {
const [sortBy, setSortBy] = useState(() => application.getPreference(PrefKey.SortNotesBy, CollectionSort.CreatedAt))
const [sortReverse, setSortReverse] = useState(() => application.getPreference(PrefKey.SortNotesReverse, false))
const [hidePreview, setHidePreview] = useState(() => application.getPreference(PrefKey.NotesHideNotePreview, false))
const [hideDate, setHideDate] = useState(() => application.getPreference(PrefKey.NotesHideDate, false))
const [hideTags, setHideTags] = useState(() => application.getPreference(PrefKey.NotesHideTags, true))
const [hidePinned, setHidePinned] = useState(() => application.getPreference(PrefKey.NotesHidePinned, false))
const [showArchived, setShowArchived] = useState(() => application.getPreference(PrefKey.NotesShowArchived, false))
const [showTrashed, setShowTrashed] = useState(() => application.getPreference(PrefKey.NotesShowTrashed, false))
const [hideProtected, setHideProtected] = useState(() => application.getPreference(PrefKey.NotesHideProtected, false))
const [sortBy, setSortBy] = useState(() =>
application.getPreference(PrefKey.SortNotesBy, PrefDefaults[PrefKey.SortNotesBy]),
)
const [sortReverse, setSortReverse] = useState(() =>
application.getPreference(PrefKey.SortNotesReverse, PrefDefaults[PrefKey.SortNotesReverse]),
)
const [hidePreview, setHidePreview] = useState(() =>
application.getPreference(PrefKey.NotesHideNotePreview, PrefDefaults[PrefKey.NotesHideNotePreview]),
)
const [hideDate, setHideDate] = useState(() =>
application.getPreference(PrefKey.NotesHideDate, PrefDefaults[PrefKey.NotesHideDate]),
)
const [hideTags, setHideTags] = useState(() =>
application.getPreference(PrefKey.NotesHideTags, PrefDefaults[PrefKey.NotesHideTags]),
)
const [hidePinned, setHidePinned] = useState(() =>
application.getPreference(PrefKey.NotesHidePinned, PrefDefaults[PrefKey.NotesHidePinned]),
)
const [showArchived, setShowArchived] = useState(() =>
application.getPreference(PrefKey.NotesShowArchived, PrefDefaults[PrefKey.NotesShowArchived]),
)
const [showTrashed, setShowTrashed] = useState(() =>
application.getPreference(PrefKey.NotesShowTrashed, PrefDefaults[PrefKey.NotesShowTrashed]),
)
const [hideProtected, setHideProtected] = useState(() =>
application.getPreference(PrefKey.NotesHideProtected, PrefDefaults[PrefKey.NotesHideProtected]),
)
const [hideEditorIcon, setHideEditorIcon] = useState(() =>
application.getPreference(PrefKey.NotesHideEditorIcon, false),
application.getPreference(PrefKey.NotesHideEditorIcon, PrefDefaults[PrefKey.NotesHideEditorIcon]),
)
const toggleSortReverse = useCallback(() => {

View File

@@ -64,7 +64,7 @@ const Navigation: FunctionComponent<Props> = ({ application }) => {
id="navigation"
className={classNames(
'sn-component section app-column h-screen max-h-screen overflow-hidden pt-safe-top md:h-full md:max-h-full md:min-h-0 md:pb-0',
'w-[220px] xl:w-87.5 xsm-only:!w-full sm-only:!w-full',
'w-[220px] xl:w-[220px] xsm-only:!w-full sm-only:!w-full',
selectedPane === AppPaneId.Navigation
? 'pointer-coarse:md-only:!w-48 pointer-coarse:lg-only:!w-48'
: 'pointer-coarse:md-only:!w-0 pointer-coarse:lg-only:!w-0',

View File

@@ -41,6 +41,7 @@ import AutoresizingNoteViewTextarea from './AutoresizingTextarea'
import MobileItemsListButton from '../NoteGroupView/MobileItemsListButton'
import NoteTagsPanel from '../NoteTags/NoteTagsPanel'
import NoteTagsContainer from '../NoteTags/NoteTagsContainer'
import { PrefDefaults } from '@/Constants/PrefDefaults'
const MinimumStatusDuration = 400
const TextareaDebounce = 100
@@ -686,9 +687,15 @@ class NoteView extends PureComponent<NoteViewProps, State> {
}
async reloadPreferences() {
const monospaceFont = this.application.getPreference(PrefKey.EditorMonospaceEnabled, true)
const monospaceFont = this.application.getPreference(
PrefKey.EditorMonospaceEnabled,
PrefDefaults[PrefKey.EditorMonospaceEnabled],
)
const marginResizersEnabled = this.application.getPreference(PrefKey.EditorResizersEnabled, true)
const marginResizersEnabled = this.application.getPreference(
PrefKey.EditorResizersEnabled,
PrefDefaults[PrefKey.EditorResizersEnabled],
)
await this.reloadSpellcheck()
@@ -700,14 +707,14 @@ class NoteView extends PureComponent<NoteViewProps, State> {
reloadFont(monospaceFont)
if (marginResizersEnabled) {
const width = this.application.getPreference(PrefKey.EditorWidth, null)
const width = this.application.getPreference(PrefKey.EditorWidth, PrefDefaults[PrefKey.EditorWidth])
if (width != null) {
this.setState({
leftResizerWidth: width,
rightResizerWidth: width,
})
}
const left = this.application.getPreference(PrefKey.EditorLeft, null)
const left = this.application.getPreference(PrefKey.EditorLeft, PrefDefaults[PrefKey.EditorLeft])
if (left != null) {
this.setState({
leftResizerOffset: left,

View File

@@ -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(() => {

View File

@@ -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">

View File

@@ -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

View File

@@ -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 = () => {

View File

@@ -5,14 +5,15 @@ import MenuItem from '../Menu/MenuItem'
import { MenuItemType } from '../Menu/MenuItemType'
import { PANEL_NAME_NAVIGATION, PANEL_NAME_NOTES } from '@/Constants/Constants'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { PrefDefaults } from '@/Constants/PrefDefaults'
type Props = {
application: WebApplication
}
const WidthForCollapsedPanel = 5
const MinimumNavPanelWidth = 220
const MinimumNotesPanelWidth = 350
const MinimumNavPanelWidth = PrefDefaults[PrefKey.TagsPanelWidth]
const MinimumNotesPanelWidth = PrefDefaults[PrefKey.NotesPanelWidth]
const PanelSettingsSection = ({ application }: Props) => {
const [currentNavPanelWidth, setCurrentNavPanelWidth] = useState(