From 01dd04cd5ab7b55d2a9af7d0ebf405bee9579b09 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 8 Mar 2022 16:26:30 +0100 Subject: [PATCH] Display avatar in embed poster --- client/package.json | 1 - .../player/dock/peertube-dock-component.ts | 65 +++++++++++++++++ .../player/dock/peertube-dock-plugin.ts | 25 +++++++ .../assets/player/peertube-player-manager.ts | 1 - .../assets/player/peertube-videojs-typings.ts | 3 +- client/src/sass/player/dock.scss | 73 ++++++++++++++++--- client/src/standalone/videos/embed.scss | 1 - client/src/standalone/videos/embed.ts | 15 +++- client/yarn.lock | 10 +-- 9 files changed, 169 insertions(+), 25 deletions(-) create mode 100644 client/src/assets/player/dock/peertube-dock-component.ts create mode 100644 client/src/assets/player/dock/peertube-dock-plugin.ts diff --git a/client/package.json b/client/package.json index 690e3b982..9e2657a94 100644 --- a/client/package.json +++ b/client/package.json @@ -130,7 +130,6 @@ "typescript": "~4.4.4", "url": "^0.11.0", "video.js": "^7", - "videojs-dock": "^3.0.0", "videostream": "~3.2.1", "wdio-chromedriver-service": "^7.2.0", "wdio-geckodriver-service": "^2.0.3", diff --git a/client/src/assets/player/dock/peertube-dock-component.ts b/client/src/assets/player/dock/peertube-dock-component.ts new file mode 100644 index 000000000..183c7a00f --- /dev/null +++ b/client/src/assets/player/dock/peertube-dock-component.ts @@ -0,0 +1,65 @@ +import videojs from 'video.js' + +const Component = videojs.getComponent('Component') + +export type PeerTubeDockComponentOptions = { + title?: string + description?: string + avatarUrl?: string +} + +class PeerTubeDockComponent extends Component { + + createEl () { + const options = this.options_ as PeerTubeDockComponentOptions + + const el = super.createEl('div', { + className: 'peertube-dock' + }) + + if (options.avatarUrl) { + const avatar = videojs.dom.createEl('img', { + className: 'peertube-dock-avatar', + src: options.avatarUrl + }) + + el.appendChild(avatar) + } + + const elWrapperTitleDescription = super.createEl('div', { + className: 'peertube-dock-title-description' + }) + + if (options.title) { + const title = videojs.dom.createEl('div', { + className: 'peertube-dock-title', + title: options.title, + innerHTML: options.title + }) + + elWrapperTitleDescription.appendChild(title) + } + + if (options.description) { + const description = videojs.dom.createEl('div', { + className: 'peertube-dock-description', + title: options.description, + innerHTML: options.description + }) + + elWrapperTitleDescription.appendChild(description) + } + + if (options.title || options.description) { + el.appendChild(elWrapperTitleDescription) + } + + return el + } +} + +videojs.registerComponent('PeerTubeDockComponent', PeerTubeDockComponent) + +export { + PeerTubeDockComponent +} diff --git a/client/src/assets/player/dock/peertube-dock-plugin.ts b/client/src/assets/player/dock/peertube-dock-plugin.ts new file mode 100644 index 000000000..245981692 --- /dev/null +++ b/client/src/assets/player/dock/peertube-dock-plugin.ts @@ -0,0 +1,25 @@ +import videojs from 'video.js' +import { PeerTubeDockComponent } from './peertube-dock-component' + +const Plugin = videojs.getPlugin('plugin') + +export type PeerTubeDockPluginOptions = { + title?: string + description?: string + avatarUrl?: string +} + +class PeerTubeDockPlugin extends Plugin { + constructor (player: videojs.Player, options: videojs.PlayerOptions & PeerTubeDockPluginOptions) { + super(player, options) + + this.player.addClass('peertube-dock') + + this.player.ready(() => { + this.player.addChild('PeerTubeDockComponent', options) as PeerTubeDockComponent + }) + } +} + +videojs.registerPlugin('peertubeDock', PeerTubeDockPlugin) +export { PeerTubeDockPlugin } diff --git a/client/src/assets/player/peertube-player-manager.ts b/client/src/assets/player/peertube-player-manager.ts index 2ef42a961..9d2b29811 100644 --- a/client/src/assets/player/peertube-player-manager.ts +++ b/client/src/assets/player/peertube-player-manager.ts @@ -1,4 +1,3 @@ -import 'videojs-dock' import '@peertube/videojs-contextmenu' import './upnext/end-card' import './upnext/upnext-plugin' diff --git a/client/src/assets/player/peertube-videojs-typings.ts b/client/src/assets/player/peertube-videojs-typings.ts index 246f0d390..09996f75d 100644 --- a/client/src/assets/player/peertube-videojs-typings.ts +++ b/client/src/assets/player/peertube-videojs-typings.ts @@ -1,6 +1,7 @@ import { HlsConfig, Level } from 'hls.js' import videojs from 'video.js' import { VideoFile, VideoPlaylist, VideoPlaylistElement } from '@shared/models' +import { PeerTubeDockPluginOptions } from './dock/peertube-dock-plugin' import { Html5Hlsjs } from './p2p-media-loader/hls-plugin' import { P2pMediaLoaderPlugin } from './p2p-media-loader/p2p-media-loader-plugin' import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager' @@ -50,7 +51,7 @@ declare module 'video.js' { tracks_: (TextTrack & { id: string, label: string, src: string })[] } - dock (options: { title: string, description: string }): void + peertubeDock (options: PeerTubeDockPluginOptions): void upnext (options: Partial): void diff --git a/client/src/sass/player/dock.scss b/client/src/sass/player/dock.scss index 4fa1ebd54..4939ea3e5 100644 --- a/client/src/sass/player/dock.scss +++ b/client/src/sass/player/dock.scss @@ -4,24 +4,62 @@ @use './_player-variables' as *; .video-js.vjs-peertube-skin { - .vjs-dock-text { + + .peertube-dock { + --avatarSize: 48px; + @include padding-right(60px); + transition: opacity 0.1s; + + display: flex; + align-items: center; + pointer-events: none; + position: absolute; + top: 0; + left: 0; + width: 100%; + + font-size: 23px; padding: $dock-padding; background: linear-gradient(to bottom, rgba(20, 20, 20, .7) 0, rgba(20, 20, 20, 0)); } - .vjs-dock-title { + .peertube-dock-avatar { + border-radius: 50%; + margin-right: 10px; + min-width: var(--avatarSize); + min-height: var(--avatarSize); + max-height: var(--avatarSize); + max-height: var(--avatarSize); + } + + .peertube-dock-title-description { + // For ellipsis + min-width: 0; + } + + .peertube-dock-title { font-weight: $font-semibold; + letter-spacing: 1px; + line-height: normal; + min-width: 0; } - .vjs-dock-title, - .vjs-dock-description { + .peertube-dock-title, + .peertube-dock-description { + @include ellipsis; + text-shadow: 0 1px 3px rgba(0, 0, 0, .5); } - .vjs-dock-description { + .peertube-dock-title + .peertube-dock-description { + margin-top: 3px; + } + + .peertube-dock-description { font-size: 11px; + line-height: 1.5; .text::before { @include margin-right(4px); @@ -34,24 +72,41 @@ } @media screen and (max-width: $screen-width-750) { - .vjs-dock-text { + .peertube-dock-avatar { + --avatarSize: 40px; + } + + .peertube-dock { font-size: 16px; } - .vjs-dock-description { + .peertube-dock-description { font-size: 9px; } } @media screen and (max-width: $screen-width-570) { - .vjs-dock-text { + .peertube-dock-avatar { + --avatarSize: 35px; + } + + .peertube-dock { font-size: 14px; } } @media screen and (max-width: $screen-width-350) { - .vjs-dock-text { + .peertube-dock-avatar { + --avatarSize: 30px; + } + + .peertube-dock { font-size: 13px; } } + + &.vjs-playing.vjs-user-inactive { + opacity: 0; + transition: opacity 1s; + } } diff --git a/client/src/standalone/videos/embed.scss b/client/src/standalone/videos/embed.scss index c2ee16ae2..91ab822c8 100644 --- a/client/src/standalone/videos/embed.scss +++ b/client/src/standalone/videos/embed.scss @@ -1,7 +1,6 @@ @use '_variables' as *; @use '_mixins' as *; @use 'video.js/dist/video-js'; -@use 'videojs-dock/dist/videojs-dock'; $assets-path: '../../assets/'; @use '../../sass/player/index'; diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts index 054f771ab..38ff39890 100644 --- a/client/src/standalone/videos/embed.ts +++ b/client/src/standalone/videos/embed.ts @@ -1,4 +1,6 @@ import './embed.scss' +import '../../assets/player/dock/peertube-dock-component' +import '../../assets/player/dock/peertube-dock-plugin' import videojs from 'video.js' import { peertubeTranslate } from '../../../../shared/core-utils/i18n' import { @@ -678,15 +680,22 @@ export class PeerTubeEmbed { if (!this.player.player_) return const title = this.title ? videoInfo.name : undefined - const description = this.warningTitle && this.p2pEnabled ? '' + peertubeTranslate('Watching this video may reveal your IP address to others.') + '' : undefined + const availableAvatars = videoInfo.channel.avatars.filter(a => a.width < 50) + const avatar = availableAvatars.length !== 0 + ? availableAvatars[0] + : undefined + if (title || description) { - this.player.dock({ + this.player.peertubeDock({ title, - description + description, + avatarUrl: title && avatar + ? avatar.path + : undefined }) } } diff --git a/client/yarn.lock b/client/yarn.lock index 847fe77d2..278f04942 100644 --- a/client/yarn.lock +++ b/client/yarn.lock @@ -10941,7 +10941,7 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -"video.js@^6 || ^7", video.js@^7, video.js@^7.17.0, video.js@^7.6.0: +"video.js@^6 || ^7", video.js@^7, video.js@^7.6.0: version "7.17.0" resolved "https://registry.yarnpkg.com/video.js/-/video.js-7.17.0.tgz#35918cc03748a5680f5d5f1da410e06eeea7786e" integrity sha512-8RbLu9+Pdpep9OTPncUHIvZXFgn/7hKdPnSTE/lGSnlFSucXtTUBp41R7NDwncscMLQ0WgazUbmFlvr4MNWMbA== @@ -10960,14 +10960,6 @@ verror@1.10.0: videojs-font "3.2.0" videojs-vtt.js "^0.15.3" -videojs-dock@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/videojs-dock/-/videojs-dock-3.0.0.tgz#fd343934be410c525cfc6106d6eef8a1b6c21189" - integrity sha512-v4NCw5mM2BO2pJqJQzjGq9BaEpnqPInNRNXzCBRrDTTxNwPHMG9zSoldpsUMj7lOlboAuB9pSiva/XX1eMWXDA== - dependencies: - global "^4.4.0" - video.js "^7.17.0" - videojs-font@3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-3.2.0.tgz#212c9d3f4e4ec3fa7345167d64316add35e92232" -- 2.41.0