Timestamp (#430)

* Test

Messing around to figure out docker and whatnot

* Revert "Test"

This reverts commit 43b76932c5.

* Update docker dev yaml

Update the docker to the environement with the latest version of selenium (and their new arguments), and to be on firefox

* Timestamp on play

Adds the a one time event that jumps to a timestamp if there is a t parameter in the URL

* Timestamp when sharing DRAFT

First draft to show the timestamp when sharing. Missing checkbox and appending the get param to shown link

* Checkbox and update share url

Checkbox show a clean timestamp and the media URL updates with the correct timestamp upon selection

* Cleaning before PR

removing un-necessary modified  files

* Clean up before PR - remove statics

* Timestamp in comments

Parse the comments to wrap timestamps with an appropriate anchor

* Forgotten comments and console.logs

* Last touch for PR

- Cleaning media.js for PR
- Using  MediaPageStore instead of window.location when wrapping the timestamp in comments

* Screenshot

Adding the screenshot for the user_docs

* PR amends

Amending VideoPlayer componnent to take check if the Get param 't' is a number, and to keep it within the duration of the video.
Required to change the listener from 'play' to 'loadedmetadata' to have access to the video duration (otherwise it was too early)

Also changed the User_doc file to inform users of the timestamp function
This commit is contained in:
MrPercheul
2022-03-23 16:38:02 +01:00
committed by GitHub
parent fb0f3ee739
commit e7ae2833d9
7 changed files with 115 additions and 4 deletions

View File

@ -368,8 +368,36 @@ export default function CommentsList(props) {
const [displayComments, setDisplayComments] = useState(false);
function onCommentsLoad() {
displayCommentsRelatedAlert();
setComments([...MediaPageStore.get('media-comments')]);
const retrievedComments = [...MediaPageStore.get('media-comments')];
retrievedComments.forEach(comment => {
comment.text = setTimestampAnchors(comment.text);
});
displayCommentsRelatedAlert();
setComments(retrievedComments);
}
function setTimestampAnchors(text)
{
function wrapTimestampWithAnchor(match, string)
{
let split = match.split(':'), s = 0, m = 1;
let searchParameters = new URLSearchParams(window.location.search);
while (split.length > 0)
{
s += m * parseInt(split.pop(), 10);
m *= 60;
}
searchParameters.set('t', s)
const wrapped = "<a href=\"" + MediaPageStore.get('media-url').split('?')[0] + "?" + searchParameters + "\">" + match + "</a>";
return wrapped;
}
const timeRegex = new RegExp('((\\d)?\\d:)?(\\d)?\\d:\\d\\d', 'g');
return text.replace(timeRegex , wrapTimestampWithAnchor);
}
function onCommentSubmit(commentId) {

View File

@ -182,9 +182,27 @@ function updateDimensions() {
};
}
function getTimestamp() {
const videoPlayer = document.getElementsByTagName("video");
return videoPlayer[0]?.currentTime;
}
function ToHHMMSS (timeInt) {
let sec_num = parseInt(timeInt, 10);
let hours = Math.floor(sec_num / 3600);
let minutes = Math.floor((sec_num - (hours * 3600)) / 60);
let seconds = sec_num - (hours * 3600) - (minutes * 60);
if (hours < 10) {hours = "0"+hours;}
if (minutes < 10) {minutes = "0"+minutes;}
if (seconds < 10) {seconds = "0"+seconds;}
return hours >= 1 ? hours + ':' + minutes + ':' + seconds : minutes + ':' + seconds;
}
export function MediaShareOptions(props) {
const containerRef = useRef(null);
const shareOptionsInnerRef = useRef(null);
const mediaUrl = MediaPageStore.get('media-url');
const [inlineSlider, setInlineSlider] = useState(null);
const [sliderButtonsVisible, setSliderButtonsVisible] = useState({ prev: false, next: false });
@ -192,6 +210,12 @@ export function MediaShareOptions(props) {
const [dimensions, setDimensions] = useState(updateDimensions());
const [shareOptions] = useState(ShareOptions());
const [timestamp, setTimestamp] = useState(0);
const [formattedTimestamp, setFormattedTimestamp] = useState(0);
const [startAtSelected, setStartAtSelected] = useState(false);
const [shareMediaLink, setShareMediaLink] = useState(mediaUrl);
function onWindowResize() {
setDimensions(updateDimensions());
}
@ -219,6 +243,17 @@ export function MediaShareOptions(props) {
});
}
function updateStartAtCheckbox() {
setStartAtSelected(!startAtSelected);
updateShareMediaLink();
}
function updateShareMediaLink()
{
const newLink = startAtSelected ? mediaUrl : mediaUrl + "&t=" + Math.trunc(timestamp);
setShareMediaLink(newLink);
}
function nextSlide() {
inlineSlider.nextSlide();
updateSlider();
@ -243,6 +278,10 @@ export function MediaShareOptions(props) {
useEffect(() => {
PageStore.on('window_resize', onWindowResize);
MediaPageStore.on('copied_media_link', onCompleteCopyMediaLink);
const localTimestamp = getTimestamp();
setTimestamp(localTimestamp);
setFormattedTimestamp(ToHHMMSS(localTimestamp));
return () => {
PageStore.removeListener('window_resize', onWindowResize);
@ -273,10 +312,22 @@ export function MediaShareOptions(props) {
</div>
<div className="copy-field">
<div>
<input type="text" readOnly value={MediaPageStore.get('media-url')} />
<input type="text" readOnly value={shareMediaLink} />
<button onClick={onClickCopyMediaLink}>COPY</button>
</div>
</div>
<div className="start-at">
<label>
<input
type="checkbox"
name="start-at-checkbox"
id="id-start-at-checkbox"
checked={startAtSelected}
onChange={updateStartAtCheckbox}
/>
Start at {formattedTimestamp}
</label>
</div>
</div>
);
}
}

View File

@ -192,6 +192,13 @@ export function VideoPlayer(props) {
document.addEventListener('visibilitychange', initPlayer);
}
player.player.one('loadedmetadata', () => {
const urlParams = new URLSearchParams(window.location.search);
const paramT = Number(urlParams.get('t'));
const timestamp = !isNaN(paramT) ? paramT : 0;
player.player.currentTime(timestamp);
});
return () => {
unsetPlayer();