aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/ContextMenu.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/ContextMenu.tsx')
-rw-r--r--src/client/views/ContextMenu.tsx101
1 files changed, 48 insertions, 53 deletions
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index adefc7e9c..8dcdd80e5 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -1,40 +1,43 @@
-import React = require('react');
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, observable } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
-import './ContextMenu.scss';
-import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextMenuItem';
-import { Utils } from '../../Utils';
+import * as React from 'react';
import { StrCast } from '../../fields/Types';
-import { Doc } from '../../fields/Doc';
import { SettingsManager } from '../util/SettingsManager';
+import './ContextMenu.scss';
+import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextMenuItem';
+import { ObservableReactComponent } from './ObservableReactComponent';
@observer
-export class ContextMenu extends React.Component {
+export class ContextMenu extends ObservableReactComponent<{}> {
static Instance: ContextMenu;
- @observable private _items: Array<ContextMenuProps> = [];
- @observable private _pageX: number = 0;
- @observable private _pageY: number = 0;
- @observable private _display: boolean = false;
- @observable private _searchString: string = '';
- @observable private _showSearch: boolean = false;
+ private _ignoreUp = false;
+ private _reactionDisposer?: IReactionDisposer;
+ private _defaultPrefix: string = '';
+ private _defaultItem: ((name: string) => void) | undefined;
+ private _onDisplay?: () => void = undefined;
+
+ @observable.shallow _items: ContextMenuProps[] = [];
+ @observable _pageX: number = 0;
+ @observable _pageY: number = 0;
+ @observable _display: boolean = false;
+ @observable _searchString: string = '';
+ @observable _showSearch: boolean = false;
// afaik displaymenu can be called before all the items are added to the menu, so can't determine in displayMenu what the height of the menu will be
- @observable private _yRelativeToTop: boolean = true;
- @observable selectedIndex = -1;
+ @observable _yRelativeToTop: boolean = true;
+ @observable _selectedIndex = -1;
- @observable private _width: number = 0;
- @observable private _height: number = 0;
+ @observable _width: number = 0;
+ @observable _height: number = 0;
- @observable private _mouseX: number = -1;
- @observable private _mouseY: number = -1;
- @observable private _shouldDisplay: boolean = false;
- private _ignoreUp = false;
- private _reactionDisposer?: IReactionDisposer;
+ @observable _mouseX: number = -1;
+ @observable _mouseY: number = -1;
+ @observable _shouldDisplay: boolean = false;
- constructor(props: Readonly<{}>) {
+ constructor(props: any) {
super(props);
-
+ makeObservable(this);
ContextMenu.Instance = this;
}
@@ -74,36 +77,27 @@ export class ContextMenu extends React.Component {
this._reactionDisposer?.();
}
- @action
- componentDidMount = () => {
+ componentDidMount() {
document.addEventListener('pointerdown', this.onPointerDown, true);
document.addEventListener('pointerup', this.onPointerUp);
- };
+ }
@action
clearItems() {
- this._items = [];
+ this._items.length = 0;
this._defaultPrefix = '';
this._defaultItem = undefined;
}
- _defaultPrefix: string = '';
- _defaultItem: ((name: string) => void) | undefined;
-
- findByDescription = (target: string, toLowerCase = false) => {
- return this._items.find(menuItem => {
- let reference = menuItem.description;
- toLowerCase && (reference = reference.toLowerCase());
- return reference === target;
- });
- };
+ findByDescription = (target: string, toLowerCase = false) =>
+ this._items.find(menuItem =>
+ (toLowerCase ? menuItem.description.toLowerCase() : menuItem.description) === target); // prettier-ignore
@action
addItem(item: ContextMenuProps) {
- if (this._items.indexOf(item) === -1) {
- this._items.push(item);
- }
+ !this._items.includes(item) && this._items.push(item);
}
+
@action
moveAfter(item: ContextMenuProps, after?: ContextMenuProps) {
const curInd = this._items.findIndex(i => i.description === item.description);
@@ -111,6 +105,7 @@ export class ContextMenu extends React.Component {
const afterInd = after && this.findByDescription(after.description) ? this._items.findIndex(i => i.description === after.description) : this._items.length;
this._items.splice(afterInd, 0, item);
}
+
@action
setDefaultItem(prefix: string, item: (name: string) => void) {
this._defaultPrefix = prefix;
@@ -126,7 +121,6 @@ export class ContextMenu extends React.Component {
return this._pageY + this._height > window.innerHeight - ContextMenu.buffer ? window.innerHeight - ContextMenu.buffer - this._height : Math.max(0, this._pageY);
}
- _onDisplay?: () => void = undefined;
@action
displayMenu = (x: number, y: number, initSearch = '', showSearch = false, onDisplay?: () => void) => {
//maxX and maxY will change if the UI/font size changes, but will work for any amount
@@ -201,7 +195,7 @@ export class ContextMenu extends React.Component {
<div className="contextMenu-description">{value.join(' -> ')}</div>
</div>
) : (
- <ContextMenuItem {...value} key={index + value.description} closeMenu={this.closeMenu} selected={index === this.selectedIndex} />
+ <ContextMenuItem {...value} key={index + value.description} closeMenu={this.closeMenu} selected={index === this._selectedIndex} />
)
);
}
@@ -211,7 +205,7 @@ export class ContextMenu extends React.Component {
}
render() {
- return !this._display ? null : (
+ return (
<div
className="contextMenu-cont"
ref={action((r: any) => {
@@ -221,6 +215,7 @@ export class ContextMenu extends React.Component {
}
})}
style={{
+ display: this._display ? '' : 'none',
left: this.pageX,
...(this._yRelativeToTop ? { top: this.pageY } : { bottom: this.pageY }),
background: SettingsManager.userBackgroundColor,
@@ -242,17 +237,17 @@ export class ContextMenu extends React.Component {
@action
onKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'ArrowDown') {
- if (this.selectedIndex < this.flatItems.length - 1) {
- this.selectedIndex++;
+ if (this._selectedIndex < this.flatItems.length - 1) {
+ this._selectedIndex++;
}
e.preventDefault();
} else if (e.key === 'ArrowUp') {
- if (this.selectedIndex > 0) {
- this.selectedIndex--;
+ if (this._selectedIndex > 0) {
+ this._selectedIndex--;
}
e.preventDefault();
} else if (e.key === 'Enter' || e.key === 'Tab') {
- const item = this.flatItems[this.selectedIndex];
+ const item = this.flatItems[this._selectedIndex];
if (item) {
item.event({ x: this.pageX, y: this.pageY });
} else if (this._searchString.startsWith(this._defaultPrefix)) {
@@ -268,12 +263,12 @@ export class ContextMenu extends React.Component {
onChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this._searchString = e.target.value;
if (!this._searchString) {
- this.selectedIndex = -1;
+ this._selectedIndex = -1;
} else {
- if (this.selectedIndex === -1) {
- this.selectedIndex = 0;
+ if (this._selectedIndex === -1) {
+ this._selectedIndex = 0;
} else {
- this.selectedIndex = Math.min(this.flatItems.length - 1, this.selectedIndex);
+ this._selectedIndex = Math.min(this.flatItems.length - 1, this._selectedIndex);
}
}
};