diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-09-28 17:02:03 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-09-28 17:02:03 +0200 |
| commit | ce80f0fe7fa60fe5666057ed88c5ca69634df083 (patch) | |
| tree | fc01da35aa7df6343ab79b739f93747009403501 /animism-align | |
| parent | 62f491d7bb3e1a3c44ad35a5250896e4d1c74c9d (diff) | |
share dialog
Diffstat (limited to 'animism-align')
8 files changed, 162 insertions, 13 deletions
diff --git a/animism-align/frontend/app/views/viewer/nav/nav.css b/animism-align/frontend/app/views/viewer/nav/nav.css index a5c19d0..f84470f 100644 --- a/animism-align/frontend/app/views/viewer/nav/nav.css +++ b/animism-align/frontend/app/views/viewer/nav/nav.css @@ -128,6 +128,57 @@ opacity: 1; } +/* Share box */ + +.nav-share { + position: absolute; + bottom: 3rem; + left: 0; + width: 20rem; + transform: translateY(30rem); + transition: opacity 0.01s, transform 0.2s; + padding: 0.5rem 1.5rem; + background: black; + border: 1px solid white; + color: white; + font-size: 18px; + /*opacity: 0;*/ +} +.checklist-open .nav-share { + top: 3rem; + z-index: 21; + transform: translateY(-30rem); + bottom: auto; +} +.share-open .nav-share { + transform: translateY(0); + opacity: 1; +} +.nav-share a { + color: white; + text-decoration: none; +} +.nav-share .share-success { + display: none; +} +.nav-share.copying .share-success { + margin-left: 1rem; + display: inline; + opacity: 1; + color: white; + font-size: 0.75rem; +} +.nav-share.copying.copied .share-success { + opacity: 0; + transition: opacity 1.0s 1.0s; +} +.nav-share .share-option { + padding: 0.5rem 0; +} +.nav-share .share-copy { + cursor: pointer; +} + /* Arrows */ .arrow svg { @@ -254,4 +305,4 @@ } .zoomPlus path { stroke: white; -}
\ No newline at end of file +} diff --git a/animism-align/frontend/app/views/viewer/nav/nav.share.js b/animism-align/frontend/app/views/viewer/nav/nav.share.js new file mode 100644 index 0000000..1e32860 --- /dev/null +++ b/animism-align/frontend/app/views/viewer/nav/nav.share.js @@ -0,0 +1,65 @@ +import React, { Component } from 'react' + +import { writeToClipboard } from 'app/utils' + +export default class NavShare extends Component { + state = { + copied: false, + } + constructor(props){ + super(props) + this.copyToClipboard = this.copyToClipboard.bind(this) + } + copyToClipboard() { + const url = "https://e-flux.com/" + writeToClipboard(url).then(() =>{ + clearTimeout(this.timeout) + this.setState({ copying: true, copied: false, }) + this.timeout = setTimeout(() => { + this.setState({ copying: true, copied: true }) + this.timeout = setTimeout(() => this.setState({ copied: false, copying: false, }), 2200) + }, 50) + }) + } + render() { + const { viewer } = this.props + let className = "nav-share" + if (this.state.copying) className += " copying" + if (this.state.copied) className += " copied" + const title = "Animism Episode 1" + const url = "https://e-flux.com/" + const mailtoURL = ( + "mailto:?subject=" + encodeURIComponent(title) + + "&body=" + encodeURIComponent("I want to share this post on e-flux: " + url + "\n\n\n") + ) + const facebookURL = ( + "https://www.facebook.com/sharer.php" + + "?u=" + encodeURIComponent(url) + + "&t=" + encodeURIComponent(title) + ) + const twitterURL = ( + "https://twitter.com/intent/tweet" + + "?url=" + encodeURIComponent(url) + + "&text=" + encodeURIComponent(title) + ) + return ( + <div className={className}> + <div className="share-option"> + <a href={mailtoURL}>Email</a> + </div> + <div className="share-option"> + <a href={facebookURL}>Facebook</a> + </div> + <div className="share-option"> + <a href={twitterURL}>Twitter</a> + </div> + <div className="share-option"> + <div className="share-copy" onClick={this.copyToClipboard}> + Copy Link + <span className="share-success">success</span> + </div> + </div> + </div> + ) + } +} diff --git a/animism-align/frontend/app/views/viewer/sections/sections.css b/animism-align/frontend/app/views/viewer/sections/sections.css index a60a063..4858d7a 100644 --- a/animism-align/frontend/app/views/viewer/sections/sections.css +++ b/animism-align/frontend/app/views/viewer/sections/sections.css @@ -19,6 +19,9 @@ transform: translateZ(0) translateY(calc(3rem - 100vh)); z-index: 20; } +.sections-nav { + z-index: 22; +} /* scrolling part */ @@ -29,6 +32,9 @@ overflow-x: scroll; overflow-y: hidden; } +.checklist-open .viewer-sections .viewer-sections-scroll { + overflow-x: hidden; +} .viewer-sections-scroll::-webkit-scrollbar { cursor: pointer; user-select: none; diff --git a/animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js b/animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js index 19eb385..5a2971b 100644 --- a/animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js +++ b/animism-align/frontend/app/views/viewer/sections/viewer.sections.nav.js @@ -12,8 +12,8 @@ class ViewerSectionsNav extends Component { <div className="viewer-nav sections-nav"> <div className='nav-row'> <div> - <span className="share-link link"> - <Arrow type={'up'} /> + <span className="share-link link" onClick={() => actions.viewer.toggleComponent('share')}> + <Arrow type={viewer.checklist ? 'down' : 'up'} /> {'Share'} </span> </div> @@ -24,10 +24,7 @@ class ViewerSectionsNav extends Component { </span> </div> <div> - <span className="transcript-link link" onClick={() => { - actions.viewer.hideComponent('checklist') - actions.viewer.toggleComponent('transcript') - }}> + <span className="transcript-link link" onClick={() => actions.viewer.openTranscript()}> {'Transcript'} </span> </div> diff --git a/animism-align/frontend/app/views/viewer/viewer.actions.js b/animism-align/frontend/app/views/viewer/viewer.actions.js index 25a353f..10d6edd 100644 --- a/animism-align/frontend/app/views/viewer/viewer.actions.js +++ b/animism-align/frontend/app/views/viewer/viewer.actions.js @@ -226,7 +226,17 @@ export const hideComponent = key => dispatch => { } export const toggleComponent = key => dispatch => { - dispatch({ type: types.viewer.toggle_component, key, value: !store.getState().viewer[key] }) + const state = store.getState().viewer + if (key !== "share" && state.share) { + dispatch({ type: types.viewer.toggle_component, key: "share", value: false }) + } + dispatch({ type: types.viewer.toggle_component, key, value: !state[key] }) +} + +export const openTranscript = () => dispatch => { + actions.viewer.hideComponent('checklist') + actions.viewer.hideComponent('share') + actions.viewer.toggleComponent('transcript') } export const reachedEndOfSection = currentSection => dispatch => { @@ -255,6 +265,7 @@ export const seekToSection = section => dispatch => { actions.audio.seek(section.start_ts) actions.audio.play() actions.viewer.hideComponent('nav') + actions.viewer.hideComponent('share') } export const seekToMediaItem = (section, mediaItem) => dispatch => { @@ -263,6 +274,7 @@ export const seekToMediaItem = (section, mediaItem) => dispatch => { actions.audio.play() actions.viewer.hideComponent('nav') actions.viewer.hideComponent('checklist') + actions.viewer.hideComponent('share') } export const seekToTimestamp = play_ts => dispatch => { diff --git a/animism-align/frontend/app/views/viewer/viewer.container.js b/animism-align/frontend/app/views/viewer/viewer.container.js index 030d8b1..61e095d 100644 --- a/animism-align/frontend/app/views/viewer/viewer.container.js +++ b/animism-align/frontend/app/views/viewer/viewer.container.js @@ -21,6 +21,7 @@ import NavParent from './nav/nav.parent' import ViewerSections from './sections/viewer.sections' import ViewerRouter from './nav/viewer.router' import EfluxChrome from './nav/eflux.chrome' +import NavShare from './nav/nav.share' import Player from './player/player.container' import Transcript from './transcript/transcript.container' import Checklist from './checklist/checklist.container' @@ -39,6 +40,9 @@ class ViewerContainer extends Component { if (viewer.transcript) className += ' transcript-open' if (viewer.nav) className += ' nav-open' } + if (viewer.share) { + className += ' share-open' + } return ( <div> <div className='viewer-parent'> @@ -49,6 +53,7 @@ class ViewerContainer extends Component { <ViewerSections /> <Transcript /> <Checklist /> + <NavShare /> <Route exact path='/viewer/:component/' component={ViewerRouter} /> </div> <VitrineModal /> diff --git a/animism-align/frontend/app/views/viewer/viewer.css b/animism-align/frontend/app/views/viewer/viewer.css index b0df181..9f1238e 100644 --- a/animism-align/frontend/app/views/viewer/viewer.css +++ b/animism-align/frontend/app/views/viewer/viewer.css @@ -1,7 +1,8 @@ .viewer-parent { - position: relative; + position: fixed; width: 100vw; height: 100vh; + top: 0; left: 0; } .viewer { position: relative; diff --git a/animism-align/frontend/app/views/viewer/viewer.reducer.js b/animism-align/frontend/app/views/viewer/viewer.reducer.js index 70e94ee..1589ea4 100644 --- a/animism-align/frontend/app/views/viewer/viewer.reducer.js +++ b/animism-align/frontend/app/views/viewer/viewer.reducer.js @@ -2,25 +2,37 @@ import * as types from 'app/types' import { GROWL } from 'app/constants' const initialState = { + /* UI component display state */ transcript: false, checklist: false, nav: false, + share: false, + + /* section look and navigation */ sections: { loading: true }, currentSection: null, nextSection: null, - navStyle: 'white', - mediaTitle: null, autoAdvance: false, atEndOfSection: false, + + /* color of the bar / logo / icons */ + navStyle: 'white', + + /* title of media if in fullscreen mode */ + mediaTitle: null, + + /* growl message at top */ growlOpen: true, growlMessage: GROWL.OPENING_MESSAGE, + + /* vitrine */ vitrineModal: { open: false, media: null, index: null, }, - options: { - } + + options: {}, } export default function viewerReducer(state = initialState, action) { |
