diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-07-05 17:02:39 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-07-05 17:02:39 +0200 |
| commit | 3e5bc2f5581890f2d7d9f679ab5171c0637ff460 (patch) | |
| tree | fc88ac2387974ba0bd8377957732fdf697cef961 /animism-align/frontend | |
| parent | bc1515b965e02641cab2a984410a3cb5cfae891c (diff) | |
notion of selected annotation
Diffstat (limited to 'animism-align/frontend')
8 files changed, 82 insertions, 20 deletions
diff --git a/animism-align/frontend/app.js b/animism-align/frontend/app.js index 1c40c09..9270cc8 100644 --- a/animism-align/frontend/app.js +++ b/animism-align/frontend/app.js @@ -20,6 +20,7 @@ export default class App extends Component { actions.site.loadText() actions.site.loadPeaks() actions.annotation.index() + actions.paragraph.index() } render() { return ( diff --git a/animism-align/frontend/views/align/align.actions.js b/animism-align/frontend/views/align/align.actions.js index b10f257..b819584 100644 --- a/animism-align/frontend/views/align/align.actions.js +++ b/animism-align/frontend/views/align/align.actions.js @@ -17,6 +17,14 @@ export const setZoom = zoom => dispatch => { } } +export const setSelectedAnnotation = annotation_id => dispatch => { + dispatch({ type: types.align.set_display_setting, key: 'selected_annotation_id', value: annotation_id }) +} + +export const clearSelectedAnnotation = annotation_id => dispatch => { + dispatch({ type: types.align.set_display_setting, key: 'selected_annotation_id', value: -1 }) +} + export const throttledSetZoom = throttle(zoom => dispatch => { setZoom(zoom)(dispatch) }, 250, { leading: true }) @@ -59,9 +67,22 @@ export const updateAnnotationSettings = (key, value) => dispatch => { dispatch({ type: types.align.update_temporary_annotation_settings, key, value }) } +const getFirstPunctuationMarkIndex = text => { + return Math.min( + text.indexOf('. '), + text.indexOf('? '), + text.indexOf('! '), + text.indexOf('." '), + text.indexOf('?" '), + text.indexOf('!" '), + text.indexOf('.” '), + text.indexOf('?” '), + text.indexOf('!” '), + ) + 1 +} const cutFirstSentence = text => { const textToCrop = text.trim().replace("\n", " ").split("\n")[0] - let cropIndex = textToCrop.indexOf('. ') + 1 + let cropIndex = getFirstPunctuationMarkIndex(textToCrop) if (!cropIndex) cropIndex = textToCrop.length const croppedText = textToCrop.substr(0, cropIndex).trim() const updatedText = text.trim().replace(croppedText, '').trim() diff --git a/animism-align/frontend/views/align/align.css b/animism-align/frontend/views/align/align.css index 799693c..c2de8a1 100644 --- a/animism-align/frontend/views/align/align.css +++ b/animism-align/frontend/views/align/align.css @@ -109,6 +109,7 @@ canvas { position: absolute; left: 0.25rem; background: #448; + z-index: 10; } .annotationForm .row { justify-content: space-between; @@ -119,16 +120,42 @@ canvas { .annotationIndex .annotation { position: absolute; left: 5px; - max-width: 450px; + max-width: 400px; padding: 0.25rem 0.375rem; - box-shadow: 0px 0px 4px rgba(0,0,0,0.7); + box-shadow: 0px 0px 3px rgba(0,0,0,1.0); + border: 1px solid transparent; border-radius: 2px; font-size: 12px; cursor: pointer; } -.annotation.sentence { +.annotation.selected { + border-color: #bbf; + box-shadow: 0px 0px 4px rgba(0,0,0,1.0), 0px 0px 2px rgba(0,0,0,1.0); + z-index: 1; + background-image: linear-gradient(rgba(0,0,0,0.5), rgba(0,0,0,0.4)); +} +.annotation.sentence.even { background-color: #83b; } +.annotation.sentence.odd { + background-color: #638; +} .annotation.header { background-color: #838; } +.annotationIndex.condensed .annotation.sentence { + z-index: 0; + white-space: pre; + overflow: hidden; + text-overflow: ellipsis; +} +.annotationIndex.collapsed .annotation.header { + z-index: 1; +} + +.annotationIndex.collapsed .annotation.sentence { + height: 1px; overflow: hidden; padding: 0; z-index: 0; +} +.annotationIndex.collapsed .annotation.header { + z-index: 1; +} diff --git a/animism-align/frontend/views/align/align.reducer.js b/animism-align/frontend/views/align/align.reducer.js index f080c24..0bd6c56 100644 --- a/animism-align/frontend/views/align/align.reducer.js +++ b/animism-align/frontend/views/align/align.reducer.js @@ -7,6 +7,7 @@ const initialState = { start_ts: 0, zoom: 1, duration: 0, + selected_annotation_id: -1, }, annotation: {}, options: { diff --git a/animism-align/frontend/views/align/components/annotations/annotation.index.js b/animism-align/frontend/views/align/components/annotations/annotation.index.js index 09cb255..9117a80 100644 --- a/animism-align/frontend/views/align/components/annotations/annotation.index.js +++ b/animism-align/frontend/views/align/components/annotations/annotation.index.js @@ -41,18 +41,24 @@ class AnnotationIndex extends Component { }).map(id => lookup[id]).reverse() this.setState({ items }) } - handleClick(annotation) { + handleClick(e, annotation) { actions.audio.seek(annotation.start_ts) + actions.align.setSelectedAnnotation(annotation.id) } - handleDoubleClick(annotation) { + handleDoubleClick(e, annotation) { actions.align.showEditAnnotationForm(annotation) } render() { const { timeline } = this.props - const { start_ts } = timeline + const { start_ts, zoom, selected_annotation_id } = timeline const { items } = this.state + const className = (zoom < 2) + ? 'annotationIndex' + : (zoom < 3) + ? 'annotationIndex condensed' + : 'annotationIndex collapsed' return ( - <div className='annotationIndex'> + <div className={className}> {items.map(annotation => { const { id, type, start_ts } = annotation const AnnotationElement = AnnotationElementLookup[type] @@ -61,6 +67,7 @@ class AnnotationIndex extends Component { <AnnotationElement key={id} y={y} + selected={annotation.id === selected_annotation_id} annotation={annotation} onClick={this.handleClick} onDoubleClick={this.handleDoubleClick} diff --git a/animism-align/frontend/views/align/components/annotations/annotation.types.js b/animism-align/frontend/views/align/components/annotations/annotation.types.js index 465844f..7639821 100644 --- a/animism-align/frontend/views/align/components/annotations/annotation.types.js +++ b/animism-align/frontend/views/align/components/annotations/annotation.types.js @@ -6,28 +6,33 @@ import { ZOOM_STEPS } from '../../constants' import { clamp } from '../../../../util' import { positionToTime, timeToPosition } from '../../align.util' -export const AnnotationSentence = ({ y, annotation, onClick, onDoubleClick }) => { - const { start_ts, text } = annotation +export const AnnotationSentence = ({ y, annotation, selected, onClick, onDoubleClick }) => { + const { start_ts, text, paragraph_id } = annotation + let className = (paragraph_id % 2) + ? 'annotation sentence odd' + : 'annotation sentence even' + if (selected) className += ' selected' return ( <div - className='annotation sentence' + className={className} style={{ top: y }} - onClick={() => onClick(annotation)} - onDoubleClick={() => onDoubleClick(annotation)} + onClick={e => onClick(e, annotation)} + onDoubleClick={e => onDoubleClick(e, annotation)} > {text} </div> ) } -export const AnnotationHeader = ({ y, annotation, onClick, onDoubleClick }) => { +export const AnnotationHeader = ({ y, annotation, selected, onClick, onDoubleClick }) => { const { start_ts, text } = annotation + const className = selected ? 'annotation header selected' : 'annotation header' return ( <div - className='annotation header' + className={className} style={{ top: y }} - onClick={() => onClick(annotation)} - onDoubleClick={() => onDoubleClick(annotation)} + onClick={e => onClick(e, annotation)} + onDoubleClick={e => onDoubleClick(e, annotation)} > {text} </div> diff --git a/animism-align/frontend/views/align/components/timeline/waveform.component.js b/animism-align/frontend/views/align/components/timeline/waveform.component.js index 0a118cf..785b020 100644 --- a/animism-align/frontend/views/align/components/timeline/waveform.component.js +++ b/animism-align/frontend/views/align/components/timeline/waveform.component.js @@ -48,8 +48,8 @@ class Waveform extends Component { let widthTimeDuration = h * secondsPerPixel // secs per pixel - let timeMin = start_ts - let timeMax = Math.min(start_ts + widthTimeDuration, duration) + let timeMin = Math.round(start_ts / secondsPerPixel) * secondsPerPixel + let timeMax = Math.min(timeMin + widthTimeDuration, duration) let timeWidth = timeMax - timeMin let stepMin = Math.floor(timeMin * 10) diff --git a/animism-align/frontend/views/align/containers/timeline.container.js b/animism-align/frontend/views/align/containers/timeline.container.js index ceb9012..591af03 100644 --- a/animism-align/frontend/views/align/containers/timeline.container.js +++ b/animism-align/frontend/views/align/containers/timeline.container.js @@ -84,7 +84,7 @@ class Timeline extends Component { let { deltaY } = e let secondsPerPixel = ZOOM_STEPS[zoom] * 0.1 // 0.1 sec / step let widthTimeDuration = window.innerHeight * secondsPerPixel // secs per pixel - start_ts += (deltaY / 2) * ZOOM_STEPS[zoom] + start_ts += Math.round((deltaY / 8) * ZOOM_STEPS[zoom]) start_ts = clamp(start_ts, 0, Math.max(0, duration - widthTimeDuration / 2)) if (e.shiftKey) { if (Math.abs(deltaY) < 2) return |
