Compare commits

...
Author SHA1 Message Date
StandardNotes CI a5a866a62a chore(release): publish
- @standardnotes/[email protected].1
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].2
2022-12-24 16:55:41 +00:00
Aman Harwara 6090962b2c Merge branch 'main' of github.com:standardnotes/app 2022-12-24 21:56:48 +05:30
Aman Harwara a9445dfcca refactor(dev-only): file list item style 2022-12-24 21:56:38 +05:30
Aman Harwara b3fe769a60 refactor(dev-only): hide non-applicable options in display options menu 2022-12-24 21:55:24 +05:30
Aman Harwara fc6d28d166 refactor(dev-only): show file local backup status in table 2022-12-24 21:54:53 +05:30
Aman Harwara 03eac4353d refactor(dev-only): align text-only cells correctly in table 2022-12-24 21:54:18 +05:30
StandardNotes CI 58d84c47c1 chore(release): publish
- @standardnotes/[email protected].0
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].1
2022-12-24 15:38:00 +00:00
Aman Harwara 577318e208 feat: Persist collapsible block state in Super notes (#2119) 2022-12-24 20:35:41 +05:30
StandardNotes CI b8da877804 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].0
 - @standardnotes/[email protected].0
2022-12-24 12:40:15 +00:00
Aman Harwara 17f4d20fb5 Merge branch 'main' of github.com:standardnotes/app 2022-12-24 17:43:35 +05:30
Aman Harwara 4f07b915f0 feat: Added FileSend links to general account menu and preferences menu 2022-12-24 17:43:26 +05:30
StandardNotes CI f2f61b18e2 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2022-12-24 12:11:23 +00:00
Aman Harwara 9fb506e532 refactor(dev-only): show file link row action in table view 2022-12-24 17:09:26 +05:30
Aman Harwara 3b64acc290 refactor(dev-only): files table view attached column wrapping 2022-12-24 17:05:13 +05:30
Aman Harwara e6824a3414 chore: remove comment 2022-12-24 17:00:17 +05:30
Aman Harwara 08985bb5c8 refactor(dev-only): file preview navigation from table view 2022-12-24 16:58:46 +05:30
Aman Harwara 77cb6e7891 refactor(dev-only): files table view 2022-12-24 16:48:55 +05:30
Aman Harwara 7e7c5e14ab refactor(dev-only): files table view (#2118) 2022-12-24 16:46:18 +05:30
StandardNotes CI 631be2e494 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2022-12-23 18:11:05 +00:00
Mo fe36009482 fix: Fixed issue where navigating to a Daily Notebook on iOS would cause editor panel to be offscreen 2022-12-23 11:46:22 -06:00
StandardNotes CI e77e852801 chore(release): publish
- @standardnotes/[email protected].2
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2022-12-23 17:41:00 +00:00
Aman Harwara c59d824240 fix: Made Moments-related toast messages dismissable 2022-12-23 22:44:06 +05:30
Aman Harwara 2f3bc9b85b chore: Update Lexical to 0.7.5 (#2117) 2022-12-23 22:22:19 +05:30
StandardNotes CI 1ec173dcd6 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
2022-12-23 09:59:41 +00:00
Aman Harwara 35b00737bf fix: Fixed issue where Super note would convert whole line into tag even after closing menu 2022-12-23 15:03:18 +05:30
StandardNotes CI f3e147f4c9 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected]
2022-12-22 15:23:29 +00:00
Mo 63fdb328cb chore: adjust mobile price copy 2022-12-22 08:54:02 -06:00
Aman Harwara 94c280256e fix: Disabled Moments photo capture when app is passcode or biometrics locked (#2114) 2022-12-22 20:07:48 +05:30
StandardNotes CI cf0dc19f63 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].9
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected].4
 - @standardnotes/[email protected].9
2022-12-21 13:48:03 +00:00
Karol Sójko 2696b07759 fix(api): handling expired token responses (#2113) 2022-12-21 14:22:20 +01:00
StandardNotes CI 2cc5afb00a chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].8
 - @standardnotes/[email protected].7
 - @standardnotes/[email protected].3
 - @standardnotes/[email protected].8
2022-12-20 19:24:12 +00:00
Aman Harwara 1828f80ba5 chore: removed unnecessary warning 2022-12-21 00:27:16 +05:30
Aman Harwara 9c260c02f1 Merge branch 'main' of github.com:standardnotes/app 2022-12-20 23:58:31 +05:30
Aman Harwara e4b3028d67 fix: Increased interval between Moments capturing photos 2022-12-20 23:54:05 +05:30
Aman Harwara eceb46bed7 fix: Fixed issue where Moments-related toasts would not get correctly dismissed 2022-12-20 23:52:43 +05:30
StandardNotes CI b9e0d0d154 chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].7
2022-12-20 17:03:06 +00:00
Aman Harwara a7add80633 fix: Added potential fix for issue where some video would show as not supported 2022-12-20 22:02:30 +05:30
StandardNotes CI 0941183c8b chore(release): publish
- @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected]
 - @standardnotes/[email protected].6
2022-12-20 13:58:49 +00:00
Aman Harwara c94035c1d6 feat-dev(wip): files table view (#2100) 2022-12-20 19:01:24 +05:30
114 changed files with 2002 additions and 488 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+6
View File
@@ -3,6 +3,12 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.20.22](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)
### Bug Fixes
* **api:** handling expired token responses ([#2113](https://github.com/standardnotes/app/issues/2113)) ([2696b07](https://github.com/standardnotes/app/commit/2696b07759104fb1d40781897f69e63133ad824a))
## [1.20.21](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
**Note:** Version bump only for package @standardnotes/api
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/api",
"version": "1.20.21",
"version": "1.20.22",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+4 -5
View File
@@ -115,7 +115,7 @@ export class HttpService implements HttpServiceInterface {
return false
}
const response = (await this.post(joinPaths(this.host, Paths.v1.refreshSession), {
const response = (await this.post(Paths.v1.refreshSession, {
access_token: this.session.accessToken.value,
refresh_token: this.session.refreshToken.value,
})) as SessionRefreshResponse
@@ -265,13 +265,12 @@ export class HttpService implements HttpServiceInterface {
} catch (error) {
console.error(error)
}
if (httpStatus >= HttpStatusCode.Success && httpStatus < HttpStatusCode.MultipleChoices) {
resolve(response)
} else {
if (httpStatus >= HttpStatusCode.Success && httpStatus < HttpStatusCode.InternalServerError) {
if (httpStatus === HttpStatusCode.Forbidden && response.data && response.data.error !== undefined) {
;(response.data as HttpErrorResponseBody).error.message = ErrorMessage.RateLimited
}
resolve(response)
} else {
reject(response)
}
}
@@ -7,4 +7,5 @@ export enum HttpStatusCode {
Forbidden = 403,
Gone = 410,
ExpiredAccessToken = 498,
InternalServerError = 500,
}
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.11.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/blocks-editor
# [1.11.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
### Features
* Persist collapsible block state in Super notes ([#2119](https://github.com/standardnotes/app/issues/2119)) ([577318e](https://github.com/standardnotes/app/commit/577318e208367dc52caf2d76fd87419eaead7ed4))
## [1.10.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/blocks-editor
## [1.10.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
**Note:** Version bump only for package @standardnotes/blocks-editor
+3 -3
View File
@@ -1,17 +1,17 @@
{
"name": "@standardnotes/blocks-editor",
"version": "1.10.1",
"version": "1.11.1",
"private": true,
"main": "./src/index.ts",
"scripts": {
"tsc": "tsc -p tsconfig.json"
},
"dependencies": {
"@lexical/react": "^0.6.5",
"@lexical/react": "0.7.5",
"@standardnotes/icons": "workspace:*",
"@types/react": "^18.0.26",
"@types/react-dom": "^18.0.9",
"lexical": "^0.6.5",
"lexical": "0.7.5",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
@@ -21,6 +21,7 @@ import DraggableBlockPlugin from '../Lexical/Plugins/DraggableBlockPlugin';
import CodeHighlightPlugin from '../Lexical/Plugins/CodeHighlightPlugin';
import FloatingTextFormatToolbarPlugin from '../Lexical/Plugins/FloatingTextFormatToolbarPlugin';
import FloatingLinkEditorPlugin from '../Lexical/Plugins/FloatingLinkEditorPlugin';
import {TabIndentationPlugin} from '../Lexical/Plugins/TabIndentationPlugin';
import {truncateString} from './Utils';
import {SuperEditorContentId} from './Constants';
import {classNames} from '@standardnotes/utils';
@@ -107,7 +108,7 @@ export const BlocksEditor: FunctionComponent<BlocksEditorProps> = ({
</div>
</div>
}
placeholder=""
placeholder={null}
ErrorBoundary={LexicalErrorBoundary}
/>
<ListPlugin />
@@ -125,6 +126,7 @@ export const BlocksEditor: FunctionComponent<BlocksEditorProps> = ({
<TwitterPlugin />
<YouTubePlugin />
<CollapsiblePlugin />
<TabIndentationPlugin />
{!readonly && floatingAnchorElem && (
<>
<FloatingTextFormatToolbarPlugin anchorElem={floatingAnchorElem} />
@@ -192,9 +192,10 @@ export function AutoEmbedDialog({
const embedResult =
text != null && urlMatch != null ? embedConfig.parseUrl(text) : null;
const onClick = () => {
if (embedResult != null) {
embedConfig.insertNode(editor, embedResult);
const onClick = async () => {
const result = await embedResult;
if (result != null) {
embedConfig.insertNode(editor, result);
onClose();
}
};
@@ -20,6 +20,7 @@ type SerializedCollapsibleContainerNode = Spread<
{
type: 'collapsible-container';
version: 1;
open: boolean;
},
SerializedElementNode
>;
@@ -29,25 +30,27 @@ export class CollapsibleContainerNode extends ElementNode {
constructor(open: boolean, key?: NodeKey) {
super(key);
this.__open = open;
this.__open = open ?? false;
}
static getType(): string {
static override getType(): string {
return 'collapsible-container';
}
static clone(node: CollapsibleContainerNode): CollapsibleContainerNode {
static override clone(
node: CollapsibleContainerNode,
): CollapsibleContainerNode {
return new CollapsibleContainerNode(node.__open, node.__key);
}
createDOM(config: EditorConfig): HTMLElement {
override createDOM(config: EditorConfig): HTMLElement {
const dom = document.createElement('details');
dom.classList.add('Collapsible__container');
dom.open = this.__open;
return dom;
}
updateDOM(
override updateDOM(
prevNode: CollapsibleContainerNode,
dom: HTMLDetailsElement,
): boolean {
@@ -62,18 +65,19 @@ export class CollapsibleContainerNode extends ElementNode {
return {};
}
static importJSON(
static override importJSON(
serializedNode: SerializedCollapsibleContainerNode,
): CollapsibleContainerNode {
const node = $createCollapsibleContainerNode();
const node = $createCollapsibleContainerNode(serializedNode.open);
return node;
}
exportJSON(): SerializedCollapsibleContainerNode {
override exportJSON(): SerializedCollapsibleContainerNode {
return {
...super.exportJSON(),
type: 'collapsible-container',
version: 1,
open: this.__open,
};
}
@@ -91,8 +95,10 @@ export class CollapsibleContainerNode extends ElementNode {
}
}
export function $createCollapsibleContainerNode(): CollapsibleContainerNode {
return new CollapsibleContainerNode(true);
export function $createCollapsibleContainerNode(
open: boolean,
): CollapsibleContainerNode {
return new CollapsibleContainerNode(open);
}
export function $isCollapsibleContainerNode(
@@ -24,21 +24,24 @@ type SerializedCollapsibleContentNode = Spread<
>;
export class CollapsibleContentNode extends ElementNode {
static getType(): string {
static override getType(): string {
return 'collapsible-content';
}
static clone(node: CollapsibleContentNode): CollapsibleContentNode {
static override clone(node: CollapsibleContentNode): CollapsibleContentNode {
return new CollapsibleContentNode(node.__key);
}
createDOM(config: EditorConfig): HTMLElement {
override createDOM(config: EditorConfig): HTMLElement {
const dom = document.createElement('div');
dom.classList.add('Collapsible__content');
return dom;
}
updateDOM(prevNode: CollapsibleContentNode, dom: HTMLElement): boolean {
override updateDOM(
prevNode: CollapsibleContentNode,
dom: HTMLElement,
): boolean {
return false;
}
@@ -46,17 +49,17 @@ export class CollapsibleContentNode extends ElementNode {
return {};
}
static importJSON(
static override importJSON(
serializedNode: SerializedCollapsibleContentNode,
): CollapsibleContentNode {
return $createCollapsibleContentNode();
}
isShadowRoot(): boolean {
override isShadowRoot(): boolean {
return true;
}
exportJSON(): SerializedCollapsibleContentNode {
override exportJSON(): SerializedCollapsibleContentNode {
return {
...super.exportJSON(),
type: 'collapsible-content',
@@ -31,21 +31,34 @@ type SerializedCollapsibleTitleNode = Spread<
>;
export class CollapsibleTitleNode extends ElementNode {
static getType(): string {
static override getType(): string {
return 'collapsible-title';
}
static clone(node: CollapsibleTitleNode): CollapsibleTitleNode {
static override clone(node: CollapsibleTitleNode): CollapsibleTitleNode {
return new CollapsibleTitleNode(node.__key);
}
createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement {
override createDOM(config: EditorConfig, editor: LexicalEditor): HTMLElement {
const dom = document.createElement('summary');
dom.classList.add('Collapsible__title');
dom.onclick = (event) => {
event.preventDefault();
event.stopPropagation();
editor.update(() => {
const containerNode = this.getParentOrThrow();
if ($isCollapsibleContainerNode(containerNode)) {
containerNode.toggleOpen();
}
});
};
return dom;
}
updateDOM(prevNode: CollapsibleTitleNode, dom: HTMLElement): boolean {
override updateDOM(
prevNode: CollapsibleTitleNode,
dom: HTMLElement,
): boolean {
return false;
}
@@ -53,13 +66,13 @@ export class CollapsibleTitleNode extends ElementNode {
return {};
}
static importJSON(
static override importJSON(
serializedNode: SerializedCollapsibleTitleNode,
): CollapsibleTitleNode {
return $createCollapsibleTitleNode();
}
exportJSON(): SerializedCollapsibleTitleNode {
override exportJSON(): SerializedCollapsibleTitleNode {
return {
...super.exportJSON(),
type: 'collapsible-title',
@@ -67,12 +80,12 @@ export class CollapsibleTitleNode extends ElementNode {
};
}
collapseAtStart(_selection: RangeSelection): boolean {
override collapseAtStart(_selection: RangeSelection): boolean {
this.getParentOrThrow().insertBefore(this);
return true;
}
insertNewAfter(): ElementNode {
override insertNewAfter(): ElementNode {
const containerNode = this.getParentOrThrow();
if (!$isCollapsibleContainerNode(containerNode)) {
@@ -204,7 +204,7 @@ export default function CollapsiblePlugin(): JSX.Element | null {
const content = $createCollapsibleContentNode().append(
$createParagraphNode(),
);
const container = $createCollapsibleContainerNode().append(
const container = $createCollapsibleContainerNode(true).append(
title,
content,
);
@@ -12,6 +12,7 @@ import {mergeRegister} from '@lexical/utils';
import {
$getNearestNodeFromDOMNode,
$getNodeByKey,
$getRoot,
COMMAND_PRIORITY_HIGH,
COMMAND_PRIORITY_LOW,
DRAGOVER_COMMAND,
@@ -58,8 +59,7 @@ function getCurrentIndex(keysLength: number): number {
}
function getTopLevelNodeKeys(editor: LexicalEditor): string[] {
const root = editor.getEditorState()._nodeMap.get('root');
return root ? root.__children : [];
return editor.getEditorState().read(() => $getRoot().getChildrenKeys());
}
function elementContainingEventLocation(
@@ -0,0 +1,50 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import {useLexicalComposerContext} from '@lexical/react/LexicalComposerContext';
import {
$getSelection,
$isRangeSelection,
COMMAND_PRIORITY_EDITOR,
INDENT_CONTENT_COMMAND,
KEY_TAB_COMMAND,
OUTDENT_CONTENT_COMMAND,
} from 'lexical';
import {useEffect} from 'react';
/**
* This plugin adds the ability to indent content using the tab key. Generally, we don't
* recommend using this plugin as it could negatively affect acessibility for keyboard
* users, causing focus to become trapped within the editor.
*/
export function TabIndentationPlugin(): null {
const [editor] = useLexicalComposerContext();
useEffect(() => {
return editor.registerCommand<KeyboardEvent>(
KEY_TAB_COMMAND,
(event) => {
const selection = $getSelection();
if (!$isRangeSelection(selection)) {
return false;
}
event.preventDefault();
return editor.dispatchCommand(
event.shiftKey ? OUTDENT_CONTENT_COMMAND : INDENT_CONTENT_COMMAND,
undefined,
);
},
COMMAND_PRIORITY_EDITOR,
);
});
return null;
}
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.104.43](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.42](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.41](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.40](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.39](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.38](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.37](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.36](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-22)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.35](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.34](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.33](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.32](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/desktop
## [3.104.31](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
**Note:** Version bump only for package @standardnotes/desktop
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "@standardnotes/desktop",
"main": "./app/dist/index.js",
"version": "3.104.31",
"version": "3.104.43",
"license": "AGPL-3.0-or-later",
"author": "Standard Notes.",
"private": true,
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.49.40](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.39](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.38](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.37](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.36](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.35](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.34](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.33](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-22)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.32](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.31](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.30](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.29](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/mobile
## [3.49.28](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
**Note:** Version bump only for package @standardnotes/mobile
+2 -2
View File
@@ -583,7 +583,7 @@ EXTERNAL SOURCES:
SPEC CHECKSUMS:
boost: a7c83b31436843459a1961bfd74b96033dc77234
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662
FBLazyVector: 48289402952f4f7a4e235de70a9a590aa0b79ef4
FBReactNativeSpec: dd1186fd05255e3457baa2f4ca65e94c2cd1e3ac
Flipper: 26fc4b7382499f1281eb8cb921e5c3ad6de91fe0
@@ -596,7 +596,7 @@ SPEC CHECKSUMS:
Flipper-RSocket: d9d9ade67cbecf6ac10730304bf5607266dd2541
FlipperKit: cbdee19bdd4e7f05472a66ce290f1b729ba3cb86
fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
glog: 85ecdd10ee8d8ec362ef519a6a45ff9aa27b2e85
hermes-engine: 2af7b7a59128f250adfd86f15aa1d5a2ecd39995
libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913
OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/mobile",
"version": "3.49.28",
"version": "3.49.40",
"author": "Standard Notes.",
"private": true,
"license": "AGPL-3.0-or-later",
+48
View File
@@ -3,6 +3,54 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.4.66](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.65](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.64](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.63](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.62](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.61](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.60](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.59](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-22)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.58](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.57](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.56](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.55](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/releases
## [1.4.54](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
**Note:** Version bump only for package @standardnotes/releases
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/releases",
"version": "1.4.54",
"version": "1.4.66",
"license": "AGPL-3.0-or-later",
"main": "dist/releases.json",
"types": "dist/index.d.ts",
+8
View File
@@ -3,6 +3,14 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [1.50.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)
**Note:** Version bump only for package @standardnotes/services
## [1.50.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/services
## [1.50.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
**Note:** Version bump only for package @standardnotes/services
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/services",
"version": "1.50.7",
"version": "1.50.9",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -4,8 +4,6 @@ export const InfoStrings = {
'This backup file was created using a newer version of the application and cannot be imported here. Please update your application and try again.',
BackupFileMoreRecentThanAccount:
"This backup file was created using a newer encryption version than your account's. Please run the available encryption upgrade and try again.",
SavingWhileDocumentHidden:
'Attempting to save an item while the application is hidden. To protect data integrity, please refresh the application window and try again.',
InvalidNote:
"The note you are attempting to save can not be found or has been deleted. Changes you make will not be synced. Please copy this note's text and start a new note.",
}
+16
View File
@@ -3,6 +3,22 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.156.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-22)
### Bug Fixes
* Disabled Moments photo capture when app is passcode or biometrics locked ([#2114](https://github.com/standardnotes/app/issues/2114)) ([94c2802](https://github.com/standardnotes/app/commit/94c280256e0a71fb8078f0d0e4d7ad2b6d3c1462))
## [2.156.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)
### Bug Fixes
* **api:** handling expired token responses ([#2113](https://github.com/standardnotes/app/issues/2113)) ([2696b07](https://github.com/standardnotes/app/commit/2696b07759104fb1d40781897f69e63133ad824a))
## [2.156.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/snjs
## [2.156.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
### Bug Fixes
+6 -2
View File
@@ -178,6 +178,7 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
private launched = false
/** Whether the application has been destroyed via .deinit() */
public dealloced = false
private isBiometricsSoftLockEngaged = false
private revokingSession = false
private handledFullSyncStage = false
@@ -940,11 +941,12 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
return this.protocolService.hasPasscode()
}
isLocked(): Promise<boolean> {
async isLocked(): Promise<boolean> {
if (!this.started) {
return Promise.resolve(true)
}
return this.challengeService.isPasscodeLocked()
const isPasscodeLocked = await this.challengeService.isPasscodeLocked()
return isPasscodeLocked || this.isBiometricsSoftLockEngaged
}
public async lock(): Promise<void> {
@@ -964,10 +966,12 @@ export class SNApplication implements ApplicationInterface, AppGroupManagedAppli
void this.promptForCustomChallenge(challenge)
this.isBiometricsSoftLockEngaged = true
void this.notifyEvent(ApplicationEvent.BiometricsSoftLockEngaged)
this.addChallengeObserver(challenge, {
onComplete: () => {
this.isBiometricsSoftLockEngaged = false
void this.notifyEvent(ApplicationEvent.BiometricsSoftLockDisengaged)
},
})
+1 -1
View File
@@ -2,7 +2,7 @@ import * as Factory from './lib/factory.js'
chai.use(chaiAsPromised)
const expect = chai.expect
describe.skip('subscriptions', function () {
describe('subscriptions', function () {
this.timeout(Factory.TwentySecondTimeout)
let application
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/snjs",
"version": "2.156.6",
"version": "2.156.9",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
+14
View File
@@ -3,6 +3,20 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [1.21.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
### Features
* Added FileSend links to general account menu and preferences menu ([4f07b91](https://github.com/standardnotes/app/commit/4f07b915f0a60632a9e537b3b0394290d25fa071))
## [1.20.4](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.20.3](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/ui-services
## [1.20.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
**Note:** Version bump only for package @standardnotes/ui-services
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/ui-services",
"version": "1.20.2",
"version": "1.21.0",
"engines": {
"node": ">=16.0.0 <17.0.0"
},
@@ -10,6 +10,7 @@ const PREFERENCE_IDS = [
'get-free-month',
'help-feedback',
'whats-new',
'filesend',
] as const
export type PreferenceId = typeof PREFERENCE_IDS[number]
+63
View File
@@ -3,6 +3,69 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [3.128.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/web
## [3.128.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/web
# [3.128.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
### Features
* Added FileSend links to general account menu and preferences menu ([4f07b91](https://github.com/standardnotes/app/commit/4f07b915f0a60632a9e537b3b0394290d25fa071))
## [3.127.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)
**Note:** Version bump only for package @standardnotes/web
## [3.127.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
### Bug Fixes
* Fixed issue where navigating to a Daily Notebook on iOS would cause editor panel to be offscreen ([fe36009](https://github.com/standardnotes/app/commit/fe36009482ff1615612ca965abb956318d8bc626))
## [3.127.12](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
### Bug Fixes
* Made Moments-related toast messages dismissable ([c59d824](https://github.com/standardnotes/app/commit/c59d82424012f98638625e057f88124982ad0734))
## [3.127.11](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)
### Bug Fixes
* Fixed issue where Super note would convert whole line into tag even after closing menu ([35b0073](https://github.com/standardnotes/app/commit/35b00737bf13ceb8e66d64c67925f2fe9df2587c))
## [3.127.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-22)
### Bug Fixes
* Disabled Moments photo capture when app is passcode or biometrics locked ([#2114](https://github.com/standardnotes/app/issues/2114)) ([94c2802](https://github.com/standardnotes/app/commit/94c280256e0a71fb8078f0d0e4d7ad2b6d3c1462))
## [3.127.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)
**Note:** Version bump only for package @standardnotes/web
## [3.127.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
### Bug Fixes
* Fixed issue where Moments-related toasts would not get correctly dismissed ([eceb46b](https://github.com/standardnotes/app/commit/eceb46bed7117c8bf5ea34d87a800f8bf02881ac))
* Increased interval between Moments capturing photos ([e4b3028](https://github.com/standardnotes/app/commit/e4b3028d673a037f2740939b294cf6301db0d529))
## [3.127.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
### Bug Fixes
* Added potential fix for issue where some video would show as not supported ([a7add80](https://github.com/standardnotes/app/commit/a7add80633ea603f7883db2dbc1f886d40450979))
## [3.127.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)
**Note:** Version bump only for package @standardnotes/web
## [3.127.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)
**Note:** Version bump only for package @standardnotes/web
+155
View File
@@ -1,5 +1,160 @@
{
"versions": [
{
"version": "3.128.2",
"title": "[3.128.2](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.128.1",
"title": "[3.128.1](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.128.0",
"title": "[3.128.0](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)",
"date": null,
"body": "### Features\n\n* Added FileSend links to general account menu and preferences menu ([4f07b91](https://github.com/standardnotes/app/commit/4f07b915f0a60632a9e537b3b0394290d25fa071))",
"parsed": {
"_": [
"Added FileSend links to general account menu and preferences menu (4f07b91)"
],
"Features": [
"Added FileSend links to general account menu and preferences menu (4f07b91)"
]
}
},
{
"version": "3.127.14",
"title": "[3.127.14](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-24)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.127.13",
"title": "[3.127.13](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where navigating to a Daily Notebook on iOS would cause editor panel to be offscreen ([fe36009](https://github.com/standardnotes/app/commit/fe36009482ff1615612ca965abb956318d8bc626))",
"parsed": {
"_": [
"Fixed issue where navigating to a Daily Notebook on iOS would cause editor panel to be offscreen (fe36009)"
],
"Bug Fixes": [
"Fixed issue where navigating to a Daily Notebook on iOS would cause editor panel to be offscreen (fe36009)"
]
}
},
{
"version": "3.127.12",
"title": "[3.127.12](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)",
"date": null,
"body": "### Bug Fixes\n\n* Made Moments-related toast messages dismissable ([c59d824](https://github.com/standardnotes/app/commit/c59d82424012f98638625e057f88124982ad0734))",
"parsed": {
"_": [
"Made Moments-related toast messages dismissable (c59d824)"
],
"Bug Fixes": [
"Made Moments-related toast messages dismissable (c59d824)"
]
}
},
{
"version": "3.127.11",
"title": "[3.127.11](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-23)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where Super note would convert whole line into tag even after closing menu ([35b0073](https://github.com/standardnotes/app/commit/35b00737bf13ceb8e66d64c67925f2fe9df2587c))",
"parsed": {
"_": [
"Fixed issue where Super note would convert whole line into tag even after closing menu (35b0073)"
],
"Bug Fixes": [
"Fixed issue where Super note would convert whole line into tag even after closing menu (35b0073)"
]
}
},
{
"version": "3.127.10",
"title": "[3.127.10](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-22)",
"date": null,
"body": "### Bug Fixes\n\n* Disabled Moments photo capture when app is passcode or biometrics locked ([#2114](https://github.com/standardnotes/app/issues/2114)) ([94c2802](https://github.com/standardnotes/app/commit/94c280256e0a71fb8078f0d0e4d7ad2b6d3c1462))",
"parsed": {
"_": [
"Disabled Moments photo capture when app is passcode or biometrics locked (#2114) (94c2802)"
],
"Bug Fixes": [
"Disabled Moments photo capture when app is passcode or biometrics locked (#2114) (94c2802)"
]
}
},
{
"version": "3.127.9",
"title": "[3.127.9](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-21)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.127.8",
"title": "[3.127.8](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)",
"date": null,
"body": "### Bug Fixes\n\n* Fixed issue where Moments-related toasts would not get correctly dismissed ([eceb46b](https://github.com/standardnotes/app/commit/eceb46bed7117c8bf5ea34d87a800f8bf02881ac))\n* Increased interval between Moments capturing photos ([e4b3028](https://github.com/standardnotes/app/commit/e4b3028d673a037f2740939b294cf6301db0d529))",
"parsed": {
"_": [
"Fixed issue where Moments-related toasts would not get correctly dismissed (eceb46b)",
"Increased interval between Moments capturing photos (e4b3028)"
],
"Bug Fixes": [
"Fixed issue where Moments-related toasts would not get correctly dismissed (eceb46b)",
"Increased interval between Moments capturing photos (e4b3028)"
]
}
},
{
"version": "3.127.7",
"title": "[3.127.7](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)",
"date": null,
"body": "### Bug Fixes\n\n* Added potential fix for issue where some video would show as not supported ([a7add80](https://github.com/standardnotes/app/commit/a7add80633ea603f7883db2dbc1f886d40450979))",
"parsed": {
"_": [
"Added potential fix for issue where some video would show as not supported (a7add80)"
],
"Bug Fixes": [
"Added potential fix for issue where some video would show as not supported (a7add80)"
]
}
},
{
"version": "3.127.6",
"title": "[3.127.6](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-20)",
"date": null,
"body": "**Note:** Version bump only for package @standardnotes/web",
"parsed": {
"_": [
"Note: Version bump only for package @standardnotes/web"
]
}
},
{
"version": "3.127.5",
"title": "[3.127.5](https://github.com/standardnotes/app/compare/@standardnotes/[email protected]...@standardnotes/[email protected]) (2022-12-19)",
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "@standardnotes/web",
"version": "3.127.5",
"version": "3.128.2",
"license": "AGPL-3.0-or-later",
"main": "dist/app.js",
"author": "Standard Notes.",
@@ -28,7 +28,7 @@
"@babel/plugin-transform-react-jsx": "^7.19.0",
"@babel/preset-env": "*",
"@babel/preset-typescript": "^7.18.6",
"@lexical/react": "^0.6.5",
"@lexical/react": "0.7.5",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"@reach/alert": "^0.18.0",
"@reach/alert-dialog": "^0.18.0",
@@ -84,7 +84,7 @@
"identity-obj-proxy": "^3.0.0",
"jest": "^29.3.1",
"jest-environment-jsdom": "^29.3.1",
"lexical": "0.6.5",
"lexical": "0.7.5",
"lint-staged": ">=13",
"mini-css-extract-plugin": "^2.7.2",
"minimatch": "^5.1.1",
@@ -84,6 +84,17 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({
setMenuPane(AccountMenuPane.SignIn)
}, [setMenuPane])
const openFileSend = useCallback(() => {
const link = 'https://filesend.standardnotes.com/'
if (application.isNativeMobileWeb()) {
application.mobileDevice().openUrl(link)
return
}
window.open(link, '_blank')
}, [application])
const CREATE_ACCOUNT_INDEX = 1
const SWITCHER_INDEX = 0
@@ -172,6 +183,10 @@ const GeneralAccountMenu: FunctionComponent<Props> = ({
</div>
<span className="text-neutral">v{application.version}</span>
</MenuItem>
<MenuItem onClick={openFileSend}>
<Icon type="open-in" className={iconClassName} />
Open FileSend
</MenuItem>
{user ? (
<>
<MenuItemSeparator />
@@ -1,6 +1,6 @@
import { FileItem } from '@standardnotes/snjs'
export enum PopoverFileItemActionType {
export enum FileItemActionType {
AttachFileToNote,
DetachFileToNote,
DeleteFile,
@@ -10,34 +10,32 @@ export enum PopoverFileItemActionType {
PreviewFile,
}
export type PopoverFileItemAction =
export type FileItemAction =
| {
type: Exclude<
PopoverFileItemActionType,
| PopoverFileItemActionType.RenameFile
| PopoverFileItemActionType.ToggleFileProtection
| PopoverFileItemActionType.PreviewFile
FileItemActionType,
FileItemActionType.RenameFile | FileItemActionType.ToggleFileProtection | FileItemActionType.PreviewFile
>
payload: {
file: FileItem
}
}
| {
type: PopoverFileItemActionType.ToggleFileProtection
type: FileItemActionType.ToggleFileProtection
payload: {
file: FileItem
}
callback: (isProtected: boolean) => void
}
| {
type: PopoverFileItemActionType.RenameFile
type: FileItemActionType.RenameFile
payload: {
file: FileItem
name: string
}
}
| {
type: PopoverFileItemActionType.PreviewFile
type: FileItemActionType.PreviewFile
payload: {
file: FileItem
otherFiles?: FileItem[]
@@ -13,6 +13,7 @@ import { NotesController } from '@/Controllers/NotesController/NotesController'
import { ElementIds } from '@/Constants/ElementIDs'
import { classNames } from '@standardnotes/utils'
import { ContentType, SNTag } from '@standardnotes/snjs'
import { featureTrunkEnabled, FeatureTrunkName } from '@/FeatureTrunk'
type Props = {
application: WebApplication
@@ -97,6 +98,8 @@ const ContentList: FunctionComponent<Props> = ({
const hasNotes = items.some((item) => item.content_type === ContentType.Note)
const isFilesTableViewEnabled = featureTrunkEnabled(FeatureTrunkName.FilesTableView)
return (
<div
className={classNames(
@@ -132,8 +135,8 @@ const ContentList: FunctionComponent<Props> = ({
onSelect={selectItem}
tags={getTagsForItem(item)}
notesController={notesController}
isPreviousItemTiled={previousItem?.content_type === ContentType.File}
isNextItemTiled={nextItem?.content_type === ContentType.File}
isPreviousItemTiled={previousItem?.content_type === ContentType.File && !isFilesTableViewEnabled}
isNextItemTiled={nextItem?.content_type === ContentType.File && !isFilesTableViewEnabled}
/>
)
})}
@@ -1,16 +1,25 @@
import { featureTrunkEnabled, FeatureTrunkName } from '@/FeatureTrunk'
import { ContentType, FileItem, SNNote } from '@standardnotes/snjs'
import React, { FunctionComponent } from 'react'
import FileListItem from './FileListItem'
import FileListItemCard from './FileListItemCard'
import NoteListItem from './NoteListItem'
import { AbstractListItemProps, doListItemPropsMeritRerender } from './Types/AbstractListItemProps'
import { ListableContentItem } from './Types/ListableContentItem'
const ContentListItem: FunctionComponent<AbstractListItemProps<ListableContentItem>> = (props) => {
const isFilesTableViewEnabled = featureTrunkEnabled(FeatureTrunkName.FilesTableView)
switch (props.item.content_type) {
case ContentType.Note:
return <NoteListItem {...props} item={props.item as SNNote} />
case ContentType.File:
return <FileListItem {...props} item={props.item as FileItem} />
case ContentType.File: {
if (isFilesTableViewEnabled) {
return <FileListItem {...props} item={props.item as FileItem} />
}
return <FileListItemCard {...props} item={props.item as FileItem} />
}
default:
return null
}
@@ -9,7 +9,7 @@ import {
} from '@standardnotes/ui-services'
import { WebApplication } from '@/Application/Application'
import { PANEL_NAME_NOTES } from '@/Constants/Constants'
import { FileItem, PrefKey, WebAppEvent } from '@standardnotes/snjs'
import { FileItem, PrefKey, SystemViewId, WebAppEvent } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { forwardRef, useCallback, useEffect, useMemo } from 'react'
import ContentList from '@/Components/ContentListView/ContentList'
@@ -37,6 +37,9 @@ import { PanelResizedData } from '@/Types/PanelResizedData'
import { useForwardedRef } from '@/Hooks/useForwardedRef'
import { isMobileScreen } from '@/Utils'
import FloatingAddButton from './FloatingAddButton'
import FilesTableView from '../FilesTableView/FilesTableView'
import { FeaturesController } from '@/Controllers/FeaturesController'
import { featureTrunkEnabled, FeatureTrunkName } from '@/FeatureTrunk'
type Props = {
accountMenuController: AccountMenuController
@@ -49,6 +52,7 @@ type Props = {
selectionController: SelectedItemsController
searchOptionsController: SearchOptionsController
linkingController: LinkingController
featuresController: FeaturesController
className?: string
id: string
children?: React.ReactNode
@@ -68,6 +72,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
selectionController,
searchOptionsController,
linkingController,
featuresController,
className,
id,
children,
@@ -280,6 +285,9 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
}
}, [selectedUuids, innerRef, isCurrentNoteTemplate, renderedItems, panes])
const isFilesTableViewEnabled = featureTrunkEnabled(FeatureTrunkName.FilesTableView)
const shouldShowFilesTableView = isFilesTableViewEnabled && selectedTag?.uuid === SystemViewId.Files
return (
<div
id={id}
@@ -300,12 +308,16 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
addButtonLabel={addButtonLabel}
addNewItem={addNewItem}
isFilesSmartView={isFilesSmartView}
isFilesTableViewEnabled={isFilesTableViewEnabled}
optionsSubtitle={optionsSubtitle}
selectedTag={selectedTag}
filesController={filesController}
itemListController={itemListController}
/>
)}
<SearchBar itemListController={itemListController} searchOptionsController={searchOptionsController} />
{!isFilesTableViewEnabled && (
<SearchBar itemListController={itemListController} searchOptionsController={searchOptionsController} />
)}
<NoAccountWarning
accountMenuController={accountMenuController}
noAccountWarningController={noAccountWarningController}
@@ -324,13 +336,18 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
{!dailyMode && completedFullSync && !renderedItems.length ? (
<p className="empty-items-list opacity-50">No items.</p>
) : null}
{!dailyMode && !completedFullSync && !renderedItems.length ? (
<p className="empty-items-list opacity-50">Loading...</p>
) : null}
{!dailyMode && renderedItems.length ? (
<>
shouldShowFilesTableView ? (
<FilesTableView
application={application}
filesController={filesController}
featuresController={featuresController}
linkingController={linkingController}
/>
) : (
<ContentList
items={renderedItems}
selectedUuids={selectedUuids}
@@ -342,7 +359,7 @@ const ContentListView = forwardRef<HTMLDivElement, Props>(
notesController={notesController}
selectionController={selectionController}
/>
</>
)
) : null}
<div className="absolute bottom-0 h-safe-bottom w-full" />
{children}
@@ -9,13 +9,12 @@ import { DisplayableListItemProps } from './Types/DisplayableListItemProps'
import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider'
import { useContextMenuEvent } from '@/Hooks/useContextMenuEvent'
import { classNames } from '@standardnotes/utils'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
import { getIconForFileType } from '@/Utils/Items/Icons/getIconForFileType'
import { useApplication } from '../ApplicationProvider'
import Icon from '../Icon/Icon'
import { PaneLayout } from '@/Controllers/PaneController/PaneLayout'
import ListItemFlagIcons from './ListItemFlagIcons'
const FileListItem: FunctionComponent<DisplayableListItemProps<FileItem>> = ({
const FileListItemCard: FunctionComponent<DisplayableListItemProps<FileItem>> = ({
filesController,
hideDate,
hideIcon,
@@ -75,57 +74,38 @@ const FileListItem: FunctionComponent<DisplayableListItemProps<FileItem>> = ({
}, [file, onSelect, setPaneLayout])
const IconComponent = () =>
getFileIconComponent(getIconForFileType((file as FileItem).mimeType), 'w-10 h-10 flex-shrink-0')
getFileIconComponent(getIconForFileType((file as FileItem).mimeType), 'w-5 h-5 flex-shrink-0')
useContextMenuEvent(listItemRef, openContextMenu)
return (
<div
ref={listItemRef}
className={classNames('flex max-h-[300px] w-[190px] cursor-pointer px-1 pt-2 text-text md:w-[200px]')}
className={classNames(
'content-list-item flex w-full cursor-pointer items-stretch text-text',
selected && 'selected border-l-2px border-solid border-info',
)}
id={file.uuid}
onClick={onClick}
>
<div
className={`flex flex-col justify-between overflow-hidden rounded bg-passive-5 pt-5 transition-all hover:bg-passive-4 ${
selected ? 'border-[1px] border-solid border-info' : 'border-[1px] border-solid border-border'
}`}
>
<div className={'px-5'}>
{!hideIcon ? (
<div className="mr-0">
<IconComponent />
</div>
) : (
<div className="pr-4" />
)}
<div className="min-w-0 flex-grow py-4 px-0">
<div className="line-clamp-2 overflow-hidden text-editor font-semibold">
<div className="break-word line-clamp-2 mr-2 overflow-hidden">{file.title}</div>
</div>
<ListItemMetadata item={file} hideDate={hideDate} sortBy={sortBy} />
<ListItemTags hideTags={hideTags} tags={tags} />
<ListItemConflictIndicator item={file} />
</div>
{!hideIcon ? (
<div className="mr-0 flex flex-col items-center justify-between p-4.5 pr-3">
<IconComponent />
</div>
<div
className={classNames(
'border-t-[1px] border-solid border-border p-3 text-xs font-bold',
selected ? 'bg-info text-info-contrast' : 'bg-passive-4 text-neutral',
)}
>
<div className="flex justify-between">
{formatSizeToReadableString(file.decryptedSize)}
{backupInfo && (
<div title="File is backed up locally">
<Icon type="check-circle" />
</div>
)}
</div>
) : (
<div className="pr-4" />
)}
<div className="min-w-0 flex-grow border-b border-solid border-border py-4 px-0">
<div className="flex items-start justify-between overflow-hidden text-base font-semibold leading-[1.3]">
<div className="break-word mr-2">{file.title}</div>
</div>
<ListItemMetadata item={file} hideDate={hideDate} sortBy={sortBy} />
<ListItemTags hideTags={hideTags} tags={tags} />
<ListItemConflictIndicator item={file} />
</div>
<ListItemFlagIcons className="p-4" item={file} isFileBackedUp={!!backupInfo} />
</div>
)
}
export default observer(FileListItem)
export default observer(FileListItemCard)
@@ -0,0 +1,131 @@
import { FileItem, FileBackupRecord } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
import { getFileIconComponent } from '../FilePreview/getFileIconComponent'
import ListItemConflictIndicator from './ListItemConflictIndicator'
import ListItemTags from './ListItemTags'
import ListItemMetadata from './ListItemMetadata'
import { DisplayableListItemProps } from './Types/DisplayableListItemProps'
import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider'
import { useContextMenuEvent } from '@/Hooks/useContextMenuEvent'
import { classNames } from '@standardnotes/utils'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
import { getIconForFileType } from '@/Utils/Items/Icons/getIconForFileType'
import { useApplication } from '../ApplicationProvider'
import Icon from '../Icon/Icon'
import { PaneLayout } from '@/Controllers/PaneController/PaneLayout'
const FileListItemCard: FunctionComponent<DisplayableListItemProps<FileItem>> = ({
filesController,
hideDate,
hideIcon,
hideTags,
item: file,
onSelect,
selected,
sortBy,
tags,
}) => {
const { setPaneLayout } = useResponsiveAppPane()
const application = useApplication()
const [backupInfo, setBackupInfo] = useState<FileBackupRecord | undefined>(undefined)
useEffect(() => {
void application.fileBackups?.getFileBackupInfo(file).then(setBackupInfo)
}, [application, file])
const listItemRef = useRef<HTMLDivElement>(null)
const openFileContextMenu = useCallback(
(posX: number, posY: number) => {
filesController.setShowFileContextMenu(false)
filesController.setFileContextMenuLocation({
x: posX,
y: posY,
})
filesController.setShowFileContextMenu(true)
},
[filesController],
)
const openContextMenu = useCallback(
async (posX: number, posY: number) => {
let shouldOpenContextMenu = selected
if (!selected) {
const { didSelect } = await onSelect(file)
if (didSelect) {
shouldOpenContextMenu = true
}
}
if (shouldOpenContextMenu) {
openFileContextMenu(posX, posY)
}
},
[selected, onSelect, file, openFileContextMenu],
)
const onClick = useCallback(async () => {
const { didSelect } = await onSelect(file, true)
if (didSelect) {
setPaneLayout(PaneLayout.Editing)
}
}, [file, onSelect, setPaneLayout])
const IconComponent = () =>
getFileIconComponent(getIconForFileType((file as FileItem).mimeType), 'w-10 h-10 flex-shrink-0')
useContextMenuEvent(listItemRef, openContextMenu)
return (
<div
ref={listItemRef}
className={classNames('flex max-h-[300px] w-[190px] cursor-pointer px-1 pt-2 text-text md:w-[200px]')}
id={file.uuid}
onClick={onClick}
>
<div
className={`flex flex-col justify-between overflow-hidden rounded bg-passive-5 pt-5 transition-all hover:bg-passive-4 ${
selected ? 'border-[1px] border-solid border-info' : 'border-[1px] border-solid border-border'
}`}
>
<div className={'px-5'}>
{!hideIcon ? (
<div className="mr-0">
<IconComponent />
</div>
) : (
<div className="pr-4" />
)}
<div className="min-w-0 flex-grow py-4 px-0">
<div className="line-clamp-2 overflow-hidden text-editor font-semibold">
<div className="break-word line-clamp-2 mr-2 overflow-hidden">{file.title}</div>
</div>
<ListItemMetadata item={file} hideDate={hideDate} sortBy={sortBy} />
<ListItemTags hideTags={hideTags} tags={tags} />
<ListItemConflictIndicator item={file} />
</div>
</div>
<div
className={classNames(
'border-t-[1px] border-solid border-border p-3 text-xs font-bold',
selected ? 'bg-info text-info-contrast' : 'bg-passive-4 text-neutral',
)}
>
<div className="flex justify-between">
{formatSizeToReadableString(file.decryptedSize)}
{backupInfo && (
<div title="File is backed up locally">
<Icon type="check-circle" />
</div>
)}
</div>
</div>
</div>
</div>
)
}
export default observer(FileListItemCard)
@@ -44,12 +44,8 @@ const AddItemMenuButton = ({
<>
<button
className={classNames(
'hidden md:flex',
'h-8 w-8 hover:brightness-125',
'z-editor-title-bar ml-3 cursor-pointer items-center',
`justify-center rounded-full border border-solid border-transparent ${
isDailyEntry ? 'bg-danger text-danger-contrast' : 'bg-info text-info-contrast'
}`,
'z-editor-title-bar hidden h-8 w-8 cursor-pointer items-center justify-center rounded-full border border-solid border-transparent hover:brightness-125 md:flex',
isDailyEntry ? 'bg-danger text-danger-contrast' : 'bg-info text-info-contrast',
)}
title={addButtonLabel}
aria-label={addButtonLabel}
@@ -11,6 +11,8 @@ import { AnyTag } from '@/Controllers/Navigation/AnyTagType'
import { MediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
import AddItemMenuButton from './AddItemMenuButton'
import { FilesController } from '@/Controllers/FilesController'
import SearchButton from './SearchButton'
import { ItemListController } from '@/Controllers/ItemList/ItemListController'
type Props = {
application: WebApplication
@@ -19,9 +21,11 @@ type Props = {
addButtonLabel: string
addNewItem: () => void
isFilesSmartView: boolean
isFilesTableViewEnabled: boolean
optionsSubtitle?: string
selectedTag: AnyTag
filesController: FilesController
itemListController: ItemListController
}
const ContentListHeader = ({
@@ -31,9 +35,11 @@ const ContentListHeader = ({
addButtonLabel,
addNewItem,
isFilesSmartView,
isFilesTableViewEnabled,
optionsSubtitle,
selectedTag,
filesController,
itemListController,
}: Props) => {
const displayOptionsContainerRef = useRef<HTMLDivElement>(null)
const displayOptionsButtonRef = useRef<HTMLButtonElement>(null)
@@ -98,6 +104,14 @@ const ContentListHeader = ({
)
}, [addButtonLabel, addNewItem, filesController, isDailyEntry, isFilesSmartView])
const SearchBarButton = useMemo(() => {
if (!isFilesSmartView || !isFilesTableViewEnabled) {
return null
}
return <SearchButton itemListController={itemListController} />
}, [isFilesSmartView, isFilesTableViewEnabled, itemListController])
const FolderName = useMemo(() => {
return (
<div className="flex min-w-0 flex-grow flex-col break-words pt-1 lg:pt-0">
@@ -125,13 +139,14 @@ const ContentListHeader = ({
<div className={'flex w-full justify-between md:flex'}>
<NavigationMenuButton />
{FolderName}
<div className="flex">
<div className="flex items-center gap-3">
{SearchBarButton}
{OptionsMenu}
{AddButton}
</div>
</div>
)
}, [OptionsMenu, AddButton, FolderName])
}, [FolderName, SearchBarButton, OptionsMenu, AddButton])
const TabletLayout = useMemo(() => {
return (
@@ -5,6 +5,7 @@ import {
isSmartView,
isSystemView,
PrefKey,
SystemViewId,
TagMutator,
TagPreferences,
VectorIconNameOrEmoji,
@@ -23,6 +24,7 @@ import NoSubscriptionBanner from '@/Components/NoSubscriptionBanner/NoSubscripti
import MenuRadioButtonItem from '@/Components/Menu/MenuRadioButtonItem'
import MenuSwitchButtonItem from '@/Components/Menu/MenuSwitchButtonItem'
import { Pill } from '@/Components/Preferences/PreferencesComponents/Content'
import { featureTrunkEnabled, FeatureTrunkName } from '@/FeatureTrunk'
const DailyEntryModeEnabled = true
@@ -201,6 +203,9 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
)
}
const isFilesTableViewEnabled = featureTrunkEnabled(FeatureTrunkName.FilesTableView)
const shouldHideNonApplicableOptions = isFilesTableViewEnabled && selectedTag?.uuid === SystemViewId.Files
return (
<Menu className="text-sm" a11yLabel="Notes list options menu" isOpen={isOpen}>
<div className="my-1 px-3 text-base font-semibold uppercase text-text lg:text-xs">Preferences for</div>
@@ -283,76 +288,80 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
) : null}
</div>
</MenuRadioButtonItem>
<MenuItemSeparator />
<div className="px-3 py-1 text-base font-semibold uppercase text-text lg:text-xs">View</div>
{!isFilesSmartView && (
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideNotePreview}
onChange={toggleHidePreview}
>
<div className="max-w-3/4 flex flex-col">Show note preview</div>
</MenuSwitchButtonItem>
{!shouldHideNonApplicableOptions && (
<>
<MenuItemSeparator />
<div className="px-3 py-1 text-base font-semibold uppercase text-text lg:text-xs">View</div>
{!isFilesSmartView && (
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideNotePreview}
onChange={toggleHidePreview}
>
<div className="max-w-3/4 flex flex-col">Show note preview</div>
</MenuSwitchButtonItem>
)}
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideDate}
onChange={toggleHideDate}
>
Show date
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideTags}
onChange={toggleHideTags}
>
Show tags
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideEditorIcon}
onChange={toggleEditorIcon}
>
Show icon
</MenuSwitchButtonItem>
<MenuItemSeparator />
<div className="px-3 py-1 text-base font-semibold uppercase text-text lg:text-xs">Other</div>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hidePinned}
onChange={toggleHidePinned}
>
Show pinned
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideProtected}
onChange={toggleHideProtected}
>
Show protected
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={Boolean(preferences.showArchived)}
onChange={toggleShowArchived}
>
Show archived
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={Boolean(preferences.showTrashed)}
onChange={toggleShowTrashed}
>
Show trashed
</MenuSwitchButtonItem>
</>
)}
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideDate}
onChange={toggleHideDate}
>
Show date
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideTags}
onChange={toggleHideTags}
>
Show tags
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideEditorIcon}
onChange={toggleEditorIcon}
>
Show icon
</MenuSwitchButtonItem>
<MenuItemSeparator />
<div className="px-3 py-1 text-base font-semibold uppercase text-text lg:text-xs">Other</div>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hidePinned}
onChange={toggleHidePinned}
>
Show pinned
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={!preferences.hideProtected}
onChange={toggleHideProtected}
>
Show protected
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={Boolean(preferences.showArchived)}
onChange={toggleShowArchived}
>
Show archived
</MenuSwitchButtonItem>
<MenuSwitchButtonItem
disabled={controlsDisabled}
className="py-1 hover:bg-contrast focus:bg-info-backdrop"
checked={Boolean(preferences.showTrashed)}
onChange={toggleShowTrashed}
>
Show trashed
</MenuSwitchButtonItem>
{currentMode === 'tag' && DailyEntryModeEnabled && (
<>
@@ -376,15 +385,18 @@ const DisplayOptionsMenu: FunctionComponent<DisplayOptionsMenuProps> = ({
</>
)}
<MenuItemSeparator />
<NewNotePreferences
disabled={controlsDisabled}
application={application}
selectedTag={selectedTag}
mode={currentMode}
changePreferencesCallback={changePreferences}
/>
{!shouldHideNonApplicableOptions && (
<>
<MenuItemSeparator />
<NewNotePreferences
disabled={controlsDisabled}
application={application}
selectedTag={selectedTag}
mode={currentMode}
changePreferencesCallback={changePreferences}
/>
</>
)}
</Menu>
)
}
@@ -0,0 +1,53 @@
import RoundIconButton from '@/Components/Button/RoundIconButton'
import ClearInputButton from '@/Components/ClearInputButton/ClearInputButton'
import Icon from '@/Components/Icon/Icon'
import DecoratedInput from '@/Components/Input/DecoratedInput'
import { ElementIds } from '@/Constants/ElementIDs'
import { ItemListController } from '@/Controllers/ItemList/ItemListController'
import { observer } from 'mobx-react-lite'
import { useState } from 'react'
type Props = {
itemListController: ItemListController
}
const SearchButton = ({ itemListController }: Props) => {
const { noteFilterText, setNoteFilterText, clearFilterText } = itemListController
const [isSearchBarVisible, setIsSearchBarVisible] = useState(false)
return (
<>
{isSearchBarVisible && (
<DecoratedInput
autocomplete={false}
id={ElementIds.SearchBar}
className={{
container: 'px-1',
input: 'text-base placeholder:text-passive-0 lg:text-sm',
}}
placeholder={'Search...'}
value={noteFilterText}
ref={(node) => {
if (node && document.activeElement !== node) {
node.focus()
}
}}
onChange={(query) => setNoteFilterText(query)}
left={[<Icon type="search" className="mr-1 h-4.5 w-4.5 flex-shrink-0 text-passive-1" />]}
right={[noteFilterText && <ClearInputButton onClick={clearFilterText} />]}
roundedFull
/>
)}
<RoundIconButton
onClick={() => {
setIsSearchBarVisible(!isSearchBarVisible)
}}
icon={isSearchBarVisible ? 'close' : 'search'}
label="Display options menu"
/>
</>
)
}
export default observer(SearchButton)
@@ -12,10 +12,17 @@ type Props = {
}
hasFiles?: boolean
hasBorder?: boolean
isFileBackedUp?: boolean
className?: string
}
const ListItemFlagIcons: FunctionComponent<Props> = ({ item, hasFiles = false, hasBorder = true, className }) => {
const ListItemFlagIcons: FunctionComponent<Props> = ({
item,
hasFiles = false,
hasBorder = true,
isFileBackedUp = false,
className,
}) => {
return (
<div className={`flex items-start ${hasBorder && 'border-b border-solid border-border'} ${className} pl-0`}>
{item.locked && (
@@ -48,6 +55,11 @@ const ListItemFlagIcons: FunctionComponent<Props> = ({ item, hasFiles = false, h
<Icon ariaLabel="Starred" type="star-filled" className="text-warning" size="medium" />
</span>
)}
{isFileBackedUp && (
<span className="ml-1.5 flex items-center" title="File is backed up locally">
<Icon ariaLabel="File is backed up locally" type="check-circle" className="text-info" size="medium" />
</span>
)}
</div>
)
}
@@ -13,6 +13,7 @@ type Props = {
const FileContextMenu: FunctionComponent<Props> = observer(({ filesController, selectionController }) => {
const { showFileContextMenu, setShowFileContextMenu, fileContextMenuLocation } = filesController
const { selectedFiles } = selectionController
return (
<Popover
@@ -25,7 +26,7 @@ const FileContextMenu: FunctionComponent<Props> = observer(({ filesController, s
<Menu a11yLabel="File context menu" isOpen={showFileContextMenu}>
<FileMenuOptions
filesController={filesController}
selectionController={selectionController}
selectedFiles={selectedFiles}
closeMenu={() => setShowFileContextMenu(false)}
shouldShowRenameOption={false}
shouldShowAttachOption={false}
@@ -1,9 +1,8 @@
import { FunctionComponent, useCallback, useMemo } from 'react'
import { PopoverFileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
import { FileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
import Icon from '@/Components/Icon/Icon'
import { observer } from 'mobx-react-lite'
import { FilesController } from '@/Controllers/FilesController'
import { SelectedItemsController } from '@/Controllers/SelectedItemsController'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
import { useResponsiveAppPane } from '../Panes/ResponsivePaneProvider'
@@ -11,27 +10,27 @@ import { AppPaneId } from '../Panes/AppPaneMetadata'
import MenuItem from '../Menu/MenuItem'
import { FileContextMenuBackupOption } from './FileContextMenuBackupOption'
import MenuSwitchButtonItem from '../Menu/MenuSwitchButtonItem'
import { FileItem } from '@standardnotes/snjs'
type Props = {
closeMenu: () => void
filesController: FilesController
selectionController: SelectedItemsController
isFileAttachedToNote?: boolean
renameToggleCallback?: (isRenamingFile: boolean) => void
shouldShowRenameOption: boolean
shouldShowAttachOption: boolean
selectedFiles: FileItem[]
}
const FileMenuOptions: FunctionComponent<Props> = ({
closeMenu,
filesController,
selectionController,
isFileAttachedToNote,
renameToggleCallback,
shouldShowRenameOption,
shouldShowAttachOption,
selectedFiles,
}) => {
const { selectedFiles } = selectionController
const { handleFileAction } = filesController
const { toggleAppPane } = useResponsiveAppPane()
@@ -46,7 +45,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
const onDetach = useCallback(() => {
const file = selectedFiles[0]
void handleFileAction({
type: PopoverFileItemActionType.DetachFileToNote,
type: FileItemActionType.DetachFileToNote,
payload: { file },
})
closeMenu()
@@ -55,7 +54,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
const onAttach = useCallback(() => {
const file = selectedFiles[0]
void handleFileAction({
type: PopoverFileItemActionType.AttachFileToNote,
type: FileItemActionType.AttachFileToNote,
payload: { file },
})
closeMenu()
@@ -86,7 +85,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
<MenuSwitchButtonItem
checked={hasProtectedFiles}
onChange={(hasProtectedFiles) => {
void filesController.setProtectionForFiles(hasProtectedFiles, selectionController.selectedFiles)
void filesController.setProtectionForFiles(hasProtectedFiles, selectedFiles)
}}
>
<Icon type="lock" className="mr-2 text-neutral" />
@@ -95,7 +94,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
<HorizontalSeparator classes="my-1" />
<MenuItem
onClick={() => {
void filesController.downloadFiles(selectionController.selectedFiles)
void filesController.downloadFiles(selectedFiles)
}}
>
<Icon type="download" className="mr-2 text-neutral" />
@@ -114,7 +113,7 @@ const FileMenuOptions: FunctionComponent<Props> = ({
<MenuItem
onClick={() => {
closeMenuAndToggleFilesList()
void filesController.deleteFilesPermanently(selectionController.selectedFiles)
void filesController.deleteFilesPermanently(selectedFiles)
}}
>
<Icon type="trash" className="mr-2 text-danger" />
@@ -25,7 +25,7 @@ const FilesOptionsPanel = ({ filesController, selectionController }: Props) => {
<Menu a11yLabel="File options panel" isOpen={isOpen}>
<FileMenuOptions
filesController={filesController}
selectionController={selectionController}
selectedFiles={selectionController.selectedFiles}
closeMenu={() => {
setIsOpen(false)
}}
@@ -23,10 +23,6 @@ const FilePreviewModal: FunctionComponent<Props> = observer(({ application, view
return null
}
if (!application.isAuthorizedToRenderItem(currentFile)) {
return null
}
const [showFileInfoPanel, setShowFileInfoPanel] = useState(false)
const closeButtonRef = useRef<HTMLButtonElement>(null)
@@ -83,7 +83,11 @@ const PreviewComponent: FunctionComponent<Props> = ({
}
if (file.mimeType.startsWith('video/')) {
return <video className="h-full w-full" src={objectUrl} controls autoPlay />
return (
<video className="h-full w-full" controls autoPlay>
<source src={objectUrl} type={file.mimeType} />
</video>
)
}
if (file.mimeType.startsWith('audio/')) {
@@ -0,0 +1,335 @@
import { WebApplication } from '@/Application/Application'
import { PrefDefaults } from '@/Constants/PrefDefaults'
import { FilesController } from '@/Controllers/FilesController'
import { formatDateForContextMenu } from '@/Utils/DateUtils'
import { getIconForFileType } from '@/Utils/Items/Icons/getIconForFileType'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
import {
ContentType,
FileItem,
SortableItem,
PrefKey,
ApplicationEvent,
naturalSort,
FileBackupRecord,
} from '@standardnotes/snjs'
import { useState, useEffect, useCallback, useMemo, useRef } from 'react'
import { FileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
import { getFileIconComponent } from '../FilePreview/getFileIconComponent'
import Popover from '../Popover/Popover'
import Table from '../Table/Table'
import { TableColumn } from '../Table/CommonTypes'
import { useTable } from '../Table/useTable'
import Menu from '../Menu/Menu'
import FileMenuOptions from '../FileContextMenu/FileMenuOptions'
import Icon from '../Icon/Icon'
import { createLinkFromItem } from '@/Utils/Items/Search/createLinkFromItem'
import LinkedItemBubble from '../LinkedItems/LinkedItemBubble'
import LinkedItemsPanel from '../LinkedItems/LinkedItemsPanel'
import { LinkingController } from '@/Controllers/LinkingController'
import { FeaturesController } from '@/Controllers/FeaturesController'
import { MutuallyExclusiveMediaQueryBreakpoints, useMediaQuery } from '@/Hooks/useMediaQuery'
import { useApplication } from '../ApplicationProvider'
const ContextMenuCell = ({ files, filesController }: { files: FileItem[]; filesController: FilesController }) => {
const [contextMenuVisible, setContextMenuVisible] = useState(false)
const anchorElementRef = useRef<HTMLButtonElement>(null)
return (
<>
<button
className="rounded-full border border-border bg-default p-1"
ref={anchorElementRef}
onClick={(event) => {
event.preventDefault()
event.stopPropagation()
setContextMenuVisible((visible) => !visible)
}}
>
<Icon type="more" />
</button>
<Popover
open={contextMenuVisible}
anchorElement={anchorElementRef.current}
togglePopover={() => {
setContextMenuVisible(false)
}}
side="bottom"
align="start"
className="py-2"
>
<Menu a11yLabel="File context menu" isOpen={contextMenuVisible}>
<FileMenuOptions
closeMenu={() => {
setContextMenuVisible(false)
}}
filesController={filesController}
shouldShowRenameOption={false}
shouldShowAttachOption={false}
selectedFiles={files}
/>
</Menu>
</Popover>
</>
)
}
const FileLinksCell = ({
file,
filesController,
linkingController,
featuresController,
}: {
file: FileItem
filesController: FilesController
linkingController: LinkingController
featuresController: FeaturesController
}) => {
const [contextMenuVisible, setContextMenuVisible] = useState(false)
const anchorElementRef = useRef<HTMLButtonElement>(null)
return (
<>
<button
className="rounded-full border border-border bg-default p-1"
ref={anchorElementRef}
onClick={(event) => {
event.preventDefault()
event.stopPropagation()
setContextMenuVisible((visible) => !visible)
}}
>
<Icon type="link" />
</button>
<Popover
open={contextMenuVisible}
anchorElement={anchorElementRef.current}
togglePopover={() => {
setContextMenuVisible(false)
}}
side="bottom"
align="start"
className="py-2"
>
<LinkedItemsPanel
linkingController={linkingController}
filesController={filesController}
featuresController={featuresController}
isOpen={contextMenuVisible}
item={file}
/>
</Popover>
</>
)
}
const FileNameCell = ({ file }: { file: FileItem }) => {
const application = useApplication()
const [backupInfo, setBackupInfo] = useState<FileBackupRecord | undefined>(undefined)
useEffect(() => {
void application.fileBackups?.getFileBackupInfo(file).then(setBackupInfo)
}, [application, file])
return (
<div className="flex items-center gap-3 whitespace-normal">
<span className="relative">
{getFileIconComponent(getIconForFileType(file.mimeType), 'w-6 h-6 flex-shrink-0')}
{backupInfo && (
<div
className="absolute bottom-1 right-1 translate-x-1/2 translate-y-1/2 rounded-full bg-default text-success"
title="File is backed up locally"
>
<Icon size="small" type="check-circle-filled" />
</div>
)}
</span>
<span className="overflow-hidden text-ellipsis whitespace-nowrap text-sm font-medium">{file.title}</span>
{file.protected && (
<span className="flex items-center" title="File is protected">
<Icon ariaLabel="File is protected" type="lock-filled" className="h-3.5 w-3.5 text-passive-1" size="custom" />
</span>
)}
</div>
)
}
type Props = {
application: WebApplication
filesController: FilesController
featuresController: FeaturesController
linkingController: LinkingController
}
const FilesTableView = ({ application, filesController, featuresController, linkingController }: Props) => {
const files = application.items
.getDisplayableNotesAndFiles()
.filter((item) => item.content_type === ContentType.File) as FileItem[]
const [sortBy, setSortBy] = useState<keyof SortableItem>(
application.getPreference(PrefKey.SortNotesBy, PrefDefaults[PrefKey.SortNotesBy]),
)
const [sortReversed, setSortReversed] = useState(
application.getPreference(PrefKey.SortNotesReverse, PrefDefaults[PrefKey.SortNotesReverse]),
)
useEffect(() => {
return application.addEventObserver(async (event) => {
if (event === ApplicationEvent.PreferencesChanged) {
setSortBy(application.getPreference(PrefKey.SortNotesBy, PrefDefaults[PrefKey.SortNotesBy]))
setSortReversed(application.getPreference(PrefKey.SortNotesReverse, PrefDefaults[PrefKey.SortNotesReverse]))
}
})
}, [application])
const onSortChange = useCallback(
async (sortBy: keyof SortableItem, sortReversed: boolean) => {
await application.setPreference(PrefKey.SortNotesBy, sortBy)
await application.setPreference(PrefKey.SortNotesReverse, sortReversed)
},
[application],
)
const [contextMenuFile, setContextMenuFile] = useState<FileItem | undefined>(undefined)
const [contextMenuPosition, setContextMenuPosition] = useState<{ x: number; y: number } | undefined>(undefined)
const isSmallBreakpoint = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.sm)
const isMediumBreakpoint = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.md)
const isLargeBreakpoint = useMediaQuery(MutuallyExclusiveMediaQueryBreakpoints.lg)
const columnDefs: TableColumn<FileItem>[] = useMemo(
() => [
{
name: 'Name',
sortBy: 'title',
cell: (file) => <FileNameCell file={file} />,
},
{
name: 'Upload date',
sortBy: 'created_at',
cell: (file) => {
return formatDateForContextMenu(file.created_at)
},
hidden: isSmallBreakpoint,
},
{
name: 'Size',
cell: (file) => {
return formatSizeToReadableString(file.decryptedSize)
},
hidden: isSmallBreakpoint,
},
{
name: 'Attached to',
hidden: isSmallBreakpoint || isMediumBreakpoint || isLargeBreakpoint,
cell: (file) => {
const links = [
...naturalSort(application.items.referencesForItem(file), 'title').map((item) =>
createLinkFromItem(item, 'linked'),
),
...naturalSort(application.items.itemsReferencingItem(file), 'title').map((item) =>
createLinkFromItem(item, 'linked-by'),
),
...application.items.getSortedTagsForItem(file).map((item) => createLinkFromItem(item, 'linked')),
]
if (!links.length) {
return null
}
return (
<div className="flex items-center gap-2">
<LinkedItemBubble
className="overflow-hidden"
link={links[0]}
key={links[0].id}
unlinkItem={async (itemToUnlink) => {
void application.items.unlinkItems(file, itemToUnlink)
}}
isBidirectional={false}
/>
{links.length > 1 && <span>and {links.length - 1} more...</span>}
</div>
)
},
},
],
[application.items, isLargeBreakpoint, isMediumBreakpoint, isSmallBreakpoint],
)
const getRowId = useCallback((file: FileItem) => file.uuid, [])
const table = useTable({
data: files,
sortBy,
sortReversed,
onSortChange,
getRowId,
columns: columnDefs,
enableRowSelection: true,
enableMultipleRowSelection: true,
onRowDoubleClick(file) {
void filesController.handleFileAction({
type: FileItemActionType.PreviewFile,
payload: {
file,
otherFiles: files,
},
})
},
onRowContextMenu(x, y, file) {
setContextMenuPosition({ x, y })
setContextMenuFile(file)
},
rowActions: (file) => {
return (
<div className="flex items-center gap-2">
<FileLinksCell
file={file}
filesController={filesController}
featuresController={featuresController}
linkingController={linkingController}
/>
<ContextMenuCell files={[file]} filesController={filesController} />
</div>
)
},
selectionActions: (fileIds) => (
<ContextMenuCell files={files.filter((file) => fileIds.includes(file.uuid))} filesController={filesController} />
),
showSelectionActions: true,
})
return (
<>
<Table table={table} />
{contextMenuPosition && contextMenuFile && (
<Popover
open={true}
anchorPoint={contextMenuPosition}
togglePopover={() => {
setContextMenuPosition(undefined)
setContextMenuFile(undefined)
}}
side="bottom"
align="start"
className="py-2"
>
<Menu a11yLabel="File context menu" isOpen={true}>
<FileMenuOptions
closeMenu={() => {
setContextMenuPosition(undefined)
setContextMenuFile(undefined)
}}
filesController={filesController}
shouldShowRenameOption={false}
shouldShowAttachOption={false}
selectedFiles={[contextMenuFile]}
/>
</Menu>
</Popover>
)}
</>
)
}
export default FilesTableView
@@ -2,17 +2,20 @@ import * as icons from '@standardnotes/icons'
export const IconNameToSvgMapping = {
'account-circle': icons.AccountCircleIcon,
'arrow-down': icons.ArrowDownIcon,
'arrow-left': icons.ArrowLeftIcon,
'arrow-right': icons.ArrowRightIcon,
'arrow-up': icons.ArrowUpIcon,
'arrows-sort-down': icons.ArrowsSortDownIcon,
'arrows-sort-up': icons.ArrowsSortUpIcon,
'attachment-file': icons.AttachmentFileIcon,
'check-bold': icons.CheckBoldIcon,
'check-circle': icons.CheckCircleIcon,
'chevron-up': icons.ChevronUpIcon,
'check-circle-filled': icons.CheckCircleFilledIcon,
'chevron-down': icons.ChevronDownIcon,
'chevron-left': icons.ChevronLeftIcon,
'chevron-right': icons.ChevronRightIcon,
'chevron-up': icons.ChevronUpIcon,
'clear-circle-filled': icons.ClearCircleFilledIcon,
'cloud-off': icons.CloudOffIcon,
'diamond-filled': icons.DiamondFilledIcon,
@@ -26,6 +29,11 @@ export const IconNameToSvgMapping = {
'file-ppt': icons.FilePptIcon,
'file-xls': icons.FileXlsIcon,
'file-zip': icons.FileZipIcon,
'format-align-center': icons.FormatAlignCenterIcon,
'format-align-justify': icons.FormatAlignJustifyIcon,
'format-align-left': icons.FormatAlignLeftIcon,
'format-align-right': icons.FormatAlignRightIcon,
'fullscreen-exit': icons.FullscreenExitIcon,
'hashtag-off': icons.HashtagOffIcon,
'link-off': icons.LinkOffIcon,
'list-bulleted': icons.ListBulleted,
@@ -36,27 +44,22 @@ export const IconNameToSvgMapping = {
'menu-close': icons.MenuCloseIcon,
'menu-variant': icons.MenuVariantIcon,
'notes-filled': icons.NotesFilledIcon,
'open-in': icons.OpenInIcon,
'pencil-filled': icons.PencilFilledIcon,
'pencil-off': icons.PencilOffIcon,
'pin-filled': icons.PinFilledIcon,
'plain-text': icons.PlainTextIcon,
'premium-feature': icons.PremiumFeatureIcon,
'rich-text': icons.RichTextIcon,
'safe-square': icons.SafeSquareIcon,
'sort-descending': icons.SortDescendingIcon,
'star-circle-filled': icons.StarCircleFilled,
'star-filled': icons.StarFilledIcon,
'star-variant-filled': icons.StarVariantFilledIcon,
'safe-square': icons.SafeSquareIcon,
'trash-filled': icons.TrashFilledIcon,
'trash-sweep': icons.TrashSweepIcon,
'user-add': icons.UserAddIcon,
'user-switch': icons.UserSwitch,
'fullscreen-exit': icons.FullscreenExitIcon,
'format-align-left': icons.FormatAlignLeftIcon,
'format-align-center': icons.FormatAlignCenterIcon,
'format-align-right': icons.FormatAlignRightIcon,
'format-align-justify': icons.FormatAlignJustifyIcon,
drag: icons.DragIcon,
accessibility: icons.AccessibilityIcon,
add: icons.AddIcon,
archive: icons.ArchiveIcon,
@@ -70,6 +73,7 @@ export const IconNameToSvgMapping = {
dashboard: icons.DashboardIcon,
diamond: icons.DiamondIcon,
download: icons.DownloadIcon,
drag: icons.DragIcon,
editor: icons.EditorIcon,
email: icons.EmailIcon,
eye: icons.EyeIcon,
@@ -2,7 +2,7 @@ import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants'
import { FilesController } from '@/Controllers/FilesController'
import { FileItem } from '@standardnotes/snjs'
import { useState } from 'react'
import { PopoverFileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
import { FileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
import { FileContextMenuBackupOption } from '../FileContextMenu/FileContextMenuBackupOption'
import Icon from '../Icon/Icon'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
@@ -24,7 +24,7 @@ const LinkedFileMenuOptions = ({ file, closeMenu, handleFileAction, setIsRenamin
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
void handleFileAction({
type: PopoverFileItemActionType.PreviewFile,
type: FileItemActionType.PreviewFile,
payload: {
file,
otherFiles: [],
@@ -41,7 +41,7 @@ const LinkedFileMenuOptions = ({ file, closeMenu, handleFileAction, setIsRenamin
className="flex w-full cursor-pointer items-center justify-between border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
handleFileAction({
type: PopoverFileItemActionType.ToggleFileProtection,
type: FileItemActionType.ToggleFileProtection,
payload: { file },
callback: (isProtected: boolean) => {
setIsFileProtected(isProtected)
@@ -60,7 +60,7 @@ const LinkedFileMenuOptions = ({ file, closeMenu, handleFileAction, setIsRenamin
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
handleFileAction({
type: PopoverFileItemActionType.DownloadFile,
type: FileItemActionType.DownloadFile,
payload: { file },
}).catch(console.error)
closeMenu()
@@ -83,7 +83,7 @@ const LinkedFileMenuOptions = ({ file, closeMenu, handleFileAction, setIsRenamin
className="flex w-full cursor-pointer items-center border-0 bg-transparent px-3 py-1.5 text-left text-sm text-text hover:bg-contrast hover:text-foreground focus:bg-info-backdrop focus:shadow-none"
onClick={() => {
handleFileAction({
type: PopoverFileItemActionType.DeleteFile,
type: FileItemActionType.DeleteFile,
payload: { file },
}).catch(console.error)
closeMenu()
@@ -11,7 +11,6 @@ import { LinkableItem } from '@/Utils/Items/Search/LinkableItem'
import { ItemLink } from '@/Utils/Items/Search/ItemLink'
import { FOCUS_TAGS_INPUT_COMMAND, keyboardStringForShortcut } from '@standardnotes/ui-services'
import { useCommandService } from '../CommandProvider'
import { useApplication } from '../ApplicationProvider'
import { useItemLinks } from '@/Hooks/useItemLinks'
type Props = {
@@ -19,14 +18,11 @@ type Props = {
}
const LinkedItemBubblesContainer = ({ linkingController }: Props) => {
const application = useApplication()
const activeItem = application.itemControllerGroup.activeItemViewController?.item
const { toggleAppPane } = useResponsiveAppPane()
const commandService = useCommandService()
const { unlinkItemFromSelectedItem: unlinkItem, activateItem } = linkingController
const { activeItem, unlinkItemFromSelectedItem: unlinkItem, activateItem } = linkingController
const { notesLinkedToItem, filesLinkedToItem, tagsLinkedToItem, notesLinkingToItem, filesLinkingToItem } =
useItemLinks(activeItem)
@@ -3,7 +3,6 @@ import { FilesController } from '@/Controllers/FilesController'
import { LinkingController } from '@/Controllers/LinkingController'
import { observer } from 'mobx-react-lite'
import { useRef, useCallback } from 'react'
import { useApplication } from '../ApplicationProvider'
import RoundIconButton from '../Button/RoundIconButton'
import Popover from '../Popover/Popover'
import StyledTooltip from '../StyledTooltip/StyledTooltip'
@@ -17,10 +16,7 @@ type Props = {
}
const LinkedItemsButton = ({ linkingController, filesController, onClickPreprocessing, featuresController }: Props) => {
const application = useApplication()
const activeItem = application.itemControllerGroup.activeItemViewController?.item
const { isLinkingPanelOpen, setIsLinkingPanelOpen } = linkingController
const { activeItem, isLinkingPanelOpen, setIsLinkingPanelOpen } = linkingController
const buttonRef = useRef<HTMLButtonElement>(null)
const toggleMenu = useCallback(async () => {
@@ -13,6 +13,7 @@ import DecoratedInput from '../Input/DecoratedInput'
import LinkedItemSearchResults from './LinkedItemSearchResults'
import { LinkedItemsSectionItem } from './LinkedItemsSectionItem'
import { DecryptedItem } from '@standardnotes/snjs'
import { useItemLinks } from '@/Hooks/useItemLinks'
const LinkedItemsPanel = ({
linkingController,
@@ -27,22 +28,10 @@ const LinkedItemsPanel = ({
isOpen: boolean
item: DecryptedItem
}) => {
const {
getLinkedTagsForItem,
getFilesLinksForItem,
getLinkedNotesForItem,
getNotesLinkingToItem,
linkItems,
unlinkItemFromSelectedItem,
activateItem,
createAndAddNewTag,
isEntitledToNoteLinking,
} = linkingController
const { linkItems, unlinkItems, activateItem, createAndAddNewTag, isEntitledToNoteLinking } = linkingController
const tagsLinkedToItem = getLinkedTagsForItem(item) || []
const { filesLinkedToItem, filesLinkingToItem } = getFilesLinksForItem(item)
const notesLinkedToItem = getLinkedNotesForItem(item) || []
const notesLinkingToItem = getNotesLinkingToItem(item) || []
const { notesLinkedToItem, notesLinkingToItem, filesLinkedToItem, filesLinkingToItem, tagsLinkedToItem } =
useItemLinks(item)
const { entitledToFiles } = featuresController
const application = useApplication()
@@ -128,7 +117,7 @@ const LinkedItemsPanel = ({
key={link.id}
item={link.item}
searchQuery={searchQuery}
unlinkItem={() => unlinkItemFromSelectedItem(link.item)}
unlinkItem={() => unlinkItems(item, link.item)}
activateItem={activateItem}
handleFileAction={filesController.handleFileAction}
/>
@@ -148,7 +137,7 @@ const LinkedItemsPanel = ({
key={link.id}
item={link.item}
searchQuery={searchQuery}
unlinkItem={() => unlinkItemFromSelectedItem(link.item)}
unlinkItem={() => unlinkItems(item, link.item)}
activateItem={activateItem}
handleFileAction={filesController.handleFileAction}
/>
@@ -172,7 +161,7 @@ const LinkedItemsPanel = ({
key={link.id}
item={link.item}
searchQuery={searchQuery}
unlinkItem={() => unlinkItemFromSelectedItem(link.item)}
unlinkItem={() => unlinkItems(item, link.item)}
activateItem={activateItem}
handleFileAction={filesController.handleFileAction}
/>
@@ -191,7 +180,7 @@ const LinkedItemsPanel = ({
key={link.id}
item={link.item}
searchQuery={searchQuery}
unlinkItem={() => unlinkItemFromSelectedItem(link.item)}
unlinkItem={() => unlinkItems(item, link.item)}
activateItem={activateItem}
handleFileAction={filesController.handleFileAction}
/>
@@ -208,7 +197,7 @@ const LinkedItemsPanel = ({
key={link.id}
item={link.item}
searchQuery={searchQuery}
unlinkItem={() => unlinkItemFromSelectedItem(link.item)}
unlinkItem={() => unlinkItems(item, link.item)}
activateItem={activateItem}
handleFileAction={filesController.handleFileAction}
/>
@@ -227,7 +216,7 @@ const LinkedItemsPanel = ({
key={link.id}
item={link.item}
searchQuery={searchQuery}
unlinkItem={() => unlinkItemFromSelectedItem(link.item)}
unlinkItem={() => unlinkItems(item, link.item)}
activateItem={activateItem}
handleFileAction={filesController.handleFileAction}
/>
@@ -9,7 +9,7 @@ import { FileItem } from '@standardnotes/snjs'
import { KeyboardKey } from '@standardnotes/ui-services'
import { useRef, useState } from 'react'
import { useApplication } from '../ApplicationProvider'
import { PopoverFileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
import { FileItemActionType } from '../AttachedFilesPopover/PopoverFileItemAction'
import Icon from '../Icon/Icon'
import MenuItem from '../Menu/MenuItem'
import Popover from '../Popover/Popover'
@@ -46,7 +46,7 @@ export const LinkedItemsSectionItem = ({
return
}
await handleFileAction({
type: PopoverFileItemActionType.RenameFile,
type: FileItemActionType.RenameFile,
payload: {
file: item,
name: name,
@@ -235,10 +235,6 @@ export class NoteViewController implements ItemViewControllerInterface {
const isTemplate = this.isTemplateNote
if (typeof document !== 'undefined' && document.hidden) {
void this.application.alertService.alert(InfoStrings.SavingWhileDocumentHidden)
}
if (isTemplate) {
await this.insertTemplatedNote()
}
@@ -36,8 +36,6 @@ export default function BlockPickerMenuPlugin(): JSX.Element {
minLength: 0,
})
const [popoverOpen, setPopoverOpen] = useState(true)
const options = useMemo(() => {
const indentOutdentOptions = application.isNativeMobileWeb() ? GetIndentOutdentBlocks(editor) : []
@@ -90,7 +88,6 @@ export default function BlockPickerMenuPlugin(): JSX.Element {
nodeToRemove.remove()
}
selectedOption.onSelect(matchingString)
setPopoverOpen(false)
closeMenu()
})
},
@@ -105,12 +102,6 @@ export default function BlockPickerMenuPlugin(): JSX.Element {
onSelectOption={onSelectOption}
triggerFn={checkForTriggerMatch}
options={options}
onClose={() => {
setPopoverOpen(false)
}}
onOpen={() => {
setPopoverOpen(true)
}}
menuRenderFn={(anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => {
if (!anchorElementRef.current || !options.length) {
return null
@@ -120,10 +111,7 @@ export default function BlockPickerMenuPlugin(): JSX.Element {
<Popover
align="start"
anchorElement={anchorElementRef.current}
open={popoverOpen}
togglePopover={() => {
setPopoverOpen((prevValue) => !prevValue)
}}
open={true}
disableMobileFullscreenTakeover={true}
side={isMobileScreen() ? 'top' : 'bottom'}
maxHeight={(mh) => mh / 2}
@@ -31,8 +31,6 @@ export const ItemSelectionPlugin: FunctionComponent<Props> = ({ currentNote }) =
minLength: 0,
})
const [popoverOpen, setPopoverOpen] = useState(true)
const onSelectOption = useCallback(
(selectedOption: ItemOption, nodeToRemove: TextNode | null, closeMenu: () => void, matchingString: string) => {
editor.update(() => {
@@ -40,7 +38,6 @@ export const ItemSelectionPlugin: FunctionComponent<Props> = ({ currentNote }) =
nodeToRemove.remove()
}
selectedOption.options.onSelect(matchingString)
setPopoverOpen(false)
closeMenu()
})
},
@@ -92,12 +89,6 @@ export const ItemSelectionPlugin: FunctionComponent<Props> = ({ currentNote }) =
onSelectOption={onSelectOption}
triggerFn={checkForTriggerMatch}
options={options}
onClose={() => {
setPopoverOpen(false)
}}
onOpen={() => {
setPopoverOpen(true)
}}
menuRenderFn={(anchorElementRef, { selectedIndex, selectOptionAndCleanUp, setHighlightedIndex }) => {
if (!anchorElementRef.current || !options.length) {
return null
@@ -107,10 +98,7 @@ export const ItemSelectionPlugin: FunctionComponent<Props> = ({ currentNote }) =
<Popover
align="start"
anchorElement={anchorElementRef.current}
open={popoverOpen}
togglePopover={() => {
setPopoverOpen((prevValue) => !prevValue)
}}
open={true}
disableMobileFullscreenTakeover={true}
side={isMobileScreen() ? 'top' : 'bottom'}
maxHeight={(mh) => mh / 2}
@@ -28,6 +28,8 @@ export async function animatePaneEntranceTransitionFromOffscreenToTheRight(eleme
await animation.finished
performSafariAnimationFix(element)
animation.finish()
}
@@ -58,3 +60,21 @@ export async function animatePaneExitTransitionOffscreenToTheRight(elementId: st
animation.finish()
}
/**
* Safari has a bug where animations don't properly commit sometimes and a tap on the screen or click anywhere fixes it.
* The workaround here is just to get Safari to recompute the element layout. This issue manifests itself when selecting
* a Daily Notebook tag from navigation whereby two pane animations are simulatensouly triggered (the items panel, then
* the editor panel), causing Safari to get tripped up.
*/
function performSafariAnimationFix(element: HTMLElement): void {
const isSafari = /Safari/.test(navigator.userAgent) || /AppleWebKit/.test(navigator.userAgent)
if (!isSafari) {
return
}
element.style.opacity = '0.999'
setTimeout(() => {
element.style.opacity = '1.0'
}, 0)
}
@@ -303,6 +303,7 @@ const PanesSystemComponent = () => {
selectionController={viewControllerManager.selectionController}
searchOptionsController={viewControllerManager.searchOptionsController}
linkingController={viewControllerManager.linkingController}
featuresController={viewControllerManager.featuresController}
>
{showPanelResizers && listRef && (
<PanelResizer
@@ -75,7 +75,7 @@ const Popover = ({
if (open) {
removeListener = addAndroidBackHandler(() => {
togglePopover()
togglePopover?.()
return true
})
}
@@ -90,7 +90,7 @@ const PositionedPopoverContent = ({
onKeyDown={(event) => {
if (event.key === 'Escape') {
event.stopPropagation()
togglePopover()
togglePopover?.()
if (anchorElement) {
anchorElement.focus()
}

Some files were not shown because too many files have changed in this diff Show More