feat: Add note attributes to notes options menu (#681)

This commit is contained in:
Aman Harwara
2021-10-19 20:12:13 +05:30
committed by GitHub
parent 29138ea597
commit 7f1dddf2d2
2 changed files with 100 additions and 7 deletions

View File

@@ -2,7 +2,7 @@ import { AppState } from '@/ui_models/app_state';
import { Icon } from './Icon';
import { Switch } from './Switch';
import { observer } from 'mobx-react-lite';
import { useRef, useState, useEffect } from 'preact/hooks';
import { useRef, useState, useEffect, useMemo } from 'preact/hooks';
import {
Disclosure,
DisclosureButton,
@@ -11,6 +11,7 @@ import {
import { SNNote } from '@standardnotes/snjs/dist/@types';
import { WebApplication } from '@/ui_models/application';
import { KeyboardModifier } from '@/services/ioService';
import { FunctionComponent } from 'preact';
type Props = {
application: WebApplication;
@@ -20,9 +21,9 @@ type Props = {
};
type DeletePermanentlyButtonProps = {
closeOnBlur: Props["closeOnBlur"];
closeOnBlur: Props['closeOnBlur'];
onClick: () => void;
}
};
const DeletePermanentlyButton = ({
closeOnBlur,
@@ -34,6 +35,87 @@ const DeletePermanentlyButton = ({
</button>
);
const countNoteAttributes = (text: string) => {
try {
JSON.parse(text);
return {
characters: 'N/A',
words: 'N/A',
paragraphs: 'N/A',
};
} catch {
const characters = text.length;
const words = text.match(/[\w'-]+\b/g)?.length;
const paragraphs = text.replace(/\n$/gm, '').split(/\n/).length;
return {
characters,
words,
paragraphs,
};
}
};
const calculateReadTime = (words: number) => {
const timeToRead = Math.round(words / 200);
if (timeToRead === 0) {
return '< 1 minute';
} else {
return `${timeToRead} ${timeToRead > 1 ? 'minutes' : 'minute'}`;
}
};
const formatDate = (date: Date | undefined) => {
if (!date) return;
return `${date.toDateString()} ${date.toLocaleTimeString()}`;
};
const NoteAttributes: FunctionComponent<{ note: SNNote }> = ({ note }) => {
const { words, characters, paragraphs } = useMemo(
() => countNoteAttributes(note.text),
[note.text]
);
const readTime = useMemo(
() => (typeof words === 'number' ? calculateReadTime(words) : 'N/A'),
[words]
);
const dateLastModified = useMemo(
() => formatDate(note.serverUpdatedAt),
[note.serverUpdatedAt]
);
const dateCreated = useMemo(
() => formatDate(note.created_at),
[note.created_at]
);
return (
<div className="px-3 pt-1.5 pb-1 text-xs color-neutral font-medium">
{typeof words === 'number' ? (
<>
<div className="mb-1">
{words} words · {characters} characters · {paragraphs} paragraphs
</div>
<div className="mb-1">
<span className="font-semibold">Read time:</span> {readTime}
</div>
</>
) : null}
<div className="mb-1">
<span className="font-semibold">Last modified:</span> {dateLastModified}
</div>
<div className="mb-1">
<span className="font-semibold">Created:</span> {dateCreated}
</div>
<div>
<span className="font-semibold">Note ID:</span> {note.uuid}
</div>
</div>
);
};
export const NotesOptions = observer(
({ application, appState, closeOnBlur, onSubmenuChange }: Props) => {
const [tagsMenuOpen, setTagsMenuOpen] = useState(false);
@@ -45,8 +127,9 @@ export const NotesOptions = observer(
top: 0,
right: 0,
});
const [tagsMenuMaxHeight, setTagsMenuMaxHeight] =
useState<number | 'auto'>('auto');
const [tagsMenuMaxHeight, setTagsMenuMaxHeight] = useState<number | 'auto'>(
'auto'
);
const [altKeyDown, setAltKeyDown] = useState(false);
const toggleOn = (condition: (note: SNNote) => boolean) => {
@@ -86,7 +169,7 @@ export const NotesOptions = observer(
},
onKeyUp: () => {
setAltKeyDown(false);
}
},
});
return () => {
@@ -163,7 +246,7 @@ export const NotesOptions = observer(
Protect
</span>
</Switch>
<div className="h-1px my-2 bg-border"></div>
<div className="min-h-1px my-2 bg-border"></div>
{appState.tags.tagsCount > 0 && (
<Disclosure open={tagsMenuOpen} onChange={openTagsMenu}>
<DisclosureButton
@@ -327,6 +410,12 @@ export const NotesOptions = observer(
</button>
</>
)}
{notes.length === 1 ? (
<>
<div className="min-h-1px my-2 bg-border"></div>
<NoteAttributes note={notes[0]} />
</>
) : null}
</>
);
}