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 { 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 { 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 { SelectionManager } from '../util/SelectionManager';
import { undoBatch } from '../util/UndoManager';
import { CollectionDockingView } from './collections/CollectionDockingView';
import { GoogleRef } from "./nodes/formattedText/FormattedTextBox";
import './PropertiesButtons.scss';
import React = require("react");
import { CollectionViewType } from './collections/CollectionView';
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.Views().length) {
return SelectionManager.Views()[0];
} else return undefined;
}
@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">
{
e.altKey && (this.openHover = UtilityButtonState.OpenExternally);
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, _fitWidth: true, _nativeWidth: 960, _nativeHeight: 800, isAnnotating: false, useCors: false };
googleDoc = Docs.Create.WebDocument(googleDocUrl, options);
dataDoc.googleDoc = googleDoc;
}
CollectionDockingView.AddSplit(googleDoc, "right");
} 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
;
}
@action @undoBatch
onLock = () => {
SelectionManager.Views().forEach(dv => dv.docView?.toggleLockPosition());
}
@computed
get lockButton() {
const targetDoc = this.selectedDoc;
return !targetDoc ? (null) : {`${this.selectedDoc?.lockedPosition ? "Unlock" : "Lock"} Position`}} placement="top">
;
}
@computed
get downloadButton() {
const targetDoc = this.selectedDoc;
return !targetDoc ? (null) : {"Download Document"}} placement="top">
this.selectedDoc && Doc.Zip(this.selectedDoc)}>
downld
;
}
@undoBatch
@action
setDictation = () => {
SelectionManager.Views().forEach(dv => dv.rootDoc._showAudio = dv.rootDoc._showAudio === !dv.rootDoc._showAudio);
}
@computed
get dictationButton() {
const targetDoc = this.selectedDoc;
return !targetDoc ? (null) : {"Show Dictation Controls"}} placement="top">
;
}
@undoBatch
@action
setTitle = () => {
SelectionManager.Views().forEach(dv => dv.rootDoc._showTitle = dv.rootDoc._showTitle === undefined ? "title" : undefined);
}
@computed
get titleButton() {
const targetDoc = this.selectedDoc;
return !targetDoc ? (null) : {"Show Title Header"}} placement="top">
;
}
@undoBatch
@action
setCaption = () => {
SelectionManager.Views().forEach(dv => dv.rootDoc._showCaption = dv.rootDoc._showCaption === undefined ? "caption" : undefined);
}
@computed
get captionButton() {
const targetDoc = this.selectedDoc;
return !targetDoc ? (null) : {"Show Caption Footer"}} placement="top">
;
}
@undoBatch
@action
setChrome = () => {
SelectionManager.Views().forEach(dv => dv.rootDoc._chromeStatus = dv.rootDoc._chromeStatus === "disabled" ? "enabled" : "disabled");
}
@computed
get chromeButton() {
const targetDoc = this.selectedDoc;
return !targetDoc ? (null) : {"Show Editing UI"}} placement="top">
;
}
@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);
SelectionManager.Views().forEach(dv => {
dv.docView?.noOnClick();
switch (value) {
case "enterPortal": dv.docView?.makeIntoPortal(); break;
case "toggleDetail": dv.docView?.toggleDetail(); break;
case "linkInPlace": dv.docView?.toggleFollowLink("inPlace", true, false); break;
case "linkOnRight": dv.docView?.toggleFollowLink("add:right", false, false); break;
}
});
}
@undoBatch @action
editOnClickScript = () => {
if (this.selectedDoc) {
if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => DocUtils.makeCustomViewClicked(dv.rootDoc, undefined, "onClick"));
else DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, "onClick");
}
}
@computed
get onClickFlyout() {
return
{Doc.UserDoc().noviceMode ? (null) :
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">
;
}
@action @undoBatch
changeFitToBox = () => {
if (this.selectedDoc) {
if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._fitToBox = !dv.rootDoc._fitToBox);
else this.selectedDoc._fitToBox = !this.selectedDoc._fitToBox;
}
}
@action @undoBatch
changeClusters = () => {
if (this.selectedDoc) {
if (SelectionManager.Views().length) SelectionManager.Views().forEach(dv => dv.rootDoc._useClusters = !dv.rootDoc._useClusters);
else 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">
;
}
render() {
if (!this.selectedDoc) return (null);
const layoutField = this.selectedDoc[Doc.LayoutFieldKey(this.selectedDoc)];
const isText = layoutField instanceof RichTextField;
const isImage = layoutField instanceof ImageField;
const isInk = layoutField instanceof InkField;
const isCollection = this.selectedDoc.type === DocumentType.COL;
const isFreeForm = this.selectedDoc._viewType === CollectionViewType.Freeform;
const considerPull = isText && this.considerGoogleDocsPull;
const considerPush = isText && this.considerGoogleDocsPush;
return
{this.titleButton}
{this.captionButton}
{this.chromeButton}
{this.lockButton}
{this.dictationButton}
{this.onClickButton}
{this.considerGoogleDocsPush}
{this.considerGoogleDocsPull}
{this.googlePhotosButton}
{this.clustersButton}
{this.fitContentButton}
{this.maskButton}
;
}
}