aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/views/DocumentButtonBar.tsx31
-rw-r--r--src/client/views/GlobalKeyHandler.ts5
-rw-r--r--src/client/views/nodes/DocumentLinksButton.scss34
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx67
-rw-r--r--src/client/views/nodes/DocumentView.scss2
-rw-r--r--src/client/views/nodes/DocumentView.tsx80
6 files changed, 93 insertions, 126 deletions
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index d42ff436f..ce77b7446 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -317,24 +317,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
</Tooltip>
);
}
-
- @computed
- get moreButton() {
- const targetDoc = this.view0?.props.Document;
- return !targetDoc ? null : (
- <Tooltip
- title={
- <>
- <div className="dash-tooltip">{`${SettingsManager.propertiesWidth > 0 ? 'Close' : 'Open'} Properties Panel`}</div>
- </>
- }>
- <div className="documentButtonBar-icon" style={{ color: 'white', cursor: 'e-resize' }} onClick={action(e => (SettingsManager.propertiesWidth = SettingsManager.propertiesWidth > 0 ? 0 : 250))}>
- <FontAwesomeIcon className="documentdecorations-icon" icon="ellipsis-h" />
- </div>
- </Tooltip>
- );
- }
-
@computed
get metadataButton() {
const view0 = this.view0;
@@ -464,6 +446,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
return (
<div className="documentButtonBar">
<div className="documentButtonBar-button">
+ <DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} ShowCount={true} />
+ </div>
+ <div className="documentButtonBar-button">
<DocumentLinksButton View={this.view0} AlwaysOn={true} InMenu={true} StartLink={true} />
</div>
{(DocumentLinksButton.StartLink || Doc.UserDoc()['documentLinksButton-fullMenu']) && DocumentLinksButton.StartLink !== doc ? (
@@ -475,11 +460,8 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
{
Doc.noviceMode ? null : <div className="documentButtonBar-button">{this.templateButton}</div>
/*<div className="documentButtonBar-button">
- {this.metadataButton}
- </div>
- <div className="documentButtonBar-button">
- {this.contextButton}
- </div> */
+ {this.metadataButton}
+ </div> */
}
{!SelectionManager.Views()?.some(v => v.allLinks.length) ? null : <div className="documentButtonBar-button">{this.followLinkButton}</div>}
<div className="documentButtonBar-button">{this.pinButton}</div>
@@ -493,9 +475,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
{this.considerGoogleDocsPull}
</div>
<div className="documentButtonBar-button">{this.menuButton}</div>
- {/* {Doc.noviceMode ? (null) : <div className="documentButtonBar-button">
- {this.moreButton}
- </div>} */}
</div>
);
}
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 8e9c18cf3..c19e6831f 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -151,11 +151,6 @@ export class KeyManager {
SelectionManager.DeselectAll();
} else DocumentDecorations.Instance.onCloseClick(true);
}, 'backspace');
- // const selected = SelectionManager.Views().filter(dv => !dv.topMost);
- // UndoManager.RunInBatch(() => {
- // SelectionManager.DeselectAll();
- // selected.map(dv => !dv.props.Document._stayInCollection && dv.props.removeDocument?.(dv.props.Document));
- // }, "delete");
return { stopPropagation: true, preventDefault: true };
}
break;
diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss
index 0f3eb14bc..6da0b73ba 100644
--- a/src/client/views/nodes/DocumentLinksButton.scss
+++ b/src/client/views/nodes/DocumentLinksButton.scss
@@ -1,8 +1,9 @@
-@import "../global/globalCssVariables.scss";
+@import '../global/globalCssVariables.scss';
.documentLinksButton-wrapper {
transform-origin: top left;
width: 100%;
+ height: 100%;
}
.documentLinksButton-menu {
@@ -21,6 +22,16 @@
position: absolute;
}
+.documentLinksButton-showCount {
+ position: absolute;
+ border-radius: 50%;
+ opacity: 0.9;
+ pointer-events: auto;
+ display: flex;
+ align-items: center;
+ background-color: $light-blue;
+ color: black;
+}
.documentLinksButton,
.documentLinksButton-endLink,
.documentLinksButton-startLink {
@@ -34,6 +45,7 @@
text-transform: uppercase;
letter-spacing: 2px;
font-size: 10px;
+ transform-origin: top left;
transition: transform 0.2s;
text-align: center;
display: flex;
@@ -46,13 +58,10 @@
cursor: pointer;
}
}
-
.documentLinksButton {
background-color: $dark-gray;
color: $white;
font-weight: bold;
- width: 80%;
- height: 80%;
font-size: 100%;
font-family: 'Roboto';
transition: 0.2s ease all;
@@ -61,31 +70,20 @@
background-color: $black;
}
}
-
.documentLinksButton.startLink {
background-color: $medium-blue;
+ width: 75%;
+ height: 75%;
color: $white;
font-weight: bold;
- width: 80%;
- height: 80%;
font-size: 100%;
transition: 0.2s ease all;
-
- &:hover {
- background-color: $black;
- }
}
.documentLinksButton-endLink {
border: $medium-blue 2px dashed;
color: $medium-blue;
background-color: none !important;
- width: 80%;
- height: 80%;
font-size: 100%;
transition: 0.2s ease all;
-
- &:hover {
- background-color: $light-blue;
- }
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 9ffbf8e37..1d455ad08 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.tsx
@@ -4,19 +4,18 @@ import { action, computed, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { Doc, Opt } from '../../../fields/Doc';
import { StrCast } from '../../../fields/Types';
-import { TraceMobx } from '../../../fields/util';
import { emptyFunction, returnFalse, setupMoveUpEvents, StopEvent } from '../../../Utils';
import { DocUtils } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
import { Hypothesis } from '../../util/HypothesisUtils';
import { LinkManager } from '../../util/LinkManager';
import { undoBatch, UndoManager } from '../../util/UndoManager';
-import { Colors } from '../global/globalEnums';
import './DocumentLinksButton.scss';
import { DocumentView } from './DocumentView';
import { LinkDescriptionPopup } from './LinkDescriptionPopup';
import { TaskCompletionBox } from './TaskCompletedBox';
import React = require('react');
+import _ = require('lodash');
const higflyout = require('@hig/flyout');
export const { anchorPoints } = higflyout;
@@ -24,10 +23,12 @@ export const Flyout = higflyout.default;
interface DocumentLinksButtonProps {
View: DocumentView;
- Offset?: (number | undefined)[];
+ Bottom?: boolean;
AlwaysOn?: boolean;
InMenu?: boolean;
+ OnHover?: boolean;
StartLink?: boolean; //whether the link HAS been started (i.e. now needs to be completed)
+ ShowCount?: boolean;
scaling?: () => number; // how uch doc is scaled so that link buttons can invert it
}
@observer
@@ -119,7 +120,6 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
DocumentLinksButton.StartLink = this.props.View.props.Document;
DocumentLinksButton.StartLinkView = this.props.View;
}
- //action(() => Doc.BrushDoc(this.props.View.Document));
}
};
@@ -256,28 +256,32 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
* todo:glr / anh seperate functionality such as onClick onPointerDown of link menu button
*/
@computed get linkButtonInner() {
- const btnDim = '30px';
- const link = <img style={{ width: '22px', height: '16px' }} src={`/assets/${'link.png'}`} />;
+ const btnDim = 30;
const isActive = DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink;
- return !this.props.InMenu ? (
- <div className="documentLinksButton-cont" style={{ left: this.props.Offset?.[0], top: this.props.Offset?.[1], right: this.props.Offset?.[2], bottom: this.props.Offset?.[3] }}>
- <div
- className={'documentLinksButton'}
- onPointerDown={this.onLinkMenuOpen}
- onClick={this.onLinkClick}
- style={{
- backgroundColor: Colors.LIGHT_BLUE,
- color: Colors.BLACK,
- fontSize: '20px',
- width: btnDim,
- height: btnDim,
- }}>
- {Array.from(this.filteredLinks).length}
- </div>
+ const scaling = Math.min(1, this.props.scaling?.() || 1);
+ const showLinkCount = (onHover?: boolean, offset?: boolean) => (
+ <div
+ className="documentLinksButton-showCount"
+ onPointerDown={this.onLinkMenuOpen}
+ style={{
+ fontSize: (onHover ? btnDim / 2 : 20) * scaling,
+ width: (onHover ? btnDim / 2 : btnDim) * scaling,
+ height: (onHover ? btnDim / 2 : btnDim) * scaling,
+ bottom: offset ? 5 * scaling : onHover ? (-btnDim / 2) * scaling : undefined,
+ }}>
+ <span style={{ width: '100%', display: 'inline-block', textAlign: 'center' }}>{Array.from(this.filteredLinks).length}</span>
</div>
+ );
+ return this.props.ShowCount ? (
+ showLinkCount(this.props.OnHover, this.props.Bottom)
) : (
<div className="documentLinksButton-menu">
- {this.props.InMenu && !this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node
+ {this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
+ <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton} onPointerDown={isActive ? StopEvent : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}>
+ <FontAwesomeIcon className="documentdecorations-icon" icon="link" />
+ </div>
+ ) : null}
+ {!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node
<div
className={'documentLinksButton-endLink'}
ref={this._linkButton}
@@ -286,34 +290,25 @@ export class DocumentLinksButton extends React.Component<DocumentLinksButtonProp
<FontAwesomeIcon className="documentdecorations-icon" icon="link" />
</div>
) : null}
- {this.props.InMenu && this.props.StartLink ? ( //if link has been started from current node, then set behavior of link button to deactivate linking when clicked again
- <div className={`documentLinksButton ${isActive ? `startLink` : ``}`} ref={this._linkButton} onPointerDown={isActive ? StopEvent : this.onLinkButtonDown} onClick={isActive ? this.clearLinks : this.onLinkClick}>
- <FontAwesomeIcon className="documentdecorations-icon" icon="link" />
- </div>
- ) : null}
</div>
);
}
render() {
- TraceMobx();
-
const menuTitle = this.props.StartLink ? 'Drag or tap to start link' : 'Tap to complete link';
const buttonTitle = 'Tap to view links; double tap to open link collection';
- const title = this.props.InMenu ? menuTitle : buttonTitle;
+ const title = this.props.ShowCount ? buttonTitle : menuTitle;
//render circular tooltip if it isn't set to invisible and show the number of doc links the node has, and render inner-menu link button for starting/stopping links if currently in menu
return !Array.from(this.filteredLinks).length && !this.props.AlwaysOn ? null : (
<div
className="documentLinksButton-wrapper"
style={{
- transform: `scale(${this.props.scaling?.() || 1})`,
+ position: this.props.InMenu ? 'relative' : 'absolute',
+ top: 0,
+ pointerEvents: 'none',
}}>
- {(this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink)) || (!DocumentLinksButton.LinkEditorDocView && !this.props.InMenu) ? (
- <Tooltip title={<div className="dash-tooltip">{title}</div>}>{this.linkButtonInner}</Tooltip>
- ) : (
- this.linkButtonInner
- )}
+ <Tooltip title={!DocumentLinksButton.LinkEditorDocView ? <div className="dash-tooltip">{title}</div> : <></>}>{this.linkButtonInner}</Tooltip>
</div>
);
}
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index 6cadeec41..5c95177c5 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -209,7 +209,7 @@
.contentFittingDocumentView {
position: relative;
- display: flex;
+ display: block;
width: 100%;
height: 100%;
transition: inherit;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index b5dde211b..50b76896e 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,7 +1,7 @@
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@material-ui/core';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction, trace } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, Opt, StrListCast, WidthSym } from '../../../fields/Doc';
import { Document } from '../../../fields/documentSchemas';
@@ -198,6 +198,7 @@ export interface DocumentViewInternalProps extends DocumentViewProps {
NativeWidth: () => number;
NativeHeight: () => number;
isSelected: (outsideReaction?: boolean) => boolean;
+ isHovering: () => boolean;
select: (ctrlPressed: boolean) => void;
DocumentView: () => DocumentView;
viewPath: () => DocumentView[];
@@ -257,9 +258,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
@computed get borderRounding() {
return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding);
}
- @computed get hideLinkButton() {
- return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton + (this.props.isSelected() ? ':selected' : ''));
- }
@computed get widgetDecorations() {
return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Decorations + (this.props.isSelected() ? ':selected' : ''));
}
@@ -1054,7 +1052,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
? true
: false;
};
- linkButtonInverseScaling = () => (this.props.NativeDimScaling?.() || 1) * this.props.DocumentView().screenToLocalTransform().Scale;
get audioAnnoState() {
return this.dataDoc.audioAnnoState ?? 'stopped';
}
@@ -1066,7 +1063,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
['playing', 'green'],
['stopped', audioAnnosCount ? 'blue' : 'gray'],
]);
- return this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (!this.props.isSelected() && !this._isHovering && this.audioAnnoState !== 'recording') || (!audioAnnosCount && this.audioAnnoState === 'stopped') ? null : (
+ return this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (!this.props.isSelected() && !this.props.isHovering() && this.audioAnnoState !== 'recording') || (!audioAnnosCount && this.audioAnnoState === 'stopped') ? null : (
<Tooltip title={<div>{audioTextAnnos?.lastElement()}</div>}>
<div className="documentView-audioBackground" onPointerDown={this.playAnnotation}>
<FontAwesomeIcon className="documentView-audioFont" style={{ color: audioIconColors.get(StrCast(this.audioAnnoState)) }} icon={!audioAnnosCount ? 'microphone' : 'file-audio'} size="sm" />
@@ -1074,15 +1071,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
</Tooltip>
);
}
- @computed get linkCountView() {
- return this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (!this.props.isSelected() && !this._isHovering) || this.hideLinkButton ? null : (
- <DocumentLinksButton
- View={this.props.DocumentView()}
- scaling={this.linkButtonInverseScaling}
- Offset={[this.topMost ? 0 : !this.props.isSelected() ? -15 : -36, undefined, undefined, this.topMost ? 10 : !this.props.isSelected() ? -15 : -32]}
- />
- );
- }
@computed get contents() {
TraceMobx();
return (
@@ -1119,7 +1107,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
{...this.props}
docViewPath={this.props.viewPath}
thumbShown={this.thumbShown}
- isHovering={this.isHovering}
+ isHovering={this.props.isHovering}
setContentView={this.setContentView}
NativeDimScaling={this.props.NativeDimScaling}
PanelHeight={this.panelHeight}
@@ -1132,7 +1120,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
layoutKey={this.finalLayoutKey}
/>
{this.layoutDoc.hideAllLinks ? null : this.allLinkEndpoints}
- {this.linkCountView}
{this.audioAnnoView}
</div>
);
@@ -1149,16 +1136,13 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
anchorPanelWidth = () => this.props.PanelWidth() || 1;
anchorPanelHeight = () => this.props.PanelHeight() || 1;
anchorStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
+ // prettier-ignore
switch (property) {
- case StyleProp.ShowTitle:
- return '';
- case StyleProp.PointerEvents:
- return 'none';
- case StyleProp.LinkSource:
- return this.props.Document; // pass the LinkSource to the LinkAnchorBox
- default:
- return this.props.styleProvider?.(doc, props, property);
+ case StyleProp.ShowTitle: return '';
+ case StyleProp.PointerEvents: return 'none';
+ case StyleProp.LinkSource: return this.props.Document; // pass the LinkSource to the LinkAnchorBox
}
+ return this.props.styleProvider?.(doc, props, property);
};
// We need to use allrelatedLinks to get not just links to the document as a whole, but links to
// anchors that are not rendered as DocumentViews (marked as 'unrendered' with their 'annotationOn' set to this document). e.g.,
@@ -1360,10 +1344,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
</div>
);
}
- isHovering = () => this._isHovering;
- @observable _isHovering = false;
@observable _: string = '';
- _hoverTimeout: any = undefined;
renderDoc = (style: object) => {
TraceMobx();
const thumb = ImageCast(this.layoutDoc['thumb-frozen'], ImageCast(this.layoutDoc.thumb))?.url?.href.replace('.png', '_m.png');
@@ -1374,17 +1355,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
<div
className={`documentView-node${this.topMost ? '-topmost' : ''}`}
id={this.props.Document[Id]}
- onPointerEnter={action(() => {
- clearTimeout(this._hoverTimeout);
- this._isHovering = true;
- })}
- onPointerLeave={action(() => {
- clearTimeout(this._hoverTimeout);
- this._hoverTimeout = setTimeout(
- action(() => (this._isHovering = false)),
- 500
- );
- })}
style={{
...style,
background: isButton || thumb ? undefined : this.backgroundColor,
@@ -1535,6 +1505,18 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return this.props.fitWidth?.(this.rootDoc) || this.layoutDoc.fitWidth;
}
+ @computed get hideLinkButton() {
+ return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HideLinkButton + (this.isSelected() ? ':selected' : ''));
+ }
+ linkButtonInverseScaling = () => (this.props.NativeDimScaling?.() || 1) * this.screenToLocalTransform().Scale;
+
+ @computed get linkCountView() {
+ return (this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (this.isSelected() && this.props.renderDepth) || !this._isHovering || this.hideLinkButton) &&
+ DocumentLinksButton.LinkEditorDocView?.rootDoc !== this.rootDoc ? null : (
+ <DocumentLinksButton View={this} scaling={this.linkButtonInverseScaling} OnHover={true} Bottom={this.topMost} ShowCount={true} />
+ );
+ }
+
@computed get docViewPath(): DocumentView[] {
return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this];
}
@@ -1680,6 +1662,9 @@ export class DocumentView extends React.Component<DocumentViewProps> {
Object.values(this._disposers).forEach(disposer => disposer?.());
!BoolCast(this.props.Document.dontRegisterView, this.props.dontRegisterView) && DocumentManager.Instance.RemoveView(this);
}
+ _hoverTimeout: any = undefined;
+ isHovering = () => this._isHovering;
+ @observable _isHovering = false;
render() {
TraceMobx();
@@ -1687,7 +1672,19 @@ export class DocumentView extends React.Component<DocumentViewProps> {
const yshift = Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined;
const isButton = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;
return (
- <div className="contentFittingDocumentView">
+ <div
+ className="contentFittingDocumentView"
+ onPointerEnter={action(() => {
+ clearTimeout(this._hoverTimeout);
+ this._isHovering = true;
+ })}
+ onPointerLeave={action(() => {
+ clearTimeout(this._hoverTimeout);
+ this._hoverTimeout = setTimeout(
+ action(() => (this._isHovering = false)),
+ 500
+ );
+ })}>
{!this.props.Document || !this.props.PanelWidth() ? null : (
<div
className="contentFittingDocumentView-previewDoc"
@@ -1712,12 +1709,15 @@ export class DocumentView extends React.Component<DocumentViewProps> {
NativeDimScaling={this.NativeDimScaling}
isSelected={this.isSelected}
select={this.select}
+ isHovering={this.isHovering}
ScreenToLocalTransform={this.screenToLocalTransform}
focus={this.props.focus || emptyFunction}
ref={action((r: DocumentViewInternal | null) => r && (this.docView = r))}
/>
</div>
)}
+
+ {this.linkCountView}
</div>
);
}