From 89bc3dd843aafe95e13b428d6fc2bef9b05442ce Mon Sep 17 00:00:00 2001 From: Julio Sgarbi Date: Mon, 10 Jul 2023 21:24:07 -0300 Subject: [PATCH 01/10] feat: LSDV-5255: Highlight the active paragraph text segment --- src/assets/icons/index.tsx | 2 + src/assets/icons/pause.svg | 4 ++ src/assets/icons/play.svg | 3 + src/tags/object/Paragraphs/HtxParagraphs.js | 2 +- .../object/Paragraphs/Paragraphs.module.scss | 64 ++++++++++++++++++- src/tags/object/Paragraphs/Phrases.js | 42 ++++++++++-- src/tags/object/Paragraphs/model.js | 28 ++++++-- 7 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 src/assets/icons/pause.svg create mode 100644 src/assets/icons/play.svg diff --git a/src/assets/icons/index.tsx b/src/assets/icons/index.tsx index 967b5adc6..071101730 100644 --- a/src/assets/icons/index.tsx +++ b/src/assets/icons/index.tsx @@ -32,6 +32,8 @@ export { ReactComponent as IconFast } from './fast.svg'; export { ReactComponent as IconDuplicate } from './duplicate.svg'; export { ReactComponent as IconEllipsis } from './ellipsis.svg'; export { ReactComponent as IconWarning } from './warning.svg'; +export { ReactComponent as IconPlay } from './play.svg'; +export { ReactComponent as IconPause } from './pause.svg'; export { ReactComponent as IconCheck } from './check.svg'; export { ReactComponent as IconCheckBold } from './check-bold.svg'; diff --git a/src/assets/icons/pause.svg b/src/assets/icons/pause.svg new file mode 100644 index 000000000..50c2605a5 --- /dev/null +++ b/src/assets/icons/pause.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/play.svg b/src/assets/icons/play.svg new file mode 100644 index 000000000..bda9a7a41 --- /dev/null +++ b/src/assets/icons/play.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/tags/object/Paragraphs/HtxParagraphs.js b/src/tags/object/Paragraphs/HtxParagraphs.js index d454300d6..0f8ea51f6 100644 --- a/src/tags/object/Paragraphs/HtxParagraphs.js +++ b/src/tags/object/Paragraphs/HtxParagraphs.js @@ -461,7 +461,7 @@ class HtxParagraphsView extends Component { className={contextScroll ? styles.scroll_container : styles.container} onMouseUp={this.onMouseUp.bind(this)} > - + ); diff --git a/src/tags/object/Paragraphs/Paragraphs.module.scss b/src/tags/object/Paragraphs/Paragraphs.module.scss index 2f4b646fe..3f5b8bfdf 100644 --- a/src/tags/object/Paragraphs/Paragraphs.module.scss +++ b/src/tags/object/Paragraphs/Paragraphs.module.scss @@ -38,7 +38,7 @@ $border-thin: 1px solid rgba(137, 128, 152, 0.16); .dialoguename { font-weight: bold; - background: white !important; + background: white; border-radius: 5px; padding: 5px; margin-right: 10px; @@ -151,6 +151,19 @@ $border-thin: 1px solid rgba(137, 128, 152, 0.16); z-index: 1; } +.playNewUi { + user-select: none; + cursor: pointer; + position: absolute; + left: 5px; + margin-top: -0.3em; + font-size: inherit; + + &:hover, &:active, &:focus { + background: none; + } +} + .play { user-select: none; position: absolute; @@ -168,3 +181,52 @@ $border-thin: 1px solid rgba(137, 128, 152, 0.16); fill: #1890ff; } } + +.newUI { + transition: all .1s ease-out; + border: 1px solid rgba(137, 128, 152, 0.16); + border-radius: 4px; + display: flex; + flex-wrap: wrap; + width: calc(100% - 36px); + padding: 8px 12px 8px 12px; + + .dialoguename { + transition: all .1s ease-out; + background: none; + font-size: 16px; + font-style: normal; + font-weight: 500; + line-height: 24px; + letter-spacing: 0.15px; + padding: 0 + } + + .dialoguetext { + transition: all .1s ease-out; + font-size: 14px; + font-style: normal; + font-weight: 400; + line-height: 20px; + letter-spacing: 0.25px; + color: #1F1F1F; + width: 100%; + margin-top: 8px; + } + + .titleWrapper { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + + .time { + font-size: 12px; + font-style: normal; + font-weight: 500; + line-height: 16px; + letter-spacing: 0.5px; + color: #898098; + } + } +} diff --git a/src/tags/object/Paragraphs/Phrases.js b/src/tags/object/Paragraphs/Phrases.js index b520f285f..a76ef8a17 100644 --- a/src/tags/object/Paragraphs/Phrases.js +++ b/src/tags/object/Paragraphs/Phrases.js @@ -3,34 +3,62 @@ import { getRoot } from 'mobx-state-tree'; import { Button } from 'antd'; import { PauseCircleOutlined, PlayCircleOutlined } from '@ant-design/icons'; import styles from './Paragraphs.module.scss'; +import { FF_LSDV_E_278, isFF } from '../../../utils/feature-flags'; +import { IconPause, IconPlay } from '../../../assets/icons'; -export const Phrases = observer(({ item }) => { +const formatTime = (seconds) => { + const hours = Math.floor(seconds / 3600); + const minutes = Math.floor((seconds % 3600) / 60); + const remainingSeconds = seconds % 60; + + const formattedHours = String(hours).padStart(2, '0'); + const formattedMinutes = String(minutes).padStart(2, '0'); + const formattedSeconds = String(remainingSeconds).padStart(2, '0'); + + return `${formattedHours}:${formattedMinutes}:${formattedSeconds}`; +}; + +export const Phrases = observer(({ item, playingId, activeRef }) => { const cls = item.layoutClasses; const withAudio = !!item.audio; if (!item._value) return null; const val = item._value.map((v, idx) => { - const style = item.layoutStyles(v); + const isPlaying = playingId === idx && item.playing; + const style = (isFF(FF_LSDV_E_278) && !isPlaying) ? item.layoutStyles(v).inactive: item.layoutStyles(v); const classNames = [cls.phrase]; const isContentVisible = item.isVisibleForAuthorFilter(v); - const isPlaying = item.playingId === idx && item.playing; + const startTime = formatTime(item._value[idx]?.start); + const endTime = formatTime(!item._value[idx]?.end ? item._value[idx]?.start + item._value[idx]?.duration : item._value[idx]?.end); + + console.log(playingId, idx, item.playing); if (withAudio) classNames.push(styles.withAudio); if (!isContentVisible) classNames.push(styles.collapsed); if (getRoot(item).settings.showLineNumbers) classNames.push(styles.numbered); return ( -
+
{isContentVisible && withAudio && !isNaN(v.start) && (
); diff --git a/src/tags/object/Paragraphs/model.js b/src/tags/object/Paragraphs/model.js index 6b502b37a..1a37e5178 100644 --- a/src/tags/object/Paragraphs/model.js +++ b/src/tags/object/Paragraphs/model.js @@ -101,10 +101,30 @@ const Model = types layoutStyles(data) { if (self.layout === 'dialogue') { const seed = data[self.namekey]; - - return { - phrase: { backgroundColor: Utils.Colors.convertToRGBA(ColorScheme.make_color({ seed })[0], 0.25) }, - }; + const color = ColorScheme.make_color({ seed })[0]; + + if (isFF(FF_LSDV_E_278)) { + return { + phrase: { + background: '#FFF', + border: `1px solid ${color}`, + borderLeft: `4px solid ${color}`, + }, + name: { color }, + inactive: { + phrase: { + background: '#FAFAFA', + border: '1px solid rgba(137, 128, 152, 0.16)', + borderLeft: `4px solid ${Utils.Colors.convertToRGBA(color, 0.4)}`, + }, + name: { color: Utils.Colors.convertToRGBA(color, 0.9) }, + }, + }; + } else { + return { + phrase: { backgroundColor: Utils.Colors.convertToRGBA(color, 0.25) }, + }; + } } return {}; From f0cb79d1901ea2c99a3be3b667fcb3fbe725c174 Mon Sep 17 00:00:00 2001 From: Julio Sgarbi Date: Wed, 12 Jul 2023 11:49:36 -0300 Subject: [PATCH 02/10] put wrapper behind FF --- src/tags/object/Paragraphs/Phrases.js | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/tags/object/Paragraphs/Phrases.js b/src/tags/object/Paragraphs/Phrases.js index a76ef8a17..d2fd68d49 100644 --- a/src/tags/object/Paragraphs/Phrases.js +++ b/src/tags/object/Paragraphs/Phrases.js @@ -32,8 +32,6 @@ export const Phrases = observer(({ item, playingId, activeRef }) => { const startTime = formatTime(item._value[idx]?.start); const endTime = formatTime(!item._value[idx]?.end ? item._value[idx]?.start + item._value[idx]?.duration : item._value[idx]?.end); - console.log(playingId, idx, item.playing); - if (withAudio) classNames.push(styles.withAudio); if (!isContentVisible) classNames.push(styles.collapsed); if (getRoot(item).settings.showLineNumbers) classNames.push(styles.numbered); @@ -53,12 +51,15 @@ export const Phrases = observer(({ item, playingId, activeRef }) => { onClick={() => item.play(idx)} /> )} - - {v[item.namekey]} - {isFF(FF_LSDV_E_278) && ( + {isFF(FF_LSDV_E_278) ? ( + + {v[item.namekey]} {startTime} - {endTime} - )} - + + ) : ( + {v[item.namekey]} + )} + {v[item.textkey]}
); From 9fbad53b5f7964a395f2ccdf1862b05f13319116 Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Wed, 12 Jul 2023 14:40:56 -0500 Subject: [PATCH 03/10] fix the paragraphs container overflow to not have horizontal scrollbars --- src/tags/object/Paragraphs/Paragraphs.module.scss | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tags/object/Paragraphs/Paragraphs.module.scss b/src/tags/object/Paragraphs/Paragraphs.module.scss index 2bdf0c750..b0ab1f2a4 100644 --- a/src/tags/object/Paragraphs/Paragraphs.module.scss +++ b/src/tags/object/Paragraphs/Paragraphs.module.scss @@ -63,7 +63,8 @@ $border-thin: 1px solid rgba(137, 128, 152, 0.16); .scroll_container { position: relative; - overflow: auto; + overflow-y: auto; + overflow-x: hidden; counter-reset: phrase; border: $border-thin; padding: 8px; From 02a50e319767a1852801792abd1f48c42c806b3e Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Wed, 12 Jul 2023 15:48:54 -0500 Subject: [PATCH 04/10] fix paragraph active indicator to work regardless of playback state, fix NaN formatting of time ranges. --- src/tags/object/Paragraphs/Phrases.js | 20 ++++++++++++++------ src/tags/object/Paragraphs/model.js | 7 ++++++- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/tags/object/Paragraphs/Phrases.js b/src/tags/object/Paragraphs/Phrases.js index d2fd68d49..770c23494 100644 --- a/src/tags/object/Paragraphs/Phrases.js +++ b/src/tags/object/Paragraphs/Phrases.js @@ -7,6 +7,8 @@ import { FF_LSDV_E_278, isFF } from '../../../utils/feature-flags'; import { IconPause, IconPlay } from '../../../assets/icons'; const formatTime = (seconds) => { + if (isNaN(seconds)) return ''; + const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = seconds % 60; @@ -25,19 +27,25 @@ export const Phrases = observer(({ item, playingId, activeRef }) => { if (!item._value) return null; const val = item._value.map((v, idx) => { - const isPlaying = playingId === idx && item.playing; - const style = (isFF(FF_LSDV_E_278) && !isPlaying) ? item.layoutStyles(v).inactive: item.layoutStyles(v); + const isActive = playingId === idx; + const isPlaying = isActive && item.playing; + const style = (isFF(FF_LSDV_E_278) && !isActive) ? item.layoutStyles(v).inactive: item.layoutStyles(v); const classNames = [cls.phrase]; const isContentVisible = item.isVisibleForAuthorFilter(v); - const startTime = formatTime(item._value[idx]?.start); - const endTime = formatTime(!item._value[idx]?.end ? item._value[idx]?.start + item._value[idx]?.duration : item._value[idx]?.end); + + const withFormattedTime = (item) => { + const startTime = formatTime(item._value[idx]?.start); + const endTime = formatTime(!item._value[idx]?.end ? item._value[idx]?.start + item._value[idx]?.duration : item._value[idx]?.end); + + return `${startTime} - ${endTime}`; + }; if (withAudio) classNames.push(styles.withAudio); if (!isContentVisible) classNames.push(styles.collapsed); if (getRoot(item).settings.showLineNumbers) classNames.push(styles.numbered); return ( -
+
{isContentVisible && withAudio && !isNaN(v.start) && (