From 34b305a10b8b411ff5eeff7f19acb6ad0d2e4d9c Mon Sep 17 00:00:00 2001 From: Kyle Chan Date: Mon, 11 Nov 2024 15:21:44 +0800 Subject: [PATCH 1/5] feat: add copy video button to extra buttons in video page --- .../www.youtube.com/appearance.js | 27 +++++++++++++++++++ menu/skeleton-parts/player.js | 5 ++++ 2 files changed, 32 insertions(+) diff --git a/js&css/web-accessible/www.youtube.com/appearance.js b/js&css/web-accessible/www.youtube.com/appearance.js index e92dae4bb..12efd8a1d 100644 --- a/js&css/web-accessible/www.youtube.com/appearance.js +++ b/js&css/web-accessible/www.youtube.com/appearance.js @@ -460,6 +460,33 @@ ImprovedTube.improvedtubeYoutubeButtonsUnderPlayer = function () { svg.appendChild(path); button.appendChild(svg); section.insertAdjacentElement('afterend', button) } + + if (this.storage.copy_video_id !== false) { + var button = document.createElement('button'), + svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), + path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + + button.className = 'improvedtube-player-button'; + button.dataset.tooltip = 'CopyVideoID'; + svg.style.opacity = '.5'; + svg.setAttributeNS(null, 'viewBox', '0 0 24 24'); + path.setAttributeNS(null, 'd', 'M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z'); + // https://stackoverflow.com/questions/3452546/how-do-i-get-the-youtube-video-id-from-a-url + const videoIDRegex = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/; + button.onclick = function () { + svg.style.opacity = '1'; + const videoId = window.location.href.match(videoIDRegex)[1]; + navigator.clipboard.writeText(videoId); + button.dataset.tooltip = 'Copied!'; + setTimeout(function() { + button.dataset.tooltip = 'CopyVideoID'; + svg.style.opacity = '.5'; + }, 500); + } + + svg.appendChild(path); button.appendChild(svg); + section.insertAdjacentElement('afterend', button) + } } } }; diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index dee256eb3..bf4929ec1 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -1163,6 +1163,11 @@ extension.skeleton.main.layers.section.player.on.click = { component: 'switch', text: 'loop', value: true + }, + copy_video_id: { + component: 'switch', + text: 'copyVideoID', + value: true } }, player_hide_controls_options: { From 33cc0f1f7534b9aa12dc63997f55ad6f9e643a54 Mon Sep 17 00:00:00 2001 From: Kyle Chan Date: Tue, 19 Nov 2024 18:37:07 +0800 Subject: [PATCH 2/5] feat: add copy video id button to playlist and css for the button --- js&css/extension/www.youtube.com/styles.css | 20 +++++++++ js&css/web-accessible/init.js | 1 + .../www.youtube.com/playlist.js | 41 +++++++++++++++++++ 3 files changed, 62 insertions(+) diff --git a/js&css/extension/www.youtube.com/styles.css b/js&css/extension/www.youtube.com/styles.css index 1ecc02214..02367abf9 100644 --- a/js&css/extension/www.youtube.com/styles.css +++ b/js&css/extension/www.youtube.com/styles.css @@ -266,6 +266,26 @@ body.no-scroll .it-player-button--tooltip { fill: #f00; } +/*------------------------------------------------------------------------------ +5.2 COPY VIDEO ID +------------------------------------------------------------------------------*/ +.it-playlist-copy-video-id { + width: 40px; + height: 40px; + cursor: pointer; + border: none; + outline: none; + background: none; + fill: var(--yt-spec-icon-inactive); + align-self: center; +} + +.it-playlist-copy-video-id:hover::after { + content: attr(data-tooltip); + transform: translateX(-50%); + color: var(--paper-tooltip-text-color, white); + background-color: var(--paper-tooltip-background, #616161); +} /*------------------------------------------------------------------------------ 6.0 CHANNEL diff --git a/js&css/web-accessible/init.js b/js&css/web-accessible/init.js index ca6596ca6..f94dd692e 100644 --- a/js&css/web-accessible/init.js +++ b/js&css/web-accessible/init.js @@ -82,6 +82,7 @@ ImprovedTube.init = function () { ImprovedTube.playlistShuffle(); ImprovedTube.playlistReverse(); ImprovedTube.playlistPopup(); + ImprovedTube.playlistCopyVideoIdButton(); } }); this.pageType(); diff --git a/js&css/web-accessible/www.youtube.com/playlist.js b/js&css/web-accessible/www.youtube.com/playlist.js index 79628849f..5ceaca2bd 100644 --- a/js&css/web-accessible/www.youtube.com/playlist.js +++ b/js&css/web-accessible/www.youtube.com/playlist.js @@ -214,6 +214,47 @@ ImprovedTube.playlistPopupCreateButton = function (playlistID, altButtonStyle, c return button; }; + +/*------------------------------------------------------------------------------ +4.5.6 PLAYLIST COPY VIDEO ID BUTTON +------------------------------------------------------------------------------*/ +/** +*/ +ImprovedTube.playlistCopyVideoIdButton = function () { + if (this.storage.playlist_copy_video_id === true) { + const playlistItems = document.querySelectorAll('ytd-playlist-panel-video-renderer'); + const videoIDRegex = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/; + playlistItems.forEach(item => { + if (!item.querySelector('.it-playlist-copy-video-id')) { + const button = document.createElement('button'); + svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'); + path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); + button.className = ('it-playlist-copy-video-id'); + button.dataset.tooltip = 'CopyVideoId'; + svg.setAttributeNS(null, 'viewBox', '0 0 24 24'); + path.setAttributeNS(null, 'd', 'M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z'); + svg.append(path); + button.append(svg); + button.addEventListener('click', () => { + const playlistLink = item.querySelector('a#wc-endpoint'); + if (playlistLink) { + const playlistURL = playlistLink.href.match(videoIDRegex)[1]; + navigator.clipboard.writeText(playlistURL); + } + button.dataset.tooltip = 'Copied!'; + setTimeout(function() { + button.dataset.tooltip = 'CopyVideoID'; + }, 500); + }); + const menuElement = item.querySelector('#menu'); + if (menuElement) { + menuElement.parentNode.insertBefore(button, menuElement); + } + } + }); + } +} + /** * ## Adds a playlist popup button to each playlist panel found or update the links of existing popup buttons * - buttons will be added on the playlist page (next to the share button), in the playlist panel (after the loop and shuffle buttons), and/or the mini playlist section of the mini player (after the loop and shuffle buttons) From 2f5a4b083be50ff7f3c6271b8c38d8dec44cb8ea Mon Sep 17 00:00:00 2001 From: Kyle Chan Date: Tue, 19 Nov 2024 18:38:30 +0800 Subject: [PATCH 3/5] feat: add and remove copy id button based on user options --- js&css/web-accessible/core.js | 16 ++++++++++++++++ .../web-accessible/www.youtube.com/appearance.js | 2 +- menu/skeleton-parts/playlist.js | 4 ++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/js&css/web-accessible/core.js b/js&css/web-accessible/core.js index 9fcfd69b3..43e799029 100644 --- a/js&css/web-accessible/core.js +++ b/js&css/web-accessible/core.js @@ -369,6 +369,15 @@ document.addEventListener('it-message-from-extension', function () { } break + case 'copyVideoId': + if (ImprovedTube.storage.copy_video_id === false) { + document.querySelector('.improvedtube-player-button[data-tooltip="CopyVideoId"]')?.remove(); + } else if (ImprovedTube.storage.copy_video_id === true) { + document.querySelectorAll('.improvedtube-player-button').forEach(e => e.remove()); + ImprovedTube.improvedtubeYoutubeButtonsUnderPlayer(); + } + break + case 'dayOfWeek': if (ImprovedTube.storage.day_of_week === false) { document.querySelector(".ytd-day-of-week")?.remove(); @@ -405,6 +414,13 @@ document.addEventListener('it-message-from-extension', function () { if (playlistData.currentIndex != playlistData.localCurrentIndex) { playlistData.currentIndex = playlistData.localCurrentIndex;} } break + case 'playlistCopyVideoId': + if (ImprovedTube.storage.playlist_copy_video_id === false) { + document.querySelectorAll('.it-playlist-copy-video-id').forEach(e => e.remove()); + } else if (ImprovedTube.storage.playlist_copy_video_id === true) { + ImprovedTube.playlistCopyVideoIdButton(); + } + break } // dont trigger shortcuts on config change, reinitialize handler instead diff --git a/js&css/web-accessible/www.youtube.com/appearance.js b/js&css/web-accessible/www.youtube.com/appearance.js index 12efd8a1d..5bcfadd71 100644 --- a/js&css/web-accessible/www.youtube.com/appearance.js +++ b/js&css/web-accessible/www.youtube.com/appearance.js @@ -467,7 +467,7 @@ ImprovedTube.improvedtubeYoutubeButtonsUnderPlayer = function () { path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); button.className = 'improvedtube-player-button'; - button.dataset.tooltip = 'CopyVideoID'; + button.dataset.tooltip = 'CopyVideoId'; svg.style.opacity = '.5'; svg.setAttributeNS(null, 'viewBox', '0 0 24 24'); path.setAttributeNS(null, 'd', 'M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z'); diff --git a/menu/skeleton-parts/playlist.js b/menu/skeleton-parts/playlist.js index 6aba3bf24..512775548 100644 --- a/menu/skeleton-parts/playlist.js +++ b/menu/skeleton-parts/playlist.js @@ -42,6 +42,10 @@ extension.skeleton.main.layers.section.playlist = { playlist_popup: { component: 'switch', text: 'popupPlayer' + }, + playlist_copy_video_id: { + component: 'switch', + text: 'copyVideoId' } } } From fdf5305427c73d9293da65083c5a8e7123e9e765 Mon Sep 17 00:00:00 2001 From: Kyle Chan Date: Thu, 21 Nov 2024 11:37:55 +0800 Subject: [PATCH 4/5] feat: Use ImprovedTube regex instead of rewrite regex --- js&css/web-accessible/www.youtube.com/appearance.js | 5 ++--- js&css/web-accessible/www.youtube.com/playlist.js | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/js&css/web-accessible/www.youtube.com/appearance.js b/js&css/web-accessible/www.youtube.com/appearance.js index 5bcfadd71..222eb871c 100644 --- a/js&css/web-accessible/www.youtube.com/appearance.js +++ b/js&css/web-accessible/www.youtube.com/appearance.js @@ -471,11 +471,10 @@ ImprovedTube.improvedtubeYoutubeButtonsUnderPlayer = function () { svg.style.opacity = '.5'; svg.setAttributeNS(null, 'viewBox', '0 0 24 24'); path.setAttributeNS(null, 'd', 'M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2m0 16H8V7h11z'); - // https://stackoverflow.com/questions/3452546/how-do-i-get-the-youtube-video-id-from-a-url - const videoIDRegex = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/; button.onclick = function () { svg.style.opacity = '1'; - const videoId = window.location.href.match(videoIDRegex)[1]; + const videoURL = ImprovedTube.elements.player?.getVideoUrl(); + const videoId = videoURL.match(ImprovedTube.regex.video_id)?.[1]; navigator.clipboard.writeText(videoId); button.dataset.tooltip = 'Copied!'; setTimeout(function() { diff --git a/js&css/web-accessible/www.youtube.com/playlist.js b/js&css/web-accessible/www.youtube.com/playlist.js index 5ceaca2bd..d38fd9a65 100644 --- a/js&css/web-accessible/www.youtube.com/playlist.js +++ b/js&css/web-accessible/www.youtube.com/playlist.js @@ -223,7 +223,6 @@ ImprovedTube.playlistPopupCreateButton = function (playlistID, altButtonStyle, c ImprovedTube.playlistCopyVideoIdButton = function () { if (this.storage.playlist_copy_video_id === true) { const playlistItems = document.querySelectorAll('ytd-playlist-panel-video-renderer'); - const videoIDRegex = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/; playlistItems.forEach(item => { if (!item.querySelector('.it-playlist-copy-video-id')) { const button = document.createElement('button'); @@ -238,7 +237,7 @@ ImprovedTube.playlistCopyVideoIdButton = function () { button.addEventListener('click', () => { const playlistLink = item.querySelector('a#wc-endpoint'); if (playlistLink) { - const playlistURL = playlistLink.href.match(videoIDRegex)[1]; + const playlistURL = playlistLink.href.match(ImprovedTube.regex.video_id)?.[1]; navigator.clipboard.writeText(playlistURL); } button.dataset.tooltip = 'Copied!'; From d398ee1689815e809509165e7795a9e7bb647fd2 Mon Sep 17 00:00:00 2001 From: Kyle Chan Date: Thu, 21 Nov 2024 11:39:20 +0800 Subject: [PATCH 5/5] feat(lang): add CN, TW and EN message and update text in player copy video id --- _locales/en/messages.json | 3 +++ _locales/zh_CN/messages.json | 3 +++ _locales/zh_TW/messages.json | 3 +++ menu/skeleton-parts/player.js | 2 +- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 988af9f18..712dc26e6 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -320,6 +320,9 @@ "cores": { "message": "Cores" }, + "copyVideoId": { + "message": "Copy Video Id" + }, "cropChapterTitles": { "message": "Crop chapter titles" }, diff --git a/_locales/zh_CN/messages.json b/_locales/zh_CN/messages.json index abc5e0c94..de14d4b1d 100644 --- a/_locales/zh_CN/messages.json +++ b/_locales/zh_CN/messages.json @@ -143,6 +143,9 @@ "cores": { "message": "核心" }, + "copyVideoId": { + "message": "复制影片 ID" + }, "cropChapterTitles": { "message": "裁剪章节标题" }, diff --git a/_locales/zh_TW/messages.json b/_locales/zh_TW/messages.json index 9e1c091f1..7b02f0014 100644 --- a/_locales/zh_TW/messages.json +++ b/_locales/zh_TW/messages.json @@ -143,6 +143,9 @@ "cores": { "message": "核心數" }, + "copyVideoId": { + "message": "複製影片 ID" + }, "cropChapterTitles": { "message": "截斷章節名稱" }, diff --git a/menu/skeleton-parts/player.js b/menu/skeleton-parts/player.js index bf4929ec1..50e335782 100644 --- a/menu/skeleton-parts/player.js +++ b/menu/skeleton-parts/player.js @@ -1166,7 +1166,7 @@ extension.skeleton.main.layers.section.player.on.click = { }, copy_video_id: { component: 'switch', - text: 'copyVideoID', + text: 'copyVideoId', value: true } },