diff --git a/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.html b/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.html index 4c68cd1a5..3752de49f 100644 --- a/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.html +++ b/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.html @@ -1,4 +1,4 @@ -
+
Avatar diff --git a/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts b/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts index 9434b196f..9517a3705 100644 --- a/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts +++ b/client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts @@ -3,6 +3,7 @@ import { NotificationsService } from 'angular2-notifications' import { VideoChannel } from '@app/shared/video-channel/video-channel.model' import { I18n } from '@ngx-translate/i18n-polyfill' import { UserSubscriptionService } from '@app/shared/user-subscription' +import { ComponentPagination } from '@app/shared/rest/component-pagination.model' @Component({ selector: 'my-account-subscriptions', @@ -12,6 +13,12 @@ import { UserSubscriptionService } from '@app/shared/user-subscription' export class MyAccountSubscriptionsComponent implements OnInit { videoChannels: VideoChannel[] = [] + pagination: ComponentPagination = { + currentPage: 1, + itemsPerPage: 10, + totalItems: null + } + constructor ( private userSubscriptionService: UserSubscriptionService, private notificationsService: NotificationsService, @@ -19,12 +26,27 @@ export class MyAccountSubscriptionsComponent implements OnInit { ) {} ngOnInit () { - this.userSubscriptionService.listSubscriptions() - .subscribe( - res => this.videoChannels = res.data, + this.loadSubscriptions() + } - error => this.notificationsService.error(this.i18n('Error'), error.message) - ) + loadSubscriptions () { + this.userSubscriptionService.listSubscriptions(this.pagination) + .subscribe( + res => { + this.videoChannels = this.videoChannels.concat(res.data) + this.pagination.totalItems = res.total + }, + + error => this.notificationsService.error(this.i18n('Error'), error.message) + ) + } + + onNearOfBottom () { + // Last page + if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return + + this.pagination.currentPage += 1 + this.loadSubscriptions() } } diff --git a/client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.html b/client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.html index b2b6c3d60..329948cb5 100644 --- a/client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.html +++ b/client/src/app/+my-account/my-account-video-imports/my-account-video-imports.component.html @@ -29,10 +29,10 @@ - {{ videoImport.video.name }} + {{ videoImport.video?.name }} - - {{ videoImport.video.name }} + + {{ videoImport.video?.name }} @@ -40,7 +40,7 @@ {{ videoImport.createdAt }} - + diff --git a/client/src/app/search/search.component.html b/client/src/app/search/search.component.html index 128cc52f5..83d014987 100644 --- a/client/src/app/search/search.component.html +++ b/client/src/app/search/search.component.html @@ -1,4 +1,4 @@ -
+
diff --git a/client/src/app/search/search.component.ts b/client/src/app/search/search.component.ts index f88df6391..ed84e24d9 100644 --- a/client/src/app/search/search.component.ts +++ b/client/src/app/search/search.component.ts @@ -87,9 +87,17 @@ export class SearchComponent implements OnInit, OnDestroy { .subscribe( ([ videosResult, videoChannelsResult ]) => { this.videos = this.videos.concat(videosResult.videos) - this.pagination.totalItems = videosResult.totalVideos + this.pagination.totalItems = videosResult.totalVideos + videoChannelsResult.total - this.videoChannels = videoChannelsResult.data + this.videoChannels = this.videoChannels.concat(videoChannelsResult.data) + + // Focus on channels + if (this.channelsPerPage !== 10 && this.videos.length < this.pagination.itemsPerPage) { + this.resetPagination() + + this.channelsPerPage = 10 + this.search() + } }, error => { @@ -116,8 +124,10 @@ export class SearchComponent implements OnInit, OnDestroy { private resetPagination () { this.pagination.currentPage = 1 this.pagination.totalItems = null + this.channelsPerPage = 2 this.videos = [] + this.videoChannels = [] } private updateTitle () { diff --git a/client/src/app/shared/user-subscription/user-subscription.service.ts b/client/src/app/shared/user-subscription/user-subscription.service.ts index cf622019f..3d05f071e 100644 --- a/client/src/app/shared/user-subscription/user-subscription.service.ts +++ b/client/src/app/shared/user-subscription/user-subscription.service.ts @@ -1,4 +1,4 @@ -import { bufferTime, catchError, filter, map, share, switchMap, tap } from 'rxjs/operators' +import { bufferTime, catchError, filter, first, map, share, switchMap } from 'rxjs/operators' import { HttpClient, HttpParams } from '@angular/common/http' import { Injectable } from '@angular/core' import { ResultList } from '../../../../../shared' @@ -8,6 +8,7 @@ import { Observable, ReplaySubject, Subject } from 'rxjs' import { VideoChannel } from '@app/shared/video-channel/video-channel.model' import { VideoChannelService } from '@app/shared/video-channel/video-channel.service' import { VideoChannel as VideoChannelServer } from '../../../../../shared/models/videos' +import { ComponentPagination } from '@app/shared/rest/component-pagination.model' type SubscriptionExistResult = { [ uri: string ]: boolean } @@ -17,7 +18,7 @@ export class UserSubscriptionService { // Use a replay subject because we "next" a value before subscribing private existsSubject: Subject = new ReplaySubject(1) - private existsObservable: Observable + private readonly existsObservable: Observable constructor ( private authHttp: HttpClient, @@ -25,7 +26,6 @@ export class UserSubscriptionService { private restService: RestService ) { this.existsObservable = this.existsSubject.pipe( - tap(u => console.log(u)), bufferTime(500), filter(uris => uris.length !== 0), switchMap(uris => this.areSubscriptionExist(uris)), @@ -54,10 +54,15 @@ export class UserSubscriptionService { ) } - listSubscriptions (): Observable> { + listSubscriptions (componentPagination: ComponentPagination): Observable> { const url = UserSubscriptionService.BASE_USER_SUBSCRIPTIONS_URL - return this.authHttp.get>(url) + const pagination = this.restService.componentPaginationToRestPagination(componentPagination) + + let params = new HttpParams() + params = this.restService.addRestGetParams(params, pagination) + + return this.authHttp.get>(url, { params }) .pipe( map(res => VideoChannelService.extractVideoChannels(res)), catchError(err => this.restExtractor.handleError(err)) @@ -67,11 +72,10 @@ export class UserSubscriptionService { isSubscriptionExists (nameWithHost: string) { this.existsSubject.next(nameWithHost) - return this.existsObservable + return this.existsObservable.pipe(first()) } private areSubscriptionExist (uris: string[]): Observable { - console.log(uris) const url = UserSubscriptionService.BASE_USER_SUBSCRIPTIONS_URL + '/exist' let params = new HttpParams() diff --git a/client/src/app/shared/video/infinite-scroller.directive.ts b/client/src/app/shared/video/infinite-scroller.directive.ts index 0448e2c23..4dc1f86e7 100644 --- a/client/src/app/shared/video/infinite-scroller.directive.ts +++ b/client/src/app/shared/video/infinite-scroller.directive.ts @@ -11,7 +11,7 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { @Input() containerHeight: number @Input() pageHeight: number @Input() percentLimit = 70 - @Input() autoLoading = false + @Input() autoInit = false @Output() nearOfBottom = new EventEmitter() @Output() nearOfTop = new EventEmitter() @@ -29,7 +29,7 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { } ngOnInit () { - if (this.autoLoading === true) return this.initialize() + if (this.autoInit === true) return this.initialize() } ngOnDestroy () { diff --git a/client/src/app/videos/+video-watch/comment/video-comments.component.html b/client/src/app/videos/+video-watch/comment/video-comments.component.html index 8871980e9..bf6706ed3 100644 --- a/client/src/app/videos/+video-watch/comment/video-comments.component.html +++ b/client/src/app/videos/+video-watch/comment/video-comments.component.html @@ -21,7 +21,7 @@
diff --git a/server/models/activitypub/actor-follow.ts b/server/models/activitypub/actor-follow.ts index 81fcf7001..ebb2d47c2 100644 --- a/server/models/activitypub/actor-follow.ts +++ b/server/models/activitypub/actor-follow.ts @@ -169,9 +169,6 @@ export class ActorFollowModel extends Model { static loadByActorAndTargetNameAndHostForAPI (actorId: number, targetName: string, targetHost: string, t?: Sequelize.Transaction) { const actorFollowingPartInclude: IIncludeOptions = { - attributes: { - exclude: unusedActorAttributesForAPI - }, model: ActorModel, required: true, as: 'ActorFollowing', @@ -203,7 +200,12 @@ export class ActorFollowModel extends Model { actorId }, include: [ - actorFollowingPartInclude + actorFollowingPartInclude, + { + model: ActorModel, + required: true, + as: 'ActorFollower' + } ], transaction: t } diff --git a/server/models/activitypub/actor.ts b/server/models/activitypub/actor.ts index ec0b4b2d9..e16bd5d79 100644 --- a/server/models/activitypub/actor.ts +++ b/server/models/activitypub/actor.ts @@ -49,7 +49,8 @@ export const unusedActorAttributesForAPI = [ 'outboxUrl', 'sharedInboxUrl', 'followersUrl', - 'followingUrl' + 'followingUrl', + 'url' ] @DefaultScope({ @@ -322,45 +323,6 @@ export class ActorModel extends Model { }) } - static async getActorsFollowerSharedInboxUrls (actors: ActorModel[], t: Sequelize.Transaction) { - const query = { - // attribute: [], - where: { - id: { - [Sequelize.Op.in]: actors.map(a => a.id) - } - }, - include: [ - { - // attributes: [ ], - model: ActorFollowModel.unscoped(), - required: true, - as: 'ActorFollowers', - where: { - state: 'accepted' - }, - include: [ - { - attributes: [ 'sharedInboxUrl' ], - model: ActorModel.unscoped(), - as: 'ActorFollower', - required: true - } - ] - } - ], - transaction: t - } - - const hash: { [ id: number ]: string[] } = {} - const res = await ActorModel.findAll(query) - for (const actor of res) { - hash[actor.id] = actor.ActorFollowers.map(follow => follow.ActorFollower.sharedInboxUrl) - } - - return hash - } - toFormattedJSON () { let avatar: Avatar = null if (this.Avatar) {