aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2020-08-14 20:14:25 -0400
committerGitHub <noreply@github.com>2020-08-14 20:14:25 -0400
commit2971ade07c7b9674c666446fa49e533e05197f1f (patch)
treea9d5bd81fe0c2b824e9fb0ec965e7b495b8d70b4 /src
parentcd7b13c2c1086739d866e4a6ad9c239a46d89244 (diff)
parent13e808c6802f10996558303bccac3ec5ba2c9b60 (diff)
Merge pull request #610 from browngraphicslab/new_audio
New audio
Diffstat (limited to 'src')
-rw-r--r--src/.DS_Storebin0 -> 8196 bytes
-rw-r--r--src/client/util/CurrentUserUtils.ts25
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx1
-rw-r--r--src/client/views/nodes/AudioBox.scss16
-rw-r--r--src/client/views/nodes/AudioBox.tsx199
-rw-r--r--src/client/views/nodes/FieldView.tsx7
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx7
-rw-r--r--src/mobile/ImageUpload.tsx2
-rw-r--r--src/mobile/MobileInterface.tsx2
-rw-r--r--src/mobile/MobileMenu.scss271
10 files changed, 420 insertions, 110 deletions
diff --git a/src/.DS_Store b/src/.DS_Store
new file mode 100644
index 000000000..299b902c6
--- /dev/null
+++ b/src/.DS_Store
Binary files differ
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index bd22b8e9d..27bf1a774 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -667,8 +667,29 @@ export class CurrentUserUtils {
return Cast(userDoc.thumbDoc, Doc);
}
- // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker.
- // when clicked, this panel will be displayed in the target container (ie, sidebarContainer)
+ static setupMobileInkingDoc(userDoc: Doc) {
+ return Docs.Create.FreeformDocument([], { title: "Mobile Inking", backgroundColor: "white", system: true });
+ }
+
+ static setupMobileUploadDoc(userDoc: Doc) {
+ // const addButton = Docs.Create.FontIconDocument({ onDragStart: ScriptField.MakeScript('addWebToMobileUpload()'), title: "Add Web Doc to Upload Collection", icon: "plus", backgroundColor: "black" })
+ const webDoc = Docs.Create.WebDocument("https://www.britannica.com/biography/Miles-Davis", {
+ title: "Upload Images From the Web", _chromeStatus: "enabled", lockedPosition: true, system: true
+ });
+ const uploadDoc = Docs.Create.StackingDocument([], {
+ title: "Mobile Upload Collection", backgroundColor: "white", lockedPosition: true, system: true
+ });
+ return Docs.Create.StackingDocument([webDoc, uploadDoc], {
+ _width: screen.width, lockedPosition: true, _chromeStatus: "disabled", title: "Upload", _autoHeight: true, _yMargin: 80, backgroundColor: "lightgray", system: true
+ });
+ }
+
+ static setupLibrary(userDoc: Doc) {
+ return CurrentUserUtils.setupWorkspaces(userDoc);
+ }
+
+ // setup the Creator button which will display the creator panel. This panel will include the drag creators and the color picker.
+ // when clicked, this panel will be displayed in the target container (ie, sidebarContainer)
static async setupToolsBtnPanel(doc: Doc) {
// setup a masonry view of all he creators
const creatorBtns = await CurrentUserUtils.setupCreatorButtons(doc);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 55c2b253b..46e30f616 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -605,6 +605,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
pan = (e: PointerEvent | React.Touch | { clientX: number, clientY: number }): void => {
// bcz: theres should be a better way of doing these than referencing these static instances directly
MarqueeOptionsMenu.Instance?.fadeOut(true);// I think it makes sense for the marquee menu to go away when panned. -syip2
+ // PDFMenu.Instance.fadeOut(true); (commented out for mobile)
const [dx, dy] = this.getTransform().transformDirection(e.clientX - this._lastX, e.clientY - this._lastY);
this.setPan((this.Document._panX || 0) - dx, (this.Document._panY || 0) - dy, undefined, true);
diff --git a/src/client/views/nodes/AudioBox.scss b/src/client/views/nodes/AudioBox.scss
index c80e3af24..f16d13a4e 100644
--- a/src/client/views/nodes/AudioBox.scss
+++ b/src/client/views/nodes/AudioBox.scss
@@ -17,6 +17,22 @@
display: flex;
width: 100%;
align-items: center;
+ height: 100%;
+
+ .audiobox-dictation {
+ position: relative;
+ width: 30px;
+ height: 100%;
+ align-items: center;
+ display: inherit;
+ background: dimgray;
+ left: 0px;
+ }
+
+ .audiobox-dictation:hover {
+ color: white;
+ cursor: pointer;
+ }
}
.audiobox-handle {
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 900963eb0..5c8cb5e35 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -530,113 +530,112 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
bringToFront={emptyFunction}
scriptContext={this} />;
};
- return <div className="audiobox-container" onContextMenu={this.specificContextMenu} onClick={!this.path ? this.recordClick : undefined}>
- <div className="audiobox-inner" style={{ pointerEvents: !interactive ? "none" : undefined }}>
- {!this.path ?
- <div className="audiobox-buttons">
- <div className="audiobox-dictation" onClick={this.onFile}>
- <FontAwesomeIcon style={{ width: "30px", background: this.layoutDoc.playOnSelect ? "yellow" : "rgba(0,0,0,0)" }} icon="file-alt" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
- </div>
- {this.audioState === "recording" ?
- <div className="recording" onClick={e => e.stopPropagation()}>
- <div className="buttons" onClick={this.recordClick}>
- <FontAwesomeIcon style={{ width: "100%" }} icon={"stop"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
- </div>
- <div className="buttons" onClick={this._paused ? this.recordPlay : this.recordPause}>
- <FontAwesomeIcon style={{ width: "100%" }} icon={this._paused ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
- </div>
- <div className="time">{formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}</div>
+ return <div className="audiobox-container" onContextMenu={this.specificContextMenu} onClick={!this.path && !this._recorder ? this.recordAudioAnnotation : undefined} style={{ pointerEvents: !interactive ? "none" : undefined }}>
+ {!this.path ?
+ <div className="audiobox-buttons">
+ <div className="audiobox-dictation" onClick={this.onFile}>
+ <FontAwesomeIcon style={{ width: "30px", background: this.layoutDoc.playOnSelect ? "yellow" : "rgba(0,0,0,0)" }} icon="file-alt" size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
+ </div>
+ {this.audioState === "recording" || this.audioState === "paused" ?
+ <div className="recording" onClick={e => e.stopPropagation()}>
+ <div className="buttons" onClick={this.recordClick}>
+ <FontAwesomeIcon style={{ width: "100%" }} icon={"stop"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
+ </div>
+ <div className="buttons" onClick={this._paused ? this.recordPlay : this.recordPause}>
+ <FontAwesomeIcon style={{ width: "100%" }} icon={this._paused ? "play" : "pause"} size={this.props.PanelHeight() < 36 ? "1x" : "2x"} />
</div>
- :
- <button className={`audiobox-record${interactive}`} style={{ backgroundColor: "black" }}>
- RECORD
+ <div className="time">{formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}</div>
+ </div>
+ :
+ <button className={`audiobox-record${interactive}`} style={{ backgroundColor: "black" }}>
+ RECORD
</button>}
- </div> :
- <div className="audiobox-controls" >
- <div className="audiobox-dictation"></div>
- <div className="audiobox-player" >
- <div className="audiobox-playhead" title={this.audioState === "paused" ? "play" : "pause"} onClick={this.onPlay}> <FontAwesomeIcon style={{ width: "100%", position: "absolute", left: "0px", top: "5px", borderWidth: "thin", borderColor: "white" }} icon={this.audioState === "paused" ? "play" : "pause"} size={"1x"} /></div>
- <div className="audiobox-timeline" onClick={e => { e.stopPropagation(); e.preventDefault(); }}
- onPointerDown={e => {
- if (e.button === 0 && !e.ctrlKey) {
- const rect = (e.target as any).getBoundingClientRect();
-
- if (e.target !== this._audioRef.current) {
- const wasPaused = this.audioState === "paused";
- this._ele!.currentTime = this.layoutDoc.currentTimecode = (e.clientX - rect.x) / rect.width * this.audioDuration;
- wasPaused && this.pause();
- }
-
- this.onPointerDownTimeline(e);
- }
- }}>
- <div className="waveform">
- {this.waveform}
- </div>
- {DocListCast(this.dataDoc[this.annotationKey]).map((m, i) =>
- (!m.isLabel) ?
- (this.layoutDoc.hideMarkers) ? (null) :
- <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container1`} key={i}
- title={`${formatTime(Math.round(NumCast(m.audioStart)))}` + " - " + `${formatTime(Math.round(NumCast(m.audioEnd)))}`}
- style={{
- left: `${NumCast(m.audioStart) / this.audioDuration * 100}%`,
- top: `${this.isOverlap(m) * 1 / (this.dataDoc.markerAmount + 1) * 100}%`,
- width: `${(NumCast(m.audioEnd) - NumCast(m.audioStart)) / this.audioDuration * 100}%`, height: `${1 / (this.dataDoc.markerAmount + 1) * 100}%`
- }}
- onClick={e => { this.playFrom(NumCast(m.audioStart), NumCast(m.audioEnd)); e.stopPropagation(); }} >
- <div className="left-resizer" onPointerDown={e => this.onPointerDown(e, m, true)}></div>
- {markerDoc(m, this.rangeScript)}
- <div className="resizer" onPointerDown={e => this.onPointerDown(e, m, false)}></div>
- </div>
- :
- (this.layoutDoc.hideLabels) ? (null) :
- <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container`} key={i}
- style={{ left: `${NumCast(m.audioStart) / this.audioDuration * 100}%` }}>
- {markerDoc(m, this.labelScript)}
- </div>
- )}
- {DocListCast(this.dataDoc.links).map((l, i) => {
- const { la1, la2, linkTime } = this.getLinkData(l);
- let startTime = linkTime;
- if (la2.audioStart && !la2.audioEnd) {
- startTime = NumCast(la2.audioStart);
+ </div> :
+ <div className="audiobox-controls" >
+ <div className="audiobox-dictation"></div>
+ <div className="audiobox-player" >
+ <div className="audiobox-playhead" title={this.audioState === "paused" ? "play" : "pause"} onClick={this.onPlay}> <FontAwesomeIcon style={{ width: "100%", position: "absolute", left: "0px", top: "5px", borderWidth: "thin", borderColor: "white" }} icon={this.audioState === "paused" ? "play" : "pause"} size={"1x"} /></div>
+ <div className="audiobox-timeline" onClick={e => { e.stopPropagation(); e.preventDefault(); }}
+ onPointerDown={e => {
+ if (e.button === 0 && !e.ctrlKey) {
+ const rect = (e.target as any).getBoundingClientRect();
+
+ if (e.target !== this._audioRef.current) {
+ const wasPaused = this.audioState === "paused";
+ this._ele!.currentTime = this.layoutDoc.currentTimecode = (e.clientX - rect.x) / rect.width * this.audioDuration;
+ wasPaused && this.pause();
}
- return !linkTime ? (null) :
- <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container`} key={l[Id]} style={{ left: `${startTime / this.audioDuration * 100}%` }} onClick={e => e.stopPropagation()}>
- <DocumentView {...this.props}
- Document={l}
- NativeHeight={returnZero}
- NativeWidth={returnZero}
- rootSelected={returnFalse}
- ContainingCollectionDoc={this.props.Document}
- parentActive={returnTrue}
- bringToFront={emptyFunction}
- backgroundColor={returnTransparent}
- ContentScaling={returnOne}
- forcedBackgroundColor={returnTransparent}
- pointerEvents={false}
- LayoutTemplate={undefined}
- LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(l, la2)}`)}
- />
- <div key={i} className={`audiobox-marker`} onPointerEnter={() => Doc.linkFollowHighlight(la1)}
- onPointerDown={e => { if (e.button === 0 && !e.ctrlKey) { this.playFrom(startTime); e.stopPropagation(); e.preventDefault(); } }} />
- </div>;
- })}
- {this._visible ? this.selectionContainer : null}
-
- <div className="audiobox-current" ref={this._audioRef} onClick={e => { e.stopPropagation(); e.preventDefault(); }} style={{ left: `${NumCast(this.layoutDoc.currentTimecode) / this.audioDuration * 100}%`, pointerEvents: "none" }} />
- {this.audio}
- </div>
- <div className="current-time">
- {formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}
- </div>
- <div className="total-time">
- {formatTime(Math.round(this.audioDuration))}
+ this.onPointerDownTimeline(e);
+ }
+ }}>
+ <div className="waveform">
+ {this.waveform}
</div>
+ {DocListCast(this.dataDoc[this.annotationKey]).map((m, i) =>
+ (!m.isLabel) ?
+ (this.layoutDoc.hideMarkers) ? (null) :
+ <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container1`} key={i}
+ title={`${formatTime(Math.round(NumCast(m.audioStart)))}` + " - " + `${formatTime(Math.round(NumCast(m.audioEnd)))}`}
+ style={{
+ left: `${NumCast(m.audioStart) / this.audioDuration * 100}%`,
+ top: `${this.isOverlap(m) * 1 / (this.dataDoc.markerAmount + 1) * 100}%`,
+ width: `${(NumCast(m.audioEnd) - NumCast(m.audioStart)) / this.audioDuration * 100}%`, height: `${1 / (this.dataDoc.markerAmount + 1) * 100}%`
+ }}
+ onClick={e => { this.playFrom(NumCast(m.audioStart), NumCast(m.audioEnd)); e.stopPropagation(); }} >
+ <div className="left-resizer" onPointerDown={e => this.onPointerDown(e, m, true)}></div>
+ {markerDoc(m, this.rangeScript)}
+ <div className="resizer" onPointerDown={e => this.onPointerDown(e, m, false)}></div>
+ </div>
+ :
+ (this.layoutDoc.hideLabels) ? (null) :
+ <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container`} key={i}
+ style={{ left: `${NumCast(m.audioStart) / this.audioDuration * 100}%` }}>
+ {markerDoc(m, this.labelScript)}
+ </div>
+ )}
+ {DocListCast(this.dataDoc.links).map((l, i) => {
+ const { la1, la2, linkTime } = this.getLinkData(l);
+ let startTime = linkTime;
+ if (la2.audioStart && !la2.audioEnd) {
+ startTime = NumCast(la2.audioStart);
+ }
+
+ return !linkTime ? (null) :
+ <div className={`audiobox-marker-${this.props.PanelHeight() < 32 ? "mini" : ""}container`} key={l[Id]} style={{ left: `${startTime / this.audioDuration * 100}%` }} onClick={e => e.stopPropagation()}>
+ <DocumentView {...this.props}
+ Document={l}
+ NativeHeight={returnZero}
+ NativeWidth={returnZero}
+ rootSelected={returnFalse}
+ ContainingCollectionDoc={this.props.Document}
+ parentActive={returnTrue}
+ bringToFront={emptyFunction}
+ backgroundColor={returnTransparent}
+ ContentScaling={returnOne}
+ forcedBackgroundColor={returnTransparent}
+ pointerEvents={false}
+ LayoutTemplate={undefined}
+ LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(l, la2)}`)}
+ />
+ <div key={i} className={`audiobox-marker`} onPointerEnter={() => Doc.linkFollowHighlight(la1)}
+ onPointerDown={e => { if (e.button === 0 && !e.ctrlKey) { this.playFrom(startTime); e.stopPropagation(); e.preventDefault(); } }} />
+ </div>;
+ })}
+ {this._visible ? this.selectionContainer : null}
+
+ <div className="audiobox-current" ref={this._audioRef} onClick={e => { e.stopPropagation(); e.preventDefault(); }} style={{ left: `${NumCast(this.layoutDoc.currentTimecode) / this.audioDuration * 100}%`, pointerEvents: "none" }} />
+ {this.audio}
+ </div>
+ <div className="current-time">
+ {formatTime(Math.round(NumCast(this.layoutDoc.currentTimecode)))}
+ </div>
+ <div className="total-time">
+ {formatTime(Math.round(this.audioDuration))}
</div>
</div>
- }</div>
+ </div>
+ }
</div>;
}
}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 3f2a590ab..9d61ec6d1 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -102,9 +102,10 @@ export class FieldView extends React.Component<FieldViewProps> {
else if (field instanceof VideoField) {
return <VideoBox {...this.props} />;
}
- else if (field instanceof AudioField) {
- return <AudioBox {...this.props} />;
- } else if (field instanceof DateField) {
+ // else if (field instanceof AudioField) {
+ // return <AudioBox {...this.props} />;
+ //}
+ else if (field instanceof DateField) {
return <p>{field.date.toLocaleString()}</p>;
}
else if (field instanceof Doc) {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c31e7469f..54d79f4b8 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -304,18 +304,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
// for inserting timestamps
insertTime = () => {
+ let audioState;
if (this._first) {
- this._first = false;
DocListCast(this.dataDoc.links).map((l, i) => {
let la1 = l.anchor1 as Doc;
let la2 = l.anchor2 as Doc;
this._linkTime = NumCast(l.anchor2_timecode);
+ audioState = la2.audioState;
if (Doc.AreProtosEqual(la2, this.dataDoc)) {
la1 = l.anchor2 as Doc;
la2 = l.anchor1 as Doc;
this._linkTime = NumCast(l.anchor1_timecode);
+ audioState = la1.audioState;
}
-
});
}
this._currentTime = Date.now();
@@ -336,7 +337,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
}
}
}
- if (time) {
+ if (time && audioState === "recording") {
let value = "";
this._break = false;
value = this.layoutDoc._timeStampOnEnter ? "[" + time + "] " : "\n" + "[" + time + "] ";
diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx
index c6420bab5..d21d326f6 100644
--- a/src/mobile/ImageUpload.tsx
+++ b/src/mobile/ImageUpload.tsx
@@ -177,4 +177,4 @@ export class Uploader extends React.Component<ImageUploadProps> {
);
}
-}
+} \ No newline at end of file
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index 40aa65372..02993fdcb 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -681,4 +681,4 @@ Scripting.addGlobal(function openMobileSettings() { return SettingsManager.Insta
// Other global functions for mobile
Scripting.addGlobal(function switchMobileView(doc: Doc, renderView?: () => JSX.Element, onSwitch?: () => void) { return MobileInterface.Instance.switchCurrentView(doc, renderView, onSwitch); },
- "changes the active document displayed on the Dash Mobile", "(doc: any)");
+ "changes the active document displayed on the Dash Mobile", "(doc: any)"); \ No newline at end of file
diff --git a/src/mobile/MobileMenu.scss b/src/mobile/MobileMenu.scss
index e69de29bb..7f286efc4 100644
--- a/src/mobile/MobileMenu.scss
+++ b/src/mobile/MobileMenu.scss
@@ -0,0 +1,271 @@
+$navbar-height: 120px;
+$pathbar-height: 50px;
+
+* {
+ margin: 0px;
+ padding: 0px;
+ box-sizing: border-box;
+ font-family: "Open Sans";
+}
+
+body {
+ overflow: hidden;
+}
+
+.navbar {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ width: 100vw;
+ height: $navbar-height;
+ background-color: whitesmoke;
+ border-bottom: 5px solid black;
+}
+
+.navbar .toggle-btn {
+ position: absolute;
+ right: 20px;
+ top: 30px;
+ height: 70px;
+ width: 70px;
+ transition: all 300ms ease-in-out 200ms;
+}
+
+.navbar .header {
+ position: absolute;
+ top: 50%;
+ top: calc(9px + 50%);
+ right: 50%;
+ transform: translate(50%, -50%);
+ font-size: 40;
+ user-select: none;
+ text-transform: uppercase;
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+.navbar .toggle-btn span {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ width: 70%;
+ height: 4px;
+ background: black;
+ transition: all 200ms ease;
+}
+
+.navbar .toggle-btn span:nth-child(1) {
+ transition: top 200ms ease-in-out;
+ top: 30%;
+}
+
+.navbar .toggle-btn span:nth-child(3) {
+ transition: top 200ms ease-in-out;
+ top: 70%;
+}
+
+.navbar .toggle-btn.active {
+ transition: transform 200ms ease-in-out 200ms;
+ transform: rotate(135deg);
+}
+
+.navbar .toggle-btn.active span:nth-child(1) {
+ top: 50%;
+}
+
+.navbar .toggle-btn.active span:nth-child(2) {
+ transform: translate(-50%, -50%) rotate(90deg);
+}
+
+.navbar .toggle-btn.active span:nth-child(3) {
+ top: 50%;
+}
+// .navbar .home {
+// position: relative;
+// right: 5px;
+// transform: translate(50%, -50%);
+// font-size: 40;
+// user-select: none;
+// text-transform: uppercase;
+// font-family: Arial, Helvetica, sans-serif;
+// z-index: 200;
+// }
+
+.sidebar {
+ position: absolute;
+ top: 200px;
+ opacity: 0;
+ right: -100%;
+ width: 100%;
+ height: calc(100% - (200px));
+ z-index: 5;
+ background-color: whitesmoke;
+ transition: all 400ms ease 50ms;
+ padding: 20px;
+ // overflow-y: auto;
+ // -webkit-overflow-scrolling: touch;
+
+ // border-right: 5px solid black;
+}
+
+.sidebar .item {
+ width: 100%;
+ padding: 13px 12px;
+ border-bottom: 1px solid rgba(200, 200, 200, 0.7);
+ font-family: Arial, Helvetica, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ user-select: none;
+ font-size: 35px;
+ text-transform: uppercase;
+ color: black;
+
+}
+
+.sidebar .ink {
+ width: 100%;
+ padding: 13px 12px;
+ border-bottom: 1px solid rgba(200, 200, 200, 0.7);
+ font-family: Arial, Helvetica, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ user-select: none;
+ font-size: 35px;
+ text-transform: uppercase;
+ color: black;
+}
+
+.sidebar .ink:focus {
+ outline: 1px solid blue;
+}
+
+.sidebar .home {
+ position: absolute;
+ top: -135px;
+ right: calc(50% + 80px);
+ transform: translate(0%, -50%);
+ font-size: 40;
+ user-select: none;
+ text-transform: uppercase;
+ font-family: Arial, Helvetica, sans-serif;
+ z-index: 200;
+}
+
+.type {
+ display: inline;
+ text-transform: lowercase;
+ margin-left: 20px;
+ font-size: 35px;
+ font-style: italic;
+ color: rgb(28, 28, 28);
+}
+
+.right {
+ margin-left: 20px;
+ z-index: 200;
+}
+
+.left {
+ width: 100%;
+ height: 100%;
+}
+
+.sidebar .logout {
+ width: 100%;
+ padding: 13px 12px;
+ border-bottom: 1px solid rgba(200, 200, 200, 0.7);
+ font-family: Arial, Helvetica, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ user-select: none;
+ font-size: 30px;
+ text-transform: uppercase;
+ color: black;
+}
+
+.sidebar .settings {
+ width: 100%;
+ padding: 13px 12px;
+ border-bottom: 1px solid rgba(200, 200, 200, 0.7);
+ font-family: Arial, Helvetica, sans-serif;
+ font-style: normal;
+ font-weight: normal;
+ user-select: none;
+ font-size: 30px;
+ text-transform: uppercase;
+ color: black;
+}
+
+
+.sidebar.active {
+ right: 0%;
+ opacity: 1;
+}
+
+.back {
+ position: absolute;
+ top: -140px;
+ left: 50px;
+ transform: translate(0%, -50%);
+ color: black;
+ font-size: 60;
+ user-select: none;
+ text-transform: uppercase;
+ z-index: 100;
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+
+.pathbar {
+ position: absolute;
+ top: 118px;
+ background: #1a1a1a;
+ z-index: 20;
+ border-radius: 0px;
+ width: 100%;
+ height: 80px;
+ transition: all 400ms ease 50ms;
+}
+
+.pathname {
+ position: relative;
+ font-size: 25;
+ top: 50%;
+ width: 90%;
+ left: 3%;
+ color: whitesmoke;
+ transform: translate(0%, -50%);
+ z-index: 20;
+ font-family: sans-serif;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ direction: rtl;
+ text-align: left;
+ text-transform: uppercase;
+}
+
+.homeContainer {
+ position: relative;
+ top: 200px;
+ height: calc(100% - 250px);
+ width: 90%;
+ overflow: scroll;
+ left: 5%;
+ background-color: lightpink;
+}
+
+.pinButton {
+ position: relative;
+ width: 100px;
+ height: 100px;
+ font-size: 90px;
+ text-align: center;
+ left: 50%;
+ transform: translate(-50%, 0);
+ border-style: solid;
+ border-radius: 50px;
+ border-width: medium;
+ background-color: pink;
+ z-index: 100;
+} \ No newline at end of file