import { IconProp } from '@fortawesome/fontawesome-svg-core'; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Tooltip } from '@material-ui/core'; import { action, computed, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { AclAdmin, AclEdit, DataSym, Doc } from "../../fields/Doc"; import { InkField } from '../../fields/InkField'; import { RichTextField } from '../../fields/RichTextField'; import { Cast, NumCast } from "../../fields/Types"; import { ImageField } from '../../fields/URLField'; import { GetEffectiveAcl } from '../../fields/util'; import { emptyFunction, setupMoveUpEvents } from "../../Utils"; import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils'; import { GooglePhotos } from '../apis/google_docs/GooglePhotosClientUtils'; import { Docs, DocUtils } from '../documents/Documents'; import { DocumentType } from '../documents/DocumentTypes'; import { DragManager } from '../util/DragManager'; import { SelectionManager } from '../util/SelectionManager'; import { SharingManager } from '../util/SharingManager'; import { undoBatch } from '../util/UndoManager'; import { CollectionDockingView, DockedFrameRenderer } from './collections/CollectionDockingView'; import { ParentDocSelector } from './collections/ParentDocumentSelector'; import './collections/ParentDocumentSelector.scss'; import { MetadataEntryMenu } from './MetadataEntryMenu'; import { DocumentView } from './nodes/DocumentView'; import { GoogleRef } from "./nodes/formattedText/FormattedTextBox"; import { PresBox } from './nodes/PresBox'; import './PropertiesButtons.scss'; import { TemplateMenu } from "./TemplateMenu"; import { Template, Templates } from "./Templates"; import React = require("react"); const higflyout = require("@hig/flyout"); export const { anchorPoints } = higflyout; export const Flyout = higflyout.default; const cloud: IconProp = "cloud-upload-alt"; const fetch: IconProp = "sync-alt"; enum UtilityButtonState { Default, OpenRight, OpenExternally } @observer export class PropertiesButtons extends React.Component<{}, {}> { private _pullAnimating = false; private _pushAnimating = false; private _pullColorAnimating = false; @observable private pushIcon: IconProp = "arrow-alt-circle-up"; @observable private pullIcon: IconProp = "arrow-alt-circle-down"; @observable private pullColor: string = "white"; @observable public isAnimatingFetch = false; @observable public isAnimatingPulse = false; @observable private openHover: UtilityButtonState = UtilityButtonState.Default; @observable public static Instance: PropertiesButtons; public static hasPushedHack = false; public static hasPulledHack = false; @computed get selectedDoc() { return SelectionManager.SelectedSchemaDoc() || this.selectedDocumentView?.rootDoc; } @computed get selectedDocumentView() { if (SelectionManager.SelectedDocuments().length) { return SelectionManager.SelectedDocuments()[0]; } else return undefined; } @computed get dataDoc() { return this.selectedDocumentView?.dataDoc; } @computed get onClick() { return this.selectedDoc?.onClickBehavior ? this.selectedDoc?.onClickBehavior : "nothing"; } public startPullOutcome = action((success: boolean) => { if (!this._pullAnimating) { this._pullAnimating = true; this.pullIcon = success ? "check-circle" : "stop-circle"; setTimeout(() => runInAction(() => { this.pullIcon = "arrow-alt-circle-down"; this._pullAnimating = false; }), 1000); } }); public startPushOutcome = action((success: boolean) => { this.isAnimatingPulse = false; if (!this._pushAnimating) { this._pushAnimating = true; this.pushIcon = success ? "check-circle" : "stop-circle"; setTimeout(() => runInAction(() => { this.pushIcon = "arrow-alt-circle-up"; this._pushAnimating = false; }), 1000); } }); public setPullState = action((unchanged: boolean) => { this.isAnimatingFetch = false; if (!this._pullColorAnimating) { this._pullColorAnimating = true; this.pullColor = unchanged ? "lawngreen" : "red"; setTimeout(this.clearPullColor, 1000); } }); private clearPullColor = action(() => { this.pullColor = "white"; this._pullColorAnimating = false; }); @computed get considerGoogleDocsPush() { const targetDoc = this.selectedDoc; const published = targetDoc && Doc.GetProto(targetDoc)[GoogleRef] !== undefined; const animation = this.isAnimatingPulse ? "shadow-pulse 1s linear infinite" : "none"; return !targetDoc ? (null) : {`${published ? "Push" : "Publish"} to Google Docs`}} placement="top">
{ await GoogleAuthenticationManager.Instance.fetchOrGenerateAccessToken(); !published && runInAction(() => this.isAnimatingPulse = true); PropertiesButtons.hasPushedHack = false; targetDoc[Pushes] = NumCast(targetDoc[Pushes]) + 1; }}>
Google
; } @computed get considerGoogleDocsPull() { const targetDoc = this.selectedDoc; const dataDoc = targetDoc && Doc.GetProto(targetDoc); const animation = this.isAnimatingFetch ? "spin 0.5s linear infinite" : "none"; const title = (() => { switch (this.openHover) { default: case UtilityButtonState.Default: return `${!dataDoc?.unchanged ? "Pull from" : "Fetch"} Google Docs`; case UtilityButtonState.OpenRight: return "Open in Right Split"; case UtilityButtonState.OpenExternally: return "Open in new Browser Tab"; } })(); return !targetDoc || !dataDoc || !dataDoc[GoogleRef] ? (null) :
{title}
} placement="top">
{ if (e.altKey) { this.openHover = UtilityButtonState.OpenExternally; } else if (e.shiftKey) { this.openHover = UtilityButtonState.OpenRight; } })} onPointerLeave={action(() => this.openHover = UtilityButtonState.Default)} onClick={async e => { const googleDocUrl = `https://docs.google.com/document/d/${dataDoc[GoogleRef]}/edit`; if (e.shiftKey) { e.preventDefault(); let googleDoc = await Cast(dataDoc.googleDoc, Doc); if (!googleDoc) { const options = { _width: 600, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, UseCors: false }; googleDoc = Docs.Create.WebDocument(googleDocUrl, options); dataDoc.googleDoc = googleDoc; } CollectionDockingView.AddRightSplit(googleDoc); } else if (e.altKey) { e.preventDefault(); window.open(googleDocUrl); } else { this.clearPullColor(); PropertiesButtons.hasPulledHack = false; targetDoc[Pulls] = NumCast(targetDoc[Pulls]) + 1; dataDoc.unchanged && runInAction(() => this.isAnimatingFetch = true); } }}> { switch (this.openHover) { default: case UtilityButtonState.Default: return dataDoc.unchanged === false ? (this.pullIcon as any) : fetch; case UtilityButtonState.OpenRight: return "arrow-alt-circle-right"; case UtilityButtonState.OpenExternally: return "share"; } })()} />
Fetch
; } @computed get metadataButton() { //const view0 = this.view0; if (this.selectedDoc) { return
Show metadata panel
} placement="top">
/* tfs: @bcz This might need to be the data document? */}>
e.stopPropagation()} > {}
Metadata
; } else { return null; } } @computed get templateButton() { const docView = this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined; const templates: Map = new Map(); const views = [this.selectedDocumentView]; Array.from(Object.values(Templates.TemplateList)).map(template => templates.set(template, views.reduce((checked, doc) => checked || doc?.props.Document["_show" + template.Name] ? true : false, false as boolean))); return !docView ? (null) : Customize layout} placement="top">
this._aliasDown = true)} onClose={action(() => this._aliasDown = false)} content={ v).map(v => v as DocumentView)} templates={templates} />}>
Layout
; } @action @undoBatch onLock = () => { const docView = this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined; docView?.toggleLockPosition(); } @computed get lockButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : {`${this.selectedDoc?.lockedPosition ? "Unlock" : "Lock"} " Position"`}} placement="top">
Position
; } @computed get downloadButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : {"Download Document"}} placement="top">
this.selectedDoc && Doc.Zip(this.selectedDoc)}>
downld
; } @computed get deleteButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : Close Document} placement="top">
close
; } @undoBatch @action deleteDocument = () => { const removeDoc = this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView?.props.removeDocument : SelectionManager.SelectedSchemaCollection()?.props.removeDocument; this.selectedDoc && removeDoc?.(this.selectedDoc); SelectionManager.DeselectAll(); } @undoBatch @action setDictation = () => { this.selectedDoc && (this.selectedDoc._showAudio = !this.selectedDoc._showAudio); } @computed get dictationButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : {"Show Dictation Controls"}} placement="top">
Dictate
; } @undoBatch @action setTitle = () => { this.selectedDoc && (this.selectedDoc._showTitle = this.selectedDoc._showTitle === undefined ? "title" : undefined); } @computed get titleButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : {"Show Title Header"}} placement="top">
Title
; } @undoBatch @action setCaption = () => { this.selectedDoc && (this.selectedDoc._showCaption = this.selectedDoc._showCaption === undefined ? "caption" : undefined); } @computed get captionButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : {"Show Caption Footer"}} placement="top">
Caption
; } @undoBatch @action setChrome = () => { this.selectedDoc && (this.selectedDoc._chromeStatus = this.selectedDoc._chromeStatus === "disabled" ? "enabled" : "disabled"); } @computed get chromeButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : {"Show Editing UI"}} placement="top">
Controls
; } @computed get onClickButton() { if (this.selectedDoc) { return
Choose onClick behavior
} placement="top">
e.stopPropagation()} > {}
onclick
; } else { return null; } } @undoBatch @action handleOptionChange = (e: any) => { const value = e.target.value; this.selectedDoc && (this.selectedDoc.onClickBehavior = e.target.value); const docView = this.selectedDocumentView?.props.Document === this.selectedDoc ? this.selectedDocumentView : undefined; if (value === "nothing") { docView?.noOnClick(); } else if (value === "enterPortal") { docView?.noOnClick(); docView?.makeIntoPortal(); } else if (value === "toggleDetail") { docView?.noOnClick(); docView?.toggleDetail(); } else if (value === "linkInPlace") { docView?.noOnClick(); docView?.toggleFollowLink("inPlace", true, false); } else if (value === "linkOnRight") { docView?.noOnClick(); docView?.toggleFollowLink("onRight", false, false); } } @undoBatch @action editOnClickScript = () => { if (this.selectedDoc) { DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick"); } } @computed get onClickFlyout() { return
Edit onClick Script
; } @computed get googlePhotosButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) :
{"Export to Google Photos"}
} placement="top">
this.selectedDoc && GooglePhotos.Export.CollectionToAlbum({ collection: this.selectedDoc }).then(console.log)}> {}
google
; } @computed get clustersButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) :
{this.selectedDoc?._useClusters ? "Stop Showing Clusters" : "Show Clusters"}
} placement="top">
clusters
; } @action @undoBatch changeFitToBox = () => { this.selectedDoc && (this.selectedDoc._fitToBox = !this.selectedDoc._fitToBox); } @action @undoBatch changeClusters = () => { this.selectedDoc && (this.selectedDoc._useClusters = !this.selectedDoc._useClusters); } @computed get fitContentButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) :
{this.selectedDoc?._fitToBox ? "Stop Fitting Content" : "Fit Content"}
} placement="top">
{this.selectedDoc?._fitToBox ? "unfit" : "fit"}
; } @undoBatch @action private makeMask = () => { if (this.selectedDoc) { this.selectedDoc._backgroundColor = "rgba(0,0,0,0.7)"; this.selectedDoc.mixBlendMode = "hard-light"; this.selectedDoc.color = "#9b9b9bff"; this.selectedDoc._stayInCollection = true; this.selectedDoc.isInkMask = true; } } @computed get maskButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) :
Make Mask
} placement="top">
mask
; } @computed get contextButton() { if (this.selectedDoc) { return
Show Context
} placement="top">
{ where === "onRight" ? CollectionDockingView.AddRightSplit(doc) : this.selectedDocumentView?.props.addDocTab(doc, "onRight"); return true; }} />
context
; } else { return false; } } // @computed // get importButton() { // const targetDoc = this.selectedDoc; // return !targetDoc ? (null) :
{"Import a Document"}
}> //
{ // if (this.selectedDocumentView) { // CollectionFreeFormView.importDocument(100, 100); // } // }}> // {} //
//
; // } render() { if (!this.selectedDoc) return (null); const isText = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof RichTextField; const considerPull = isText && this.considerGoogleDocsPull; const considerPush = isText && this.considerGoogleDocsPush; const isImage = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof ImageField; const isInk = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)] instanceof InkField; const isCollection = this.selectedDoc.type === DocumentType.COL ? true : false; const isFreeForm = this.selectedDoc._viewType === "freeform" ? true : false; const hasContext = this.selectedDoc.context ? true : false; const collectionAcl = GetEffectiveAcl(this.selectedDocumentView?.props.ContainingCollectionDoc?.[DataSym]); return
{/*
{this.templateButton}
*/} {/*
{this.metadataButton}
*/}
{this.titleButton}
{this.captionButton}
{this.chromeButton}
{this.lockButton}
{this.dictationButton}
{/* {collectionAcl === AclAdmin || collectionAcl === AclEdit ?
{this.deleteButton}
: (null)} */}
{this.onClickButton}
{this.contextButton}
{this.considerGoogleDocsPush}
{this.considerGoogleDocsPull}
{this.googlePhotosButton}
{/*
{this.importButton}
*/}
{this.clustersButton}
{this.fitContentButton}
{this.maskButton}
; } }