Compare commits
	
		
			5 commits
		
	
	
		
			f0c45176d8
			...
			6064db4335
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
							 | 
						6064db4335 | ||
| 
							 | 
						db69b78f1b | ||
| 
							 | 
						ff5a32ff3e | ||
| 
							 | 
						1c33c6a388 | ||
| 
							 | 
						a93217d2da | 
					 20 changed files with 45 additions and 104 deletions
				
			
		
							
								
								
									
										12
									
								
								CHANGELOG.md
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								CHANGELOG.md
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1,5 +1,17 @@
 | 
			
		|||
# Changelog
 | 
			
		||||
 | 
			
		||||
## v6.0.4
 | 
			
		||||
 | 
			
		||||
### IMPORTANT NOTES
 | 
			
		||||
 | 
			
		||||
 * If you upgrade from PeerTube **< v6.0.0**, please follow v6.0.0 IMPORTANT NOTES
 | 
			
		||||
 * If you upgrade from PeerTube **v6.0.0**, please follow v6.0.1 IMPORTANT NOTES
 | 
			
		||||
 | 
			
		||||
### SECURITY
 | 
			
		||||
 | 
			
		||||
 * **Important:** Prevent XSS injection in embed. Thanks [Syst3m0ver](https://www.linkedin.com/in/ahmed-hasnaoui-790618180)!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## v6.0.3
 | 
			
		||||
 | 
			
		||||
### IMPORTANT NOTES
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "peertube-client",
 | 
			
		||||
  "version": "6.0.3",
 | 
			
		||||
  "version": "6.0.4",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "license": "AGPL-3.0",
 | 
			
		||||
  "author": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,6 @@ import { AppComponent } from './app.component'
 | 
			
		|||
import { CoreModule, PluginService, RedirectService, ServerService } from './core'
 | 
			
		||||
import { EmptyComponent } from './empty.component'
 | 
			
		||||
import { HeaderComponent, SearchTypeaheadComponent, SuggestionComponent } from './header'
 | 
			
		||||
import { HighlightPipe } from './header/highlight.pipe'
 | 
			
		||||
import { polyfillICU } from './helpers'
 | 
			
		||||
import { LanguageChooserComponent, MenuComponent, NotificationComponent } from './menu'
 | 
			
		||||
import { AccountSetupWarningModalComponent } from './modal/account-setup-warning-modal.component'
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +57,6 @@ export function loadConfigFactory (server: ServerService, pluginService: PluginS
 | 
			
		|||
    HeaderComponent,
 | 
			
		||||
    SearchTypeaheadComponent,
 | 
			
		||||
    SuggestionComponent,
 | 
			
		||||
    HighlightPipe,
 | 
			
		||||
 | 
			
		||||
    AccountSetupWarningModalComponent,
 | 
			
		||||
    CustomModalComponent,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,54 +0,0 @@
 | 
			
		|||
import { PipeTransform, Pipe } from '@angular/core'
 | 
			
		||||
import { SafeHtml } from '@angular/platform-browser'
 | 
			
		||||
 | 
			
		||||
// Thanks https://gist.github.com/adamrecsko/0f28f474eca63e0279455476cc11eca7#gistcomment-2917369
 | 
			
		||||
@Pipe({ name: 'highlight' })
 | 
			
		||||
export class HighlightPipe implements PipeTransform {
 | 
			
		||||
  /* use this for single match search */
 | 
			
		||||
  static SINGLE_MATCH = 'Single-Match'
 | 
			
		||||
  /* use this for single match search with a restriction that target should start with search string */
 | 
			
		||||
  static SINGLE_AND_STARTS_WITH_MATCH = 'Single-And-StartsWith-Match'
 | 
			
		||||
  /* use this for global search */
 | 
			
		||||
  static MULTI_MATCH = 'Multi-Match'
 | 
			
		||||
 | 
			
		||||
  transform (
 | 
			
		||||
    contentString: string = null,
 | 
			
		||||
    stringToHighlight: string = null,
 | 
			
		||||
    option = 'Single-And-StartsWith-Match',
 | 
			
		||||
    caseSensitive = false,
 | 
			
		||||
    highlightStyleName = 'search-highlight'
 | 
			
		||||
  ): SafeHtml {
 | 
			
		||||
    if (stringToHighlight && contentString && option) {
 | 
			
		||||
      let regex: any = ''
 | 
			
		||||
      const caseFlag: string = !caseSensitive ? 'i' : ''
 | 
			
		||||
 | 
			
		||||
      switch (option) {
 | 
			
		||||
        case 'Single-Match': {
 | 
			
		||||
          regex = new RegExp(stringToHighlight, caseFlag)
 | 
			
		||||
          break
 | 
			
		||||
        }
 | 
			
		||||
        case 'Single-And-StartsWith-Match': {
 | 
			
		||||
          regex = new RegExp('^' + stringToHighlight, caseFlag)
 | 
			
		||||
          break
 | 
			
		||||
        }
 | 
			
		||||
        case 'Multi-Match': {
 | 
			
		||||
          regex = new RegExp(stringToHighlight, 'g' + caseFlag)
 | 
			
		||||
          break
 | 
			
		||||
        }
 | 
			
		||||
        default: {
 | 
			
		||||
          // default will be a global case-insensitive match
 | 
			
		||||
          regex = new RegExp(stringToHighlight, 'gi')
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const replaced = contentString.replace(
 | 
			
		||||
        regex,
 | 
			
		||||
        (match) => `<span class="${highlightStyleName}">${match}</span>`
 | 
			
		||||
      )
 | 
			
		||||
 | 
			
		||||
      return replaced
 | 
			
		||||
    } else {
 | 
			
		||||
      return contentString
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -7,8 +7,10 @@
 | 
			
		|||
 | 
			
		||||
  <div
 | 
			
		||||
    class="flex-auto overflow-hidden text-start no-wrap css-truncate css-truncate-target"
 | 
			
		||||
    [attr.aria-label]="result.text" [innerHTML]="result.text | highlight : highlight"
 | 
			
		||||
  ></div>
 | 
			
		||||
    [attr.aria-label]="result.text"
 | 
			
		||||
  >
 | 
			
		||||
    {{ result.text }}
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="border rounded flex-shrink-0 px-1 bg-gray text-gray-light ms-1 f6">
 | 
			
		||||
    <span *ngIf="result.type === 'search-instance'" i18n>In this instance's network</span>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,8 +62,8 @@ export class ConfirmComponent implements OnInit {
 | 
			
		|||
        this.confirmButtonText = confirmButtonText || $localize`Confirm`
 | 
			
		||||
 | 
			
		||||
        this.html.toSafeHtml(message)
 | 
			
		||||
          .then(message => {
 | 
			
		||||
            this.message = message
 | 
			
		||||
          .then(html => {
 | 
			
		||||
            this.message = html
 | 
			
		||||
 | 
			
		||||
            this.showModal()
 | 
			
		||||
          })
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ class PeerTubeLinkButton extends Component {
 | 
			
		|||
  createEl () {
 | 
			
		||||
    const el = videojs.dom.createEl('a', {
 | 
			
		||||
      href: this.buildLink(),
 | 
			
		||||
      innerHTML: this.options_.instanceName,
 | 
			
		||||
      innerText: this.options_.instanceName,
 | 
			
		||||
      title: this.player().localize('Video page (new window)'),
 | 
			
		||||
      className: 'vjs-peertube-link',
 | 
			
		||||
      target: '_blank'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@ class PeerTubeDockComponent extends Component {
 | 
			
		|||
      const title = videojs.dom.createEl('div', {
 | 
			
		||||
        className: 'peertube-dock-title',
 | 
			
		||||
        title: this.options_.title,
 | 
			
		||||
        innerHTML: this.options_.title
 | 
			
		||||
        innerText: this.options_.title
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      elWrapperTitleDescription.appendChild(title)
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +47,7 @@ class PeerTubeDockComponent extends Component {
 | 
			
		|||
      const description = videojs.dom.createEl('div', {
 | 
			
		||||
        className: 'peertube-dock-description',
 | 
			
		||||
        title: this.options_.description,
 | 
			
		||||
        innerHTML: this.options_.description
 | 
			
		||||
        innerText: this.options_.description
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      elWrapperTitleDescription.appendChild(description)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,19 +22,16 @@ class PlaylistButton extends ClickableComponent {
 | 
			
		|||
  createEl () {
 | 
			
		||||
    this.wrapper = super.createEl('div', {
 | 
			
		||||
      className: 'vjs-playlist-button',
 | 
			
		||||
      innerHTML: '',
 | 
			
		||||
      tabIndex: -1
 | 
			
		||||
    }) as HTMLElement
 | 
			
		||||
 | 
			
		||||
    const icon = super.createEl('div', {
 | 
			
		||||
      className: 'vjs-playlist-icon',
 | 
			
		||||
      innerHTML: '',
 | 
			
		||||
      tabIndex: -1
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    this.playlistInfoElement = super.createEl('div', {
 | 
			
		||||
      className: 'vjs-playlist-info',
 | 
			
		||||
      innerHTML: '',
 | 
			
		||||
      tabIndex: -1
 | 
			
		||||
    }) as HTMLElement
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -47,7 +44,7 @@ class PlaylistButton extends ClickableComponent {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  update () {
 | 
			
		||||
    this.playlistInfoElement.innerHTML = this.options_.getCurrentPosition() + '/' + this.options_.playlist.videosLength
 | 
			
		||||
    this.playlistInfoElement.innerText = this.options_.getCurrentPosition() + '/' + this.options_.playlist.videosLength
 | 
			
		||||
 | 
			
		||||
    this.wrapper.title = this.player().localize('Playlist: {1}', [ this.options_.playlist.displayName ])
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,8 +36,7 @@ class PlaylistMenuItem extends Component {
 | 
			
		|||
 | 
			
		||||
  createEl () {
 | 
			
		||||
    const li = super.createEl('li', {
 | 
			
		||||
      className: 'vjs-playlist-menu-item',
 | 
			
		||||
      innerHTML: ''
 | 
			
		||||
      className: 'vjs-playlist-menu-item'
 | 
			
		||||
    }) as HTMLElement
 | 
			
		||||
 | 
			
		||||
    if (!this.options_.element.video) {
 | 
			
		||||
| 
						 | 
				
			
			@ -50,7 +49,7 @@ class PlaylistMenuItem extends Component {
 | 
			
		|||
 | 
			
		||||
    const position = super.createEl('div', {
 | 
			
		||||
      className: 'item-position',
 | 
			
		||||
      innerHTML: this.options_.element.position
 | 
			
		||||
      innerText: this.options_.element.position
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    positionBlock.appendChild(position)
 | 
			
		||||
| 
						 | 
				
			
			@ -92,12 +91,12 @@ class PlaylistMenuItem extends Component {
 | 
			
		|||
    })
 | 
			
		||||
 | 
			
		||||
    const title = super.createEl('div', {
 | 
			
		||||
      innerHTML: videoElement.video.name,
 | 
			
		||||
      innerText: videoElement.video.name,
 | 
			
		||||
      className: 'title'
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const channel = super.createEl('div', {
 | 
			
		||||
      innerHTML: videoElement.video.channel.displayName,
 | 
			
		||||
      innerText: videoElement.video.channel.displayName,
 | 
			
		||||
      className: 'channel'
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +110,7 @@ class PlaylistMenuItem extends Component {
 | 
			
		|||
      if (videoElement.stopTimestamp) html += ' - ' + secondsToTime(videoElement.stopTimestamp)
 | 
			
		||||
 | 
			
		||||
      const timestamps = super.createEl('div', {
 | 
			
		||||
        innerHTML: html,
 | 
			
		||||
        innerText: html,
 | 
			
		||||
        className: 'timestamps'
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -125,7 +124,7 @@ class PlaylistMenuItem extends Component {
 | 
			
		|||
  private buildUnavailableVideo (li: HTMLElement) {
 | 
			
		||||
    const block = super.createEl('div', {
 | 
			
		||||
      className: 'item-unavailable',
 | 
			
		||||
      innerHTML: this.player().localize('Unavailable video')
 | 
			
		||||
      innerTExt: this.player().localize('Unavailable video')
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    li.appendChild(block)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,7 +73,6 @@ class PlaylistMenu extends Component {
 | 
			
		|||
 | 
			
		||||
    const menu = super.createEl('div', {
 | 
			
		||||
      className: 'vjs-playlist-menu',
 | 
			
		||||
      innerHTML: '',
 | 
			
		||||
      tabIndex: -1
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -84,13 +83,13 @@ class PlaylistMenu extends Component {
 | 
			
		|||
    const headerLeft = super.createEl('div')
 | 
			
		||||
 | 
			
		||||
    const leftTitle = super.createEl('div', {
 | 
			
		||||
      innerHTML: this.options_.playlist.displayName,
 | 
			
		||||
      innerText: this.options_.playlist.displayName,
 | 
			
		||||
      className: 'title'
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const playlistChannel = this.options_.playlist.videoChannel
 | 
			
		||||
    const leftSubtitle = super.createEl('div', {
 | 
			
		||||
      innerHTML: playlistChannel
 | 
			
		||||
      innerText: playlistChannel
 | 
			
		||||
        ? this.player().localize('By {1}', [ playlistChannel.displayName ])
 | 
			
		||||
        : '',
 | 
			
		||||
      className: 'channel'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,6 @@ class SettingsDialog extends Component {
 | 
			
		|||
 | 
			
		||||
    return super.createEl('div', {
 | 
			
		||||
      className: 'vjs-settings-dialog vjs-modal-overlay',
 | 
			
		||||
      innerHTML: '',
 | 
			
		||||
      tabIndex: -1
 | 
			
		||||
    }, {
 | 
			
		||||
      'role': 'dialog',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ class SettingsPanelChild extends Component {
 | 
			
		|||
  createEl () {
 | 
			
		||||
    return super.createEl('div', {
 | 
			
		||||
      className: 'vjs-settings-panel-child',
 | 
			
		||||
      innerHTML: '',
 | 
			
		||||
      tabIndex: -1
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,7 +7,6 @@ class SettingsPanel extends Component {
 | 
			
		|||
  createEl () {
 | 
			
		||||
    return super.createEl('div', {
 | 
			
		||||
      className: 'vjs-settings-panel',
 | 
			
		||||
      innerHTML: '',
 | 
			
		||||
      tabIndex: -1
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -285,15 +285,15 @@ class StatsCard extends Component {
 | 
			
		|||
    if (player.muted()) volume += player.localize(' (muted)')
 | 
			
		||||
 | 
			
		||||
    const networkActivity = playerNetworkInfo.downloadSpeed
 | 
			
		||||
      ? `${playerNetworkInfo.downloadSpeed} ⇓ / ${playerNetworkInfo.uploadSpeed} ⇑`
 | 
			
		||||
      ? `${playerNetworkInfo.downloadSpeed} \u21D3 / ${playerNetworkInfo.uploadSpeed} \u21D1`
 | 
			
		||||
      : undefined
 | 
			
		||||
 | 
			
		||||
    let totalTransferred = playerNetworkInfo.totalDownloaded
 | 
			
		||||
      ? `${playerNetworkInfo.totalDownloaded} ⇓`
 | 
			
		||||
      ? `${playerNetworkInfo.totalDownloaded} \u21D3`
 | 
			
		||||
      : ''
 | 
			
		||||
 | 
			
		||||
    if (playerNetworkInfo.totalUploaded) {
 | 
			
		||||
      totalTransferred += `/ ${playerNetworkInfo.totalUploaded} ⇑`
 | 
			
		||||
      totalTransferred += `/ ${playerNetworkInfo.totalUploaded} \u21D1`
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const downloadBreakdown = playerNetworkInfo.downloadedFromServer
 | 
			
		||||
| 
						 | 
				
			
			@ -337,16 +337,16 @@ class StatsCard extends Component {
 | 
			
		|||
 | 
			
		||||
    el.root.style.display = 'block'
 | 
			
		||||
 | 
			
		||||
    if (el.value.innerHTML === value) return
 | 
			
		||||
    el.value.innerHTML = value
 | 
			
		||||
    if (el.value.innerText === value) return
 | 
			
		||||
    el.value.innerText = value
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private buildInfoRow (labelText: string, valueHTML?: string) {
 | 
			
		||||
  private buildInfoRow (labelText: string) {
 | 
			
		||||
    const root = videojs.dom.createEl('div') as HTMLElement
 | 
			
		||||
    root.style.display = 'none'
 | 
			
		||||
 | 
			
		||||
    const label = videojs.dom.createEl('div', { innerText: labelText }) as HTMLElement
 | 
			
		||||
    const value = videojs.dom.createEl('span', { innerHTML: valueHTML }) as HTMLElement
 | 
			
		||||
    const value = videojs.dom.createEl('span') as HTMLElement
 | 
			
		||||
 | 
			
		||||
    root.appendChild(label)
 | 
			
		||||
    root.appendChild(value)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,7 +121,7 @@ export class EndCard extends Component {
 | 
			
		|||
    this.autoplayRing.setAttribute('stroke-dasharray', `${this.dashOffsetStart}`)
 | 
			
		||||
    this.autoplayRing.setAttribute('stroke-dashoffset', `${-this.dashOffsetStart}`)
 | 
			
		||||
 | 
			
		||||
    this.title.innerHTML = this.options_.getTitle()
 | 
			
		||||
    this.title.innerText = this.options_.getTitle()
 | 
			
		||||
 | 
			
		||||
    if (this.totalTicks === 0) {
 | 
			
		||||
      return cb(false)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,15 +60,6 @@
 | 
			
		|||
  .peertube-dock-description {
 | 
			
		||||
    font-size: 11px;
 | 
			
		||||
    line-height: 1.5;
 | 
			
		||||
 | 
			
		||||
    .text::before {
 | 
			
		||||
      @include margin-right(4px);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .text::after {
 | 
			
		||||
      @include margin-left(4px);
 | 
			
		||||
      transform: scale(-1, 1);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @media screen and (max-width: $screen-width-750) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,14 +69,14 @@ export class PlayerHTML {
 | 
			
		|||
      videoPasswordBlock.style.display = 'flex'
 | 
			
		||||
 | 
			
		||||
      const videoPasswordTitle = document.getElementById('video-password-title')
 | 
			
		||||
      videoPasswordTitle.innerHTML = translatedTitle
 | 
			
		||||
      videoPasswordTitle.innerText = translatedTitle
 | 
			
		||||
 | 
			
		||||
      const videoPasswordMessage = document.getElementById('video-password-content')
 | 
			
		||||
      videoPasswordMessage.innerHTML = translatedMessage
 | 
			
		||||
      videoPasswordMessage.innerText = translatedMessage
 | 
			
		||||
 | 
			
		||||
      if (incorrectPassword) {
 | 
			
		||||
        const videoPasswordError = document.getElementById('video-password-error')
 | 
			
		||||
        videoPasswordError.innerHTML = peertubeTranslate('Incorrect password, please enter a correct password', translations)
 | 
			
		||||
        videoPasswordError.innerText = peertubeTranslate('Incorrect password, please enter a correct password', translations)
 | 
			
		||||
        videoPasswordError.style.transform = 'scale(1.2)'
 | 
			
		||||
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ export class PlayerHTML {
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
      const videoPasswordSubmitButton = document.getElementById('video-password-submit')
 | 
			
		||||
      videoPasswordSubmitButton.innerHTML = peertubeTranslate('Watch Video', translations)
 | 
			
		||||
      videoPasswordSubmitButton.innerText = peertubeTranslate('Watch Video', translations)
 | 
			
		||||
 | 
			
		||||
      const videoPasswordInput = document.getElementById('video-password-input') as HTMLInputElement
 | 
			
		||||
      videoPasswordInput.placeholder = peertubeTranslate('Password', translations)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -436,7 +436,7 @@ export class PlayerOptionsBuilder {
 | 
			
		|||
      : undefined
 | 
			
		||||
 | 
			
		||||
    const description = this.hasWarningTitle() && this.hasP2PEnabled()
 | 
			
		||||
      ? '<span class="text">' + peertubeTranslate('Watching this video may reveal your IP address to others.') + '</span>'
 | 
			
		||||
      ? peertubeTranslate('Watching this video may reveal your IP address to others.')
 | 
			
		||||
      : undefined
 | 
			
		||||
 | 
			
		||||
    if (!title && !description) return
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "peertube",
 | 
			
		||||
  "description": "PeerTube, an ActivityPub-federated video streaming platform using P2P directly in your web browser.",
 | 
			
		||||
  "version": "6.0.3",
 | 
			
		||||
  "version": "6.0.4",
 | 
			
		||||
  "private": true,
 | 
			
		||||
  "licence": "AGPL-3.0",
 | 
			
		||||
  "engines": {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue