diff --git a/app/src/components/VideoPlayer.js b/app/src/components/VideoPlayer.js index 8e3ff424..4cf4f0bb 100644 --- a/app/src/components/VideoPlayer.js +++ b/app/src/components/VideoPlayer.js @@ -113,7 +113,7 @@ function VideoPage({videoFile, prevFile, nextFile, fetchVideo, ...props}) { if (video && video['description']) { // Only replace empty description if there is one available. description = video['description']; - description = chaptersInDescription(description, setVideoTime) + description = formatVideoDescription(description, setVideoTime) } let descriptionPane = { @@ -139,7 +139,7 @@ function VideoPage({videoFile, prevFile, nextFile, fetchVideo, ...props}) {

{video.censored ? 'Yes' : 'No'}

Codec Names

- <>{video.codec_names ? video.codec_names.map(i => ) : 'N/A'} + <>{video.codec_names ? video.codec_names.map(i => ) : 'N/A'} } @@ -212,6 +212,13 @@ function VideoPage({videoFile, prevFile, nextFile, fetchVideo, ...props}) { } + let title = video.video_path; + if (videoFile.title) { + title = hashtagLinks(videoFile.title); + } else if (videoFile.stem) { + title = videoFile.stem; + } + return <> @@ -233,7 +240,7 @@ function VideoPage({videoFile, prevFile, nextFile, fetchVideo, ...props}) { -
{videoFile.title || videoFile.stem || video.video_path}
+
{title}
{video.upload_date &&

{isoDatetimeToString(video.upload_date)}

}

{channel && @@ -272,7 +279,8 @@ export default VideoPage; const chapterRegex = new RegExp('^(\\(?(?:((\\d?\\d):)?(?:(\\d?\\d):(\\d\\d)))\\)?)\\s+(.*)$', 'i'); -function chaptersInDescription(description, setVideoTime) { +function formatVideoDescription(description, setVideoTime) { + // Convert timestamps to links which change the video's playback location. Change hashtags to search links. if (description && description.length > 0) { try { const lines = _.split(description, '\n'); @@ -300,10 +308,10 @@ function chaptersInDescription(description, setVideoTime) { } // Use the link if we could create it, otherwise fallback to the original `line`. - newLines = [...newLines, link || line]; + newLines = [...newLines, link || hashtagLinks(line)]; } else if (line !== undefined) { // Line does not start with a timestamp. - newLines = [...newLines, line]; + newLines = [...newLines, hashtagLinks(line)]; } } // Map all lines and links with a break between. @@ -317,4 +325,28 @@ function chaptersInDescription(description, setVideoTime) { } // Error occurred, or no description, don't fail. return description; + +} + +const hashtagRegex = /(#+[_a-zA-Z0-9]+)/ig; + + +function hashtagLinks(text) { + // Converts a string into a div which has hashtags converted to search links. + // Example: Some text #hashtag the rest of the text + if (text && text.length > 0) { + const parts = text.split(hashtagRegex); + let newParts = ''; + for (let i = 0; i < parts.length; i++) { + let part = parts[i]; + part = part.startsWith('#') ? + // Part is a hashtag. + {part} + // Part is not a hashtag. + : {part}; + newParts = [...newParts, part]; + } + return {newParts}; + } + return text; }