From 70c998562c8560283a7d6b9a1ae78b9207e3720f Mon Sep 17 00:00:00 2001 From: bobzel Date: Mon, 31 Oct 2022 13:26:52 -0400 Subject: cleaning up link count icon to be part of documentLinks view and to appear on tab views that have links. --- src/client/views/DocumentButtonBar.tsx | 31 ++-------- src/client/views/GlobalKeyHandler.ts | 5 -- src/client/views/nodes/DocumentLinksButton.scss | 34 +++++------ src/client/views/nodes/DocumentLinksButton.tsx | 67 ++++++++++----------- src/client/views/nodes/DocumentView.scss | 2 +- src/client/views/nodes/DocumentView.tsx | 80 ++++++++++++------------- 6 files changed, 93 insertions(+), 126 deletions(-) (limited to 'src') 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 ); } - - @computed - get moreButton() { - const targetDoc = this.view0?.props.Document; - return !targetDoc ? null : ( - -
{`${SettingsManager.propertiesWidth > 0 ? 'Close' : 'Open'} Properties Panel`}
- - }> -
(SettingsManager.propertiesWidth = SettingsManager.propertiesWidth > 0 ? 0 : 250))}> - -
-
- ); - } - @computed get metadataButton() { const view0 = this.view0; @@ -463,6 +445,9 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV const considerPush = isText && this.considerGoogleDocsPush; return (
+
+ +
@@ -475,11 +460,8 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV { Doc.noviceMode ? null :
{this.templateButton}
/*
- {this.metadataButton} -
-
- {this.contextButton} -
*/ + {this.metadataButton} +
*/ } {!SelectionManager.Views()?.some(v => v.allLinks.length) ? null :
{this.followLinkButton}
}
{this.pinButton}
@@ -493,9 +475,6 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV {this.considerGoogleDocsPull}
{this.menuButton}
- {/* {Doc.noviceMode ? (null) :
- {this.moreButton} -
} */} ); } 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 Doc.BrushDoc(this.props.View.Document)); } }; @@ -256,28 +256,32 @@ export class DocumentLinksButton extends React.Component; + const btnDim = 30; const isActive = DocumentLinksButton.StartLink === this.props.View.props.Document && this.props.StartLink; - return !this.props.InMenu ? ( -
-
- {Array.from(this.filteredLinks).length} -
+ const scaling = Math.min(1, this.props.scaling?.() || 1); + const showLinkCount = (onHover?: boolean, offset?: boolean) => ( +
+ {Array.from(this.filteredLinks).length}
+ ); + return this.props.ShowCount ? ( + showLinkCount(this.props.OnHover, this.props.Bottom) ) : (
- {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 +
+ +
+ ) : null} + {!this.props.StartLink && DocumentLinksButton.StartLink !== this.props.View.props.Document ? ( //if the origin node is not this node
) : 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 -
- -
- ) : null}
); } 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 : (
- {(this.props.InMenu && (DocumentLinksButton.StartLink || this.props.StartLink)) || (!DocumentLinksButton.LinkEditorDocView && !this.props.InMenu) ? ( - {title}
}>{this.linkButtonInner} - ) : ( - this.linkButtonInner - )} + {title}
: <>}>{this.linkButtonInner} ); } 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 (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{audioTextAnnos?.lastElement()}}>
@@ -1074,15 +1071,6 @@ export class DocumentViewInternal extends DocComponent ); } - @computed get linkCountView() { - return this.props.renderDepth === -1 || SnappingManager.GetIsDragging() || (!this.props.isSelected() && !this._isHovering) || this.hideLinkButton ? null : ( - - ); - } @computed get contents() { TraceMobx(); return ( @@ -1119,7 +1107,7 @@ export class DocumentViewInternal extends DocComponent {this.layoutDoc.hideAllLinks ? null : this.allLinkEndpoints} - {this.linkCountView} {this.audioAnnoView}
); @@ -1149,16 +1136,13 @@ export class DocumentViewInternal extends DocComponent this.props.PanelWidth() || 1; anchorPanelHeight = () => this.props.PanelHeight() || 1; anchorStyleProvider = (doc: Opt, props: Opt, 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 ); } - 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 { - 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 { 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 : ( + + ); + } + @computed get docViewPath(): DocumentView[] { return this.props.docViewPath ? [...this.props.docViewPath(), this] : [this]; } @@ -1680,6 +1662,9 @@ export class DocumentView extends React.Component { 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 { 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 ( -
+
{ + 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 : (
{ 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))} />
)} + + {this.linkCountView}
); } -- cgit v1.2.3-70-g09d2