diff options
author | geireann <60007097+geireann@users.noreply.github.com> | 2020-07-13 16:18:46 +0800 |
---|---|---|
committer | geireann <60007097+geireann@users.noreply.github.com> | 2020-07-13 16:18:46 +0800 |
commit | ec1f159d60695a3cc89327561f7c60c00a06366d (patch) | |
tree | 836cb7a224f278525ddbdcc57697fef1d2b3cf72 /src | |
parent | c7dd9ba9e953adfb8c117bee3b95528d8d8c7304 (diff) |
highlights, readjusted view, keyboard events
Diffstat (limited to 'src')
-rw-r--r-- | src/client/documents/Documents.ts | 1 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 5 | ||||
-rw-r--r-- | src/client/views/nodes/FieldView.tsx | 1 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.scss | 477 | ||||
-rw-r--r-- | src/client/views/nodes/PresBox.tsx | 611 | ||||
-rw-r--r-- | src/client/views/presentationview/PresElementBox.scss | 29 | ||||
-rw-r--r-- | src/client/views/presentationview/PresElementBox.tsx | 47 |
7 files changed, 949 insertions, 222 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 0e44a46d9..1aa3aef3e 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -131,6 +131,7 @@ export interface DocumentOptions { lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide) activeFrame?: number; // the active frame of a document in a frame base collection presTransition?: number; //the time taken for the transition TO a document + presDuration?: number; //the duration of the slide in presentation view borderRounding?: string; boxShadow?: string; dontRegisterChildViews?: boolean; diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index e961e2e5c..440368a32 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -6,7 +6,7 @@ import { faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTimesCircle, faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight, - faAngleDown, faAngleUp, faSearchPlus + faAngleDown, faAngleUp, faSearchPlus, faPlayCircle, faClock, faRocket } from '@fortawesome/free-solid-svg-icons'; import { ANTIMODEMENU_HEIGHT } from './globalCssVariables.scss'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; @@ -144,7 +144,8 @@ export class MainView extends React.Component { faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt, faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter, faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell, - faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight, faAngleDown, faAngleUp, faSearchPlus); + faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye, faArrowsAlt, faQuoteLeft, faSortAmountDown, faAlignLeft, faAlignCenter, faAlignRight, + faAngleDown, faAngleUp, faSearchPlus, faPlayCircle, faClock, faRocket); this.initEventListeners(); this.initAuthenticationRouters(); } diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index c57738361..b1132ce33 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -45,6 +45,7 @@ export interface FieldViewProps { whenActiveChanged: (isActive: boolean) => void; dontRegisterView?: boolean; focus: (doc: Doc) => void; + presMultiSelect?: (doc: Doc) => void; //added for selecting multiple documents in a presentation ignoreAutoHeight?: boolean; PanelWidth: () => number; PanelHeight: () => number; diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 9c2daf5d3..07e53fa94 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -19,16 +19,11 @@ margin-top: 10px; } - .presBox-highlight { - position: absolute; - top: 0; - height: 0; - width: 100%; - margin-top: 10px; - background-color: #ffe4b3; + .presBox-toolbar { + display: none; } - .presBox-toolbar { + .presBox-toolbar.active { position: relative; display: inline-flex; align-items: center; @@ -43,115 +38,437 @@ letter-spacing: 0; display: flex; align-items: center; + transition: 0.5s; - .toolbar-dropdown { - margin-left: 5px; + @media only screen and (max-width: 400) { + .toolbar-buttonText { + display: none; + } } + } - .toolbar-transitionTools { - display: none; - } + .toolbar-button.active { + color: #AEDDF8; + } - .toolbar-transitionTools.active { - position: absolute; - display: block; - top: 30px; - transform: translate(-10px, 0px); - border-top: solid 3px grey; - background-color: #323232; - width: 105px; - height: max-content; - z-index: 100; - - .toolbar-transitionButtons { - display: block; - - .toolbar-transition { - display: flex; - font-size: 10; - width: 100; - background-color: rgba(0, 0, 0, 0); - min-width: max-content; - - .toolbar-icon { - margin-right: 5px; - } - } + .toolbar-transitionButtons { + display: block; + + .toolbar-transition { + display: flex; + font-size: 10; + width: 100; + background-color: rgba(0, 0, 0, 0); + min-width: max-content; + + .toolbar-icon { + margin-right: 5px; } } } + } + + .toolbar-moreInfo { + position: absolute; + right: 5px; + display: flex; + width: max-content; + height: 25px; + /* background-color: pink; */ + justify-content: center; + transform: rotate(90deg); + align-items: center; + transition: 0.7s ease; - .toolbar-divider { - border-left: 1px solid white; - height: 80%; + .toolbar-moreInfoBall { + width: 4px; + height: 4px; + border-radius: 100%; + background-color: white; + margin: 1px; + position: relative; } } - .presBox-buttons { + .toolbar-moreInfo.active { + transform: rotate(0deg); + } + + .toolbar-divider { + border-left: solid #ffffff70 0.5px; + height: 20px; + } +} + +.dropdown { + font-size: 10; + margin-left: 5px; + color: darkgrey; + transition: 0.5s ease; +} + +.dropdown.active { + transform: rotate(180deg); + color: #AEDDF8; + opacity: 0.8; +} + +.presBox-ribbon { + position: relative; + display: none; + background-color: white; + color: black; + width: 100%; + height: 0; + z-index: 100; + transition: 0.7s; + + .toolbar-slider { position: relative; + -webkit-appearance: none; + transform: rotateY(180deg); + background-color: #40B3D8; + margin-top: 1px; width: 100%; - background: gray; - padding-top: 5px; - padding-bottom: 5px; + max-width: 100px; + height: 2.5px; + left: 0px; + } + + .toolbar-slider:focus { + outline: none; + } + + .toolbar-slider::-webkit-slider-thumb { + -webkit-appearance: none; + background-color: #40B3D8; + border: 1px white solid; + border-radius: 100%; + width: 9px; + height: 9px; + } + + .slider-headers { + position: relative; display: grid; - grid-column-end: 4; - grid-column-start: 1; + justify-content: space-between; + width: 100%; + grid-template-columns: auto auto auto; + grid-template-rows: auto; + font-weight: 100; + margin-top: 5px; + font-size: 8px; + } - .presBox-viewPicker { - height: 25; - position: relative; - display: inline-block; - grid-column: 1/2; - min-width: 15px; + .slider-value { + font-size: 10; + position: relative; + } + + .slider-value.none, + .slider-headers.none, + .toolbar-slider.none { + display: none; + } + + .dropdown-header { + padding-bottom: 10px; + font-weight: 800; + text-align: center; + font-size: 16; + width: 90%; + color: black; + transform: translate(5%, 0px); + border-bottom: solid 2px darkgrey; + } + + + .ribbon-textInput { + border-radius: 2px; + height: 25px; + font-size: 10; + font-weight: 100; + align-self: center; + justify-self: center; + padding-left: 10px; + border: solid 1px black; + width: 100%; + } + + .ribbon-final-box { + align-self: flex-start; + display: grid; + grid-template-rows: auto auto; + padding-left: 10px; + padding-right: 10px; + letter-spacing: normal; + width: max-content; + font-size: 13; + font-weight: 600; + position: relative; + + .selectedList { + display: block; + min-width: 50; + max-width: 120; + height: 70; + overflow-y: scroll; + + .selectedList-items { + font-size: 7; + font-weight: normal; + } } - select { - background: #323232; + + .ribbon-final-button { + position: relative; + font-size: 10; + font-weight: normal; + letter-spacing: normal; + display: flex; + justify-content: center; + align-items: center; + margin-bottom: 5px; + height: 25px; color: white; + width: 100%; + max-width: 120; + padding-left: 10; + padding-right: 10; + border-radius: 10px; + background-color: #979797; } + } - .presBox-button { - margin-right: 2.5%; - margin-left: 2.5%; - height: 25px; - border-radius: 5px; + .ribbon-box { + display: grid; + grid-template-rows: max-content auto; + padding-left: 10px; + padding-right: 10px; + letter-spacing: normal; + width: max-content; + font-weight: 600; + position: relative; + font-size: 13; + border-right: solid 2px darkgrey; + + .ribbon-button { + font-size: 10; + font-weight: 200; + height: 25; + border: solid 1px black; display: flex; + border-radius: 10px; + margin-right: 5px; + width: max-content; + justify-content: center; align-items: center; - background: #323232; - color: white; + padding-right: 10px; + padding-left: 10px; + } + + .ribbon-button.active { + background-color: #5B9FDD; + } + + .ribbon-button:hover { + background-color: lightgrey; + } + + .presBox-dropdown:hover { + border: solid 1px #378AD8; + + .presBox-dropdownOption { + font-size: 10; + display: block; + padding-left: 5px; + margin-top: 3; + margin-bottom: 3; + } + + .presBox-dropdownOption:hover { + position: relative; + background-color: lightgrey; + } + + .presBox-dropdownOption.active { + position: relative; + background-color: #9CE2F8; + } + + .presBox-dropdownOptions { + position: absolute; + top: 19px; + left: -1px; + z-index: 200; + width: 85%; + display: block; + background: #FFFFFF; + border: 0.5px solid #979797; + box-sizing: border-box; + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + } - svg { - margin: auto; + .presBox-dropdownIcon { + color: #378AD8; } } - .collectionViewBaseChrome-viewPicker { - min-width: 50; - width: 5%; - height: 25; + .presBox-dropdown { + display: grid; + grid-template-columns: auto 20%; position: relative; - display: inline-block; + border: solid 1px black; + font-size: 10; + height: 20; + padding-left: 5px; + align-items: center; + margin-top: 5px; + margin-bottom: 5px; + font-weight: 200; + width: 100%; + min-width: max-content; + max-width: 120; + overflow: visible; + + .presBox-dropdownOptions { + display: none; + } + + .presBox-dropdownIcon { + position: relative; + color: black; + align-self: center; + justify-self: center; + } } } +} - .presBox-backward, - .presBox-forward { - width: 25px; - border-radius: 5px; - top: 50%; - position: absolute; +.presBox-ribbon.active { + display: inline-flex; + height: 100px; + padding-top: 5px; + padding-bottom: 5px; + border: solid 1px black; +} + + + +.dropdown-play { + top: 32px; + transform: translate(-28%, 0px); + /* left: 0; */ + display: none; + border-radius: 5px; + width: 100px; + height: 100px; + z-index: 200; + background-color: black; + position: absolute; +} + +.dropdown-play.active { + display: flex; +} + +.presBox-buttons { + position: relative; + width: 100%; + background: gray; + padding-top: 5px; + padding-bottom: 5px; + display: grid; + grid-template-columns: auto auto; + + .presBox-viewPicker { + height: 25; + position: relative; display: inline-block; + grid-column: 1; + border-radius: 5px; + min-width: 15px; + max-width: 100px; } - .presBox-backward { - left: 5; + .presBox-presentPanel { + display: flex; + justify-self: end; + width: 100%; + } - .presBox-forward { - right: 5; + select { + background: #323232; + color: white; + } + + .presBox-button { + margin-right: 2.5px; + margin-left: 2.5px; + height: 25px; + border-radius: 5px; + display: none; + justify-content: center; + align-content: center; + align-items: center; + text-align: center; + letter-spacing: normal; + width: inherit; + background: #323232; + color: white; + } + + .presBox-button.active { + display: flex; + } + + .presBox-button.edit { + display: flex; + max-width: 25px; + } + + .presBox-button.present { + display: flex; + min-width: 100px; + width: 100px; + position: absolute; + right: 0px; + + .present-icon { + margin-right: 7px; + } + } + + + + .collectionViewBaseChrome-viewPicker { + min-width: 50; + width: 5%; + height: 25; + position: relative; + display: inline-block; } } +.presBox-backward, +.presBox-forward { + width: 25px; + border-radius: 5px; + top: 50%; + position: absolute; + display: inline-block; +} + +.presBox-backward { + left: 5; +} + +.presBox-forward { + right: 5; +} + // CSS adjusted for mobile devices @media only screen and (max-device-width: 480px) { .presBox-cont .presBox-buttons { @@ -197,4 +514,4 @@ .select { font-size: 100%; } -} +}
\ No newline at end of file diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx index 736551443..abf97142e 100644 --- a/src/client/views/nodes/PresBox.tsx +++ b/src/client/views/nodes/PresBox.tsx @@ -14,7 +14,7 @@ import { CollectionView, CollectionViewType } from "../collections/CollectionVie import { FieldView, FieldViewProps } from './FieldView'; import "./PresBox.scss"; import { ViewBoxBaseComponent } from "../DocComponent"; -import { makeInterface } from "../../../fields/Schema"; +import { makeInterface, listSpec } from "../../../fields/Schema"; import { Docs } from "../../documents/Documents"; import { PrefetchProxy } from "../../../fields/Proxy"; import { ScriptField } from "../../../fields/ScriptField"; @@ -22,6 +22,8 @@ import { Scripting } from "../../util/Scripting"; import { InkingStroke } from "../InkingStroke"; import { HighlightSpanKind } from "typescript"; import { SearchUtil } from "../../util/SearchUtil"; +import { CollectionFreeFormDocumentView } from "./CollectionFreeFormDocumentView"; +import { child } from "serializr"; type PresBoxSchema = makeInterface<[typeof documentSchema]>; const PresBoxDocument = makeInterface(documentSchema); @@ -29,15 +31,17 @@ const PresBoxDocument = makeInterface(documentSchema); @observer export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>(PresBoxDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresBox, fieldKey); } + static Instance: PresBox; @observable _isChildActive = false; @computed get childDocs() { return DocListCast(this.dataDoc[this.fieldKey]); } @computed get itemIndex() { return NumCast(this.rootDoc._itemIndex); } @computed get presElement() { return Cast(Doc.UserDoc().presElement, Doc, null); } constructor(props: any) { super(props); + PresBox.Instance = this; if (!this.presElement) { // create exactly one presElmentBox template to use by any and all presentations. Doc.UserDoc().presElement = new PrefetchProxy(Docs.Create.PresElementBoxDocument({ - title: "pres element template", backgroundColor: "transparent", _xMargin: 0, _height: 20, isTemplateDoc: true, isTemplateForField: "data" + title: "pres element template", backgroundColor: "transparent", _xMargin: 0, isTemplateDoc: true, isTemplateForField: "data" })); // this script will be called by each presElement to get rendering-specific info that the PresBox knows about but which isn't written to the PresElement // this is a design choice -- we could write this data to the presElements which would require a reaction to keep it up to date, and it would prevent @@ -53,7 +57,14 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.rootDoc.presBox = this.rootDoc; this.rootDoc._forceRenderEngine = "timeline"; this.rootDoc._replacedChrome = "replaced"; + this.layoutDoc.presStatus = "edit"; + document.addEventListener("keydown", this.keyEvents, false); } + + componentWillUnmount() { + document.removeEventListener("keydown", this.keyEvents, false); + } + updateCurrentPresentation = () => Doc.UserDoc().activePresentation = this.rootDoc; @undoBatch @@ -148,7 +159,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> /** * This method makes sure that cursor navigates to the element that * has the option open and last in the group. If not in the group, and it has - * te option open, navigates to that element. + * the option open, navigates to that element. */ navigateToElement = async (curDoc: Doc, fromDocIndex: number) => { this.updateCurrentPresentation(); @@ -203,47 +214,57 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (index >= 0 && index < this.childDocs.length) { this.rootDoc._itemIndex = index; const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null); - if (presTargetDoc.lastFrame !== undefined) { + if (presTargetDoc?.lastFrame !== undefined) { presTargetDoc.currentFrame = 0; } - - if (!this.layoutDoc.presStatus) { - this.layoutDoc.presStatus = true; - this.startPresentation(index); - } - const heights: number[] = []; - this.childDocs.forEach(doc => { - if (doc.presExpandInlineButton) heights.push(155); - else heights.push(58); - }); - let sum: number = 65; - for (let i = 0; i < this.itemIndex; i++) { - sum += heights[i]; - } - const highlight = document.getElementById("presBox-hightlight"); - if (this.itemIndex === 0 && highlight) highlight.style.top = "65"; - else if (highlight) highlight.style.top = sum.toString(); - if (this.childDocs[this.itemIndex].presExpandInlineButton && highlight) highlight.style.height = "156"; - else if (highlight) highlight.style.height = "58"; - console.log(highlight?.style.top); - console.log(highlight?.className); - console.log(sum); + // if (this.layoutDoc.presStatus === "edit") { + // this.layoutDoc.presStatus = true; + // this.startPresentation(index); + // } this.navigateToElement(this.childDocs[index], fromDoc); this.hideIfNotPresented(index); this.showAfterPresented(index); } }); + + @observable _presTimer!: NodeJS.Timeout; + //The function that starts or resets presentaton functionally, depending on status flag. + @action startOrResetPres = () => { this.updateCurrentPresentation(); - if (this.layoutDoc.presStatus) { - this.resetPresentation(); + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + if (this._presTimer && this.layoutDoc.presStatus === "auto") { + clearInterval(this._presTimer); + this.layoutDoc.presStatus = "manual"; } else { - this.layoutDoc.presStatus = true; - this.startPresentation(0); - this.gotoDocument(0, this.itemIndex); + this.layoutDoc.presStatus = "auto"; + // this.startPresentation(0); + // this.gotoDocument(0, this.itemIndex); + this._presTimer = setInterval(() => { + if (this.itemIndex + 1 < this.childDocs.length) this.next(); + else { + clearInterval(this._presTimer); + this.layoutDoc.presStatus = "manual"; + } + }, activeItem.presDuration ? NumCast(activeItem.presDuration) : 2000); + // for (let i = this.itemIndex + 1; i <= this.childDocs.length; i++) { + // if (this.itemIndex + 1 === this.childDocs.length) { + // clearTimeout(this._presTimer); + // this.layoutDoc.presStatus = "manual"; + // } else timer = setTimeout(() => { console.log(i); this.next(); }, i * 2000); + // } + } + + // if (this.layoutDoc.presStatus) { + // this.resetPresentation(); + // } else { + // this.layoutDoc.presStatus = true; + // this.startPresentation(0); + // this.gotoDocument(0, this.itemIndex); + // } } //The function that resets the presentation by removing every action done by it. It also @@ -252,7 +273,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.updateCurrentPresentation(); this.childDocs.forEach(doc => (doc.presentationTargetDoc as Doc).opacity = 1); this.rootDoc._itemIndex = 0; - this.layoutDoc.presStatus = false; + // this.layoutDoc.presStatus = false; } //The function that starts the presentation, also checking if actions should be applied @@ -297,6 +318,39 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> this.updateMinimize(e, this.rootDoc._viewType = viewType); }); + @undoBatch + movementChanged = action((movement: string) => { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + if (movement === 'zoom') { + activeItem.presZoomButton = !activeItem.presZoomButton; + activeItem.presNavButton = false; + } else if (movement === 'nav') { + activeItem.presZoomButton = false; + activeItem.presNavButton = !activeItem.presNavButton; + } else { + activeItem.presZoomButton = false; + activeItem.presNavButton = false; + } + }); + + @undoBatch + visibilityChanged = action((visibility: string) => { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + if (visibility === 'fade') { + activeItem.presFadeButton = !activeItem.presFadeButton; + } else if (visibility === 'hideBefore') { + activeItem.presHideTillShownButton = !activeItem.presHideTillShownButton; + activeItem.presHideAfterButton = false; + } else if (visibility === 'hideAfter') { + activeItem.presHideAfterButton = !activeItem.presHideAfterButton; + activeItem.presHideAfterButton = false; + } else { + activeItem.presHideAfterButton = false; + activeItem.presHideTillShownButton = false; + activeItem.presFadeButton = false; + } + }); + whenActiveChanged = action((isActive: boolean) => this.props.whenActiveChanged(this._isChildActive = isActive)); addDocumentFilter = (doc: Doc | Doc[]) => { const docs = doc instanceof Doc ? [doc] : doc; @@ -308,17 +362,124 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } childLayoutTemplate = () => this.rootDoc._viewType !== CollectionViewType.Stacking ? undefined : this.presElement; removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc); - selectElement = (doc: Doc) => this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex)); getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight panelHeight = () => this.props.PanelHeight() - 20; active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc.isBackground) && (this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false) + // KEYS + @observable _selectedArray: Doc[] = []; + + @computed get listOfSelected() { + const list = this._selectedArray.map((doc: Doc, index: any) => { + return ( + <div className="selectedList-items">{index + 1}. {doc.title}</div> + ); + }); + return list; + } + + //Regular click + @action + selectElement = (doc: Doc) => { + this._selectedArray = []; + this.gotoDocument(this.childDocs.indexOf(doc), NumCast(this.itemIndex)); + this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]); + console.log(this._selectedArray); + } + + //Command click + @action + multiSelect = (doc: Doc) => { + this._selectedArray.push(this.childDocs[this.childDocs.indexOf(doc)]); + console.log(this._selectedArray); + } + + //Shift click + @action + shiftSelect = (doc: Doc) => { + this._selectedArray = []; + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + if (activeItem) { + for (let i = Math.min(this.itemIndex, this.childDocs.indexOf(doc)); i <= Math.max(this.itemIndex, this.childDocs.indexOf(doc)); i++) { + this._selectedArray.push(this.childDocs[i]); + } + } + console.log(this._selectedArray); + } + + + + //Esc click + @action + keyEvents = (e: KeyboardEvent) => { + e.stopPropagation; + // Escape key + if (e.keyCode === 27) { + if (this.layoutDoc.presStatus === "edit") this._selectedArray = []; + else this.layoutDoc.presStatus = "edit"; + // Ctrl-A to select all + } else if ((e.metaKey || e.altKey) && e.keyCode === 65) { + this._selectedArray = this.childDocs; + } + } + + @observable private transitionTools: boolean = false; + @observable private newDocumentTools: boolean = false; + @observable private progressivizeTools: boolean = false; + @observable private moreInfoTools: boolean = false; + @observable private playTools: boolean = false; + // For toggling transition toolbar - @action - toggleTransitionTools = () => this.transitionTools = !this.transitionTools + @action toggleTransitionTools = () => { + this.transitionTools = !this.transitionTools; + this.newDocumentTools = false; + this.progressivizeTools = false; + this.moreInfoTools = false; + this.playTools = false; + } + // For toggling the add new document dropdown + @action toggleNewDocument = () => { + this.newDocumentTools = !this.newDocumentTools; + this.transitionTools = false; + this.progressivizeTools = false; + this.moreInfoTools = false; + this.playTools = false; + } + // For toggling the tools for progressivize + @action toggleProgressivize = () => { + this.progressivizeTools = !this.progressivizeTools; + this.transitionTools = false; + this.newDocumentTools = false; + this.moreInfoTools = false; + this.playTools = false; + } + // For toggling the tools for more info + @action toggleMoreInfo = () => { + this.moreInfoTools = !this.moreInfoTools; + this.transitionTools = false; + this.newDocumentTools = false; + this.progressivizeTools = false; + this.playTools = false; + } + // For toggling the options when the user wants to select play + @action togglePlay = () => { + this.playTools = !this.playTools; + this.transitionTools = false; + this.newDocumentTools = false; + this.progressivizeTools = false; + this.moreInfoTools = false; + } + + @action toggleAllDropdowns() { + this.transitionTools = false; + this.newDocumentTools = false; + this.progressivizeTools = false; + this.moreInfoTools = false; + this.playTools = false; + } @undoBatch @action @@ -330,46 +491,26 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> @undoBatch @action - viewLinks = () => { - const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null); - console.log(SearchUtil.GetContextsOfDocument(presTargetDoc)); - console.log(DocListCast(presTargetDoc.context)); - console.log(DocumentManager.Instance.getAllDocumentViews(presTargetDoc)); + viewLinks = async () => { + let docToJump = this.childDocs[0]; + // console.log(SearchUtil.GetContextsOfDocument(presTargetDoc)); + // console.log(DocListCast(presTargetDoc.context)); + // console.log(DocumentManager.Instance.getAllDocumentViews(presTargetDoc)); + const aliasOf = await DocCastAsync(docToJump.aliasOf); + const srcContext = aliasOf && await DocCastAsync(aliasOf.context); + console.log(srcContext?.title); + const viewType = srcContext?._viewType; + const fit = srcContext?._fitToBox; + if (srcContext) { + srcContext._fitToBox = true; + srcContext._viewType = "freeform"; + } // if (!DocumentManager.Instance.getDocumentView(curPres)) { // CollectionDockingView.AddRightSplit(curPres); // } } - @observable private activeItem = this.itemIndex ? this.childDocs[this.itemIndex] : null; - - - /** - * The function that is called on click to turn zoom option of docs on/off. - */ - @action - onZoomDocumentClick = (e: React.MouseEvent) => { - e.stopPropagation(); - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - activeItem.presZoomButton = !activeItem.presZoomButton; - if (activeItem.presZoomButton) { - activeItem.presNavButton = false; - } - } - - /** - * The function that is called on click to turn navigation option of docs on/off. - */ - @action - onNavigateDocumentClick = (e: React.MouseEvent) => { - e.stopPropagation(); - const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - activeItem.presNavButton = !activeItem.presNavButton; - if (activeItem.presNavButton) { - activeItem.presZoomButton = false; - } - } - /** * The function that is called on click to turn fading document after presented option on/off. * It also makes sure that the option swithches from hide-after to this one, since both @@ -387,21 +528,20 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> } } else { activeItem.presHideAfterButton = false; - if (this.rootDoc.presStatus && targetDoc) { + if (this.rootDoc.presStatus !== "edit" && targetDoc) { targetDoc.opacity = 0.5; } } } - // @computed - // transitionTimer = (doc: Doc) => { - // const slider: HTMLInputElement = document.getElementById("toolbar-slider"); - // // let output = document.getElementById("demo"); - // // if (output && slider) output.innerHTML = slider.value; // Display the default slider value - // const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); - // const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); - // targetDoc.presTransition = slider ? (Number(slider.value) * 1000) : 0.5; - // } + @action + dropdownToggle = (menu: string) => { + console.log('presBox' + menu + 'Dropdown'); + const dropMenu = document.getElementById('presBox' + menu + 'Dropdown'); + console.log(dropMenu); + console.log(dropMenu?.style.display); + if (dropMenu) dropMenu.style.display === 'none' ? dropMenu.style.display = 'block' : dropMenu.style.display = 'none'; + } setTransitionTime = (number: String) => { const timeInMS = Number(number) * 1000; @@ -410,13 +550,249 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> if (targetDoc) targetDoc.presTransition = timeInMS; } + @computed get transitionDropdown() { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + + if (activeItem) { + const targetDoc = Cast(activeItem.presentationTargetDoc, Doc, null); + const transitionSpeed = targetDoc ? String(Number(targetDoc.presTransition) / 1000) : 0.5; + const visibilityTime = targetDoc ? String(Number(targetDoc.presTransition) / 1000) : 0.5; + const thumbLocation = String(-9.48 * Number(transitionSpeed) + 93); + const movement = activeItem.presZoomButton ? 'Zoom' : activeItem.presNavbutton ? 'Navigate' : 'None'; + const visibility = activeItem.presFadeButton ? 'Fade' : activeItem.presHideTillShownButton ? 'Hide till shown' : activeItem.presHideAfter ? 'Hide on exit' : 'None'; + return ( + <div className={`presBox-ribbon ${this.transitionTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + <div className="ribbon-box"> + Movement + <div className="presBox-dropdown" + onPointerDown={e => e.stopPropagation()} + // onClick={() => this.dropdownToggle('Movement')} + > + {movement} + <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2 }} icon={"angle-down"} /> + <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onClick={e => e.stopPropagation()}> + <div className={`presBox-dropdownOption ${!activeItem.presZoomButton && !activeItem.presNavButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('none')}>None</div> + <div className={`presBox-dropdownOption ${activeItem.presZoomButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('zoom')}>Zoom</div> + <div className={`presBox-dropdownOption ${activeItem.presNavButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.movementChanged('nav')}>Navigate</div> + </div> + </div> + <div className={`slider-value ${activeItem.presZoomButton || activeItem.presNavButton ? "" : "none"}`} style={{ left: thumbLocation + '%' }}>{transitionSpeed}s</div> + <input type="range" step="0.1" min="0.1" max="10" value={transitionSpeed} className={`toolbar-slider ${activeItem.presZoomButton || activeItem.presNavButton ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} /> + <div className={`slider-headers ${activeItem.presZoomButton || activeItem.presNavButton ? "" : "none"}`}> + <div className="slider-text">Slow</div> + <div className="slider-text">Medium</div> + <div className="slider-text">Fast</div> + </div> + </div> + <div className="ribbon-box"> + Visibility + <div className="presBox-dropdown" + onPointerDown={e => e.stopPropagation()} + // onClick={() => this.dropdownToggle('Movement')} + > + {visibility} + <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2 }} icon={"angle-down"} /> + <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onClick={e => e.stopPropagation()}> + <div className={`presBox-dropdownOption ${!activeItem.presFadeButton && !activeItem.presHideAfterButton && !activeItem.presHideTillShownButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.visibilityChanged('none')}>None</div> + <div className={`presBox-dropdownOption ${activeItem.presFadeButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.visibilityChanged('fade')}>Fade on exit</div> + <div className={`presBox-dropdownOption ${activeItem.presHideAfterButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.visibilityChanged('hideAfter')}>Hide on exit</div> + <div className={`presBox-dropdownOption ${activeItem.presHideTillShownButton ? "active" : ""}`} onPointerDown={e => e.stopPropagation()} onClick={() => this.visibilityChanged('hideBefore')}>Hidden til presented</div> + </div> + </div> + <div className={`slider-value ${activeItem.presFadeButton ? "" : "none"}`} style={{ left: thumbLocation + '%' }}>{transitionSpeed}s</div> + <input type="range" step="0.1" min="0.1" max="10" value={visibilityTime} className={`toolbar-slider ${activeItem.presFadeButton ? "" : "none"}`} id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => { e.stopPropagation(); this.setTransitionTime(e.target.value); }} /> + <div className={`slider-headers ${activeItem.presFadeButton ? "" : "none"}`}> + <div className="slider-text">Slow</div> + <div className="slider-text">Medium</div> + <div className="slider-text">Fast</div> + </div> + {/* <div title="Fade After" className={`ribbon-button ${activeItem.presFadeButton ? "active" : ""}`} onClick={this.onFadeDocumentAfterPresentedClick}>Fade After</div> */} + {/* <div title="Hide After" className={`ribbon-button ${activeItem.presHideTillShownButton ? "active" : ""}`} onClick={() => console.log("hide before")}>Hide Before</div> */} + {/* <div title="Hide Before" className={`ribbon-button ${activeItem.presHideAfterButton ? "active" : ""}`} onClick={() => console.log("hide after")}>Hide After</div> */} + </div> + <div className="ribbon-box"> + Effects + <div className="presBox-dropdown" + onPointerDown={e => e.stopPropagation()} + // onClick={() => this.dropdownToggle('Movement')} + > + None + <FontAwesomeIcon className='presBox-dropdownIcon' style={{ gridColumn: 2 }} icon={"angle-down"} /> + <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onClick={e => e.stopPropagation()}> + <div className={'presBox-dropdownOption'} onPointerDown={e => e.stopPropagation()}>None</div> + </div> + </div> + </div> + <div className="ribbon-final-box"> + {this._selectedArray.length} selected + <div className="selectedList"> + {this.listOfSelected} + </div> + </div> + <div className="ribbon-final-box"> + <div className="ribbon-final-button"> + Apply to selected + </div> + <div className="ribbon-final-button"> + Apply to all + </div> + </div> + </div> + ); + } + } + + public inputRef = React.createRef<HTMLInputElement>(); + + + createNewSlide = (title: string, type: string) => { + let doc = null; + if (type === "text") { + doc = Docs.Create.TextDocument("", { _nativeWidth: 400, _width: 400, title: title }); + const data = Cast(this.rootDoc.data, listSpec(Doc)); + if (data) data.push(doc); + } else { + doc = Docs.Create.FreeformDocument([], { _nativeWidth: 400, _width: 400, title: title }); + const data = Cast(this.rootDoc.data, listSpec(Doc)); + if (data) data.push(doc); + } + } + + @computed get newDocumentDropdown() { + let type = ""; + let title = ""; + return ( + <div> + <div className={`presBox-ribbon ${this.newDocumentTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + <div className="ribbon-box"> + Slide Title: <br></br> + {/* <div className="dropdown-textInput"> */} + <input className="ribbon-textInput" placeholder="..." type="text" name="fname" ref={this.inputRef} onChange={(e) => { + e.stopPropagation(); + title = e.target.value; + }}></input> + {/* </div> */} + </div> + <div className="ribbon-box"> + Choose type: + <div style={{ display: "flex", alignSelf: "center" }}> + <div title="Text" className={`ribbon-button ${type === "text" ? "active" : ""}`} onClick={() => { type = "text"; }}>Text</div> + <div title="Freeform" className={`ribbon-button ${type === "freeform" ? "active" : ""}`} onClick={() => { type = "freeform"; }}>Freeform</div> + </div> + </div> + <div className="ribbon-final-box"> + <div className="ribbon-final-button" onClick={() => this.createNewSlide(title, type)}> + Create New Slide + </div> + </div> + </div> + </div > + ); + } + + @computed get playDropdown() { + return ( + <div className={`dropdown-play ${this.playTools ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + + </div> + ); + } + + @computed get progressivizeDropdown() { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + if (activeItem) { + return ( + <div> + <div className={`presBox-ribbon ${this.progressivizeTools && this.layoutDoc.presStatus === "edit" ? "active" : ""}`} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}> + <div className="ribbon-box"> + <div title="Progressivize" className={`ribbon-button ${activeItem.presProgressivize ? "active" : ""}`} onClick={this.progressivize}>Progressivize Child Documents</div> + </div> + <div className="ribbon-box"> + Other progressivize features: + <div title="Progressivize" className={"ribbon-button"}>Progressivize Text Bullet Points</div> + <div title="Progressivize" className={"ribbon-button"}>Internal Navigation</div> + </div> + </div> + </div> + ); + } + } + + @action + progressivize = (e: React.MouseEvent) => { + e.stopPropagation(); + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + activeItem.presProgressivize = !activeItem.presProgressivize; + const rootTarget = Cast(activeItem.presentationTargetDoc, Doc, null); + const docs = DocListCast(rootTarget[Doc.LayoutFieldKey(rootTarget)]); + if (this.rootDoc.presProgressivize) { + rootTarget.currentFrame = 0; + CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, true); + rootTarget.lastFrame = docs.length - 1; + } + } + + @computed get moreInfoDropdown() { + return (<div></div>); + + } + + @computed get toolbar() { + const activeItem = Cast(this.childDocs[this.itemIndex], Doc, null); + + if (activeItem) { + return ( + <> + <div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={this.toggleNewDocument}><FontAwesomeIcon icon={"plus"} /> + <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} /> + </div> + <div className="toolbar-divider" /> + <div className="toolbar-button"><FontAwesomeIcon title={"View Links"} icon={"object-group"} onClick={this.toolbarTest} /></div> + <div className="toolbar-button"><FontAwesomeIcon title={"Portal"} icon={"eye"} onClick={this.viewLinks} /></div> + <div className="toolbar-divider" /> + <div className={`toolbar-button ${this.transitionTools ? "active" : ""}`} onClick={this.toggleTransitionTools}> + <FontAwesomeIcon icon={"rocket"} /> + <div className="toolbar-buttonText"> Transitions</div> + <FontAwesomeIcon className={`dropdown ${this.transitionTools ? "active" : ""}`} icon={"angle-down"} /> + </div> + <div className="toolbar-divider" /> + <div className={`toolbar-button ${this.progressivizeTools ? "active" : ""}`} onClick={this.toggleProgressivize}> + <FontAwesomeIcon icon={"tasks"} /> + <div className="toolbar-buttonText"> Progressivize</div> + <FontAwesomeIcon className={`dropdown ${this.progressivizeTools ? "active" : ""}`} icon={"angle-down"} /> + </div> + <div className="toolbar-divider" /> + <div className={`toolbar-button ${this.moreInfoTools ? "active" : ""}`} onClick={this.toggleMoreInfo}> + <div className={`toolbar-moreInfo ${this.moreInfoTools ? "active" : ""}`}> + <div className="toolbar-moreInfoBall" /> + <div className="toolbar-moreInfoBall" /> + <div className="toolbar-moreInfoBall" /> + </div> + </div> + </> + ); + } else { + return ( + <> + <div className="toolbar-button"><FontAwesomeIcon icon={"plus"} onClick={this.toggleNewDocument} /> + <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"angle-down"} /> + </div> + <div className="toolbar-button"> + <FontAwesomeIcon className={`dropdown ${this.newDocumentTools ? "active" : ""}`} icon={"thumbtack"} /> + </div> + <div className="toolbar-button" onClick={this.toggleMoreInfo}> + <div className="toolbar-moreInfo"> + <div className="toolbar-moreInfoBall" /> + <div className="toolbar-moreInfoBall" /> + <div className="toolbar-moreInfoBall" /> + </div> + </div> + </> + ); + } + } render() { - // console.log("render = " + this.layoutDoc.title + " " + this.layoutDoc.presStatus); - // const presOrderedDocs = DocListCast(activeItem.presOrderedDocs); - // if (presOrderedDocs.length != this.childDocs.length || presOrderedDocs.some((pd, i) => pd !== this.childDocs[i])) { - // this.rootDoc.presOrderedDocs = new List<Doc>(this.childDocs.slice()); - // } this.childDocs.slice(); // needed to insure that the childDocs are loaded for looking up fields const mode = StrCast(this.rootDoc._viewType) as CollectionViewType; return <div className="presBox-cont" style={{ minWidth: this.layoutDoc.inOverlay ? 240 : undefined }} > @@ -430,41 +806,33 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Time}>Time</option> <option onPointerDown={e => e.stopPropagation()} value={CollectionViewType.Carousel}>Slides</option> </select> - <div className="presBox-button" title="Back" style={{ gridColumn: 2 }} onClick={this.back}> - <FontAwesomeIcon icon={"arrow-left"} /> - </div> - <div className="presBox-button" title={"Reset Presentation" + this.layoutDoc.presStatus ? "" : " From Start"} style={{ gridColumn: 3 }} onClick={this.startOrResetPres}> - <FontAwesomeIcon icon={this.layoutDoc.presStatus ? "stop" : "play"} /> - </div> - <div className="presBox-button" title="Next" style={{ gridColumn: 4 }} onClick={this.next}> - <FontAwesomeIcon icon={"arrow-right"} /> - </div> - </div> - <div className="presBox-highlight" id="presBox-hightlight" /> - <div className="presBox-toolbar"> - <div className="toolbar-button"><FontAwesomeIcon icon={"plus"} onClick={this.toolbarTest} /></div> - <div className="toolbar-divider" /> - <div className="toolbar-button"><FontAwesomeIcon icon={"plus"} onClick={this.viewLinks} /></div> - <div className="toolbar-button"><FontAwesomeIcon icon={"object-group"} onClick={this.toolbarTest} /></div> - <div className="toolbar-button"><FontAwesomeIcon icon={"eye"} onClick={this.toolbarTest} /></div> - <div className="toolbar-divider" /> - <div className="toolbar-button" onClick={this.toggleTransitionTools}> - Transitions <FontAwesomeIcon className="toolbar-dropdown" icon={"angle-down"} /> - <div className={`toolbar-transitionTools ${this.transitionTools ? "active" : ""}`} onPointerDown={e => e.stopPropagation()}> - <div className="toolbar-transitionButtons"> - <button title="Zoom" className={`toolbar-transition ${this.activeItem?.presZoomButton ? "active" : ""}`} onClick={this.onZoomDocumentClick}><FontAwesomeIcon className="toolbar-icon" icon={"search-plus"} onPointerDown={e => e.stopPropagation()} />Zoom</button> - <button title="Navigate" className={`toolbar-transition ${this.activeItem?.presNavButton ? "active" : ""}`} onClick={this.onNavigateDocumentClick}><FontAwesomeIcon className="toolbar-icon" icon={"location-arrow"} onPointerDown={e => e.stopPropagation()} />Navigate</button> - <button title="Fade After" className={`toolbar-transition ${this.activeItem?.presFadeButton ? "active" : ""}`} onClick={this.onFadeDocumentAfterPresentedClick}><FontAwesomeIcon className="toolbar-icon" icon={"file-download"} onPointerDown={e => e.stopPropagation()} /> Fade After</button> - <input type="range" min="0.1" max="10" defaultValue="0.5" className="toolbar-slider" id="toolbar-slider" onChange={(e: React.ChangeEvent<HTMLInputElement>) => this.setTransitionTime(e.target.value)} /> - {/* <button title="Hide After" className={pbi + (this.rootDoc.presHideAfterButton ? "-selected" : "")} onClick={this.onHideDocumentAfterPresentedClick}><FontAwesomeIcon icon={"file-download"} onPointerDown={e => e.stopPropagation()} /></button> */} - {/* <button title="Hide Before" className={pbi + (this.rootDoc.presHideTillShownButton ? "-selected" : "")} onClick={this.onHideDocumentUntilPressClick}><FontAwesomeIcon icon={"file"} onPointerDown={e => e.stopPropagation()} /></button> - <button title="Group With Up" className={pbi + (this.rootDoc.presGroupButton ? "-selected" : "")} onClick={e => { e.stopPropagation(); this.rootDoc.presGroupButton = !this.rootDoc.presGroupButton; }}><FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} /></button> - <button title="Progressivize" className={pbi + (this.rootDoc.pres ? "-selected" : "")} onClick={this.progressivize}><FontAwesomeIcon icon={"tasks"} onPointerDown={e => e.stopPropagation()} /></button> */} - </div> + <div className="presBox-presentPanel"> + <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title={"Reset Presentation" + this.layoutDoc.presStatus ? "" : " From Start"} style={{ gridColumn: 2 }} onClick={this.startOrResetPres}> + <FontAwesomeIcon icon={"clock"} /> + <FontAwesomeIcon icon={this.layoutDoc.presStatus === "auto" ? "pause" : "play"} /> + <div className="toolbar-divider" /> + <FontAwesomeIcon onClick={e => { e.stopPropagation; this.togglePlay(); }} className="dropdown" icon={"angle-down"} /> + {this.playDropdown} + </div> + <div className={`presBox-button ${this.layoutDoc.presStatus === "edit" ? "present" : ""}`} title="Present" onClick={() => this.layoutDoc.presStatus = "manual"}> + <FontAwesomeIcon className="present-icon" icon={"play-circle"} /> Present + </div> + <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title="Back" onClick={this.back}> + <FontAwesomeIcon icon={"arrow-left"} /> + </div> + <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "active" : ""}`} title="Next" onClick={this.next}> + <FontAwesomeIcon icon={"arrow-right"} /> + </div> + <div className={`presBox-button ${this.layoutDoc.presStatus !== "edit" ? "edit" : ""}`} title="Next" onClick={() => this.layoutDoc.presStatus = "edit"}> + <FontAwesomeIcon icon={"times"} /> </div> </div> - <div className="toolbar-divider" /> </div> + <div className={`presBox-toolbar ${this.layoutDoc.presStatus === "edit" ? "active" : ""}`}> {this.toolbar} </div> + {this.newDocumentDropdown} + {this.moreInfoDropdown} + {this.transitionDropdown} + {this.progressivizeDropdown} <div className="presBox-listCont" > {mode !== CollectionViewType.Invalid ? <CollectionView {...this.props} @@ -474,10 +842,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema> moveDocument={returnFalse} childOpacity={returnOne} childLayoutTemplate={this.childLayoutTemplate} - filterAddDocument={this.addDocumentFilter} + filterAddDocument={returnFalse} removeDocument={returnFalse} dontRegisterView={true} focus={this.selectElement} + presMultiSelect={this.multiSelect} ScreenToLocalTransform={this.getTransform} /> : (null) } @@ -493,3 +862,11 @@ Scripting.addGlobal(function lookupPresBoxField(container: Doc, field: string, d if (field === 'presBox') return container; return undefined; }); + + + + // console.log("render = " + this.layoutDoc.title + " " + this.layoutDoc.presStatus); + // const presOrderedDocs = DocListCast(activeItem.presOrderedDocs); + // if (presOrderedDocs.length != this.childDocs.length || presOrderedDocs.some((pd, i) => pd !== this.childDocs[i])) { + // this.rootDoc.presOrderedDocs = new List<Doc>(this.childDocs.slice()); + // }
\ No newline at end of file diff --git a/src/client/views/presentationview/PresElementBox.scss b/src/client/views/presentationview/PresElementBox.scss index 6d37ede8a..0e58d77a0 100644 --- a/src/client/views/presentationview/PresElementBox.scss +++ b/src/client/views/presentationview/PresElementBox.scss @@ -1,6 +1,9 @@ .presElementBox-item { - display: inline-block; - background-color: #eeeeee; + display: grid; + grid-template-rows: max-content max-content max-content; + background-color: #d0d0d0; + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + position: relative; pointer-events: all; width: 100%; height: 100%; @@ -17,6 +20,15 @@ padding: 0px; padding-bottom: 3px; + .presElementBox-highlight { + position: absolute; + transform: translate(-100px, -6px); + z-index: -1; + width: calc(100% + 200px); + height: calc(100% + 12px); + background-color: #AEDDF8; + } + .documentView-node { position: absolute; z-index: 1; @@ -38,10 +50,9 @@ } .presElementBox-active { - background: gray; color: black; border-radius: 6px; - box-shadow: black 2px 2px 5px; + border: solid 2px #5B9FDD; } .presElementBox-buttons { @@ -88,6 +99,14 @@ white-space: pre; } +.presElementBox-time { + position: relative; + font-size: 8; + font-style: italic; + letter-spacing: normal; + left: 10px; +} + .presElementBox-embedded { position: relative; display: flex; @@ -143,4 +162,4 @@ display: flex; justify-content: center; align-items: center; -} +}
\ No newline at end of file diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx index bca63e94d..f30ee2a5c 100644 --- a/src/client/views/presentationview/PresElementBox.tsx +++ b/src/client/views/presentationview/PresElementBox.tsx @@ -5,7 +5,7 @@ import { Doc, DataSym, DocListCast } from "../../../fields/Doc"; import { documentSchema } from '../../../fields/documentSchemas'; import { Id } from "../../../fields/FieldSymbols"; import { createSchema, makeInterface, listSpec } from '../../../fields/Schema'; -import { Cast, NumCast, BoolCast, ScriptCast } from "../../../fields/Types"; +import { Cast, NumCast, BoolCast, ScriptCast, StrCast } from "../../../fields/Types"; import { emptyFunction, emptyPath, returnFalse, returnTrue, returnOne, returnZero, numberRange } from "../../../Utils"; import { Transform } from "../../util/Transform"; import { CollectionViewType } from '../collections/CollectionView'; @@ -15,6 +15,7 @@ import { FieldView, FieldViewProps } from '../nodes/FieldView'; import "./PresElementBox.scss"; import React = require("react"); import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; +import { PresBox } from "../nodes/PresBox"; export const presSchema = createSchema({ presentationTargetDoc: Doc, @@ -37,19 +38,18 @@ const PresDocument = makeInterface(presSchema, documentSchema); @observer export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDocument>(PresDocument) { public static LayoutString(fieldKey: string) { return FieldView.LayoutString(PresElementBox, fieldKey); } - _heightDisposer: IReactionDisposer | undefined; // these fields are conditionally computed fields on the layout document that take this document as a parameter @computed get indexInPres() { return Number(this.lookupField("indexInPres")); } // the index field is where this document is in the presBox display list (since this value is different for each presentation element, the value can't be stored on the layout template which is used by all display elements) - @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation elemnt template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up - @computed get presStatus() { return BoolCast(this.lookupField("presStatus")); } + @computed get collapsedHeight() { return Number(this.lookupField("presCollapsedHeight")); } // the collapsed height changes depending on the state of the presBox. We could store this on the presentation element template if it's used by only one presentation - but if it's shared by multiple, then this value must be looked up + @computed get presStatus() { return StrCast(this.lookupField("presStatus")); } @computed get itemIndex() { return NumCast(this.lookupField("_itemIndex")); } @computed get presBox() { return Cast(this.lookupField("presBox"), Doc, null); } @computed get targetDoc() { return Cast(this.rootDoc.presentationTargetDoc, Doc, null) || this.rootDoc; } componentDidMount() { this._heightDisposer = reaction(() => [this.rootDoc.presExpandInlineButton, this.collapsedHeight], - params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 200 : 0), { fireImmediately: true }); + params => this.layoutDoc._height = NumCast(params[1]) + (Number(params[0]) ? 100 : 0), { fireImmediately: true }); } componentWillUnmount() { this._heightDisposer?.(); @@ -68,7 +68,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc this.targetDoc.opacity = 1; } } else { - if (this.presStatus && this.indexInPres > this.itemIndex && this.targetDoc) { + if (this.presStatus !== "edit" && this.indexInPres > this.itemIndex && this.targetDoc) { this.targetDoc.opacity = 0; } } @@ -89,7 +89,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc } } else { if (this.rootDoc.presFadeButton) this.rootDoc.presFadeButton = false; - if (this.presStatus && this.indexInPres < this.itemIndex && this.targetDoc) { + if (this.presStatus !== "edit" && this.indexInPres < this.itemIndex && this.targetDoc) { this.targetDoc.opacity = 0; } } @@ -123,7 +123,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc } } else { this.rootDoc.presHideAfterButton = false; - if (this.presStatus && (this.indexInPres < this.itemIndex) && this.targetDoc) { + if (this.presStatus !== "edit" && (this.indexInPres < this.itemIndex) && this.targetDoc) { this.targetDoc.opacity = 0.5; } } @@ -166,14 +166,13 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc @action presExpandDocumentClick = () => { - const highlight = document.getElementById("presBox-hightlight"); this.rootDoc.presExpandInlineButton = !this.rootDoc.presExpandInlineButton; - if (highlight && this.rootDoc.presExpandInlineButton) highlight.style.height = "156"; - else if (highlight && !this.rootDoc.presExpandInlineButton) highlight.style.height = "58"; } - embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight); + embedHeight = () => 100; embedWidth = () => this.props.PanelWidth() - 20; + // embedHeight = () => Math.min(this.props.PanelWidth() - 20, this.props.PanelHeight() - this.collapsedHeight); + // embedWidth = () => this.props.PanelWidth() - 20; /** * The function that is responsible for rendering a preview or not for this * presentation element. @@ -220,7 +219,18 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc return !(this.rootDoc instanceof Doc) || this.targetDoc instanceof Promise ? (null) : ( <div className={className} key={this.props.Document[Id] + this.indexInPres} style={{ outlineWidth: Doc.IsBrushed(this.targetDoc) ? `1px` : "0px", }} - onClick={e => { this.props.focus(this.rootDoc); e.stopPropagation(); }}> + onClick={e => { + if (e.ctrlKey || e.metaKey) { + PresBox.Instance.multiSelect(this.rootDoc); + console.log("cmmd click"); + } else if (e.shiftKey) { + PresBox.Instance.shiftSelect(this.rootDoc); + } else { + this.props.focus(this.rootDoc); e.stopPropagation(); + console.log("normal click"); + } + }} + onPointerDown={e => e.stopPropagation()}> {treecontainer ? (null) : <> <div className="presElementBox-number"> {`${this.indexInPres + 1}.`} @@ -228,6 +238,8 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc <div className="presElementBox-name"> {`${this.targetDoc?.title}`} </div> + <div className="presElementBox-time">{"Transition speed: " + (this.targetDoc?.presTransition) + "ms"}</div> + <div className="presElementBox-time" style={{ display: this.targetDoc.presDuration ? "block" : "none" }}>{"Duration: " + (this.targetDoc?.presDuration) + "ms"}</div> <button title="Close" className="presElementBox-closeIcon" @@ -236,21 +248,20 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc this.props.removeDocument?.(this.rootDoc); e.stopPropagation(); }}> - <FontAwesomeIcon icon={"times"} onPointerDown={e => e.stopPropagation()} /> + <FontAwesomeIcon icon={"trash"} onPointerDown={e => e.stopPropagation()} /> </button> <button title="Expand Inline" className={"presElementBox-expand" + (this.rootDoc.presExpandInlineButton ? "-selected" : "")} onClick={e => { e.stopPropagation(); this.presExpandDocumentClick(); }}> <FontAwesomeIcon icon={(this.rootDoc.presExpandInlineButton ? "angle-up" : "angle-down")} onPointerDown={e => e.stopPropagation()} /> </button> - <br /> </>} + <div className="presElementBox-highlight" style={{ display: PresBox.Instance._selectedArray.includes(this.rootDoc) ? "block" : "none" }} /> <div className="presElementBox-buttons"> - <button title="Zoom" className={pbi + (this.rootDoc.presZoomButton ? "-selected" : "")} onClick={this.onZoomDocumentClick}><FontAwesomeIcon icon={"search"} onPointerDown={e => e.stopPropagation()} /></button> + <button title="Zoom" className={pbi + (this.rootDoc.presZoomButton ? "-selected" : "")} onClick={this.onZoomDocumentClick}><FontAwesomeIcon icon={"search-plus"} onPointerDown={e => e.stopPropagation()} /></button> <button title="Navigate" className={pbi + (this.rootDoc.presNavButton ? "-selected" : "")} onClick={this.onNavigateDocumentClick}><FontAwesomeIcon icon={"location-arrow"} onPointerDown={e => e.stopPropagation()} /></button> <button title="Hide Before" className={pbi + (this.rootDoc.presHideTillShownButton ? "-selected" : "")} onClick={this.onHideDocumentUntilPressClick}><FontAwesomeIcon icon={"file"} onPointerDown={e => e.stopPropagation()} /></button> <button title="Fade After" className={pbi + (this.rootDoc.presFadeButton ? "-selected" : "")} onClick={this.onFadeDocumentAfterPresentedClick}><FontAwesomeIcon icon={"file-download"} onPointerDown={e => e.stopPropagation()} /></button> <button title="Hide After" className={pbi + (this.rootDoc.presHideAfterButton ? "-selected" : "")} onClick={this.onHideDocumentAfterPresentedClick}><FontAwesomeIcon icon={"file-download"} onPointerDown={e => e.stopPropagation()} /></button> - {/* <button title="Group With Up" className={pbi + (this.rootDoc.presGroupButton ? "-selected" : "")} onClick={e => { e.stopPropagation(); this.rootDoc.presGroupButton = !this.rootDoc.presGroupButton; }}><FontAwesomeIcon icon={"arrow-up"} onPointerDown={e => e.stopPropagation()} /></button> */} - <button title="Progressivize" className={pbi + (this.rootDoc.pres ? "-selected" : "")} onClick={this.progressivize}><FontAwesomeIcon icon={"tasks"} onPointerDown={e => e.stopPropagation()} /></button> + <button title="Progressivize" className={pbi + (this.rootDoc.presProgressivize ? "-selected" : "")} onClick={this.progressivize}><FontAwesomeIcon icon={"tasks"} onPointerDown={e => e.stopPropagation()} /></button> </div> {this.renderEmbeddedInline} </div> |