Skip to content

Commit

Permalink
[NG23-60] Support YouTube links on Learn page
Browse files Browse the repository at this point in the history
[NG23-60] Support YouTube links on Learn page
  • Loading branch information
darrensiegel authored Jan 24, 2024
2 parents 8971dcf + 7c5444a commit 00a948d
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 12 deletions.
57 changes: 48 additions & 9 deletions assets/src/hooks/video_player.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,58 @@
export const VideoPlayer = {
mounted() {
const video = document.getElementById('student_learn_video') as HTMLVideoElement;
const cloudVideo = document.getElementById('cloud_video') as HTMLVideoElement;
const youtubeIframe = document.getElementById('youtube_video') as HTMLIFrameElement;
const videoWrapper = document.getElementById('student_video_wrapper') as HTMLDivElement;

window.addEventListener('phx:play_video', (e) => {
video.classList.remove('hidden');
video.requestFullscreen();
video.setAttribute('src', (e as CustomEvent).detail.video_url);
video.play();
const videoUrl = (e as CustomEvent).detail.video_url;

videoWrapper.classList.remove('hidden');
if (videoUrl.includes('youtube.com') || videoUrl.includes('youtu.be')) {
youtubeIframe.src = this.convertToEmbedURL(videoUrl);
youtubeIframe.requestFullscreen();
} else {
cloudVideo.requestFullscreen();
cloudVideo.setAttribute('src', videoUrl);
cloudVideo.play();
}
});

video?.addEventListener('fullscreenchange', () => {
/**
The convertToEmbedURL function is designed to convert various YouTube URL formats into a standardized embeddable URL format. This is crucial for embedding YouTube videos within an iframe.
The regular expression used below is crafted to identify and extract the video ID from different YouTube URL formats. It is versatile enough to handle standard and shortened YouTube URLs.
Handled Formats:
- Standard: https://www.youtube.com/watch?v=VIDEO_ID
- Shortened: https://youtu.be/VIDEO_ID
- Embed: https://www.youtube.com/embed/VIDEO_ID
The expression consists of two main parts:
- The first part (youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=) captures the various URL structures preceding the video ID.
= The second part ([^#\&\?]*).*, which corresponds to match[2], captures the actual video ID.
YouTube video IDs typically have a length of exactly 11 characters. This standardization is a part of YouTube's design.
The check match[2].length == 11 is employed to ensure that the extracted string is indeed a valid YouTube video ID.
*/
this.convertToEmbedURL = (url: string) => {
const regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/;
const match = url.match(regExp);
const videoId = match && match[2].length == 11 ? match[2] : null;
if (videoId) {
return `https://www.youtube.com/embed/${videoId}?autoplay=1`;
} else {
return url;
}
};

document.addEventListener('fullscreenchange', () => {
if (!document.fullscreenElement) {
video.pause();
video.classList.add('hidden');
video.currentTime = 0;
cloudVideo.pause();
cloudVideo.currentTime = 0;

youtubeIframe.src = '';

videoWrapper.classList.add('hidden');
}
});
},
Expand Down
15 changes: 12 additions & 3 deletions lib/oli_web/live/delivery/student/learn_live.ex
Original file line number Diff line number Diff line change
Expand Up @@ -319,9 +319,7 @@ defmodule OliWeb.Delivery.Student.LearnLive do
def render(assigns) do
~H"""
<div id="student_learn" class="lg:container lg:mx-auto p-[25px]" phx-hook="Scroller">
<video phx-hook="VideoPlayer" id="student_learn_video" class="hidden" controls>
<source src="" type="video/mp4" /> Your browser does not support the video tag.
</video>
<.video_player />
<.unit
:for={unit <- @full_hierarchy["children"]}
unit={unit}
Expand Down Expand Up @@ -1068,6 +1066,17 @@ defmodule OliWeb.Delivery.Student.LearnLive do
"""
end

def video_player(assigns) do
~H"""
<div id="student_video_wrapper" phx-hook="VideoPlayer" class="hidden">
<iframe id="youtube_video" frameborder="0" allowfullscreen></iframe>
<video id="cloud_video" controls>
<source src="" type="video/mp4" /> Your browser does not support the video tag.
</video>
</div>
"""
end

_docp = """
Currently the intro_content for a revision does not support h1 tags. So,
if there is no <h1> tag in the content then we need to add an additional margin
Expand Down
6 changes: 6 additions & 0 deletions lib/oli_web/live/import/csv_import_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ defmodule OliWeb.Import.CSVImportView do
socket
) do
author = Repo.get(Author, author_id)
project = Oli.Authoring.Course.get_project_by_slug(project_slug)
ingest_file = ingest_file(author)

if File.exists?(ingest_file) do
Expand All @@ -46,6 +47,7 @@ defmodule OliWeb.Import.CSVImportView do
assign(socket,
breadcrumbs: set_breadcrumbs(),
author: author,
project: project,
finished: false,
results: []
)}
Expand Down Expand Up @@ -173,6 +175,10 @@ defmodule OliWeb.Import.CSVImportView do
end

def handle_info({:finished}, socket) do
socket.assigns.project
|> Oli.Delivery.Sections.get_sections_by_base_project()
|> Enum.each(&Oli.Delivery.Sections.SectionCache.clear(&1.slug))

{:noreply,
assign(socket,
finished: true
Expand Down

0 comments on commit 00a948d

Please sign in to comment.