feat: Update notes list options menu to new design (#687)
feat: Implement initial Menu component functionality.
This commit is contained in:
@@ -64,6 +64,7 @@ import { IconDirective } from './components/Icon';
|
||||
import { NoteTagsContainerDirective } from './components/NoteTagsContainer';
|
||||
import { PreferencesDirective } from './preferences';
|
||||
import { AppVersion, IsWebPlatform } from '@/version';
|
||||
import { NotesListOptionsDirective } from './components/NotesListOptionsMenu';
|
||||
import { PurchaseFlowDirective } from './purchaseFlow';
|
||||
import { QuickSettingsMenuDirective } from './components/QuickSettingsMenu';
|
||||
|
||||
@@ -164,6 +165,7 @@ const startApplication: StartApplication = async function startApplication(
|
||||
.directive('multipleSelectedNotesPanel', MultipleSelectedNotesDirective)
|
||||
.directive('notesContextMenu', NotesContextMenuDirective)
|
||||
.directive('notesOptionsPanel', NotesOptionsPanelDirective)
|
||||
.directive('notesListOptionsMenu', NotesListOptionsDirective)
|
||||
.directive('icon', IconDirective)
|
||||
.directive('noteTagsContainer', NoteTagsContainerDirective)
|
||||
.directive('preferences', PreferencesDirective)
|
||||
|
||||
@@ -48,11 +48,15 @@ import ServerIcon from '../../icons/ic-server.svg';
|
||||
import EyeIcon from '../../icons/ic-eye.svg';
|
||||
import EyeOffIcon from '../../icons/ic-eye-off.svg';
|
||||
import LockIcon from '../../icons/ic-lock.svg';
|
||||
import ArrowsSortUpIcon from '../../icons/ic-arrows-sort-up.svg';
|
||||
import ArrowsSortDownIcon from '../../icons/ic-arrows-sort-down.svg';
|
||||
|
||||
import { toDirective } from './utils';
|
||||
import { FunctionalComponent } from 'preact';
|
||||
|
||||
const ICONS = {
|
||||
'arrows-sort-up': ArrowsSortUpIcon,
|
||||
'arrows-sort-down': ArrowsSortDownIcon,
|
||||
lock: LockIcon,
|
||||
eye: EyeIcon,
|
||||
'eye-off': EyeOffIcon,
|
||||
|
||||
244
app/assets/javascripts/components/NotesListOptionsMenu.tsx
Normal file
244
app/assets/javascripts/components/NotesListOptionsMenu.tsx
Normal file
@@ -0,0 +1,244 @@
|
||||
import { WebApplication } from '@/ui_models/application';
|
||||
import { CollectionSort, PrefKey } from '@standardnotes/snjs';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { FunctionComponent } from 'preact';
|
||||
import { useState } from 'preact/hooks';
|
||||
import { Icon } from './Icon';
|
||||
import { Menu } from './menu/Menu';
|
||||
import { MenuItem, MenuItemSeparator, MenuItemType } from './menu/MenuItem';
|
||||
import { toDirective } from './utils';
|
||||
|
||||
type Props = {
|
||||
application: WebApplication;
|
||||
setShowMenuFalse: () => void;
|
||||
};
|
||||
|
||||
export const NotesListOptionsMenu: FunctionComponent<Props> = observer(
|
||||
({ setShowMenuFalse, application }) => {
|
||||
const menuClassName =
|
||||
'sn-dropdown sn-dropdown--animated min-w-70 overflow-y-auto \
|
||||
border-1 border-solid border-gray-300 text-sm z-index-dropdown-menu \
|
||||
flex flex-col py-2 bottom-0 left-2 absolute';
|
||||
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 toggleSortReverse = () => {
|
||||
application.setPreference(PrefKey.SortNotesReverse, !sortReverse);
|
||||
setSortReverse(!sortReverse);
|
||||
};
|
||||
|
||||
const toggleSortBy = (sort: CollectionSort) => {
|
||||
if (sortBy === sort) {
|
||||
toggleSortReverse();
|
||||
} else {
|
||||
setSortBy(sort);
|
||||
application.setPreference(PrefKey.SortNotesBy, sort);
|
||||
}
|
||||
};
|
||||
|
||||
const toggleSortByDateModified = () => {
|
||||
toggleSortBy(CollectionSort.UpdatedAt);
|
||||
};
|
||||
|
||||
const toggleSortByCreationDate = () => {
|
||||
toggleSortBy(CollectionSort.CreatedAt);
|
||||
};
|
||||
|
||||
const toggleSortByTitle = () => {
|
||||
toggleSortBy(CollectionSort.Title);
|
||||
};
|
||||
|
||||
const toggleHidePreview = () => {
|
||||
setHidePreview(!hidePreview);
|
||||
application.setPreference(PrefKey.NotesHideNotePreview, !hidePreview);
|
||||
};
|
||||
|
||||
const toggleHideDate = () => {
|
||||
setHideDate(!hideDate);
|
||||
application.setPreference(PrefKey.NotesHideDate, !hideDate);
|
||||
};
|
||||
|
||||
const toggleHideTags = () => {
|
||||
setHideTags(!hideTags);
|
||||
application.setPreference(PrefKey.NotesHideTags, !hideTags);
|
||||
};
|
||||
|
||||
const toggleHidePinned = () => {
|
||||
setHidePinned(!hidePinned);
|
||||
application.setPreference(PrefKey.NotesHidePinned, !hidePinned);
|
||||
};
|
||||
|
||||
const toggleShowArchived = () => {
|
||||
setShowArchived(!showArchived);
|
||||
application.setPreference(PrefKey.NotesShowArchived, !showArchived);
|
||||
};
|
||||
|
||||
const toggleShowTrashed = () => {
|
||||
setShowTrashed(!showTrashed);
|
||||
application.setPreference(PrefKey.NotesShowTrashed, !showTrashed);
|
||||
};
|
||||
|
||||
const toggleHideProtected = () => {
|
||||
setHideProtected(!hideProtected);
|
||||
application.setPreference(PrefKey.NotesHideProtected, !hideProtected);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={menuClassName}>
|
||||
<Menu a11yLabel="Sort by" closeMenu={setShowMenuFalse}>
|
||||
<div className="px-3 my-1 text-xs font-semibold color-text uppercase">
|
||||
Sort by
|
||||
</div>
|
||||
<MenuItem
|
||||
className="py-2"
|
||||
type={MenuItemType.RadioButton}
|
||||
onClick={toggleSortByDateModified}
|
||||
checked={sortBy === CollectionSort.UpdatedAt}
|
||||
>
|
||||
<div className="flex flex-grow items-center justify-between">
|
||||
<span>Date modified</span>
|
||||
{sortBy === CollectionSort.UpdatedAt ? (
|
||||
sortReverse ? (
|
||||
<Icon type="arrows-sort-up" className="color-neutral" />
|
||||
) : (
|
||||
<Icon type="arrows-sort-down" className="color-neutral" />
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
className="py-2"
|
||||
type={MenuItemType.RadioButton}
|
||||
onClick={toggleSortByCreationDate}
|
||||
checked={sortBy === CollectionSort.CreatedAt}
|
||||
>
|
||||
<div className="flex flex-grow items-center justify-between">
|
||||
<span>Creation date</span>
|
||||
{sortBy === CollectionSort.CreatedAt ? (
|
||||
sortReverse ? (
|
||||
<Icon type="arrows-sort-up" className="color-neutral" />
|
||||
) : (
|
||||
<Icon type="arrows-sort-down" className="color-neutral" />
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
className="py-2"
|
||||
type={MenuItemType.RadioButton}
|
||||
onClick={toggleSortByTitle}
|
||||
checked={sortBy === CollectionSort.Title}
|
||||
>
|
||||
<div className="flex flex-grow items-center justify-between">
|
||||
<span>Title</span>
|
||||
{sortBy === CollectionSort.Title ? (
|
||||
sortReverse ? (
|
||||
<Icon type="arrows-sort-up" className="color-neutral" />
|
||||
) : (
|
||||
<Icon type="arrows-sort-down" className="color-neutral" />
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
</MenuItem>
|
||||
<MenuItemSeparator />
|
||||
<div className="px-3 py-1 text-xs font-semibold color-text uppercase">
|
||||
View
|
||||
</div>
|
||||
<MenuItem
|
||||
type={MenuItemType.SwitchButton}
|
||||
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
|
||||
checked={!hidePreview}
|
||||
onChange={toggleHidePreview}
|
||||
>
|
||||
<div className="flex flex-col max-w-3/4">Show note preview</div>
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
type={MenuItemType.SwitchButton}
|
||||
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
|
||||
checked={!hideDate}
|
||||
onChange={toggleHideDate}
|
||||
>
|
||||
Show date
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
type={MenuItemType.SwitchButton}
|
||||
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
|
||||
checked={!hideTags}
|
||||
onChange={toggleHideTags}
|
||||
>
|
||||
Show tags
|
||||
</MenuItem>
|
||||
<div className="h-1px my-2 bg-border"></div>
|
||||
<div className="px-3 py-1 text-xs font-semibold color-text uppercase">
|
||||
Other
|
||||
</div>
|
||||
<MenuItem
|
||||
type={MenuItemType.SwitchButton}
|
||||
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
|
||||
checked={!hidePinned}
|
||||
onChange={toggleHidePinned}
|
||||
>
|
||||
Show pinned notes
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
type={MenuItemType.SwitchButton}
|
||||
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
|
||||
checked={!hideProtected}
|
||||
onChange={toggleHideProtected}
|
||||
>
|
||||
Show protected notes
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
type={MenuItemType.SwitchButton}
|
||||
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
|
||||
checked={showArchived}
|
||||
onChange={toggleShowArchived}
|
||||
>
|
||||
Show archived notes
|
||||
</MenuItem>
|
||||
<MenuItem
|
||||
type={MenuItemType.SwitchButton}
|
||||
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
|
||||
checked={showTrashed}
|
||||
onChange={toggleShowTrashed}
|
||||
>
|
||||
Show trashed notes
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const NotesListOptionsDirective = toDirective<Props>(
|
||||
NotesListOptionsMenu,
|
||||
{
|
||||
setShowMenuFalse: '=',
|
||||
state: '&',
|
||||
}
|
||||
);
|
||||
@@ -13,6 +13,7 @@ export type SwitchProps = HTMLProps<HTMLInputElement> & {
|
||||
onChange: (checked: boolean) => void;
|
||||
className?: string;
|
||||
children?: ComponentChildren;
|
||||
role?: string;
|
||||
};
|
||||
|
||||
export const Switch: FunctionalComponent<SwitchProps> = (
|
||||
@@ -24,6 +25,7 @@ export const Switch: FunctionalComponent<SwitchProps> = (
|
||||
return (
|
||||
<label
|
||||
className={`sn-component flex justify-between items-center cursor-pointer px-3 ${className}`}
|
||||
{...(props.role ? { role: props.role } : {})}
|
||||
>
|
||||
{props.children}
|
||||
<CustomCheckboxContainer
|
||||
|
||||
132
app/assets/javascripts/components/menu/Menu.tsx
Normal file
132
app/assets/javascripts/components/menu/Menu.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import {
|
||||
JSX,
|
||||
FunctionComponent,
|
||||
Ref,
|
||||
ComponentChildren,
|
||||
VNode,
|
||||
RefCallback,
|
||||
ComponentChild,
|
||||
} from 'preact';
|
||||
import { useEffect, useRef, useState } from 'preact/hooks';
|
||||
import { JSXInternal } from 'preact/src/jsx';
|
||||
import { forwardRef } from 'preact/compat';
|
||||
import { MenuItem, MenuItemListElement } from './MenuItem';
|
||||
|
||||
type MenuProps = {
|
||||
className?: string;
|
||||
style?: string | JSX.CSSProperties | undefined;
|
||||
a11yLabel: string;
|
||||
children: ComponentChildren;
|
||||
closeMenu: () => void;
|
||||
};
|
||||
|
||||
export const Menu: FunctionComponent<MenuProps> = forwardRef(
|
||||
(
|
||||
{ children, className = '', style, a11yLabel, closeMenu },
|
||||
ref: Ref<HTMLMenuElement>
|
||||
) => {
|
||||
const [currentIndex, setCurrentIndex] = useState(0);
|
||||
const menuItemRefs = useRef<(HTMLButtonElement | null)[]>([]);
|
||||
|
||||
const handleKeyDown: JSXInternal.KeyboardEventHandler<HTMLMenuElement> = (
|
||||
event
|
||||
) => {
|
||||
switch (event.key) {
|
||||
case 'Home':
|
||||
setCurrentIndex(0);
|
||||
break;
|
||||
case 'End':
|
||||
setCurrentIndex(
|
||||
menuItemRefs.current.length ? menuItemRefs.current.length - 1 : 0
|
||||
);
|
||||
break;
|
||||
case 'ArrowDown':
|
||||
setCurrentIndex((index) => {
|
||||
if (index + 1 < menuItemRefs.current.length) {
|
||||
return index + 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'ArrowUp':
|
||||
setCurrentIndex((index) => {
|
||||
if (index - 1 > -1) {
|
||||
return index - 1;
|
||||
} else {
|
||||
return menuItemRefs.current.length - 1;
|
||||
}
|
||||
});
|
||||
break;
|
||||
case 'Escape':
|
||||
closeMenu();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (menuItemRefs.current[currentIndex]) {
|
||||
menuItemRefs.current[currentIndex]?.focus();
|
||||
}
|
||||
}, [currentIndex]);
|
||||
|
||||
const pushRefToArray: RefCallback<HTMLLIElement> = (instance) => {
|
||||
if (instance && instance.children) {
|
||||
Array.from(instance.children).forEach((child) => {
|
||||
if (
|
||||
child.getAttribute('role')?.includes('menuitem') &&
|
||||
!menuItemRefs.current.includes(child as HTMLButtonElement)
|
||||
) {
|
||||
menuItemRefs.current.push(child as HTMLButtonElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const mapMenuItems = (
|
||||
child: ComponentChild,
|
||||
index: number,
|
||||
array: ComponentChild[]
|
||||
) => {
|
||||
if (!child) return;
|
||||
|
||||
const _child = child as VNode<unknown>;
|
||||
const isFirstMenuItem =
|
||||
index ===
|
||||
array.findIndex((child) => (child as VNode<unknown>).type === MenuItem);
|
||||
|
||||
const hasMultipleItems = Array.isArray(_child.props.children)
|
||||
? Array.from(_child.props.children as ComponentChild[]).some(
|
||||
(child) => (child as VNode<unknown>).type === MenuItem
|
||||
)
|
||||
: false;
|
||||
|
||||
const items = hasMultipleItems
|
||||
? [...(_child.props.children as ComponentChild[])]
|
||||
: [_child];
|
||||
|
||||
return items.map((child) => {
|
||||
return (
|
||||
<MenuItemListElement
|
||||
isFirstMenuItem={isFirstMenuItem}
|
||||
ref={pushRefToArray}
|
||||
>
|
||||
{child}
|
||||
</MenuItemListElement>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<menu
|
||||
className={`m-0 p-0 list-style-none ${className}`}
|
||||
onKeyDown={handleKeyDown}
|
||||
ref={ref}
|
||||
style={style}
|
||||
aria-label={a11yLabel}
|
||||
>
|
||||
{Array.isArray(children) ? children.map(mapMenuItems) : null}
|
||||
</menu>
|
||||
);
|
||||
}
|
||||
);
|
||||
111
app/assets/javascripts/components/menu/MenuItem.tsx
Normal file
111
app/assets/javascripts/components/menu/MenuItem.tsx
Normal file
@@ -0,0 +1,111 @@
|
||||
import {
|
||||
ComponentChild,
|
||||
ComponentChildren,
|
||||
FunctionComponent,
|
||||
VNode,
|
||||
} from 'preact';
|
||||
import { forwardRef, Ref } from 'preact/compat';
|
||||
import { JSXInternal } from 'preact/src/jsx';
|
||||
import { Icon, IconType } from '../Icon';
|
||||
import { Switch, SwitchProps } from '../Switch';
|
||||
|
||||
export enum MenuItemType {
|
||||
IconButton,
|
||||
RadioButton,
|
||||
SwitchButton,
|
||||
}
|
||||
|
||||
type MenuItemProps = {
|
||||
type: MenuItemType;
|
||||
children: ComponentChildren;
|
||||
onClick?: JSXInternal.MouseEventHandler<HTMLButtonElement>;
|
||||
onChange?: SwitchProps['onChange'];
|
||||
className?: string;
|
||||
checked?: boolean;
|
||||
icon?: IconType;
|
||||
iconClassName?: string;
|
||||
tabIndex?: number;
|
||||
};
|
||||
|
||||
export const MenuItem: FunctionComponent<MenuItemProps> = forwardRef(
|
||||
(
|
||||
{
|
||||
children,
|
||||
onClick,
|
||||
onChange,
|
||||
className = '',
|
||||
type,
|
||||
checked,
|
||||
icon,
|
||||
iconClassName,
|
||||
tabIndex,
|
||||
},
|
||||
ref: Ref<HTMLButtonElement>
|
||||
) => {
|
||||
return type === MenuItemType.SwitchButton &&
|
||||
typeof onChange === 'function' ? (
|
||||
<Switch
|
||||
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
|
||||
checked={checked}
|
||||
onChange={onChange}
|
||||
role="menuitemcheckbox"
|
||||
tabIndex={typeof tabIndex === 'number' ? tabIndex : -1}
|
||||
>
|
||||
{children}
|
||||
</Switch>
|
||||
) : (
|
||||
<button
|
||||
ref={ref}
|
||||
role={type === MenuItemType.RadioButton ? 'menuitemradio' : 'menuitem'}
|
||||
tabIndex={typeof tabIndex === 'number' ? tabIndex : -1}
|
||||
className={`sn-dropdown-item focus:bg-info-backdrop focus:shadow-none ${className}`}
|
||||
onClick={onClick}
|
||||
{...(type === MenuItemType.RadioButton
|
||||
? { 'aria-checked': checked }
|
||||
: {})}
|
||||
>
|
||||
{type === MenuItemType.IconButton && icon ? (
|
||||
<Icon type={icon} className={iconClassName} />
|
||||
) : null}
|
||||
{type === MenuItemType.RadioButton && typeof checked === 'boolean' ? (
|
||||
<div
|
||||
className={`pseudo-radio-btn ${
|
||||
checked ? 'pseudo-radio-btn--checked' : ''
|
||||
} mr-2`}
|
||||
></div>
|
||||
) : null}
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const MenuItemSeparator: FunctionComponent = () => (
|
||||
<div role="separator" className="h-1px my-2 bg-border"></div>
|
||||
);
|
||||
|
||||
type ListElementProps = {
|
||||
isFirstMenuItem: boolean;
|
||||
children: ComponentChildren;
|
||||
};
|
||||
|
||||
export const MenuItemListElement: FunctionComponent<ListElementProps> =
|
||||
forwardRef(({ children, isFirstMenuItem }, ref: Ref<HTMLLIElement>) => {
|
||||
const child = children as VNode<unknown>;
|
||||
|
||||
return (
|
||||
<li className="list-style-none" role="none" ref={ref}>
|
||||
{{
|
||||
...child,
|
||||
props: {
|
||||
...(child.props ? { ...child.props } : {}),
|
||||
...(child.type === MenuItem
|
||||
? {
|
||||
tabIndex: isFirstMenuItem ? 0 : -1,
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
}}
|
||||
</li>
|
||||
);
|
||||
});
|
||||
@@ -49,71 +49,12 @@
|
||||
| Options
|
||||
.sk-app-bar-item-column
|
||||
.sk-sublabel {{self.optionsSubtitle()}}
|
||||
#notes-options-menu.sk-menu-panel.dropdown-menu(
|
||||
ng-show='self.state.mutable.showMenu'
|
||||
)
|
||||
.sk-menu-panel-header
|
||||
.sk-menu-panel-header-title Sort By
|
||||
a.info.sk-h5(ng-click='self.toggleReverseSort()')
|
||||
| {{self.state.sortReverse === true ? 'Disable Reverse Sort' : 'Enable Reverse Sort'}}
|
||||
menu-row(
|
||||
action="self.selectedMenuItem(); self.selectedSortByCreated()"
|
||||
circle="self.state.sortBy == 'created_at' && 'success'"
|
||||
desc="'Sort notes by newest first'"
|
||||
label="'Date Added'"
|
||||
)
|
||||
menu-row(
|
||||
action="self.selectedMenuItem(); self.selectedSortByUpdated()"
|
||||
circle="self.state.sortBy == 'userModifiedDate' && 'success'"
|
||||
desc="'Sort notes with the most recently updated first'"
|
||||
label="'Date Modified'"
|
||||
)
|
||||
menu-row(
|
||||
action="self.selectedMenuItem(); self.selectedSortByTitle()"
|
||||
circle="self.state.sortBy == 'title' && 'success'"
|
||||
desc="'Sort notes alphabetically by their title'"
|
||||
label="'Title'"
|
||||
)
|
||||
.sk-menu-panel-section
|
||||
.sk-menu-panel-header
|
||||
.sk-menu-panel-header-title Display
|
||||
menu-row(
|
||||
action="self.selectedMenuItem(); self.togglePrefKey('showArchived')"
|
||||
circle="self.state.showArchived ? 'success' : 'danger'"
|
||||
desc=`'Archived notes are usually hidden.
|
||||
You can explicitly show them with this option.'`
|
||||
faded="!self.state.showArchived"
|
||||
label="'Archived Notes'"
|
||||
)
|
||||
menu-row(
|
||||
action="self.selectedMenuItem(); self.togglePrefKey('hidePinned')"
|
||||
circle="self.state.hidePinned ? 'danger' : 'success'"
|
||||
desc=`'Pinned notes always appear on top. You can hide them temporarily
|
||||
with this option so you can focus on other notes in the list.'`
|
||||
faded="self.state.hidePinned"
|
||||
label="'Pinned Notes'"
|
||||
)
|
||||
menu-row(
|
||||
action="self.selectedMenuItem(); self.togglePrefKey('hideNotePreview')"
|
||||
circle="self.state.hideNotePreview ? 'danger' : 'success'"
|
||||
desc="'Hide the note preview for a more condensed list of notes'"
|
||||
faded="self.state.hideNotePreview"
|
||||
label="'Note Preview'"
|
||||
)
|
||||
menu-row(
|
||||
action="self.selectedMenuItem(); self.togglePrefKey('hideDate')"
|
||||
circle="self.state.hideDate ? 'danger' : 'success'"
|
||||
desc="'Hide the date displayed in each row'"
|
||||
faded="self.state.hideDate"
|
||||
label="'Date'"
|
||||
)
|
||||
menu-row(
|
||||
action="self.selectedMenuItem(); self.togglePrefKey('hideTags')"
|
||||
circle="self.state.hideTags ? 'danger' : 'success'"
|
||||
desc="'Hide the list of tags associated with each note'"
|
||||
faded="self.state.hideTags"
|
||||
label="'Tags'"
|
||||
)
|
||||
notes-list-options-menu(
|
||||
ng-if='self.state.mutable.showMenu'
|
||||
app-state='self.appState'
|
||||
application='self.application'
|
||||
set-show-menu-false='self.setShowMenuFalse'
|
||||
)
|
||||
p.empty-notes-list.faded(
|
||||
ng-if="self.state.completedFullSync && !self.state.renderedNotes.length"
|
||||
) No notes.
|
||||
|
||||
@@ -96,6 +96,7 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesCtrlState> {
|
||||
this.onWindowResize = this.onWindowResize.bind(this);
|
||||
this.onPanelResize = this.onPanelResize.bind(this);
|
||||
this.onPanelWidthEvent = this.onPanelWidthEvent.bind(this);
|
||||
this.setShowMenuFalse = this.setShowMenuFalse.bind(this);
|
||||
window.addEventListener('resize', this.onWindowResize, true);
|
||||
this.registerKeyboardShortcuts();
|
||||
this.autorun(async () => {
|
||||
@@ -441,7 +442,7 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesCtrlState> {
|
||||
includeTrashed = this.state.searchOptions.includeTrashed;
|
||||
} else {
|
||||
includeArchived = this.state.showArchived ?? false;
|
||||
includeTrashed = false;
|
||||
includeTrashed = this.state.showTrashed ?? false;
|
||||
}
|
||||
|
||||
const criteria = NotesDisplayCriteria.Create({
|
||||
@@ -451,6 +452,7 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesCtrlState> {
|
||||
includeArchived,
|
||||
includeTrashed,
|
||||
includePinned: !this.state.hidePinned,
|
||||
includeProtected: !this.state.hideProtected,
|
||||
searchQuery: {
|
||||
query: searchText,
|
||||
includeProtectedNoteText: this.state.searchOptions.includeProtectedContents
|
||||
@@ -554,10 +556,18 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesCtrlState> {
|
||||
PrefKey.NotesShowArchived,
|
||||
false
|
||||
);
|
||||
viewOptions.showTrashed = this.application.getPreference(
|
||||
PrefKey.NotesShowTrashed,
|
||||
false
|
||||
) as boolean;
|
||||
viewOptions.hidePinned = this.application.getPreference(
|
||||
PrefKey.NotesHidePinned,
|
||||
false
|
||||
);
|
||||
viewOptions.hideProtected = this.application.getPreference(
|
||||
PrefKey.NotesHideProtected,
|
||||
false
|
||||
);
|
||||
viewOptions.hideNotePreview = this.application.getPreference(
|
||||
PrefKey.NotesHideNotePreview,
|
||||
false
|
||||
@@ -576,6 +586,8 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesCtrlState> {
|
||||
viewOptions.sortReverse !== state.sortReverse ||
|
||||
viewOptions.hidePinned !== state.hidePinned ||
|
||||
viewOptions.showArchived !== state.showArchived ||
|
||||
viewOptions.showTrashed !== state.showTrashed ||
|
||||
viewOptions.hideProtected !== state.hideProtected ||
|
||||
viewOptions.hideTags !== state.hideTags
|
||||
);
|
||||
await this.setNotesState({
|
||||
@@ -672,9 +684,15 @@ class NotesViewCtrl extends PureViewCtrl<unknown, NotesCtrlState> {
|
||||
if (this.state.showArchived) {
|
||||
base += " | + Archived";
|
||||
}
|
||||
if (this.state.showTrashed) {
|
||||
base += " | + Trashed";
|
||||
}
|
||||
if (this.state.hidePinned) {
|
||||
base += " | – Pinned";
|
||||
}
|
||||
if (this.state.hideProtected) {
|
||||
base += " | – Protected";
|
||||
}
|
||||
if (this.state.sortReverse) {
|
||||
base += " | Reversed";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user