Merge branch 'release/10.2.0'

This commit is contained in:
Mo Bitar
2021-12-09 08:26:47 -06:00
6 changed files with 95 additions and 109 deletions

View File

@@ -8,7 +8,7 @@ import {
DisclosureButton,
DisclosurePanel,
} from '@reach/disclosure';
import { SNNote } from '@standardnotes/snjs/dist/@types';
import { SNApplication, SNNote } from '@standardnotes/snjs/dist/@types';
import { WebApplication } from '@/ui_models/application';
import { KeyboardModifier } from '@/services/ioService';
import { FunctionComponent } from 'preact';
@@ -35,6 +35,20 @@ const DeletePermanentlyButton = ({
</button>
);
const getWordCount = (text: string) => {
if (text.trim().length === 0) {
return 0;
}
return text.split(/\s+/).length;
};
const getParagraphCount = (text: string) => {
if (text.trim().length === 0) {
return 0;
}
return text.replace(/\n$/gm, '').split(/\n/).length;
};
const countNoteAttributes = (text: string) => {
try {
JSON.parse(text);
@@ -44,12 +58,9 @@ const countNoteAttributes = (text: string) => {
paragraphs: 'N/A',
};
} catch {
const removeTags = text.replace(/<[^>]*>/g," ").replace(/\s+/g, ' ').trim();
text = removeTags;
const characters = text.length;
const words = text.split(" ")?.length;
const paragraphs = text.replace(/\n$/gm, '').split(/\n/).length;
const words = getWordCount(text);
const paragraphs = getParagraphCount(text);
return {
characters,
@@ -73,7 +84,7 @@ const formatDate = (date: Date | undefined) => {
return `${date.toDateString()} ${date.toLocaleTimeString()}`;
};
const NoteAttributes: FunctionComponent<{ note: SNNote }> = ({ note }) => {
const NoteAttributes: FunctionComponent<{ application: SNApplication, note: SNNote }> = ({ application, note }) => {
const { words, characters, paragraphs } = useMemo(
() => countNoteAttributes(note.text),
[note.text]
@@ -94,9 +105,12 @@ const NoteAttributes: FunctionComponent<{ note: SNNote }> = ({ note }) => {
[note.created_at]
);
const editor = application.componentManager.editorForNote(note);
const format = editor?.package_info?.file_type || 'txt';
return (
<div className="px-3 pt-1.5 pb-1 text-xs color-neutral font-medium">
{typeof words === 'number' ? (
{typeof words === 'number' && (format === 'txt' || format === 'md') ? (
<>
<div className="mb-1">
{words} words · {characters} characters · {paragraphs} paragraphs
@@ -473,7 +487,7 @@ export const NotesOptions = observer(
{notes.length === 1 ? (
<>
<div className="min-h-1px my-2 bg-border"></div>
<NoteAttributes note={notes[0]} />
<NoteAttributes application={application} note={notes[0]} />
</>
) : null}
</>

View File

@@ -180,15 +180,16 @@ const QuickSettingsMenu: FunctionComponent<MenuProps> = observer(
}
};
const handleQuickSettingsKeyDown: JSXInternal.KeyboardEventHandler<HTMLDivElement> =
(event) => {
quickSettingsKeyDownHandler(
closeQuickSettingsMenu,
event,
quickSettingsMenuRef,
themesMenuOpen
);
};
const handleQuickSettingsKeyDown: JSXInternal.KeyboardEventHandler<
HTMLDivElement
> = (event) => {
quickSettingsKeyDownHandler(
closeQuickSettingsMenu,
event,
quickSettingsMenuRef,
themesMenuOpen
);
};
const handlePanelKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (
event
@@ -222,54 +223,56 @@ const QuickSettingsMenu: FunctionComponent<MenuProps> = observer(
<div className="px-3 mt-1 mb-2 font-semibold color-text uppercase">
Quick Settings
</div>
<Disclosure open={themesMenuOpen} onChange={toggleThemesMenu}>
<DisclosureButton
onKeyDown={handleBtnKeyDown}
onBlur={closeOnBlur}
ref={themesButtonRef}
className="sn-dropdown-item justify-between focus:bg-info-backdrop focus:shadow-none"
>
<div className="flex items-center">
<Icon type="themes" className="color-neutral mr-2" />
Themes
</div>
<Icon type="chevron-right" className="color-neutral" />
</DisclosureButton>
<DisclosurePanel
onBlur={closeOnBlur}
ref={themesMenuRef}
onKeyDown={handlePanelKeyDown}
style={{
...themesMenuPosition,
}}
className={`${MENU_CLASSNAME} fixed sn-dropdown--animated`}
>
<div className="px-3 my-1 font-semibold color-text uppercase">
Themes
</div>
<button
className="sn-dropdown-item focus:bg-info-backdrop focus:shadow-none"
onClick={toggleDefaultTheme}
{themes && themes.length ? (
<Disclosure open={themesMenuOpen} onChange={toggleThemesMenu}>
<DisclosureButton
onKeyDown={handleBtnKeyDown}
onBlur={closeOnBlur}
ref={defaultThemeButtonRef}
ref={themesButtonRef}
className="sn-dropdown-item justify-between focus:bg-info-backdrop focus:shadow-none"
>
<div
className={`pseudo-radio-btn ${
defaultThemeOn ? 'pseudo-radio-btn--checked' : ''
} mr-2`}
></div>
Default
</button>
{themes.map((theme) => (
<ThemesMenuButton
theme={theme}
application={application}
key={theme.uuid}
<div className="flex items-center">
<Icon type="themes" className="color-neutral mr-2" />
Themes
</div>
<Icon type="chevron-right" className="color-neutral" />
</DisclosureButton>
<DisclosurePanel
onBlur={closeOnBlur}
ref={themesMenuRef}
onKeyDown={handlePanelKeyDown}
style={{
...themesMenuPosition,
}}
className={`${MENU_CLASSNAME} fixed sn-dropdown--animated`}
>
<div className="px-3 my-1 font-semibold color-text uppercase">
Themes
</div>
<button
className="sn-dropdown-item focus:bg-info-backdrop focus:shadow-none"
onClick={toggleDefaultTheme}
onBlur={closeOnBlur}
/>
))}
</DisclosurePanel>
</Disclosure>
ref={defaultThemeButtonRef}
>
<div
className={`pseudo-radio-btn ${
defaultThemeOn ? 'pseudo-radio-btn--checked' : ''
} mr-2`}
></div>
Default
</button>
{themes.map((theme) => (
<ThemesMenuButton
theme={theme}
application={application}
key={theme.uuid}
onBlur={closeOnBlur}
/>
))}
</DisclosurePanel>
</Disclosure>
) : null}
{toggleableComponents.map((component) => (
<Switch
className="sn-dropdown-item focus:bg-info-backdrop focus:shadow-none"

View File

@@ -8,7 +8,6 @@ import {
SNTheme,
ComponentArea,
CollectionSort,
SNComponent,
} from '@standardnotes/snjs';
import template from './footer-view.pug';
import { AppStateEvent, EventSource } from '@/ui_models/app_state';
@@ -43,8 +42,6 @@ class FooterViewCtrl extends PureViewCtrl<
}
> {
private $rootScope: ng.IRootScopeService;
private themes: SNTheme[] = [];
private toggleableComponents: SNComponent[] = [];
private showSyncResolution = false;
private unregisterComponent: any;
private rootScopeListener2: any;
@@ -76,8 +73,6 @@ class FooterViewCtrl extends PureViewCtrl<
deinit() {
for (const remove of this.observerRemovers) remove();
this.observerRemovers.length = 0;
this.themes.length = 0;
this.toggleableComponents.length = 0;
this.unregisterComponent();
this.unregisterComponent = undefined;
this.rootScopeListener2();
@@ -276,30 +271,6 @@ class FooterViewCtrl extends PureViewCtrl<
return !theme.errorDecrypting;
}
);
this.observerRemovers.push(
this.application.streamItems(ContentType.Theme, async () => {
const themes = this.application.getDisplayableItems(
ContentType.Theme
) as SNTheme[];
this.themes = themes;
})
);
this.observerRemovers.push(
this.application.streamItems(ContentType.Component, async () => {
const toggleableComponents = (
this.application.getDisplayableItems(
ContentType.Component
) as SNComponent[]
).filter((component) =>
[ComponentArea.EditorStack, ComponentArea.TagsList].includes(
component.area
)
);
this.toggleableComponents = toggleableComponents;
})
);
}
registerComponentHandler() {
@@ -400,11 +371,7 @@ class FooterViewCtrl extends PureViewCtrl<
quickSettingsPressed() {
this.appState.accountMenu.closeAccountMenu();
if (this.themes.length > 0 || this.toggleableComponents.length > 0) {
this.appState.quickSettingsMenu.toggle();
} else {
this.appState.preferences.openPreferences();
}
this.appState.quickSettingsMenu.toggle();
}
toggleSyncResolutionMenu() {

View File

@@ -71,6 +71,8 @@
.sn-dropdown-popover {
z-index: 3001;
max-height: 40%;
overflow: auto;
&[data-reach-listbox-popover] {
background: var(--sn-stylekit-background-color);

View File

@@ -1,6 +1,6 @@
{
"name": "standard-notes-web",
"version": "3.9.7",
"version": "3.9.8",
"license": "AGPL-3.0-or-later",
"repository": {
"type": "git",
@@ -83,9 +83,9 @@
"@reach/checkbox": "^0.16.0",
"@reach/dialog": "^0.16.2",
"@reach/listbox": "^0.16.2",
"@standardnotes/features": "1.10.1",
"@standardnotes/features": "1.10.2",
"@standardnotes/sncrypto-web": "1.5.3",
"@standardnotes/snjs": "2.19.6",
"@standardnotes/snjs": "2.20.1",
"mobx": "^6.3.5",
"mobx-react-lite": "^3.2.2",
"preact": "^10.5.15",

View File

@@ -2587,10 +2587,10 @@
dependencies:
"@standardnotes/auth" "^3.8.1"
"@standardnotes/features@1.10.1", "@standardnotes/features@^1.10.1":
version "1.10.1"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.10.1.tgz#5b5a59d2d69751ca040a270d04a08662b1591bfc"
integrity sha512-fN7WyR8jeaAsDWkm4a6SSz3JZeaNfL+CkmWAYqxRI5XoXZlWy+kBVaYWaGe7vI4T6ncwdhxRTjE7mirG4PEQ6g==
"@standardnotes/features@1.10.2", "@standardnotes/features@^1.10.2":
version "1.10.2"
resolved "https://registry.yarnpkg.com/@standardnotes/features/-/features-1.10.2.tgz#a0783f66c00e21cb7692edc0cea95ec25a0253a5"
integrity sha512-Zh6EMjli4mL6jlXEhMyU3qYIKFJj5kuhbxtHXiErUGIDy+s1hHY+THFFO53Jdga2+8wgcATWlmSBY7dieVA8uA==
dependencies:
"@standardnotes/auth" "3.8.3"
"@standardnotes/common" "^1.2.1"
@@ -2614,15 +2614,15 @@
buffer "^6.0.3"
libsodium-wrappers "^0.7.9"
"@standardnotes/snjs@2.19.6":
version "2.19.6"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.19.6.tgz#a7bf568944f87ee83e39083ef6facc2ba0d56255"
integrity sha512-OlImG2UHHgf4zo5QmMeeKb9xNoRWUVaxLdzfhpV95PQShp8Nrl4zsxrDKehh9d6zN5dM/iaxF897cI6bT9D1uw==
"@standardnotes/snjs@2.20.1":
version "2.20.1"
resolved "https://registry.yarnpkg.com/@standardnotes/snjs/-/snjs-2.20.1.tgz#4813adbfd16a1c373357bd4c7ece3085abf142b4"
integrity sha512-wJILt7YerLFaZTKoIZaCkqSuvpVWoVKqCVjP0KNHrMknnbgMHZygHqrb9sr57JL1AcNCkAULEFS/kev2GYTG3Q==
dependencies:
"@standardnotes/auth" "^3.8.1"
"@standardnotes/common" "^1.2.1"
"@standardnotes/domain-events" "^2.5.1"
"@standardnotes/features" "^1.10.1"
"@standardnotes/features" "^1.10.2"
"@standardnotes/settings" "^1.2.1"
"@standardnotes/sncrypto-common" "^1.5.2"