From f6bc505597463cc8f593e00d74b421175a69f7f3 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 28 Jul 2020 00:20:51 +0200 Subject: some fullscreen elements fading in... --- .../frontend/app/views/align/align.reducer.js | 2 +- .../annotationTypes/annotationTypes.utility.js | 2 +- .../frontend/app/views/audio/audio.actions.js | 2 +- .../components.fullscreen/fullscreen.image.js | 16 ++++++ .../components.fullscreen/fullscreen.utility.js | 18 ++++++ .../viewer/player/components.fullscreen/index.js | 19 +++++++ .../player/components.inline/elementTypes.image.js | 46 --------------- .../player/components.inline/elementTypes.text.js | 37 ------------ .../player/components.inline/elementTypes.video.js | 21 ------- .../views/viewer/player/components.inline/index.js | 6 +- .../player/components.inline/inline.image.js | 46 +++++++++++++++ .../viewer/player/components.inline/inline.text.js | 37 ++++++++++++ .../player/components.inline/inline.video.js | 21 +++++++ .../app/views/viewer/player/player.container.js | 8 +-- .../app/views/viewer/player/player.fullscreen.css | 37 +++++++++++- .../app/views/viewer/player/player.fullscreen.js | 65 +++++++++++++++++++++- .../frontend/app/views/viewer/viewer.actions.js | 19 +++++-- 17 files changed, 279 insertions(+), 123 deletions(-) create mode 100644 animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.image.js create mode 100644 animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.utility.js create mode 100644 animism-align/frontend/app/views/viewer/player/components.fullscreen/index.js delete mode 100644 animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.image.js delete mode 100644 animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.text.js delete mode 100644 animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.video.js create mode 100644 animism-align/frontend/app/views/viewer/player/components.inline/inline.image.js create mode 100644 animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js create mode 100644 animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js (limited to 'animism-align/frontend/app/views') diff --git a/animism-align/frontend/app/views/align/align.reducer.js b/animism-align/frontend/app/views/align/align.reducer.js index 1f79180..50498c5 100644 --- a/animism-align/frontend/app/views/align/align.reducer.js +++ b/animism-align/frontend/app/views/align/align.reducer.js @@ -20,7 +20,7 @@ export default function alignReducer(state = initialState, action) { // console.log(action.type, action) switch (action.type) { case types.peaks.loaded: - console.log('peaks duration:', action.data.length / 10) + // console.log('peaks duration:', action.data.length / 10) return state case types.align.set_display_setting: diff --git a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.utility.js b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.utility.js index a3c35d4..8b59e18 100644 --- a/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.utility.js +++ b/animism-align/frontend/app/views/align/components/annotations/annotationTypes/annotationTypes.utility.js @@ -33,7 +33,7 @@ export const checkAnnotationMediaNotReady = (annotation, media) => { return (!media) || (!(annotation.settings.media_id in media)) } -export const AnnotationMediaLoading = ({ y, className, onClick, onDoubleClick }) => { +export const AnnotationMediaLoading = ({ y, media, className, onClick, onDoubleClick }) => { if (!media) { return (
{ - console.log('audio duration:', audioPlayer.duration) + // console.log('audio duration:', audioPlayer.duration) dispatch({ type: types.align.set_display_setting, key: 'duration', value: audioPlayer.duration }) }) audioPlayer.addEventListener('play', () => { diff --git a/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.image.js b/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.image.js new file mode 100644 index 0000000..c0e4b0e --- /dev/null +++ b/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.image.js @@ -0,0 +1,16 @@ +import React from 'react' + +export const Image = ({ element, media, transitionDuration }) => { + const item = media.lookup[element.settings.media_id] + const style = { + transitionDuration, + backgroundImage: 'url(' + item.settings.display.url + ')', + } + return ( +
+
+ ) +} diff --git a/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.utility.js b/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.utility.js new file mode 100644 index 0000000..c86236d --- /dev/null +++ b/animism-align/frontend/app/views/viewer/player/components.fullscreen/fullscreen.utility.js @@ -0,0 +1,18 @@ +import React from 'react' + +export const Curtain = ({ element, transitionDuration }) => { + // console.log(element, isEntering) + const { color } = element + const style = { + backgroundColor: color.backgroundColor, + color: color.textColor, + transitionDuration, + } + return ( +
+
+ ) +} diff --git a/animism-align/frontend/app/views/viewer/player/components.fullscreen/index.js b/animism-align/frontend/app/views/viewer/player/components.fullscreen/index.js new file mode 100644 index 0000000..3befbde --- /dev/null +++ b/animism-align/frontend/app/views/viewer/player/components.fullscreen/index.js @@ -0,0 +1,19 @@ +import React from 'react' + +// import { +// MediaVideo +// } from './fullscreen.video' + +import { + Image +} from './fullscreen.image' + +import { + Curtain +} from './fullscreen.utility' + +export const fullscreenComponents = { + curtain: React.memo(Curtain), + // video: React.memo(MediaVideo), + image: React.memo(Image), +} diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.image.js b/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.image.js deleted file mode 100644 index f005fc0..0000000 --- a/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.image.js +++ /dev/null @@ -1,46 +0,0 @@ -import React, { Component } from 'react' - -export const MediaCitation = ({ media }) => { - if (media.citation) { - return ( - - ) - } - return ( - - {media.author} - {', '} - {media.pre_title} - {media.title} - {media.post_title} - {'. '} - {media.date && ( - ' ' + media.date + '.' - )} - {media.medium && ( - ' ' + media.medium + '.' - )} - {media.source && ( - ' ' + media.source.trim() - )} - - ) -} - -export const MediaImage = ({ paragraph, media, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => { - if (!media.lookup) return
- const className = currentParagraph ? 'media image current' : 'media image' - const annotation = paragraph.annotations[0] - const item = media.lookup[annotation.settings.media_id] - if (!item) return
Media not found: {annotation.settings.media_id}
- return ( -
onDoubleClick(e, paragraph)} - > - {"["} - - {"]"} -
- ) -} diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.text.js b/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.text.js deleted file mode 100644 index 8825479..0000000 --- a/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.text.js +++ /dev/null @@ -1,37 +0,0 @@ -import React, { Component } from 'react' - -import { ROMAN_NUMERALS } from 'app/constants' - -export const Paragraph = ({ paragraph, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => { - let className = paragraph.type - if (className !== 'paragraph') className += ' paragraph' - if (currentParagraph) className += ' current' - return ( -
onDoubleClick(e, paragraph)} - > - {paragraph.annotations.map(annotation => ( - onAnnotationClick(e, paragraph, annotation)} - dangerouslySetInnerHTML={{ __html: ' ' + annotation.text + ' ' }} - /> - ))} -
- ) -} - -export const ParagraphHeading = ({ paragraph, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => { - let className = currentParagraph ? 'header current' : 'header' - const text = paragraph.annotations.map(annotation => annotation.text).join(' ') - return ( -
onDoubleClick(e, paragraph)} - > - {ROMAN_NUMERALS[paragraph.sectionIndex]}{'. '}{text} -
- ) -} diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.video.js b/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.video.js deleted file mode 100644 index fe821eb..0000000 --- a/animism-align/frontend/app/views/viewer/player/components.inline/elementTypes.video.js +++ /dev/null @@ -1,21 +0,0 @@ -import React, { Component } from 'react' - -import { MediaCitation } from './elementTypes.image' - -export const MediaVideo = ({ paragraph, media, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => { - if (!media.lookup) return
- const className = currentParagraph ? 'media current' : 'media' - const annotation = paragraph.annotations[0] - const item = media.lookup[annotation.settings.media_id] - if (!item) return
Media not found: {annotation.settings.media_id}
- return ( -
onDoubleClick(e, paragraph)} - > - {"["} - - {"]"} -
- ) -} diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/index.js b/animism-align/frontend/app/views/viewer/player/components.inline/index.js index ee65641..89d1d42 100644 --- a/animism-align/frontend/app/views/viewer/player/components.inline/index.js +++ b/animism-align/frontend/app/views/viewer/player/components.inline/index.js @@ -2,15 +2,15 @@ import React from 'react' import { Paragraph, ParagraphHeading -} from './elementTypes.text' +} from './inline.text' import { MediaVideo -} from './elementTypes.video' +} from './inline.video' import { MediaImage -} from './elementTypes.image' +} from './inline.image' export const transcriptElementLookup = { paragraph: React.memo(Paragraph), diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/inline.image.js b/animism-align/frontend/app/views/viewer/player/components.inline/inline.image.js new file mode 100644 index 0000000..f005fc0 --- /dev/null +++ b/animism-align/frontend/app/views/viewer/player/components.inline/inline.image.js @@ -0,0 +1,46 @@ +import React, { Component } from 'react' + +export const MediaCitation = ({ media }) => { + if (media.citation) { + return ( + + ) + } + return ( + + {media.author} + {', '} + {media.pre_title} + {media.title} + {media.post_title} + {'. '} + {media.date && ( + ' ' + media.date + '.' + )} + {media.medium && ( + ' ' + media.medium + '.' + )} + {media.source && ( + ' ' + media.source.trim() + )} + + ) +} + +export const MediaImage = ({ paragraph, media, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => { + if (!media.lookup) return
+ const className = currentParagraph ? 'media image current' : 'media image' + const annotation = paragraph.annotations[0] + const item = media.lookup[annotation.settings.media_id] + if (!item) return
Media not found: {annotation.settings.media_id}
+ return ( +
onDoubleClick(e, paragraph)} + > + {"["} + + {"]"} +
+ ) +} diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js b/animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js new file mode 100644 index 0000000..8825479 --- /dev/null +++ b/animism-align/frontend/app/views/viewer/player/components.inline/inline.text.js @@ -0,0 +1,37 @@ +import React, { Component } from 'react' + +import { ROMAN_NUMERALS } from 'app/constants' + +export const Paragraph = ({ paragraph, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => { + let className = paragraph.type + if (className !== 'paragraph') className += ' paragraph' + if (currentParagraph) className += ' current' + return ( +
onDoubleClick(e, paragraph)} + > + {paragraph.annotations.map(annotation => ( + onAnnotationClick(e, paragraph, annotation)} + dangerouslySetInnerHTML={{ __html: ' ' + annotation.text + ' ' }} + /> + ))} +
+ ) +} + +export const ParagraphHeading = ({ paragraph, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => { + let className = currentParagraph ? 'header current' : 'header' + const text = paragraph.annotations.map(annotation => annotation.text).join(' ') + return ( +
onDoubleClick(e, paragraph)} + > + {ROMAN_NUMERALS[paragraph.sectionIndex]}{'. '}{text} +
+ ) +} diff --git a/animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js b/animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js new file mode 100644 index 0000000..fe821eb --- /dev/null +++ b/animism-align/frontend/app/views/viewer/player/components.inline/inline.video.js @@ -0,0 +1,21 @@ +import React, { Component } from 'react' + +import { MediaCitation } from './elementTypes.image' + +export const MediaVideo = ({ paragraph, media, currentParagraph, currentAnnotation, onAnnotationClick, onDoubleClick }) => { + if (!media.lookup) return
+ const className = currentParagraph ? 'media current' : 'media' + const annotation = paragraph.annotations[0] + const item = media.lookup[annotation.settings.media_id] + if (!item) return
Media not found: {annotation.settings.media_id}
+ return ( +
onDoubleClick(e, paragraph)} + > + {"["} + + {"]"} +
+ ) +} diff --git a/animism-align/frontend/app/views/viewer/player/player.container.js b/animism-align/frontend/app/views/viewer/player/player.container.js index 1ddb5c7..9655955 100644 --- a/animism-align/frontend/app/views/viewer/player/player.container.js +++ b/animism-align/frontend/app/views/viewer/player/player.container.js @@ -1,8 +1,8 @@ import React, { Component } from 'react' import { connect } from 'react-redux' -import { floatInRange } from 'app/utils' import actions from 'app/actions' +import { floatInRange } from 'app/utils' import PlayerTranscript from './player.transcript' import PlayerFullscreen from './player.fullscreen' @@ -38,17 +38,16 @@ class PlayerContainer extends Component { actions.viewer.setCurrentSection(sections[0]) } } - render() { // const { } = this.props - const { currentSection, fullscreenTimeline } = this.props + const { currentSection } = this.props if (!currentSection) { return
} // console.log(currentSection) return (
- +
) } @@ -57,7 +56,6 @@ class PlayerContainer extends Component { const mapStateToProps = state => ({ audio: state.audio, sections: state.viewer.sections, - fullscreenTimeline: state.viewer.fullscreenTimeline, currentSection: state.viewer.currentSection, }) diff --git a/animism-align/frontend/app/views/viewer/player/player.fullscreen.css b/animism-align/frontend/app/views/viewer/player/player.fullscreen.css index 8041c84..fb4d8af 100644 --- a/animism-align/frontend/app/views/viewer/player/player.fullscreen.css +++ b/animism-align/frontend/app/views/viewer/player/player.fullscreen.css @@ -11,4 +11,39 @@ .viewer-fullscreen.active { pointer-events: auto; user-select: auto; -} \ No newline at end of file +} + +/* transitions */ + +.viewer-fullscreen .fade-enter { + opacity: 0; +} +.viewer-fullscreen .fade-enter.fade-enter-active { + opacity: 1; + transition-property: opacity; +} +.viewer-fullscreen .fade-exit { + opacity: 1; +} +.viewer-fullscreen .fade-exit-active { + opacity: 0; + transition-property: opacity; +} + +/* elements */ + +.viewer-fullscreen .fullscreen-element { + position: absolute; + width: 100%; + height: 100%; + top: 0; + left: 0; +} + +.viewer-fullscreen .curtain { +} + +.viewer-fullscreen .image { + background-size: cover; + background-position: center center; +} diff --git a/animism-align/frontend/app/views/viewer/player/player.fullscreen.js b/animism-align/frontend/app/views/viewer/player/player.fullscreen.js index 89052ed..47c6cd2 100644 --- a/animism-align/frontend/app/views/viewer/player/player.fullscreen.js +++ b/animism-align/frontend/app/views/viewer/player/player.fullscreen.js @@ -1,22 +1,83 @@ import React, { Component } from 'react' import { connect } from 'react-redux' +import { TransitionGroup, CSSTransition } from 'react-transition-group' import actions from 'app/actions' +import { floatInRange, floatLT } from 'app/utils' + +import { fullscreenComponents } from './components.fullscreen' class PlayerFullscreen extends Component { + state = { + elements: [], + } + componentDidMount() { + this.setCurrentElements() + } + + componentDidUpdate(prevProps) { + if (this.props.audio.play_ts === prevProps.audio.play_ts) return + this.setCurrentElements() } - + + setCurrentElements() { + const { audio, timeline } = this.props + const { play_ts } = audio + const elements = timeline.filter(element => ( + floatInRange(element.start_ts, play_ts, element.fade_out_start_ts + 0.1) + )) + this.setState({ elements }) + } + render() { - const { } = this.props + const { audio, media } = this.props + const { play_ts } = audio + const { elements } = this.state + // console.log(elements, play_ts) return (
+ + {elements.map(element => { + if (!(element.type in fullscreenComponents)) { + return null + } + const isEntering = floatInRange(element.start_ts, play_ts, element.fade_in_end_ts) + const FullscreenComponent = fullscreenComponents[element.type] + const transitionDuration = (isEntering ? (1000 * element.fadeInDuration) : (1000 * element.fadeOutDuration)) + 'ms' + return ( + + + + ) + })} +
) } } +const FirstChild = (props) => { + const childrenArray = React.Children.toArray(props.children); + return childrenArray[0] || null; +} + const mapStateToProps = state => ({ + audio: state.audio, + media: state.media.index, + timeline: state.viewer.fullscreenTimeline, }) export default connect(mapStateToProps)(PlayerFullscreen) diff --git a/animism-align/frontend/app/views/viewer/viewer.actions.js b/animism-align/frontend/app/views/viewer/viewer.actions.js index 836c677..a456646 100644 --- a/animism-align/frontend/app/views/viewer/viewer.actions.js +++ b/animism-align/frontend/app/views/viewer/viewer.actions.js @@ -3,6 +3,7 @@ import { store, history, dispatch } from 'app/store' import { MEDIA_ANNOTATION_TYPES, MEDIA_LABEL_TYPES, TEXT_ANNOTATION_TYPES, UTILITY_ANNOTATION_TYPES, + CURTAIN_COLOR_LOOKUP, } from 'app/constants' import { buildParagraphs } from 'app/utils/transcript.utils' import { annotationFadeTimings } from 'app/utils/annotation.utils' @@ -26,6 +27,7 @@ export const loadSections = () => dispatch => { // keep tally of all media, so that we can display them with correct IDs in the checklist let mediaIndex = 0 + let eventIndex = 0 // dedupe the labels that we see in each section let currentMediaLabels = {} @@ -96,7 +98,7 @@ export const loadSections = () => dispatch => { // build timeline of fullscreen events if (UTILITY_ANNOTATION_TYPES.has(annotation.type) || annotation.settings.fullscreen) { - const event = makeFullscreenEvent(annotation) + const event = makeFullscreenEvent(eventIndex++, annotation) fullscreenTimeline.push(event) } @@ -121,15 +123,22 @@ export const loadSections = () => dispatch => { } } - console.log(sections) - console.log(fullscreenTimeline) + // console.log(sections) + // console.log(fullscreenTimeline) dispatch({ type: types.viewer.load_sections, sections, fullscreenTimeline }) } -const makeFullscreenEvent = annotation => { +const makeFullscreenEvent = (index, annotation) => { const timing = annotationFadeTimings(annotation) const event = { - annotation, timing + ...timing, + annotation, + index, + settings: annotation.settings, + type: annotation.type, + } + if (event.type === 'curtain') { + event.color = CURTAIN_COLOR_LOOKUP[annotation.settings.color] || CURTAIN_COLOR_LOOKUP.white } return event } -- cgit v1.2.3-70-g09d2