Fix issues with external links in search page

pull/2986/head
Chocobozzz 2020-07-20 11:37:06 +02:00
parent 69a019968e
commit 0bdad52fbb
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
9 changed files with 83 additions and 54 deletions

View File

@ -12,20 +12,12 @@ export class ChannelLazyLoadResolver implements Resolve<any> {
resolve (route: ActivatedRouteSnapshot) { resolve (route: ActivatedRouteSnapshot) {
const url = route.params.url const url = route.params.url
const externalRedirect = route.params.externalRedirect
const fromPath = route.params.fromPath
if (!url) { if (!url) {
console.error('Could not find url param.', { params: route.params }) console.error('Could not find url param.', { params: route.params })
return this.router.navigateByUrl('/404') return this.router.navigateByUrl('/404')
} }
if (externalRedirect === 'true') {
window.open(url)
this.router.navigateByUrl(fromPath)
return
}
return this.searchService.searchVideoChannels({ search: url }) return this.searchService.searchVideoChannels({ search: url })
.pipe( .pipe(
map(result => { map(result => {

View File

@ -35,15 +35,27 @@
<ng-container *ngFor="let result of results"> <ng-container *ngFor="let result of results">
<div *ngIf="isVideoChannel(result)" class="entry video-channel"> <div *ngIf="isVideoChannel(result)" class="entry video-channel">
<a [routerLink]="getChannelUrl(result)"> <a *ngIf="!isExternalChannelUrl()" [routerLink]="getChannelUrl(result)">
<img [src]="result.avatarUrl" alt="Avatar" />
</a>
<a *ngIf="isExternalChannelUrl()" [href]="getChannelUrl(result)" target="_blank">
<img [src]="result.avatarUrl" alt="Avatar" /> <img [src]="result.avatarUrl" alt="Avatar" />
</a> </a>
<div class="video-channel-info"> <div class="video-channel-info">
<a [routerLink]="getChannelUrl(result)" class="video-channel-names"> <a *ngIf="!isExternalChannelUrl()" [routerLink]="getChannelUrl(result)" class="video-channel-names">
<ng-container *ngTemplateOutlet="aContent"></ng-container>
</a>
<a *ngIf="isExternalChannelUrl()" [href]="getChannelUrl(result)" target="_blank" class="video-channel-names">
<ng-container *ngTemplateOutlet="aContent"></ng-container>
</a>
<ng-template #aContent>
<div class="video-channel-display-name">{{ result.displayName }}</div> <div class="video-channel-display-name">{{ result.displayName }}</div>
<div class="video-channel-name">{{ result.nameWithHost }}</div> <div class="video-channel-name">{{ result.nameWithHost }}</div>
</a> </ng-template>
<div i18n class="video-channel-followers">{{ result.followersCount }} subscribers</div> <div i18n class="video-channel-followers">{{ result.followersCount }} subscribers</div>
</div> </div>
@ -54,7 +66,7 @@
<div *ngIf="isVideo(result)" class="entry video"> <div *ngIf="isVideo(result)" class="entry video">
<my-video-miniature <my-video-miniature
[video]="result" [user]="userMiniature" [displayAsRow]="true" [displayVideoActions]="!hideActions()" [video]="result" [user]="userMiniature" [displayAsRow]="true" [displayVideoActions]="!hideActions()"
[displayOptions]="videoDisplayOptions" [useLazyLoadUrl]="advancedSearch.searchTarget === 'search-index'" [displayOptions]="videoDisplayOptions" [videoLinkType]="getVideoLinkType()"
(videoBlocked)="removeVideoFromArray(result)" (videoRemoved)="removeVideoFromArray(result)" (videoBlocked)="removeVideoFromArray(result)" (videoRemoved)="removeVideoFromArray(result)"
></my-video-miniature> ></my-video-miniature>
</div> </div>

View File

@ -5,7 +5,7 @@ import { AuthService, ComponentPagination, HooksService, Notifier, ServerService
import { immutableAssign } from '@app/helpers' import { immutableAssign } from '@app/helpers'
import { Video, VideoChannel } from '@app/shared/shared-main' import { Video, VideoChannel } from '@app/shared/shared-main'
import { AdvancedSearch, SearchService } from '@app/shared/shared-search' import { AdvancedSearch, SearchService } from '@app/shared/shared-search'
import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature' import { MiniatureDisplayOptions, VideoLinkType } from '@app/shared/shared-video-miniature'
import { MetaService } from '@ngx-meta/core' import { MetaService } from '@ngx-meta/core'
import { I18n } from '@ngx-translate/i18n-polyfill' import { I18n } from '@ngx-translate/i18n-polyfill'
import { SearchTargetType, ServerConfig } from '@shared/models' import { SearchTargetType, ServerConfig } from '@shared/models'
@ -119,6 +119,25 @@ export class SearchComponent implements OnInit, OnDestroy {
return this.authService.isLoggedIn() return this.authService.isLoggedIn()
} }
getVideoLinkType (): VideoLinkType {
if (this.advancedSearch.searchTarget === 'search-index') {
const remoteUriConfig = this.serverConfig.search.remoteUri
// Redirect on the external instance if not allowed to fetch remote data
if ((!this.isUserLoggedIn() && !remoteUriConfig.anonymous) || !remoteUriConfig.users) {
return 'external'
}
return 'lazy-load'
}
return 'internal'
}
isExternalChannelUrl () {
return this.getVideoLinkType() === 'external'
}
search () { search () {
forkJoin([ forkJoin([
this.getVideosObs(), this.getVideosObs(),
@ -184,19 +203,18 @@ export class SearchComponent implements OnInit, OnDestroy {
} }
getChannelUrl (channel: VideoChannel) { getChannelUrl (channel: VideoChannel) {
if (this.advancedSearch.searchTarget === 'search-index' && channel.url) { // Same algorithm than videos
const remoteUriConfig = this.serverConfig.search.remoteUri if (this.getVideoLinkType() === 'external') {
return channel.url
// Redirect on the external instance if not allowed to fetch remote data
const externalRedirect = (!this.authService.isLoggedIn() && !remoteUriConfig.anonymous) || !remoteUriConfig.users
const fromPath = window.location.pathname + window.location.search
return [ '/search/lazy-load-channel', { url: channel.url, externalRedirect, fromPath } ]
} }
if (this.getVideoLinkType() === 'internal') {
return [ '/video-channels', channel.nameWithHost ] return [ '/video-channels', channel.nameWithHost ]
} }
return [ '/search/lazy-load-channel', { url: channel.url } ]
}
hideActions () { hideActions () {
return this.lastSearchTarget === 'search-index' return this.lastSearchTarget === 'search-index'
} }

View File

@ -12,20 +12,12 @@ export class VideoLazyLoadResolver implements Resolve<any> {
resolve (route: ActivatedRouteSnapshot) { resolve (route: ActivatedRouteSnapshot) {
const url = route.params.url const url = route.params.url
const externalRedirect = route.params.externalRedirect
const fromPath = route.params.fromPath
if (!url) { if (!url) {
console.error('Could not find url param.', { params: route.params }) console.error('Could not find url param.', { params: route.params })
return this.router.navigateByUrl('/404') return this.router.navigateByUrl('/404')
} }
if (externalRedirect === 'true') {
window.open(url)
this.router.navigateByUrl(fromPath)
return
}
return this.searchService.searchVideos({ search: url }) return this.searchService.searchVideos({ search: url })
.pipe( .pipe(
map(result => { map(result => {

View File

@ -1,7 +1,12 @@
<a <a *ngIf="!videoHref" [routerLink]="getVideoRouterLink()" [queryParams]="queryParams" class="video-thumbnail">
[routerLink]="getVideoRouterLink()" [queryParams]="queryParams" <ng-container *ngTemplateOutlet="aContent"></ng-container>
class="video-thumbnail" </a>
>
<a *ngIf="videoHref" [href]="videoHref" [target]="videoTarget" class="video-thumbnail">
<ng-container *ngTemplateOutlet="aContent"></ng-container>
</a>
<ng-template #aContent>
<img alt="" [attr.aria-label]="video.name" [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" /> <img alt="" [attr.aria-label]="video.name" [attr.src]="getImageUrl()" [ngClass]="{ 'blur-filter': nsfw }" />
<div *ngIf="displayWatchLaterPlaylist" class="video-thumbnail-actions-overlay"> <div *ngIf="displayWatchLaterPlaylist" class="video-thumbnail-actions-overlay">
@ -30,4 +35,4 @@
<div class="progress-bar" *ngIf="video.userHistory?.currentTime"> <div class="progress-bar" *ngIf="video.userHistory?.currentTime">
<div [ngStyle]="{ 'width.%': getProgressPercent() }"></div> <div [ngStyle]="{ 'width.%': getProgressPercent() }"></div>
</div> </div>
</a> </ng-template>

View File

@ -11,8 +11,11 @@ import { Video } from '../shared-main'
export class VideoThumbnailComponent { export class VideoThumbnailComponent {
@Input() video: Video @Input() video: Video
@Input() nsfw = false @Input() nsfw = false
@Input() routerLink: any[]
@Input() videoRouterLink: any[]
@Input() queryParams: { [ p: string ]: any } @Input() queryParams: { [ p: string ]: any }
@Input() videoHref: string
@Input() videoTarget: string
@Input() displayWatchLaterPlaylist: boolean @Input() displayWatchLaterPlaylist: boolean
@Input() inWatchLaterPlaylist: boolean @Input() inWatchLaterPlaylist: boolean
@ -49,7 +52,7 @@ export class VideoThumbnailComponent {
} }
getVideoRouterLink () { getVideoRouterLink () {
if (this.routerLink) return this.routerLink if (this.videoRouterLink) return this.videoRouterLink
return [ '/videos/watch', this.video.uuid ] return [ '/videos/watch', this.video.uuid ]
} }

View File

@ -1,6 +1,6 @@
<div class="video-miniature" [ngClass]="{ 'display-as-row': displayAsRow, 'fit-width': fitWidth }" (mouseenter)="loadActions()"> <div class="video-miniature" [ngClass]="{ 'display-as-row': displayAsRow, 'fit-width': fitWidth }" (mouseenter)="loadActions()">
<my-video-thumbnail <my-video-thumbnail
[video]="video" [nsfw]="isVideoBlur" [routerLink]="videoLink" [video]="video" [nsfw]="isVideoBlur" [videoRouterLink]="videoRouterLink" [videoHref]="videoHref" [videoTarget]="videoTarget"
[displayWatchLaterPlaylist]="isWatchLaterPlaylistDisplayed()" [inWatchLaterPlaylist]="inWatchLaterPlaylist" (watchLaterClick)="onWatchLaterClick($event)" [displayWatchLaterPlaylist]="isWatchLaterPlaylistDisplayed()" [inWatchLaterPlaylist]="inWatchLaterPlaylist" (watchLaterClick)="onWatchLaterClick($event)"
> >
<ng-container ngProjectAs="label-warning" *ngIf="displayOptions.privacyLabel && isUnlistedVideo()" i18n>Unlisted</ng-container> <ng-container ngProjectAs="label-warning" *ngIf="displayOptions.privacyLabel && isUnlistedVideo()" i18n>Unlisted</ng-container>
@ -15,10 +15,12 @@
</a> </a>
<div class="w-100 d-flex flex-column"> <div class="w-100 d-flex flex-column">
<a <a *ngIf="!videoHref" tabindex="-1" class="video-miniature-name"
tabindex="-1" [routerLink]="videoRouterLink" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }"
class="video-miniature-name" >{{ video.name }}</a>
[routerLink]="videoLink" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }"
<a *ngIf="videoHref" tabindex="-1" class="video-miniature-name"
[href]="videoHref" [target]="videoTarget" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }"
>{{ video.name }}</a> >{{ video.name }}</a>
<span class="video-miniature-created-at-views"> <span class="video-miniature-created-at-views">

View File

@ -29,6 +29,7 @@ export type MiniatureDisplayOptions = {
blacklistInfo?: boolean blacklistInfo?: boolean
nsfw?: boolean nsfw?: boolean
} }
export type VideoLinkType = 'internal' | 'lazy-load' | 'external'
@Component({ @Component({
selector: 'my-video-miniature', selector: 'my-video-miniature',
@ -55,7 +56,7 @@ export class VideoMiniatureComponent implements OnInit {
@Input() displayVideoActions = true @Input() displayVideoActions = true
@Input() fitWidth = false @Input() fitWidth = false
@Input() useLazyLoadUrl = false @Input() videoLinkType: VideoLinkType = 'internal'
@Output() videoBlocked = new EventEmitter() @Output() videoBlocked = new EventEmitter()
@Output() videoUnblocked = new EventEmitter() @Output() videoUnblocked = new EventEmitter()
@ -85,7 +86,9 @@ export class VideoMiniatureComponent implements OnInit {
playlistElementId?: number playlistElementId?: number
} }
videoLink: any[] = [] videoRouterLink: any[] = []
videoHref: string
videoTarget: string
private ownerDisplayTypeChosen: 'account' | 'videoChannel' private ownerDisplayTypeChosen: 'account' | 'videoChannel'
@ -125,18 +128,20 @@ export class VideoMiniatureComponent implements OnInit {
} }
buildVideoLink () { buildVideoLink () {
if (this.useLazyLoadUrl && this.video.url) { if (this.videoLinkType === 'internal' || !this.video.url) {
const remoteUriConfig = this.serverConfig.search.remoteUri this.videoRouterLink = [ '/videos/watch', this.video.uuid ]
// Redirect on the external instance if not allowed to fetch remote data
const externalRedirect = (!this.authService.isLoggedIn() && !remoteUriConfig.anonymous) || !remoteUriConfig.users
const fromPath = window.location.pathname + window.location.search
this.videoLink = [ '/search/lazy-load-video', { url: this.video.url, externalRedirect, fromPath } ]
return return
} }
this.videoLink = [ '/videos/watch', this.video.uuid ] if (this.videoLinkType === 'external') {
this.videoRouterLink = null
this.videoHref = this.video.url
this.videoTarget = '_blank'
return
}
// Lazy load
this.videoRouterLink = [ '/search/lazy-load-video', { url: this.video.url } ]
} }
displayOwnerAccount () { displayOwnerAccount () {

View File

@ -8,7 +8,7 @@
<my-video-thumbnail <my-video-thumbnail
*ngIf="playlistElement.video" *ngIf="playlistElement.video"
[video]="playlistElement.video" [nsfw]="isVideoBlur(playlistElement.video)" [video]="playlistElement.video" [nsfw]="isVideoBlur(playlistElement.video)"
[routerLink]="buildRouterLink()" [queryParams]="buildRouterQuery()" [videoRouterLink]="buildRouterLink()" [queryParams]="buildRouterQuery()"
></my-video-thumbnail> ></my-video-thumbnail>
<div class="fake-thumbnail" *ngIf="!playlistElement.video"></div> <div class="fake-thumbnail" *ngIf="!playlistElement.video"></div>