Fixed merge conflicts
This commit is contained in:
		
						commit
						a25ae08b80
					
				
							
								
								
									
										14
									
								
								package.json
								
								
								
								
							
							
						
						
									
										14
									
								
								package.json
								
								
								
								
							| 
						 | 
				
			
			@ -33,7 +33,7 @@
 | 
			
		|||
    "vue": "^2.6.11",
 | 
			
		||||
    "vue-electron": "^1.0.6",
 | 
			
		||||
    "vue-i18n": "^8.20.0",
 | 
			
		||||
    "vue-router": "^3.4.2",
 | 
			
		||||
    "vue-router": "^3.4.3",
 | 
			
		||||
    "vuex": "^3.5.1",
 | 
			
		||||
    "xml2json": "^0.12.0",
 | 
			
		||||
    "youtube-chat": "^1.1.0",
 | 
			
		||||
| 
						 | 
				
			
			@ -41,9 +41,9 @@
 | 
			
		|||
    "youtube-comments-task": "^1.3.15",
 | 
			
		||||
    "youtube-suggest": "^1.1.0",
 | 
			
		||||
    "yt-channel-info": "^1.0.3",
 | 
			
		||||
    "yt-trending-scraper": "^1.0.2",
 | 
			
		||||
    "yt-trending-scraper": "^1.0.3",
 | 
			
		||||
    "yt-xml2vtt": "^1.1.1",
 | 
			
		||||
    "ytdl-core": "^3.2.0",
 | 
			
		||||
    "ytdl-core": "^3.2.1",
 | 
			
		||||
    "ytpl": "^0.2.4",
 | 
			
		||||
    "ytsr": "^0.1.21"
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			@ -54,8 +54,8 @@
 | 
			
		|||
    "@babel/plugin-proposal-object-rest-spread": "^7.11.0",
 | 
			
		||||
    "@babel/preset-env": "^7.11.0",
 | 
			
		||||
    "@babel/preset-typescript": "^7.10.4",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^3.8.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^3.8.0",
 | 
			
		||||
    "@typescript-eslint/eslint-plugin": "^3.9.0",
 | 
			
		||||
    "@typescript-eslint/parser": "^3.9.0",
 | 
			
		||||
    "acorn": "^7.4.0",
 | 
			
		||||
    "babel-eslint": "^10.1.0",
 | 
			
		||||
    "babel-loader": "^8.1.0",
 | 
			
		||||
| 
						 | 
				
			
			@ -79,8 +79,8 @@
 | 
			
		|||
    "fast-glob": "^3.2.4",
 | 
			
		||||
    "file-loader": "^6.0.0",
 | 
			
		||||
    "html-webpack-plugin": "^4.3.0",
 | 
			
		||||
    "jest": "^26.2.2",
 | 
			
		||||
    "mini-css-extract-plugin": "^0.9.0",
 | 
			
		||||
    "jest": "^26.3.0",
 | 
			
		||||
    "mini-css-extract-plugin": "^0.10.0",
 | 
			
		||||
    "node-abi": "^2.18.0",
 | 
			
		||||
    "node-loader": "^1.0.1",
 | 
			
		||||
    "npm-run-all": "^4.1.5",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,7 @@ export default Vue.extend({
 | 
			
		|||
    this.$store.dispatch('grabUserSettings')
 | 
			
		||||
    this.$store.commit('setUsingElectron', useElectron)
 | 
			
		||||
    this.checkThemeSettings()
 | 
			
		||||
    this.checkLocale()
 | 
			
		||||
 | 
			
		||||
    if (useElectron) {
 | 
			
		||||
      console.log('User is using Electron')
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +49,17 @@ export default Vue.extend({
 | 
			
		|||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    checkLocale: function () {
 | 
			
		||||
      const locale = localStorage.getItem('locale')
 | 
			
		||||
 | 
			
		||||
      if (locale === null) {
 | 
			
		||||
        // TODO: Get User default locale
 | 
			
		||||
        this.$i18n.locale = 'en-US'
 | 
			
		||||
      } else {
 | 
			
		||||
        this.$i18n.locale = locale
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    checkThemeSettings: function () {
 | 
			
		||||
      let baseTheme = localStorage.getItem('baseTheme')
 | 
			
		||||
      let mainColor = localStorage.getItem('mainColor')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ export default Vue.extend({
 | 
			
		|||
      channelName: '',
 | 
			
		||||
      channelId: '',
 | 
			
		||||
      viewCount: 0,
 | 
			
		||||
      parsedViewCount: '',
 | 
			
		||||
      uploadedTime: '',
 | 
			
		||||
      duration: '',
 | 
			
		||||
      description: '',
 | 
			
		||||
| 
						 | 
				
			
			@ -39,14 +40,6 @@ export default Vue.extend({
 | 
			
		|||
      isLive: false,
 | 
			
		||||
      isFavorited: false,
 | 
			
		||||
      hideViews: false,
 | 
			
		||||
      optionsNames: [
 | 
			
		||||
        'Open in YouTube',
 | 
			
		||||
        'Copy YouTube Link',
 | 
			
		||||
        'Open YouTube Embedded Player',
 | 
			
		||||
        'Copy YouTube Embedded Player Link',
 | 
			
		||||
        'Open in Invidious',
 | 
			
		||||
        'Copy Invidious Link'
 | 
			
		||||
      ],
 | 
			
		||||
      optionsValues: [
 | 
			
		||||
        'openYoutube',
 | 
			
		||||
        'copyYoutube',
 | 
			
		||||
| 
						 | 
				
			
			@ -90,6 +83,17 @@ export default Vue.extend({
 | 
			
		|||
      return `https://www.youtube-nocookie.com/embed/${this.id}`
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    optionsNames: function () {
 | 
			
		||||
      return [
 | 
			
		||||
        this.$t('Video.Open in YouTube'),
 | 
			
		||||
        this.$t('Video.Copy YouTube Link'),
 | 
			
		||||
        this.$t('Video.Open YouTube Embedded Player'),
 | 
			
		||||
        this.$t('Video.Copy YouTube Embedded Player Link'),
 | 
			
		||||
        this.$t('Video.Open in Invidious'),
 | 
			
		||||
        this.$t('Video.Copy Invidious Link')
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    thumbnail: function () {
 | 
			
		||||
      let baseUrl
 | 
			
		||||
      if (this.backendPreference === 'invidious') {
 | 
			
		||||
| 
						 | 
				
			
			@ -206,15 +210,16 @@ export default Vue.extend({
 | 
			
		|||
      this.duration = this.calculateVideoDuration(this.data.lengthSeconds)
 | 
			
		||||
      this.description = this.data.description
 | 
			
		||||
      this.isLive = this.data.liveNow
 | 
			
		||||
      this.viewCount = this.data.viewCount
 | 
			
		||||
 | 
			
		||||
      if (typeof (this.data.publishedText) !== 'undefined') {
 | 
			
		||||
        this.uploadedTime = this.data.publishedText
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (typeof (this.data.viewCount) !== 'undefined' && this.data.viewCount !== null) {
 | 
			
		||||
        this.viewCount = this.data.viewCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
 | 
			
		||||
        this.parsedViewCount = this.data.viewCount.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
 | 
			
		||||
      } else if (typeof (this.data.viewCountText) !== 'undefined') {
 | 
			
		||||
        this.viewCount = this.data.viewCountText.replace(' views', '')
 | 
			
		||||
        this.parsedViewCount = this.data.viewCountText.replace(' views', '')
 | 
			
		||||
      } else {
 | 
			
		||||
        this.hideViews = true
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -232,6 +237,7 @@ export default Vue.extend({
 | 
			
		|||
      if (typeof (this.data.author) === 'string') {
 | 
			
		||||
        this.channelName = this.data.author
 | 
			
		||||
        this.channelId = this.data.ucid
 | 
			
		||||
        this.viewCount = this.data.views
 | 
			
		||||
 | 
			
		||||
        // Data is returned as a literal string names 'undefined'
 | 
			
		||||
        if (this.data.length_seconds !== 'undefined') {
 | 
			
		||||
| 
						 | 
				
			
			@ -250,10 +256,10 @@ export default Vue.extend({
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
      if (this.data.views !== null && typeof (this.data.views) !== 'undefined') {
 | 
			
		||||
        this.viewCount = this.data.views.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
 | 
			
		||||
        this.parsedViewCount = this.data.views.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
 | 
			
		||||
      } else if (typeof (this.data.view_count) !== 'undefined') {
 | 
			
		||||
        const viewCount = this.data.view_count.replace(',', '')
 | 
			
		||||
        this.viewCount = viewCount.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
 | 
			
		||||
        this.parsedViewCount = viewCount.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
 | 
			
		||||
      } else {
 | 
			
		||||
        this.hideViews = true
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,7 +26,7 @@
 | 
			
		|||
        class="videoDuration"
 | 
			
		||||
        :class="{ live: isLive }"
 | 
			
		||||
      >
 | 
			
		||||
        {{ isLive ? "Live" : duration }}
 | 
			
		||||
        {{ isLive ? $t("Video.Live") : duration }}
 | 
			
		||||
      </div>
 | 
			
		||||
      <ft-icon-button
 | 
			
		||||
        v-if="!isLive"
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +41,7 @@
 | 
			
		|||
        v-if="watched"
 | 
			
		||||
        class="videoWatched"
 | 
			
		||||
      >
 | 
			
		||||
        Watched
 | 
			
		||||
        {{ $t("Video.Watched") }}
 | 
			
		||||
      </div>
 | 
			
		||||
      <div
 | 
			
		||||
        v-if="watched"
 | 
			
		||||
| 
						 | 
				
			
			@ -80,7 +80,9 @@
 | 
			
		|||
        <span
 | 
			
		||||
          v-if="!isLive && !hideViews"
 | 
			
		||||
          class="viewCount"
 | 
			
		||||
        >• {{ viewCount }} views</span>
 | 
			
		||||
        >• {{ parsedViewCount }}</span>
 | 
			
		||||
        <span v-if="viewCount > 1">{{ $t("Video.Views").toLowerCase() }}</span>
 | 
			
		||||
        <span v-if="viewCount === 1">{{ $t("Video.View") }}</span>
 | 
			
		||||
        <span
 | 
			
		||||
          v-if="uploadedTime !== '' && !isLive"
 | 
			
		||||
          class="uploadedTime"
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +90,7 @@
 | 
			
		|||
        <span
 | 
			
		||||
          v-if="isLive"
 | 
			
		||||
          class="viewCount"
 | 
			
		||||
        >• {{ viewCount }} watching</span>
 | 
			
		||||
        >• {{ viewCount }} {{ $t("Video.Watching").toLowerCase() }}</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <p
 | 
			
		||||
        v-if="listType !== 'grid' && appearance === 'result'"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ export default Vue.extend({
 | 
			
		|||
      showInvidiousInstances: false,
 | 
			
		||||
      instanceNames: [],
 | 
			
		||||
      instanceValues: [],
 | 
			
		||||
      currentLocale: '',
 | 
			
		||||
      backendValues: [
 | 
			
		||||
        'invidious',
 | 
			
		||||
        'local'
 | 
			
		||||
| 
						 | 
				
			
			@ -562,6 +563,10 @@ export default Vue.extend({
 | 
			
		|||
      return this.$store.getters.getThumbnailPreference
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    localeOptions: function () {
 | 
			
		||||
      return Object.keys(this.$i18n.messages)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    backendNames: function () {
 | 
			
		||||
      return [
 | 
			
		||||
        this.$t('Settings.General Settings.Preferred API Backend.Invidious API'),
 | 
			
		||||
| 
						 | 
				
			
			@ -614,6 +619,8 @@ export default Vue.extend({
 | 
			
		|||
    })
 | 
			
		||||
 | 
			
		||||
    this.updateInvidiousInstanceBounce = debounce(this.updateInvidiousInstance, 500)
 | 
			
		||||
 | 
			
		||||
    this.currentLocale = this.$i18n.locale
 | 
			
		||||
  },
 | 
			
		||||
  beforeDestroy: function () {
 | 
			
		||||
    if (this.invidiousInstance === '') {
 | 
			
		||||
| 
						 | 
				
			
			@ -626,6 +633,11 @@ export default Vue.extend({
 | 
			
		|||
      this.updateInvidiousInstanceBounce(invidiousInstance)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    updateLocale: function (locale) {
 | 
			
		||||
      this.$i18n.locale = locale
 | 
			
		||||
      localStorage.setItem('locale', locale)
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    ...mapActions([
 | 
			
		||||
      'updateEnableSearchSuggestions',
 | 
			
		||||
      'updateBackendFallback',
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -63,6 +63,13 @@
 | 
			
		|||
        :select-values="thumbnailTypeValues"
 | 
			
		||||
        @change="updateThumbnailPreference"
 | 
			
		||||
      />
 | 
			
		||||
      <ft-select
 | 
			
		||||
        placeholder="Change Locale"
 | 
			
		||||
        :value="currentLocale"
 | 
			
		||||
        :select-names="localeOptions"
 | 
			
		||||
        :select-values="localeOptions"
 | 
			
		||||
        @change="updateLocale"
 | 
			
		||||
      />
 | 
			
		||||
    </div>
 | 
			
		||||
    <ft-flex-box class="generalSettingsFlexBox">
 | 
			
		||||
      <ft-input
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,12 +26,6 @@ export default Vue.extend({
 | 
			
		|||
      lastUpdated: '',
 | 
			
		||||
      description: '',
 | 
			
		||||
      infoSource: '',
 | 
			
		||||
      shareHeaders: [
 | 
			
		||||
        'Copy YouTube Link',
 | 
			
		||||
        'Open in YouTube',
 | 
			
		||||
        'Copy Invidious Link',
 | 
			
		||||
        'Open in Invidious'
 | 
			
		||||
      ],
 | 
			
		||||
      shareValues: [
 | 
			
		||||
        'copyYoutube',
 | 
			
		||||
        'openYoutube',
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +47,15 @@ export default Vue.extend({
 | 
			
		|||
      return this.$store.getters.getThumbnailPreference
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    shareHeaders: function () {
 | 
			
		||||
      return [
 | 
			
		||||
        this.$t('Playlist.Share Playlist.Copy YouTube Link'),
 | 
			
		||||
        this.$t('Playlist.Share Playlist.Open in YouTube'),
 | 
			
		||||
        this.$t('Playlist.Share Playlist.Copy Invidious Link'),
 | 
			
		||||
        this.$t('Playlist.Share Playlist.Open in Invidious')
 | 
			
		||||
      ]
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    thumbnail: function () {
 | 
			
		||||
      switch (this.thumbnailPreference) {
 | 
			
		||||
        case 'start':
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,9 +11,9 @@
 | 
			
		|||
      {{ title }}
 | 
			
		||||
    </h2>
 | 
			
		||||
    <p>
 | 
			
		||||
      {{ videoCount }} videos - {{ viewCount }} views -
 | 
			
		||||
      {{ videoCount }} {{ $t("Playlist.Videos") }} - {{ viewCount }} {{ $t("Playlist.Views") }} -
 | 
			
		||||
      <span v-if="infoSource !== 'local'">
 | 
			
		||||
        Last updated on
 | 
			
		||||
        {{ $t("Playlist.Last Updated On") }}
 | 
			
		||||
      </span>
 | 
			
		||||
      {{ lastUpdated }}
 | 
			
		||||
    </p>
 | 
			
		||||
| 
						 | 
				
			
			@ -31,7 +31,7 @@
 | 
			
		|||
    </div>
 | 
			
		||||
    <br>
 | 
			
		||||
    <ft-list-dropdown
 | 
			
		||||
      title="SHARE PLAYLIST"
 | 
			
		||||
      :title="$t('Playlist.Share Playlist.Share Playlist')"
 | 
			
		||||
      :label-names="shareHeaders"
 | 
			
		||||
      :label-values="shareValues"
 | 
			
		||||
      @click="sharePlaylist"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -116,7 +116,7 @@
 | 
			
		|||
      class="getMoreComments"
 | 
			
		||||
      @click="getCommentData"
 | 
			
		||||
    >
 | 
			
		||||
      {{ $t("Load More Comments") }}
 | 
			
		||||
      {{ $t("Comments.Load More Comments") }}
 | 
			
		||||
    </h4>
 | 
			
		||||
  </ft-card>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,7 +37,7 @@
 | 
			
		|||
      v-else
 | 
			
		||||
      class="relative"
 | 
			
		||||
    >
 | 
			
		||||
      <h4>Live Chat</h4>
 | 
			
		||||
      <h4>{{ $t("Video.Live Chat") }}</h4>
 | 
			
		||||
      <div
 | 
			
		||||
        v-if="superChatComments.length > 0"
 | 
			
		||||
        class="superChatComments"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ fs.readdir('.', (err, dir) => {
 | 
			
		|||
})
 | 
			
		||||
 | 
			
		||||
// List of locales approved for use
 | 
			
		||||
const activeLocales = ['en-US']
 | 
			
		||||
const activeLocales = ['en-US', 'de-DE']
 | 
			
		||||
const messages = {}
 | 
			
		||||
 | 
			
		||||
// Take active locales and load respective YAML file
 | 
			
		||||
| 
						 | 
				
			
			@ -56,6 +56,9 @@ activeLocales.forEach((locale) => {
 | 
			
		|||
 | 
			
		||||
const i18n = new VueI18n({
 | 
			
		||||
  locale: 'en-US', // set locale
 | 
			
		||||
  fallbackLocale: {
 | 
			
		||||
    default: 'en-US'
 | 
			
		||||
  },
 | 
			
		||||
  messages // set locale messages
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,7 @@
 | 
			
		|||
            {{ $t("Channel.About.About").toUpperCase() }}
 | 
			
		||||
          </div>
 | 
			
		||||
          <ft-input
 | 
			
		||||
            placeholder="Search Channel"
 | 
			
		||||
            :placeholder="$t('Channel.Search Channel')"
 | 
			
		||||
            class="channelSearch"
 | 
			
		||||
            @click="newSearch"
 | 
			
		||||
          />
 | 
			
		||||
| 
						 | 
				
			
			@ -171,7 +171,7 @@
 | 
			
		|||
          class="getNextPage"
 | 
			
		||||
          @click="handleFetchMore"
 | 
			
		||||
        >
 | 
			
		||||
          <font-awesome-icon icon="search" /> Fetch more results…
 | 
			
		||||
          <font-awesome-icon icon="search" /> {{ $t("Search Filters.Fetch more results") }}
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </ft-card>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -395,10 +395,10 @@ export default Vue.extend({
 | 
			
		|||
          this.videoViewCount = result.viewCount
 | 
			
		||||
          this.videoLikeCount = result.likeCount
 | 
			
		||||
          this.videoDislikeCount = result.dislikeCount
 | 
			
		||||
          this.channelSubscriptionCountText = result.subCountText
 | 
			
		||||
          this.channelSubscriptionCountText = result.subCountText || 'FT-0'
 | 
			
		||||
          this.channelId = result.authorId
 | 
			
		||||
          this.channelName = result.author
 | 
			
		||||
          this.channelThumbnail = result.authorThumbnails[1].url
 | 
			
		||||
          this.channelThumbnail = result.authorThumbnails[1] ? result.authorThumbnails[1].url : ''
 | 
			
		||||
          this.videoPublished = result.published * 1000
 | 
			
		||||
          this.videoDescriptionHtml = result.descriptionHtml
 | 
			
		||||
          this.recommendedVideos = result.recommendedVideos
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,6 +106,8 @@ Settings:
 | 
			
		|||
    Fallback to Non-Preferred Backend on Failure: Falle zu nicht-präferiertem System bei Fehlschlag zurück
 | 
			
		||||
    Enable Search Suggestions: Aktiviere Suchvorschläge
 | 
			
		||||
    Default Landing Page: Standardseite
 | 
			
		||||
 | 
			
		||||
    Locale Preference: Locale Preference
 | 
			
		||||
    Preferred API Backend:
 | 
			
		||||
      Preferred API Backend: Präferiertes API System
 | 
			
		||||
      Local API: Lokale API
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,6 +106,7 @@ Settings:
 | 
			
		|||
    Fallback to Non-Preferred Backend on Failure: Fallback to Non-Preferred Backend on Failure
 | 
			
		||||
    Enable Search Suggestions: Enable Search Suggestions
 | 
			
		||||
    Default Landing Page: Default Landing Page
 | 
			
		||||
    Locale Preference: Locale Preference
 | 
			
		||||
    Preferred API Backend:
 | 
			
		||||
      Preferred API Backend: Preferred API Backend
 | 
			
		||||
      Local API: Local API
 | 
			
		||||
| 
						 | 
				
			
			@ -271,8 +272,21 @@ Channel:
 | 
			
		|||
    Channel Description: Channel Description
 | 
			
		||||
    Featured Channels: Featured Channels
 | 
			
		||||
Video:
 | 
			
		||||
  Open in YouTube: Open in YouTube
 | 
			
		||||
  Copy YouTube Link: Copy YouTube Link
 | 
			
		||||
  Open YouTube Embedded Player: Open YouTube Embedded Player
 | 
			
		||||
  Copy YouTube Embedded Player Link: Copy YouTube Embedded Player Link
 | 
			
		||||
  Open in Invidious: Open in Invidious
 | 
			
		||||
  Copy Invidious Link: Copy Invidious Link
 | 
			
		||||
  View: View
 | 
			
		||||
  Views: Views
 | 
			
		||||
  # Context is "X People Watching"
 | 
			
		||||
  Watching: Watching
 | 
			
		||||
  Watched: Watched
 | 
			
		||||
  # As in a Live Video
 | 
			
		||||
  Live: Live
 | 
			
		||||
  Live Now: Live Now
 | 
			
		||||
  Live Chat: Live Chat
 | 
			
		||||
  Enable Live Chat: Enable Live Chat
 | 
			
		||||
  Live Chat is currently not supported in this build.: Live Chat is currently not supported in this build.
 | 
			
		||||
  'Chat is disabled or the Live Stream has ended.': Chat is disabled or the Live Stream has ended.
 | 
			
		||||
| 
						 | 
				
			
			@ -314,14 +328,16 @@ Videos:
 | 
			
		|||
Playlist:
 | 
			
		||||
  #& About
 | 
			
		||||
  View Full Playlist: View Full Playlist
 | 
			
		||||
 | 
			
		||||
# On Channel Playlist Page
 | 
			
		||||
Share Playlist:
 | 
			
		||||
  Share Playlist: Share Playlist
 | 
			
		||||
  Copy YouTube Link: Copy YouTube Link
 | 
			
		||||
  Open in YouTube: Open in YouTube
 | 
			
		||||
  Copy Invidious Link: Copy Invidious Link
 | 
			
		||||
  Open in Invidious: Open in Invidious
 | 
			
		||||
  Videos: Videos
 | 
			
		||||
  View: View
 | 
			
		||||
  Views: Views
 | 
			
		||||
  Last Updated On: Last Updated On
 | 
			
		||||
  Share Playlist:
 | 
			
		||||
    Share Playlist: Share Playlist
 | 
			
		||||
    Copy YouTube Link: Copy YouTube Link
 | 
			
		||||
    Open in YouTube: Open in YouTube
 | 
			
		||||
    Copy Invidious Link: Copy Invidious Link
 | 
			
		||||
    Open in Invidious: Open in Invidious
 | 
			
		||||
 | 
			
		||||
# On Video Watch Page
 | 
			
		||||
#* Published
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue