diff options
author | Geireann <60007097+geireann@users.noreply.github.com> | 2021-04-06 20:31:25 -0400 |
---|---|---|
committer | Geireann <60007097+geireann@users.noreply.github.com> | 2021-04-06 20:31:25 -0400 |
commit | a14e2da6130ac3c0c55b03cbc8a5fa3723be45bc (patch) | |
tree | 593f42da1ae052704152c5b6ecbf878ec49fac6b | |
parent | a0fac101ef88f0983275fb14f64c85ab858aaaed (diff) |
updates
-rw-r--r-- | src/client/util/CaptureManager.scss | 465 | ||||
-rw-r--r-- | src/client/util/CaptureManager.tsx | 75 | ||||
-rw-r--r-- | src/client/views/AntimodeMenu.scss | 14 | ||||
-rw-r--r-- | src/client/views/AntimodeMenu.tsx | 2 | ||||
-rw-r--r-- | src/client/views/MainView.scss | 3 | ||||
-rw-r--r-- | src/client/views/MainView.tsx | 6 | ||||
-rw-r--r-- | src/client/views/collections/CollectionMenu.scss | 126 | ||||
-rw-r--r-- | src/client/views/collections/CollectionMenu.tsx | 78 | ||||
-rw-r--r-- | src/client/views/nodes/ScreenshotBox.tsx | 121 | ||||
-rw-r--r-- | src/client/views/nodes/VideoBox.scss | 10 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/RichTextMenu.scss | 7 | ||||
-rw-r--r-- | src/client/views/nodes/formattedText/RichTextMenu.tsx | 2 |
12 files changed, 790 insertions, 119 deletions
diff --git a/src/client/util/CaptureManager.scss b/src/client/util/CaptureManager.scss new file mode 100644 index 000000000..5ca54517c --- /dev/null +++ b/src/client/util/CaptureManager.scss @@ -0,0 +1,465 @@ +@import "../views/globalCssVariables"; + +.settings-interface { + //background-color: whitesmoke !important; + color: grey; + width: 450px; + + button { + background: #315a96; + outline: none; + border-radius: 5px; + border: 0px; + color: #fcfbf7; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 75%; + padding: 10px; + margin: 10px; + transition: transform 0.2s; + margin: 2px; + } +} + +.settings-title { + font-size: 25px; + font-weight: bold; + padding-right: 10px; + color: black; +} + +.settings-username { + font-size: 12px; + padding-right: 15px; + color: black; + margin-top: 10px; + margin-bottom: 10px; + /* right: 135; */ + // position: absolute; + // left: 243; +} + +.settings-section { + display: flex; + border-bottom: 1px solid grey; + padding-bottom: 8px; + padding-top: 6px; + + .settings-section-title { + font-size: 16; + font-weight: bold; + text-align: left; + color: black; + width: 80; + margin-right: 50px; + } + + &:last-child { + border-bottom: none; + } +} + + +.password-content { + display: flex; + flex-direction: column; + + .password-content-inputs { + width: 100; + // margin-bottom: 10px; + font-size: 10px; + + .password-inputs { + border: 1px solid rgb(160, 160, 160); + margin-bottom: 8px; + width: 130; + color: black; + border-radius: 5px; + padding:7px; + + } + } + + .password-content-buttons { + //margin-left: 84px; + //width: 100; + padding: 7px; + + .password-submit { + //margin-left: 85px; + margin-top: 5px; + } + + .password-forgot { + //margin-left: 65px; + //margin-top: -20px; + font-size: 12px; + white-space: nowrap; + } + } +} + +.accounts-content { + display: flex; +} + +.modes-content { + display: flex; + margin-left: 10px; + font-size: 12px; + + .modes-select { + // width: 170px; + width: 80%; + height: 35px; + margin-right: 10px; + color: black; + border-radius: 5px; + + &:hover { + cursor: pointer; + } + } + + .modes-playground, + .default-acl { + display: flex; + margin-left: 10px; + margin-top: 10px; + font-size: 10px; + + .playground-check, + .acl-check { + margin-right: 5px; + + &:hover { + cursor: pointer; + } + } + + .playground-text { + color: black; + margin-right: 10px; + margin-top: 2; + } + + .acl-text { + color: black; + margin-top: 2; + text-align: left; + } + + } +} + +.colorFlyout { + margin-top: 2px; + //margin-right: 18px; + + &:hover { + cursor: pointer; + } + + .colorFlyout-button { + width: 20px; + height: 20px; + border: 0.5px solid black; + border-radius: 5px; + padding-top: 3px; + } +} + +.prefs-content{ + text-align: left; +} + +.appearances-content { + display: flex; + margin-top: 4px; + color: black; + font-size: 10px; + + .preferences-color { + display: flex; + margin-top: 2px; + + .preferences-color-text { + margin-top: 3px; + margin-right: 4; + flex: 1 1 auto; + text-align: left; + } + + .colorFlyout { + align-self: flex-end; + } + } + + .preferences-font { + //height: 23px; + margin-top: 2px; + + .preferences-font-text { + color: black; + margin-top: 4; + margin-right: 4; + margin-bottom: 2px; + text-align: left; + } + + .preferences-font-controls { + display: flex; + justify-content: space-between; + } + + .font-select { + height: 35px; + color: black; + font-size: 9; + margin-right: 6; + border-radius: 5px; + width: 65%; + + &:hover { + cursor: pointer; + } + } + + .size-select { + height: 35px; + color: black; + font-size: 9; + border-radius: 5px; + width: 30%; + + &:hover { + cursor: pointer; + } + } + } + + .preferences-check { + color: black; + margin-right: 4; + margin-bottom: -3; + margin-left: 5; + margin-top: -1px; + display: inline-block; + padding-left: 5px; + text-align: left; + } +} + +.settings-interface { + display: flex; + flex-direction: column; + + button { + width: auto; + align-self: center; + background: #252b33; + margin-right: 15px; + + //margin-top: 4px; + + &:hover { + background: $main-accent; + } + } + + // .delete-button { + // background: rgb(227, 86, 86); + // } + + .close-button { + position: absolute; + right: 1em; + top: 1em; + cursor: pointer; + } + + // .logout-button { + // right: 355; + // position: absolute; + // } + + .settings-content { + background: #e4e4e4; + //border-radius: 6px; + padding: 10px; + //width: 560px; + flex: 1 1 auto; + } + + .settings-top { + display: flex; + margin-bottom: 10px; + } + + + .error-text { + color: #C40233; + width: 300; + margin-left: -20; + font-size: 10; + margin-bottom: 4; + margin-top: -3; + } + + .success-text { + width: 300; + margin-left: -20; + font-size: 10; + margin-bottom: 4; + margin-top: -3; + color: #009F6B; + } + + .focus-span { + text-decoration: underline; + } + + h1 { + color: #121721; + text-transform: uppercase; + letter-spacing: 2px; + font-size: 19; + margin-top: 0; + font-weight: bold; + } + + .container { + display: block; + position: relative; + margin-top: 10px; + margin-bottom: 10px; + font-size: 22px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + width: 700px; + min-width: 700px; + max-width: 700px; + text-align: left; + font-style: normal; + font-size: 15; + font-weight: normal; + padding: 0; + + .padding { + padding: 0 0 0 20px; + color: black; + } + + } +} + +.settings-interface { + flex-direction: row; + position: relative; + min-height: 250px; + width: 100%; + + .settings-content { + background-color: #fdfdfd; + } +} + +.settings-panel { + position: relative; + min-width: 150px; + background-color: #e4e4e4; + + .settings-user { + position: absolute; + bottom: 10px; + text-align: center; + left: 0; + right: 0; + + .settings-username { + padding-right: 0px; + } + + .logout-button { + margin-right: 2px; + } + } +} + +.settings-tabs { + // font-size: 16px; + font-weight: 600; + color: black; + + .tab-control { + padding: 10px; + border-bottom: 1px solid #9f9e9e; + cursor: pointer; + + &.active { + background-color: #fdfdfd; + } + } +} + +.settings-section-context { + width: 100%; +} + +.tab-section { + display: none; + height: 200px; + + &.active { + display: block; + } +} + +.tab-content { + display: flex; + margin: 20px 0; + + .tab-column { + flex: 0 0 50%; + + .tab-column-title { + color: black; + font-size: 16px; + font-weight: bold; + margin-bottom: 16px; + } + + .tab-column-title, .tab-column-content { + padding-left: 16px; + } + + } + +} + +.tab-column button { + font-size: 9px; +} + +@media only screen and (max-device-width: 480px) { + .settings-interface { + width: 80vw; + height: 400px; + } + + .settings-interface .settings-body .settings-content input { + font-size: 30; + } + + .settings-interface button { + width: 100%; + font-size: 30px; + background: #315a96; + } + + .settings-interface .settings-heading { + font-size: 25; + } +} diff --git a/src/client/util/CaptureManager.tsx b/src/client/util/CaptureManager.tsx new file mode 100644 index 000000000..f01fcd0d2 --- /dev/null +++ b/src/client/util/CaptureManager.tsx @@ -0,0 +1,75 @@ +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { action, computed, observable, runInAction } from "mobx"; +import { observer } from "mobx-react"; +import * as React from "react"; +import { ColorState, SketchPicker } from "react-color"; +import { Doc } from "../../fields/Doc"; +import { BoolCast, StrCast, Cast } from "../../fields/Types"; +import { addStyleSheet, addStyleSheetRule, Utils } from "../../Utils"; +import { GoogleAuthenticationManager } from "../apis/GoogleAuthenticationManager"; +import { DocServer } from "../DocServer"; +import { Networking } from "../Network"; +import { MainViewModal } from "../views/MainViewModal"; +import { CurrentUserUtils } from "./CurrentUserUtils"; +import { GroupManager } from "./GroupManager"; +import "./CaptureManager.scss"; +import { undoBatch } from "./UndoManager"; +const higflyout = require("@hig/flyout"); +export const { anchorPoints } = higflyout; +export const Flyout = higflyout.default; + +@observer +export class CaptureManager extends React.Component<{}> { + public static Instance: CaptureManager; + static _settingsStyle = addStyleSheet(); + @observable isOpen: boolean = false; // whether the CaptureManager is to be displayed or not. + + + constructor(props: {}) { + super(props); + CaptureManager.Instance = this; + } + + public close = action(() => this.isOpen = false); + public open = action(() => this.isOpen = true); + + + @computed get colorsContent() { + + return <div className="colors-content"> + + </div>; + } + + @computed get formatsContent() { + return <div className="prefs-content"> + + </div>; + } + + + + + + private get captureInterface() { + return <div className="settings-interface"> + <div className="settings-panel"> + + </div> + + <div className="close-button" onClick={this.close}> + <FontAwesomeIcon icon={"times"} color="black" size={"lg"} /> + </div> + </div>; + + } + + render() { + return <MainViewModal + contents={this.captureInterface} + isDisplayed={this.isOpen} + interactive={true} + closeOnExternalClick={this.close} + dialogueBoxStyle={{ width: "500px", height: "300px", background: Cast(Doc.SharingDoc().userColor, "string", null) }} />; + } +}
\ No newline at end of file diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss index c9b5e7658..a275901be 100644 --- a/src/client/views/AntimodeMenu.scss +++ b/src/client/views/AntimodeMenu.scss @@ -7,7 +7,7 @@ height: $antimodemenu-height; background: #323232; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); - border-radius: 0px 6px 6px 6px; + // border-radius: 0px 6px 6px 6px; z-index: 1001; display: flex; @@ -24,6 +24,16 @@ background-color: transparent; width: 35px; height: 35px; + padding: 5; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + position: relative; + + .svg { + margin: 0; + } &.active { background-color: #121212; @@ -31,7 +41,7 @@ } .antimodeMenu-button:hover { - background-color: #121212; + background-color: rgba(0, 0, 0, 0.4); } .antimodeMenu-dragger { diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx index 5acb3e4c8..fe6d39ca4 100644 --- a/src/client/views/AntimodeMenu.tsx +++ b/src/client/views/AntimodeMenu.tsx @@ -140,7 +140,7 @@ export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends React.Co left: this._left, top: this._top, opacity: this._opacity, transitionProperty: this._transitionProperty, transitionDuration: this._transitionDuration, transitionDelay: this._transitionDelay, position: this.Pinned ? "unset" : undefined }}> - <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: "20px" }} /> + {/* {this.getDragger} */} {buttons} </div> ); diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 8ccb64744..3f04a0f3a 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -358,9 +358,6 @@ .mainView-libraryFlyout-out { transition: width .25s; box-shadow: rgb(156, 147, 150) 0.2vw 0.2vw 0.2vw; - .mainView-docButtons { - left: 0; - } } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 204ec370f..7d78d74e3 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -17,6 +17,7 @@ import { emptyFunction, emptyPath, returnEmptyDoclist, returnEmptyFilter, return import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager'; import { DocServer } from '../DocServer'; import { Docs, DocUtils } from '../documents/Documents'; +import { CaptureManager } from '../util/CaptureManager'; import { CurrentUserUtils } from '../util/CurrentUserUtils'; import { DocumentManager } from '../util/DocumentManager'; import { GroupManager } from '../util/GroupManager'; @@ -177,8 +178,8 @@ export class MainView extends React.Component { const targClass = targets[0].className.toString(); if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) { const check = targets.some((thing) => - (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || - thing.className === "collectionSchema-header-menuOptions")); + (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || + thing.className === "collectionSchema-header-menuOptions")); !check && SearchBox.Instance.resetSearch(true); } !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu(); @@ -619,6 +620,7 @@ export class MainView extends React.Component { <DictationOverlay /> <SharingManager /> <SettingsManager /> + <CaptureManager /> <GroupManager /> <GoogleAuthenticationManager /> <DocumentDecorations boundsLeft={this.leftOffset} boundsTop={this.topOffset} /> diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index 2c81d727e..9eac75f4b 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -14,35 +14,53 @@ top: 0; width: 100%; - .antimodeMenu-button { - padding: 0; - width: 30px; + .recordButtonOutline { + border-radius: 100%; + width: 18px; + height: 18px; + border: solid 1px #f5f5f5; display: flex; + align-items: center; + justify-content: center; + } - svg { - margin: auto; - } + .recordButtonInner { + border-radius: 100%; + width: 70%; + height: 70%; + background: white; } .collectionMenu { display: flex; - padding-bottom: 1px; - height: 32px; - border-bottom: .5px solid rgb(180, 180, 180); + height: 100%; overflow: visible; z-index: 901; border: unset; + .collectionMenu-divider { + height: 85%; + margin-left: 3px; + margin-right: 3px; + width: 1.5px; + background-color: #656060; + } + .collectionViewBaseChrome { display: flex; + align-items: center; .collectionViewBaseChrome-viewPicker { font-size: 75%; - background: #323232; outline-color: black; color: white; border: none; - border-right: solid gray 1px; + background: #323232; + } + + .collectionViewBaseChrome-viewPicker:focus { + outline: none; + border: none; } .collectionViewBaseChrome-viewPicker:active { @@ -65,18 +83,26 @@ margin-left: 3px; margin-right: 0px; font-size: 75%; - background: #323232; + text-transform: capitalize; color: white; border: none; - border-right: solid gray 1px; + background: #323232; + } + + .collectionViewBaseChrome-cmdPicker:focus { + border: none; + outline: none; } .commandEntry-outerDiv { pointer-events: all; - background-color: #323232; + background-color: transparent; display: flex; flex-direction: row; - height: 30px; + align-items: center; + justify-content: center; + height: 100%; + overflow: hidden; .commandEntry-drop { color: white; @@ -86,6 +112,15 @@ } } + .commandEntry-outerDiv:hover{ + background-color: rgba(0,0,0,0.2); + + .collectionViewBaseChrome-viewPicker, + .collectionViewBaseChrome-cmdPicker{ + background: rgb(41,41,41); + } + } + .collectionViewBaseChrome-collapse { transition: all .5s, opacity 0.3s; position: absolute; @@ -103,11 +138,12 @@ .collectionViewBaseChrome-template, .collectionViewBaseChrome-viewModes { - display: grid; - background: rgb(238, 238, 238); + align-items: center; + height: 100%; + display: flex; + background: transparent; color: grey; - margin-top: auto; - margin-bottom: auto; + justify-content: center; } .collectionViewBaseChrome-viewSpecs { @@ -263,27 +299,52 @@ .collectionTreeViewChrome-pivotField-cont, .collection3DCarouselViewChrome-scrollSpeed-cont { justify-self: right; - display: flex; + align-items: center; + display: grid; + grid-auto-columns: auto; font-size: 75%; letter-spacing: 2px; .collectionStackingViewChrome-pivotField-label, .collectionTreeViewChrome-pivotField-label, .collection3DCarouselViewChrome-scrollSpeed-label { - vertical-align: center; - padding-left: 10px; - margin: auto; + grid-column: 1; + margin-right: 7px; + user-select: none; + font-family: 'Roboto'; + letter-spacing: normal; + } + + .collectionStackingViewChrome-sortIcon { + transition: transform .5s; + grid-column: 3; + text-align: center; + display: flex; + justify-content: center; + align-items: center; + cursor: pointer; + width: 25px; + height: 25px; + border-radius: 100%; + } + + .collectionStackingViewChrome-sortIcon:hover { + background-color: rgba(0,0,0,0.2); } .collectionStackingViewChrome-pivotField, .collectionTreeViewChrome-pivotField, .collection3DCarouselViewChrome-scrollSpeed { color: white; - width: 100%; + grid-column: 2; + grid-row: 1; + width: 90%; min-width: 100px; display: flex; + height: 80%; + border-radius: 7px; align-items: center; - background: rgb(238, 238, 238); + background: #eeeeee; .editable-view-input, input, @@ -378,20 +439,13 @@ display: inline-flex; position: relative; align-items: center; - margin-left: 10px; - - .antimodeMenu-button { - text-align: center; - display: block; - position: relative; - } + height: 100%; .color-previewI { - width: 80%; - height: 20%; - bottom: 0; + width: 60%; + top: 80%; position: absolute; - margin-left: 2px; + height: 4px; } .color-previewII { diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx index 623e05b33..3321a8d8f 100644 --- a/src/client/views/collections/CollectionMenu.tsx +++ b/src/client/views/collections/CollectionMenu.tsx @@ -15,7 +15,7 @@ import { RichTextField } from "../../../fields/RichTextField"; import { listSpec } from "../../../fields/Schema"; import { ScriptField } from "../../../fields/ScriptField"; import { BoolCast, Cast, NumCast, StrCast } from "../../../fields/Types"; -import { emptyFunction, setupMoveUpEvents, Utils } from "../../../Utils"; +import { DeepCopy, emptyFunction, setupMoveUpEvents, Utils } from "../../../Utils"; import { DocumentType } from "../../documents/DocumentTypes"; import { CurrentUserUtils } from "../../util/CurrentUserUtils"; import { DragManager } from "../../util/DragManager"; @@ -34,6 +34,9 @@ import "./CollectionMenu.scss"; import { CollectionViewType, COLLECTION_BORDER_WIDTH } from "./CollectionView"; import { TabDocView } from "./TabDocView"; import { LightboxView } from "../LightboxView"; +import { Docs } from "../../documents/Documents"; +import { DocumentManager } from "../../util/DocumentManager"; +import { CollectionDockingView } from "./CollectionDockingView"; @observer export class CollectionMenu extends AntimodeMenu<AntimodeMenuProps> { @@ -388,7 +391,32 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp return !targetDoc ? (null) : <Tooltip key="pin" title={<div className="dash-tooltip">{Doc.isDocPinned(targetDoc) ? "Unpin from presentation" : "Pin to presentation"}</div>} placement="top"> <button className="antimodeMenu-button" style={{ backgroundColor: isPinned ? "121212" : undefined, borderLeft: "1px solid gray" }} onClick={e => TabDocView.PinDoc(targetDoc, { unpin: isPinned })}> - <FontAwesomeIcon className="documentdecorations-icon" size="lg" icon="map-pin" /> + <FontAwesomeIcon className="colMenu-icon" size="lg" icon="map-pin" /> + </button> + </Tooltip>; + } + + @undoBatch + @action + startRecording = () => { + const doc = Docs.Create.ScreenshotDocument("", { _fitWidth: true, _width: 400, _height: 200, title: "screen snapshot", system: true, cloneFieldFilter: new List<string>(["system"]) }); + doc.x = 0; + doc.y = 0; + Doc.AddDocToList((Doc.UserDoc().myOverlayDocs as Doc), undefined, doc); + CollectionDockingView.AddSplit(doc, "right"); + // doc.startRec = true; + } + + @computed + get recordButton() { + const targetDoc = this.selectedDoc; + return <Tooltip key="record" title={<div className="dash-tooltip">{"Capture screen"}</div>} placement="top"> + <button className="antimodeMenu-button" + onClick={e => this.startRecording()}> + <div className="recordButtonOutline" style={{}}> + <div className="recordButtonInner" style={{}}> + </div> + </div> </button> </Tooltip>; } @@ -478,7 +506,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp const targetDoc = this.selectedDoc; return !targetDoc || targetDoc.type === DocumentType.PRES ? (null) : <Tooltip title={<div className="dash-tooltip">{"Tap or Drag to create an alias"}</div>} placement="top"> <button className="antimodeMenu-button" onPointerDown={this.onAliasButtonDown} onClick={this.onAlias} style={{ cursor: "drag" }}> - <FontAwesomeIcon className="documentdecorations-icon" icon="copy" size="lg" /> + <FontAwesomeIcon className="colMenu-icon" icon="copy" size="lg" /> </button> </Tooltip>; } @@ -486,38 +514,48 @@ export class CollectionViewBaseChrome extends React.Component<CollectionMenuProp @computed get lightboxButton() { const targetDoc = this.selectedDoc; return !targetDoc ? (null) : <Tooltip title={<div className="dash-tooltip">{"View in Lightbox"}</div>} placement="top"> - <button className="antimodeMenu-button" style={{ borderRight: "1px solid gray", justifyContent: 'center' }} onPointerDown={() => { + <button className="antimodeMenu-button" onPointerDown={() => { const docs = DocListCast(targetDoc[Doc.LayoutFieldKey(targetDoc)]); LightboxView.SetLightboxDoc(targetDoc, undefined, docs); }}> - <FontAwesomeIcon className="documentdecorations-icon" icon="desktop" size="lg" /> + <FontAwesomeIcon className="colMenu-icon" icon="desktop" size="lg" /> </button> </Tooltip>; } + @computed get toggleOverlayButton() { + return <> + <Tooltip title={<div className="dash-tooltip">Toggle Overlay Layer</div>} placement="bottom"> + <button className={"antimodeMenu-button"} key="float" + style={{ + backgroundColor: this.props.docView.layoutDoc.z ? "121212" : undefined, + pointerEvents: this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? "none" : undefined, + color: this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? "dimgrey" : undefined + }} + onClick={undoBatch(() => this.props.docView.props.CollectionFreeFormDocumentView?.().float())}> + <FontAwesomeIcon icon={["fab", "buffer"]} size={"lg"} /> + </button> + </Tooltip> + </> + } + render() { return ( <div className="collectionMenu-cont" > <div className="collectionMenu"> <div className="collectionViewBaseChrome"> + {this.notACollection || this.props.type === CollectionViewType.Invalid ? (null) : this.viewModes} + <div className="collectionMenu-divider" key="divider1"></div> {this.aliasButton} {/* {this.pinButton} */} - {this.pinWithViewButton} - {this.lightboxButton} - <Tooltip title={<div className="dash-tooltip">Toggle Overlay Layer</div>} placement="bottom"> - <button className={"antimodeMenu-button"} key="float" - style={{ - backgroundColor: this.props.docView.layoutDoc.z ? "121212" : undefined, borderRight: "1px solid gray", - pointerEvents: this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? "none" : undefined, - color: this.props.docView.props.ContainingCollectionDoc?._viewType !== CollectionViewType.Freeform ? "dimgrey" : undefined - }} - onClick={undoBatch(() => this.props.docView.props.CollectionFreeFormDocumentView?.().float())}> - <FontAwesomeIcon icon={["fab", "buffer"]} size={"lg"} /> - </button> - </Tooltip> + {/* {this.pinWithViewButton} */} + {this.toggleOverlayButton} + <div className="collectionMenu-divider" key="divider2"></div> {this.subChrome} - {this.notACollection || this.props.type === CollectionViewType.Invalid ? (null) : this.viewModes} - {!this._buttonizableCommands ? (null) : this.templateChrome} + <div className="collectionMenu-divider" key="divider3"></div> + {this.lightboxButton} + {this.recordButton} + {/* {!this._buttonizableCommands ? (null) : this.templateChrome} */} </div> </div> </div> diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx index 8163b652c..4c24dc5e1 100644 --- a/src/client/views/nodes/ScreenshotBox.tsx +++ b/src/client/views/nodes/ScreenshotBox.tsx @@ -1,6 +1,6 @@ import React = require("react"); import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { action, computed, observable } from "mobx"; +import { action, computed, IReactionDisposer, observable, ObservableMap, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; import { DateField } from "../../../fields/DateField"; import { Doc, WidthSym } from "../../../fields/Doc"; @@ -25,6 +25,7 @@ import "./ScreenshotBox.scss"; import { VideoBox } from "./VideoBox"; import { TraceMobx } from "../../../fields/util"; import { FormattedTextBox } from "./formattedText/FormattedTextBox"; +import { CaptureManager } from "../../util/CaptureManager"; declare class MediaRecorder { constructor(e: any, options?: any); // whatever MediaRecorder has } @@ -40,6 +41,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl private _videoRec: any; @observable _screenCapture = false; @computed get recordingStart() { return Cast(this.dataDoc[this.props.fieldKey + "-recordingStart"], DateField)?.date.getTime(); } + private _disposers: { [name: string]: IReactionDisposer } = {}; + constructor(props: any) { super(props); @@ -66,10 +69,14 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl componentDidMount() { this.dataDoc.nativeWidth = this.dataDoc.nativeHeight = 0; this.props.setContentView?.(this); // this tells the DocumentView that this ScreenshotBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link. + this._disposers.rec = reaction(() => this.rootDoc.startRec == true, + this.toggleRecording + ); } componentWillUnmount() { const ind = DocUtils.ActiveRecordings.indexOf(this); ind !== -1 && (DocUtils.ActiveRecordings.splice(ind, 1)); + Object.values(this._disposers).forEach(disposer => disposer?.()); } specificContextMenu = (e: React.MouseEvent): void => { @@ -91,6 +98,13 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl } toggleRecording = action(async () => { + console.log("toggleRecording"); + console.log("2:" + this._videoRef.current!.srcObject); + if (this._screenCapture) { + CaptureManager.Instance.open(this.rootDoc); + } else { + console.log("opening"); + } this._screenCapture = !this._screenCapture; if (this._screenCapture) { this._audioRec = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true })); @@ -149,57 +163,62 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatabl formattedPanelHeight = () => Math.max(0, this.props.PanelHeight() - this.videoPanelHeight()); render() { TraceMobx(); - return <div className="videoBox" onContextMenu={this.specificContextMenu} style={{ width: "100%", height: "100%" }} > - <div className="videoBox-viewer" > - <div style={{ position: "relative", height: this.videoPanelHeight() }}> - <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} - PanelHeight={this.videoPanelHeight} - PanelWidth={this.props.PanelWidth} - focus={this.props.focus} - isSelected={this.props.isSelected} - isAnnotationOverlay={true} - select={emptyFunction} - isContentActive={returnFalse} - scaling={returnOne} - whenChildContentsActiveChanged={emptyFunction} - removeDocument={returnFalse} - moveDocument={returnFalse} - addDocument={returnFalse} - CollectionView={undefined} - ScreenToLocalTransform={this.props.ScreenToLocalTransform} - renderDepth={this.props.renderDepth + 1} - ContainingCollectionDoc={this.props.ContainingCollectionDoc}> - {this.contentFunc} - </CollectionFreeFormView></div> - <div style={{ position: "relative", height: this.formattedPanelHeight() }}> - <FormattedTextBox {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} - Document={this.dataDoc[this.fieldKey + "-dictation"]} - fieldKey={"text"} - PanelHeight={this.formattedPanelHeight} - PanelWidth={this.props.PanelWidth} - focus={this.props.focus} - isSelected={this.props.isSelected} - isAnnotationOverlay={true} - select={emptyFunction} - isContentActive={returnFalse} - scaling={returnOne} - xMargin={25} - yMargin={10} - whenChildContentsActiveChanged={emptyFunction} - removeDocument={returnFalse} - moveDocument={returnFalse} - addDocument={returnFalse} - CollectionView={undefined} - ScreenToLocalTransform={this.props.ScreenToLocalTransform} - renderDepth={this.props.renderDepth + 1} - ContainingCollectionDoc={this.props.ContainingCollectionDoc}> - </FormattedTextBox></div> + return this.rootDoc.startRec ? + <div className="mini-viewer"> + </div> - {!this.props.isSelected() ? (null) : <div className="screenshotBox-uiButtons"> - <div className="screenshotBox-recorder" key="snap" onPointerDown={this.toggleRecording} > - <FontAwesomeIcon icon="file" size="lg" /> + : + <div className="videoBox" onContextMenu={this.specificContextMenu} style={{ width: "100%", height: "100%" }} > + <div className="videoBox-viewer" > + <div style={{ position: "relative", height: this.videoPanelHeight() }}> + <CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} + PanelHeight={this.videoPanelHeight} + PanelWidth={this.props.PanelWidth} + focus={this.props.focus} + isSelected={this.props.isSelected} + isAnnotationOverlay={true} + select={emptyFunction} + isContentActive={returnFalse} + scaling={returnOne} + whenChildContentsActiveChanged={emptyFunction} + removeDocument={returnFalse} + moveDocument={returnFalse} + addDocument={returnFalse} + CollectionView={undefined} + ScreenToLocalTransform={this.props.ScreenToLocalTransform} + renderDepth={this.props.renderDepth + 1} + ContainingCollectionDoc={this.props.ContainingCollectionDoc}> + {this.contentFunc} + </CollectionFreeFormView></div> + <div style={{ position: "relative", height: this.formattedPanelHeight() }}> + <FormattedTextBox {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit} + Document={this.dataDoc[this.fieldKey + "-dictation"]} + fieldKey={"text"} + PanelHeight={this.formattedPanelHeight} + PanelWidth={this.props.PanelWidth} + focus={this.props.focus} + isSelected={this.props.isSelected} + isAnnotationOverlay={true} + select={emptyFunction} + isContentActive={returnFalse} + scaling={returnOne} + xMargin={25} + yMargin={10} + whenChildContentsActiveChanged={emptyFunction} + removeDocument={returnFalse} + moveDocument={returnFalse} + addDocument={returnFalse} + CollectionView={undefined} + ScreenToLocalTransform={this.props.ScreenToLocalTransform} + renderDepth={this.props.renderDepth + 1} + ContainingCollectionDoc={this.props.ContainingCollectionDoc}> + </FormattedTextBox></div> </div> - </div>} - </div >; + {!this.props.isSelected() ? (null) : <div className="screenshotBox-uiButtons"> + <div className="screenshotBox-recorder" key="snap" onPointerDown={this.toggleRecording} > + <FontAwesomeIcon icon="file" size="lg" /> + </div> + </div>} + </div >; } }
\ No newline at end of file diff --git a/src/client/views/nodes/VideoBox.scss b/src/client/views/nodes/VideoBox.scss index dd8d77603..30f0c4393 100644 --- a/src/client/views/nodes/VideoBox.scss +++ b/src/client/views/nodes/VideoBox.scss @@ -1,3 +1,13 @@ +.mini-viewer{ + cursor: grab; + position: absolute; + right: 10; + top: 10; + opacity: 0.1; + transition: all 0.4s; + color: white; +} + .videoBox { transform-origin: top left; width: 100%; diff --git a/src/client/views/nodes/formattedText/RichTextMenu.scss b/src/client/views/nodes/formattedText/RichTextMenu.scss index fbc468292..1d24d6833 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.scss +++ b/src/client/views/nodes/formattedText/RichTextMenu.scss @@ -95,9 +95,10 @@ .color-preview-button { .color-preview { - width: 100%; - height: 3px; - margin-top: 3px; + width: 60%; + top: 80%; + position: absolute; + height: 4px; } } diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx index 5da868281..071491463 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.tsx +++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx @@ -976,7 +976,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> { const row2 = <div className="antimodeMenu-row row-2" key="row2"> {this.collapsed ? this.getDragger() : (null)} <div key="row 2" style={{ display: this.collapsed ? "none" : undefined }}> - <div className="richTextMenu-divider" key="divider 3" />, + <div className="richTextMenu-divider" key="divider 3" /> {[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size", action((val: string) => { this.activeFontSize = val; SelectionManager.Views().map(dv => dv.props.Document._fontSize = val); |