diff --git a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts index 3af20ea0a..4fe5ec441 100644 --- a/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts +++ b/client/src/app/+admin/moderation/video-block-list/video-block-list.component.ts @@ -1,6 +1,6 @@ import { SortMeta } from 'primeng/api' import { switchMap } from 'rxjs/operators' -import { buildVideoEmbedLink, buildVideoOrPlaylistEmbed, decorateVideoLink } from 'src/assets/player/utils' +import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils' import { environment } from 'src/environments/environment' import { Component, OnInit } from '@angular/core' import { DomSanitizer } from '@angular/platform-browser' @@ -9,6 +9,7 @@ import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable, S import { AdvancedInputFilter } from '@app/shared/shared-forms' import { DropdownAction, Video, VideoService } from '@app/shared/shared-main' import { VideoBlockService } from '@app/shared/shared-moderation' +import { buildVideoEmbedLink, decorateVideoLink } from '@shared/core-utils' import { VideoBlacklist, VideoBlacklistType } from '@shared/models' @Component({ diff --git a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts index 6af224920..968abcbe5 100644 --- a/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts +++ b/client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts @@ -4,7 +4,7 @@ import { ActivatedRoute, Router } from '@angular/router' import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' import { ComponentPagination, ConfirmService, hasMoreItems, Notifier } from '@app/core' import { PluginService } from '@app/core/plugins/plugin.service' -import { compareSemVer } from '@shared/core-utils/miscs/miscs' +import { compareSemVer } from '@shared/core-utils' import { PeerTubePlugin, PluginType } from '@shared/models' @Component({ diff --git a/client/src/app/+videos/+video-watch/video-watch.component.ts b/client/src/app/+videos/+video-watch/video-watch.component.ts index 9212b78be..ccb9c5e71 100644 --- a/client/src/app/+videos/+video-watch/video-watch.component.ts +++ b/client/src/app/+videos/+video-watch/video-watch.component.ts @@ -21,6 +21,7 @@ import { isXPercentInViewport, scrollToTop } from '@app/helpers' import { Video, VideoCaptionService, VideoDetails, VideoService } from '@app/shared/shared-main' import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription' import { VideoPlaylist, VideoPlaylistService } from '@app/shared/shared-video-playlist' +import { timeToInt } from '@shared/core-utils' import { HTMLServerConfig, HttpStatusCode, @@ -39,7 +40,6 @@ import { PlayerMode, videojs } from '../../../assets/player/peertube-player-manager' -import { timeToInt } from '../../../assets/player/utils' import { environment } from '../../../environments/environment' import { VideoWatchPlaylistComponent } from './shared' diff --git a/client/src/app/core/renderer/markdown.service.ts b/client/src/app/core/renderer/markdown.service.ts index 01d44864b..36258ca98 100644 --- a/client/src/app/core/renderer/markdown.service.ts +++ b/client/src/app/core/renderer/markdown.service.ts @@ -1,6 +1,6 @@ import * as MarkdownIt from 'markdown-it' -import { buildVideoLink, decorateVideoLink } from 'src/assets/player/utils' import { Injectable } from '@angular/core' +import { buildVideoLink, decorateVideoLink } from '@shared/core-utils' import { COMPLETE_RULES, ENHANCED_RULES, diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts index 393108ac9..a7932ebab 100644 --- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts +++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.ts @@ -1,7 +1,7 @@ import * as debug from 'debug' import truncate from 'lodash-es/truncate' import { SortMeta } from 'primeng/api' -import { buildVideoEmbedLink, buildVideoOrPlaylistEmbed, decorateVideoLink } from 'src/assets/player/utils' +import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils' import { environment } from 'src/environments/environment' import { Component, Input, OnInit, ViewChild } from '@angular/core' import { DomSanitizer } from '@angular/platform-browser' @@ -10,6 +10,7 @@ import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } import { Account, Actor, DropdownAction, Video, VideoService } from '@app/shared/shared-main' import { AbuseService, BlocklistService, VideoBlockService } from '@app/shared/shared-moderation' import { VideoCommentService } from '@app/shared/shared-video-comment' +import { buildVideoEmbedLink, decorateVideoLink } from '@shared/core-utils' import { AbuseState, AdminAbuse } from '@shared/models' import { AdvancedInputFilter } from '../shared-forms' import { AbuseMessageModalComponent } from './abuse-message-modal.component' diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts index ba8969d5b..53b70cc47 100644 --- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts +++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/embed-markup.component.ts @@ -1,6 +1,7 @@ -import { buildPlaylistEmbedLink, buildVideoEmbedLink, buildVideoOrPlaylistEmbed } from 'src/assets/player/utils' +import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils' import { environment } from 'src/environments/environment' import { Component, ElementRef, Input, OnInit } from '@angular/core' +import { buildPlaylistEmbedLink, buildVideoEmbedLink } from '@shared/core-utils' import { CustomMarkupComponent } from './shared' @Component({ diff --git a/client/src/app/shared/shared-forms/timestamp-input.component.ts b/client/src/app/shared/shared-forms/timestamp-input.component.ts index 0ffd03d02..3fc705905 100644 --- a/client/src/app/shared/shared-forms/timestamp-input.component.ts +++ b/client/src/app/shared/shared-forms/timestamp-input.component.ts @@ -1,6 +1,6 @@ import { ChangeDetectorRef, Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core' import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' -import { secondsToTime, timeToInt } from '../../../assets/player/utils' +import { secondsToTime, timeToInt } from '@shared/core-utils' @Component({ selector: 'my-timestamp-input', diff --git a/client/src/app/shared/shared-main/video/video.model.ts b/client/src/app/shared/shared-main/video/video.model.ts index f0a4a3f37..b7720c8d2 100644 --- a/client/src/app/shared/shared-main/video/video.model.ts +++ b/client/src/app/shared/shared-main/video/video.model.ts @@ -2,6 +2,7 @@ import { AuthUser } from '@app/core' import { User } from '@app/core/users/user.model' import { durationToString, getAbsoluteAPIUrl, getAbsoluteEmbedUrl } from '@app/helpers' import { Actor } from '@app/shared/shared-main/account/actor.model' +import { buildVideoWatchPath } from '@shared/core-utils' import { peertubeTranslate } from '@shared/core-utils/i18n' import { ActorImage, @@ -92,7 +93,7 @@ export class Video implements VideoServerModel { pluginData?: any static buildWatchUrl (video: Partial>) { - return '/w/' + (video.shortUUID || video.uuid) + return buildVideoWatchPath({ shortUUID: video.shortUUID || video.uuid }) } static buildUpdateUrl (video: Pick) { diff --git a/client/src/app/shared/shared-moderation/report-modals/video-report.component.ts b/client/src/app/shared/shared-moderation/report-modals/video-report.component.ts index 41f4fa30d..e509ac88f 100644 --- a/client/src/app/shared/shared-moderation/report-modals/video-report.component.ts +++ b/client/src/app/shared/shared-moderation/report-modals/video-report.component.ts @@ -1,5 +1,5 @@ import { mapValues, pickBy } from 'lodash-es' -import { buildVideoOrPlaylistEmbed, decorateVideoLink } from 'src/assets/player/utils' +import { buildVideoOrPlaylistEmbed } from 'src/assets/player/utils' import { Component, Input, OnInit, ViewChild } from '@angular/core' import { DomSanitizer, SafeHtml } from '@angular/platform-browser' import { Notifier } from '@app/core' @@ -7,6 +7,7 @@ import { ABUSE_REASON_VALIDATOR } from '@app/shared/form-validators/abuse-valida import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref' +import { decorateVideoLink } from '@shared/core-utils' import { abusePredefinedReasonsMap } from '@shared/core-utils/abuse' import { AbusePredefinedReasonsString } from '@shared/models' import { Video } from '../../shared-main' diff --git a/client/src/app/shared/shared-share-modal/video-share.component.ts b/client/src/app/shared/shared-share-modal/video-share.component.ts index cdfe50836..341abdc2b 100644 --- a/client/src/app/shared/shared-share-modal/video-share.component.ts +++ b/client/src/app/shared/shared-share-modal/video-share.component.ts @@ -2,14 +2,9 @@ import { Component, ElementRef, Input, ViewChild } from '@angular/core' import { VideoDetails } from '@app/shared/shared-main' import { VideoPlaylist } from '@app/shared/shared-video-playlist' import { NgbModal } from '@ng-bootstrap/ng-bootstrap' +import { buildPlaylistLink, buildVideoLink, decoratePlaylistLink, decorateVideoLink } from '@shared/core-utils' import { VideoCaption } from '@shared/models' -import { - buildPlaylistLink, - buildVideoLink, - buildVideoOrPlaylistEmbed, - decoratePlaylistLink, - decorateVideoLink -} from '../../../assets/player/utils' +import { buildVideoOrPlaylistEmbed } from '../../../assets/player/utils' type Customizations = { startAtCheckbox: boolean diff --git a/client/src/app/shared/shared-video-miniature/abstract-video-list.ts b/client/src/app/shared/shared-video-miniature/abstract-video-list.ts index 52e72d35b..33061a837 100644 --- a/client/src/app/shared/shared-video-miniature/abstract-video-list.ts +++ b/client/src/app/shared/shared-video-miniature/abstract-video-list.ts @@ -24,7 +24,7 @@ import { } from '@app/core' import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' import { GlobalIconName } from '@app/shared/shared-icons' -import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@shared/core-utils/miscs/date' +import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@shared/core-utils' import { HTMLServerConfig, UserRight, VideoFilter, VideoSortField } from '@shared/models' import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' import { Syndication, Video } from '../shared-main' diff --git a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts index 681e5becd..8b019103c 100644 --- a/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts +++ b/client/src/app/shared/shared-video-playlist/video-add-to-playlist.component.ts @@ -4,6 +4,7 @@ import { debounceTime, filter } from 'rxjs/operators' import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges } from '@angular/core' import { AuthService, DisableForReuseHook, Notifier } from '@app/core' import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' +import { secondsToTime } from '@shared/core-utils' import { Video, VideoExistInPlaylist, @@ -12,7 +13,6 @@ import { VideoPlaylistElementUpdate, VideoPlaylistPrivacy } from '@shared/models' -import { secondsToTime } from '../../../assets/player/utils' import { VIDEO_PLAYLIST_DISPLAY_NAME_VALIDATOR } from '../form-validators/video-playlist-validators' import { CachedPlaylist, VideoPlaylistService } from './video-playlist.service' diff --git a/client/src/app/shared/shared-video-playlist/video-playlist-element-miniature.component.ts b/client/src/app/shared/shared-video-playlist/video-playlist-element-miniature.component.ts index d99170e4e..2e495ec26 100644 --- a/client/src/app/shared/shared-video-playlist/video-playlist-element-miniature.component.ts +++ b/client/src/app/shared/shared-video-playlist/video-playlist-element-miniature.component.ts @@ -2,8 +2,8 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, In import { AuthService, Notifier, ServerService } from '@app/core' import { Video } from '@app/shared/shared-main' import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap' +import { secondsToTime } from '@shared/core-utils' import { HTMLServerConfig, VideoPlaylistElementType, VideoPlaylistElementUpdate } from '@shared/models' -import { secondsToTime } from '../../../assets/player/utils' import { VideoPlaylistElement } from './video-playlist-element.model' import { VideoPlaylist } from './video-playlist.model' import { VideoPlaylistService } from './video-playlist.service' diff --git a/client/src/app/shared/shared-video-playlist/video-playlist.model.ts b/client/src/app/shared/shared-video-playlist/video-playlist.model.ts index 55013e4c5..fcc2ce705 100644 --- a/client/src/app/shared/shared-video-playlist/video-playlist.model.ts +++ b/client/src/app/shared/shared-video-playlist/video-playlist.model.ts @@ -1,5 +1,6 @@ import { getAbsoluteAPIUrl, getAbsoluteEmbedUrl } from '@app/helpers' import { Actor } from '@app/shared/shared-main' +import { buildPlaylistWatchPath } from '@shared/core-utils' import { peertubeTranslate } from '@shared/core-utils/i18n' import { AccountSummary, @@ -44,7 +45,7 @@ export class VideoPlaylist implements ServerVideoPlaylist { videoChannelBy?: string static buildWatchUrl (playlist: Pick) { - return '/w/p/' + (playlist.shortUUID || playlist.uuid) + return buildPlaylistWatchPath({ shortUUID: playlist.shortUUID || playlist.uuid }) } constructor (hash: ServerVideoPlaylist, translations: {}) { diff --git a/client/src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts b/client/src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts index f1bd9f0c4..2eb849d2b 100644 --- a/client/src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts +++ b/client/src/assets/player/p2p-media-loader/p2p-media-loader-plugin.ts @@ -2,8 +2,8 @@ import * as Hlsjs from 'hls.js/dist/hls.light.js' import { Events, Segment } from 'p2p-media-loader-core' import { Engine, initHlsJsPlayer, initVideoJsContribHlsJsPlayer } from 'p2p-media-loader-hlsjs' import videojs from 'video.js' +import { timeToInt } from '@shared/core-utils' import { P2PMediaLoaderPluginOptions, PlayerNetworkInfo } from '../peertube-videojs-typings' -import { timeToInt } from '../utils' import { registerConfigPlugin, registerSourceHandler } from './hls-plugin' registerConfigPlugin(videojs) diff --git a/client/src/assets/player/peertube-player-manager.ts b/client/src/assets/player/peertube-player-manager.ts index 6f0b804cd..766ad203e 100644 --- a/client/src/assets/player/peertube-player-manager.ts +++ b/client/src/assets/player/peertube-player-manager.ts @@ -23,6 +23,7 @@ import './videojs-components/theater-button' import './playlist/playlist-plugin' import videojs from 'video.js' import { PluginsManager } from '@root-helpers/plugins-manager' +import { buildVideoLink, decorateVideoLink } from '@shared/core-utils' import { isDefaultLocale } from '@shared/core-utils/i18n' import { VideoFile } from '@shared/models' import { copyToClipboard } from '../../root-helpers/utils' @@ -40,7 +41,7 @@ import { VideoJSPluginOptions } from './peertube-videojs-typings' import { TranslationsManager } from './translations-manager' -import { buildVideoLink, buildVideoOrPlaylistEmbed, decorateVideoLink, getRtcConfig, isIOS, isSafari } from './utils' +import { buildVideoOrPlaylistEmbed, getRtcConfig, isIOS, isSafari } from './utils' // Change 'Playback Rate' to 'Speed' (smaller for our settings menu) (videojs.getComponent('PlaybackRateMenuButton') as any).prototype.controlText_ = 'Speed' diff --git a/client/src/assets/player/peertube-plugin.ts b/client/src/assets/player/peertube-plugin.ts index 07c7e33f6..919b7c239 100644 --- a/client/src/assets/player/peertube-plugin.ts +++ b/client/src/assets/player/peertube-plugin.ts @@ -1,12 +1,6 @@ -import videojs from 'video.js' import './videojs-components/settings-menu-button' -import { - PeerTubePluginOptions, - ResolutionUpdateData, - UserWatching, - VideoJSCaption -} from './peertube-videojs-typings' -import { isMobile, timeToInt } from './utils' +import videojs from 'video.js' +import { timeToInt } from '@shared/core-utils' import { getStoredLastSubtitle, getStoredMute, @@ -16,6 +10,8 @@ import { saveVideoWatchHistory, saveVolumeInStore } from './peertube-player-local-storage' +import { PeerTubePluginOptions, ResolutionUpdateData, UserWatching, VideoJSCaption } from './peertube-videojs-typings' +import { isMobile } from './utils' const Plugin = videojs.getPlugin('plugin') diff --git a/client/src/assets/player/playlist/playlist-menu-item.ts b/client/src/assets/player/playlist/playlist-menu-item.ts index 87a72b6a3..2519a34c7 100644 --- a/client/src/assets/player/playlist/playlist-menu-item.ts +++ b/client/src/assets/player/playlist/playlist-menu-item.ts @@ -1,7 +1,7 @@ import videojs from 'video.js' +import { secondsToTime } from '@shared/core-utils' import { VideoPlaylistElement } from '@shared/models' import { PlaylistItemOptions } from '../peertube-videojs-typings' -import { secondsToTime } from '../utils' const Component = videojs.getComponent('Component') diff --git a/client/src/assets/player/stats/stats-card.ts b/client/src/assets/player/stats/stats-card.ts index a93f59506..b271d0526 100644 --- a/client/src/assets/player/stats/stats-card.ts +++ b/client/src/assets/player/stats/stats-card.ts @@ -1,6 +1,7 @@ import videojs from 'video.js' +import { secondsToTime } from '@shared/core-utils' import { PlayerNetworkInfo as EventPlayerNetworkInfo } from '../peertube-videojs-typings' -import { bytes, secondsToTime } from '../utils' +import { bytes } from '../utils' interface StatsCardOptions extends videojs.ComponentOptions { videoUUID: string diff --git a/client/src/assets/player/utils.ts b/client/src/assets/player/utils.ts index eb9302493..f0a1b1aee 100644 --- a/client/src/assets/player/utils.ts +++ b/client/src/assets/player/utils.ts @@ -1,5 +1,5 @@ -import { Video, VideoFile, VideoPlaylist } from '@shared/models' import { escapeHTML } from '@shared/core-utils/renderer' +import { VideoFile } from '@shared/models' function toTitleCase (str: string) { return str.charAt(0).toUpperCase() + str.slice(1) @@ -43,144 +43,9 @@ function isMobile () { return /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) } -function buildPlaylistLink (playlist: Pick, base?: string) { - return (base ?? window.location.origin) + '/w/p/' + playlist.shortUUID -} - -function buildVideoLink (video: Pick, base?: string) { - return (base ?? window.location.origin) + '/w/' + video.shortUUID -} - -function buildPlaylistEmbedLink (playlist: Pick, base?: string) { - return (base ?? window.location.origin) + '/video-playlists/embed/' + playlist.uuid -} - -function buildVideoEmbedLink (video: Pick, base?: string) { - return (base ?? window.location.origin) + '/videos/embed/' + video.uuid -} - -function decorateVideoLink (options: { - url: string - - startTime?: number - stopTime?: number - - subtitle?: string - - loop?: boolean - autoplay?: boolean - muted?: boolean - - // Embed options - title?: boolean - warningTitle?: boolean - controls?: boolean - peertubeLink?: boolean -}) { - const { url } = options - - const params = generateParams(window.location.search) - - if (options.startTime !== undefined && options.startTime !== null) { - const startTimeInt = Math.floor(options.startTime) - params.set('start', secondsToTime(startTimeInt)) - } - - if (options.stopTime) { - const stopTimeInt = Math.floor(options.stopTime) - params.set('stop', secondsToTime(stopTimeInt)) - } - - if (options.subtitle) params.set('subtitle', options.subtitle) - - if (options.loop === true) params.set('loop', '1') - if (options.autoplay === true) params.set('autoplay', '1') - if (options.muted === true) params.set('muted', '1') - if (options.title === false) params.set('title', '0') - if (options.warningTitle === false) params.set('warningTitle', '0') - if (options.controls === false) params.set('controls', '0') - if (options.peertubeLink === false) params.set('peertubeLink', '0') - - return buildUrl(url, params) -} - -function decoratePlaylistLink (options: { - url: string - - playlistPosition?: number -}) { - const { url } = options - - const params = generateParams(window.location.search) - - if (options.playlistPosition) params.set('playlistPosition', '' + options.playlistPosition) - - return buildUrl(url, params) -} - -function buildUrl (url: string, params: URLSearchParams) { - let hasParams = false - params.forEach(() => hasParams = true) - - if (hasParams) return url + '?' + params.toString() - - return url -} - -function generateParams (url: string) { - const params = new URLSearchParams(window.location.search) - // Unused parameters in embed - params.delete('videoId') - params.delete('resume') - - return params -} - -function timeToInt (time: number | string) { - if (!time) return 0 - if (typeof time === 'number') return time - - const reg = /^((\d+)[h:])?((\d+)[m:])?((\d+)s?)?$/ - const matches = time.match(reg) - - if (!matches) return 0 - - const hours = parseInt(matches[2] || '0', 10) - const minutes = parseInt(matches[4] || '0', 10) - const seconds = parseInt(matches[6] || '0', 10) - - return hours * 3600 + minutes * 60 + seconds -} - -function secondsToTime (seconds: number, full = false, symbol?: string) { - let time = '' - - if (seconds === 0 && !full) return '0s' - - const hourSymbol = (symbol || 'h') - const minuteSymbol = (symbol || 'm') - const secondsSymbol = full ? '' : 's' - - const hours = Math.floor(seconds / 3600) - if (hours >= 1) time = hours + hourSymbol - else if (full) time = '0' + hourSymbol - - seconds %= 3600 - const minutes = Math.floor(seconds / 60) - if (minutes >= 1 && minutes < 10 && full) time += '0' + minutes + minuteSymbol - else if (minutes >= 1) time += minutes + minuteSymbol - else if (full) time += '00' + minuteSymbol - - seconds %= 60 - if (seconds >= 1 && seconds < 10 && full) time += '0' + seconds + secondsSymbol - else if (seconds >= 1) time += seconds + secondsSymbol - else if (full) time += '00' - - return time -} - function buildVideoOrPlaylistEmbed (embedUrl: string, embedTitle: string) { const title = escapeHTML(embedTitle) + return '