diff --git a/src/assets/js/copyLink.js b/src/assets/js/copyLink.js new file mode 100644 index 0000000..8b3168e --- /dev/null +++ b/src/assets/js/copyLink.js @@ -0,0 +1,28 @@ +const copyBtn = document.getElementById("copyLink"); + +copyBtn.addEventListener("click", async () => { + try{ + + const timestamp = Math.floor(player.playerInfo.currentTime) || 0; + const url = window.location.href; + let link = url; + if (!url.includes("?")) { + link += `?t=${timestamp}`; + } else if (url.includes("t=")) { + link = url.replace(/t=\d+/, `t=${timestamp}`); + } else { + // this is for the case where there are other query strings + link += `&t=${timestamp}`; + } + await navigator.clipboard.writeText(link); + copyBtn.innerHTML = "Copied!"; + + // reset button text after 3 seconds + setTimeout(() => { + copyBtn.innerHTML = "Copy link at current time"; + }, 2000); + }catch(err){ + console.error('Failed to copy: ', err); + } + +}); diff --git a/src/controllers/lessons.js b/src/controllers/lessons.js index f37ab42..58dab40 100644 --- a/src/controllers/lessons.js +++ b/src/controllers/lessons.js @@ -122,6 +122,7 @@ export const getLessonProgress = async (userId, lesson) => { export const showLesson = async (req, res) => { try { + const timeStart = req.query.t || 0; let lesson = await Lesson.findOne({ permalink: req.params.permalink, }).lean(); @@ -148,7 +149,7 @@ export const showLesson = async (req, res) => { assigned = await getHwProgress(req.user.id, assigned); if (due.length) due = await getHwProgress(req.user.id, due); } - res.render("lesson", { lesson, next, prev, assigned, due }); + res.render("lesson", { lesson, next, prev, assigned, due, timeStart }); } catch (err) { console.log(err); res.redirect("/class/all"); diff --git a/src/views/lesson.pug b/src/views/lesson.pug index 25bb9bc..f291015 100644 --- a/src/views/lesson.pug +++ b/src/views/lesson.pug @@ -44,6 +44,9 @@ block content if next h3 a(href="/class/" + next) Next Class + button#copyLink.hidden.p-2.border.bg-pink-800.text-white.text-xs.font-medium.mt-4.rounded-md Copy link at current time + + #info if loggedIn if lesson.videoId @@ -84,13 +87,19 @@ block content .mb-6(class="shadow-[0_2px_10px_0_rgba(0,0,0,0.1)]") +homework(homework) + + append scripts + script(src="/js/copyLink.js") if loggedIn script(src="/js/hwDone.js") script(src="/js/hwProgress.js") script(src="/js/lessonProgress.js") + script. + const timeStart = #{timeStart} || 0; if lesson.videoId && !lesson.twitchVideo + script. var tag = document.createElement('script'); tag.src = "https://www.youtube.com/iframe_api"; @@ -100,12 +109,23 @@ append scripts function onYouTubeIframeAPIReady() { player = new YT.Player('player', { videoId: '#{lesson.videoId}' === 'o3IIobN4xR0' ? 'YRemMgGfbKg' : '#{lesson.videoId}', + playerVars: { + // this unfortunately doesn't work if the user is logged in and has 'youtube history' turned on + // see https://stackoverflow.com/questions/77691282/youtube-iframe-api-start-time-not-working-when-youtube-history-is-enabled for possible workaround (not implemented yet) + start: timeStart + + }, + events: { + 'onReady': onPlayerReady, + } }); + + + } + function onPlayerReady(event) { + // this will lazy load the button + document.getElementById('copyLink').classList.remove('hidden'); } - //- function setCurrentTime(slideNum) { - //- var object = [ 0, 320 ]; - //- player.seekTo(object[slideNum]); - //- } else if lesson.twitchVideo script(src="https://player.twitch.tv/js/embed/v1.js")