feat: Allow changing per-view display preferences for system views (#2120)

This commit is contained in:
Aman Harwara
2022-12-27 23:33:08 +05:30
committed by GitHub
parent 771758fcd4
commit dc33aef660
4 changed files with 115 additions and 39 deletions

View File

@@ -1,5 +1,7 @@
import { CollectionSortProperty } from '../../Runtime/Collection/CollectionSort'
import { EditorIdentifier, FeatureIdentifier } from '@standardnotes/features'
import { SystemViewId } from '../SmartView'
import { TagPreferences } from '../Tag'
export enum PrefKey {
TagsPanelWidth = 'tagsPanelWidth',
@@ -40,6 +42,7 @@ export enum PrefKey {
DarkMode = 'darkMode',
DefaultEditorIdentifier = 'defaultEditorIdentifier',
MomentsDefaultTagUuid = 'momentsDefaultTagUuid',
SystemViewPreferences = 'systemViewPreferences',
}
export enum NewNoteTitleFormat {
@@ -105,4 +108,5 @@ export type PrefValue = {
[PrefKey.DarkMode]: boolean
[PrefKey.DefaultEditorIdentifier]: EditorIdentifier
[PrefKey.MomentsDefaultTagUuid]: string | undefined
[PrefKey.SystemViewPreferences]: Partial<Record<SystemViewId, TagPreferences>>
}

View File

@@ -35,11 +35,14 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
selectedTag,
}) => {
const isSystemTag = isSmartView(selectedTag) && isSystemView(selectedTag)
const [currentMode, setCurrentMode] = useState<PreferenceMode>(selectedTag.preferences ? 'tag' : 'global')
const selectedTagPreferences = isSystemTag
? application.getPreference(PrefKey.SystemViewPreferences)?.[selectedTag.uuid as SystemViewId]
: selectedTag.preferences
const [currentMode, setCurrentMode] = useState<PreferenceMode>(selectedTagPreferences ? 'tag' : 'global')
const [preferences, setPreferences] = useState<TagPreferences>({})
const hasSubscription = application.hasValidSubscription()
const controlsDisabled = currentMode === 'tag' && !hasSubscription
const isDailyEntry = selectedTag.preferences?.entryMode === 'daily'
const isDailyEntry = selectedTagPreferences?.entryMode === 'daily'
const reloadPreferences = useCallback(() => {
const globalValues: TagPreferences = {
@@ -71,24 +74,59 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
} else {
setPreferences({
...globalValues,
...selectedTag.preferences,
...selectedTagPreferences,
})
}
}, [currentMode, setPreferences, selectedTag, application])
}, [application, currentMode, selectedTagPreferences])
useEffect(() => {
reloadPreferences()
}, [reloadPreferences])
const changeGlobalPreferences = useCallback(
async (properties: Partial<TagPreferences>) => {
for (const key of Object.keys(properties)) {
const value = properties[key as keyof TagPreferences]
await application.setPreference(key as PrefKey, value).catch(console.error)
reloadPreferences()
}
},
[application, reloadPreferences],
)
const changeSystemViewPreferences = useCallback(
async (properties: Partial<TagPreferences>) => {
if (!selectedTag) {
return
}
if (!isSystemTag) {
return
}
const systemViewPreferences = application.getPreference(PrefKey.SystemViewPreferences) || {}
const systemViewPreferencesForTag = systemViewPreferences[selectedTag.uuid as SystemViewId] || {}
await application.setPreference(PrefKey.SystemViewPreferences, {
...systemViewPreferences,
[selectedTag.uuid as SystemViewId]: {
...systemViewPreferencesForTag,
...properties,
},
})
reloadPreferences()
},
[application, isSystemTag, reloadPreferences, selectedTag],
)
const changePreferences = useCallback(
async (properties: Partial<TagPreferences>) => {
if (currentMode === 'global') {
for (const key of Object.keys(properties)) {
const value = properties[key as keyof TagPreferences]
await application.setPreference(key as PrefKey, value).catch(console.error)
reloadPreferences()
}
await changeGlobalPreferences(properties)
} else if (isSystemTag) {
await changeSystemViewPreferences(properties)
} else {
await application.mutator.changeAndSaveItem<TagMutator>(selectedTag, (mutator) => {
mutator.preferences = {
@@ -98,14 +136,23 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
})
}
},
[reloadPreferences, application, currentMode, selectedTag],
[currentMode, isSystemTag, changeGlobalPreferences, changeSystemViewPreferences, application.mutator, selectedTag],
)
const resetTagPreferences = useCallback(() => {
const resetTagPreferences = useCallback(async () => {
if (isSystemTag) {
await application.setPreference(PrefKey.SystemViewPreferences, {
...application.getPreference(PrefKey.SystemViewPreferences),
[selectedTag.uuid as SystemViewId]: undefined,
})
reloadPreferences()
return
}
void application.mutator.changeAndSaveItem<TagMutator>(selectedTag, (mutator) => {
mutator.preferences = undefined
})
}, [application, selectedTag])
}, [application, isSystemTag, reloadPreferences, selectedTag])
const toggleSortReverse = useCallback(() => {
void changePreferences({ sortReverse: !preferences.sortReverse })
@@ -212,7 +259,7 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
<div className={classNames('mt-1.5 flex w-full justify-between px-3', !controlsDisabled && 'mb-3')}>
<div className="flex items-center gap-1.5">
<TabButton label="Global" mode="global" />
{!isSystemTag && <TabButton label={selectedTag.title} icon={selectedTag.iconString} mode="tag" />}
<TabButton label={selectedTag.title} icon={selectedTag.iconString} mode="tag" />
</div>
{currentMode === 'tag' && (
<button className="text-base lg:text-sm" onClick={resetTagPreferences}>
@@ -363,7 +410,7 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
</>
)}
{currentMode === 'tag' && DailyEntryModeEnabled && (
{currentMode === 'tag' && !isSystemTag && DailyEntryModeEnabled && (
<>
<MenuItemSeparator />
<MenuSwitchButtonItem
@@ -385,7 +432,7 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
</>
)}
{!shouldHideNonApplicableOptions && (
{!shouldHideNonApplicableOptions && (!isSystemTag || currentMode === 'global') && (
<>
<MenuItemSeparator />
<NewNotePreferences

View File

@@ -1,4 +1,13 @@
import { FeatureIdentifier, NewNoteTitleFormat, PrefKey, EditorIdentifier, TagPreferences } from '@standardnotes/snjs'
import {
FeatureIdentifier,
NewNoteTitleFormat,
PrefKey,
EditorIdentifier,
TagPreferences,
isSmartView,
isSystemView,
SystemViewId,
} from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { ChangeEventHandler, FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
import { PrefDefaults } from '@/Constants/PrefDefaults'
@@ -31,6 +40,11 @@ const NewNotePreferences: FunctionComponent<Props> = ({
changePreferencesCallback,
disabled,
}: Props) => {
const isSystemTag = isSmartView(selectedTag) && isSystemView(selectedTag)
const selectedTagPreferences = isSystemTag
? application.getPreference(PrefKey.SystemViewPreferences)?.[selectedTag.uuid as SystemViewId]
: selectedTag.preferences
const [editorItems, setEditorItems] = useState<DropdownItem[]>([])
const [defaultEditorIdentifier, setDefaultEditorIdentifier] = useState<EditorIdentifier>(
FeatureIdentifier.PlainEditor,
@@ -45,15 +59,15 @@ const NewNotePreferences: FunctionComponent<Props> = ({
}, [application])
const reloadPreferences = useCallback(() => {
if (mode === 'tag' && selectedTag.preferences?.editorIdentifier) {
setDefaultEditorIdentifier(selectedTag.preferences?.editorIdentifier)
if (mode === 'tag' && selectedTagPreferences?.editorIdentifier) {
setDefaultEditorIdentifier(selectedTagPreferences?.editorIdentifier)
} else {
const globalDefault = getGlobalEditorDefaultIdentifier()
setDefaultEditorIdentifier(globalDefault)
}
if (mode === 'tag' && selectedTag.preferences?.newNoteTitleFormat) {
setNewNoteTitleFormat(selectedTag.preferences?.newNoteTitleFormat)
if (mode === 'tag' && selectedTagPreferences?.newNoteTitleFormat) {
setNewNoteTitleFormat(selectedTagPreferences?.newNoteTitleFormat)
} else {
setNewNoteTitleFormat(
application.getPreference(PrefKey.NewNoteTitleFormat, PrefDefaults[PrefKey.NewNoteTitleFormat]),
@@ -61,22 +75,21 @@ const NewNotePreferences: FunctionComponent<Props> = ({
}
}, [
mode,
selectedTag,
application,
selectedTagPreferences?.editorIdentifier,
selectedTagPreferences?.newNoteTitleFormat,
getGlobalEditorDefaultIdentifier,
setDefaultEditorIdentifier,
setNewNoteTitleFormat,
application,
])
useEffect(() => {
if (mode === 'tag' && selectedTag.preferences?.customNoteTitleFormat) {
setCustomNoteTitleFormat(selectedTag.preferences?.customNoteTitleFormat)
if (mode === 'tag' && selectedTagPreferences?.customNoteTitleFormat) {
setCustomNoteTitleFormat(selectedTagPreferences?.customNoteTitleFormat)
} else {
setCustomNoteTitleFormat(
application.getPreference(PrefKey.CustomNoteTitleFormat, PrefDefaults[PrefKey.CustomNoteTitleFormat]),
)
}
}, [application, mode, selectedTag])
}, [application, mode, selectedTag, selectedTagPreferences?.customNoteTitleFormat])
useEffect(() => {
void reloadPreferences()

View File

@@ -20,6 +20,8 @@ import {
useBoolean,
isTag,
isFile,
isSmartView,
isSystemView,
} from '@standardnotes/snjs'
import { action, computed, makeObservable, observable, reaction, runInAction } from 'mobx'
import { WebApplication } from '../../Application/Application'
@@ -502,10 +504,14 @@ export class ItemListController extends AbstractViewController implements Intern
const newDisplayOptions = {} as DisplayOptions
const newWebDisplayOptions = {} as WebDisplayOptions
const selectedTag = this.navigationController.selected
const isSystemTag = selectedTag && isSmartView(selectedTag) && isSystemView(selectedTag)
const selectedTagPreferences = isSystemTag
? this.application.getPreference(PrefKey.SystemViewPreferences)?.[selectedTag.uuid as SystemViewId]
: selectedTag?.preferences
const currentSortBy = this.displayOptions.sortBy
let sortBy =
selectedTag?.preferences?.sortBy ||
selectedTagPreferences?.sortBy ||
this.application.getPreference(PrefKey.SortNotesBy, PrefDefaults[PrefKey.SortNotesBy])
if (sortBy === CollectionSort.UpdatedAt || (sortBy as string) === 'client_updated_at') {
sortBy = CollectionSort.UpdatedAt
@@ -515,49 +521,49 @@ export class ItemListController extends AbstractViewController implements Intern
const currentSortDirection = this.displayOptions.sortDirection
newDisplayOptions.sortDirection =
useBoolean(
selectedTag?.preferences?.sortReverse,
selectedTagPreferences?.sortReverse,
this.application.getPreference(PrefKey.SortNotesReverse, PrefDefaults[PrefKey.SortNotesReverse]),
) === false
? 'dsc'
: 'asc'
newDisplayOptions.includeArchived = useBoolean(
selectedTag?.preferences?.showArchived,
selectedTagPreferences?.showArchived,
this.application.getPreference(PrefKey.NotesShowArchived, PrefDefaults[PrefKey.NotesShowArchived]),
)
newDisplayOptions.includeTrashed = useBoolean(
selectedTag?.preferences?.showTrashed,
selectedTagPreferences?.showTrashed,
this.application.getPreference(PrefKey.NotesShowTrashed, PrefDefaults[PrefKey.NotesShowTrashed]),
)
newDisplayOptions.includePinned = !useBoolean(
selectedTag?.preferences?.hidePinned,
selectedTagPreferences?.hidePinned,
this.application.getPreference(PrefKey.NotesHidePinned, PrefDefaults[PrefKey.NotesHidePinned]),
)
newDisplayOptions.includeProtected = !useBoolean(
selectedTag?.preferences?.hideProtected,
selectedTagPreferences?.hideProtected,
this.application.getPreference(PrefKey.NotesHideProtected, PrefDefaults[PrefKey.NotesHideProtected]),
)
newWebDisplayOptions.hideNotePreview = useBoolean(
selectedTag?.preferences?.hideNotePreview,
selectedTagPreferences?.hideNotePreview,
this.application.getPreference(PrefKey.NotesHideNotePreview, PrefDefaults[PrefKey.NotesHideNotePreview]),
)
newWebDisplayOptions.hideDate = useBoolean(
selectedTag?.preferences?.hideDate,
selectedTagPreferences?.hideDate,
this.application.getPreference(PrefKey.NotesHideDate, PrefDefaults[PrefKey.NotesHideDate]),
)
newWebDisplayOptions.hideTags = useBoolean(
selectedTag?.preferences?.hideTags,
selectedTagPreferences?.hideTags,
this.application.getPreference(PrefKey.NotesHideTags, PrefDefaults[PrefKey.NotesHideTags]),
)
newWebDisplayOptions.hideEditorIcon = useBoolean(
selectedTag?.preferences?.hideEditorIcon,
selectedTagPreferences?.hideEditorIcon,
this.application.getPreference(PrefKey.NotesHideEditorIcon, PrefDefaults[PrefKey.NotesHideEditorIcon]),
)
@@ -621,8 +627,14 @@ export class ItemListController extends AbstractViewController implements Intern
return this.noteFilterText
}
const selectedTag = this.navigationController.selected
const isSystemTag = selectedTag && isSmartView(selectedTag) && isSystemView(selectedTag)
const selectedTagPreferences = isSystemTag
? this.application.getPreference(PrefKey.SystemViewPreferences)?.[selectedTag.uuid as SystemViewId]
: selectedTag?.preferences
const titleFormat =
this.navigationController.selected?.preferences?.newNoteTitleFormat ||
selectedTagPreferences?.newNoteTitleFormat ||
this.application.getPreference(PrefKey.NewNoteTitleFormat, PrefDefaults[PrefKey.NewNoteTitleFormat])
if (titleFormat === NewNoteTitleFormat.CurrentNoteCount) {