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 984b0039c..e9f9bbdac 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 @@ -2,7 +2,7 @@ import { NgFor, NgIf } from '@angular/common' import { Component, OnInit } from '@angular/core' 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 { ComponentPagination, ConfirmService, hasMoreItems, Notifier, resetCurrentPage, updatePaginationOnDelete } from '@app/core' import { PluginService } from '@app/core/plugins/plugin.service' import { compareSemVer } from '@peertube/peertube-core-utils' import { PeerTubePlugin, PluginType, PluginType_Type } from '@peertube/peertube-models' @@ -69,8 +69,8 @@ export class PluginListInstalledComponent implements OnInit { } reloadPlugins () { - this.pagination.currentPage = 1 this.plugins = [] + resetCurrentPage(this.pagination) this.loadMorePlugins() } @@ -143,7 +143,7 @@ export class PluginListInstalledComponent implements OnInit { this.notifier.success($localize`${plugin.name} uninstalled.`) this.plugins = this.plugins.filter(p => p.name !== plugin.name) - this.pagination.totalItems-- + updatePaginationOnDelete(this.pagination) this.uninstalling[pluginKey] = false }, diff --git a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts index 753657062..a95c00e57 100644 --- a/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts +++ b/client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts @@ -2,7 +2,7 @@ import { NgFor, NgIf } from '@angular/common' import { Component, OnInit } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { PluginApiService } from '@app/+admin/plugins/shared/plugin-api.service' -import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService } from '@app/core' +import { ComponentPagination, ConfirmService, hasMoreItems, Notifier, PluginService, resetCurrentPage } from '@app/core' import { AlertComponent } from '@app/shared/shared-main/common/alert.component' import { PeerTubePluginIndex, PluginType, PluginType_Type } from '@peertube/peertube-models' import { logger } from '@root-helpers/logger' @@ -94,7 +94,7 @@ export class PluginSearchComponent implements OnInit { } reloadPlugins () { - this.pagination.currentPage = 1 + resetCurrentPage(this.pagination) this.plugins = [] this.loadMorePlugins() diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts index c3a9b635a..ba8eadb99 100644 --- a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts +++ b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.ts @@ -1,7 +1,16 @@ import { NgFor, NgIf } from '@angular/common' import { Component } from '@angular/core' import { RouterLink } from '@angular/router' -import { AuthService, ComponentPagination, ConfirmService, Notifier, ScreenService, hasMoreItems } from '@app/core' +import { + AuthService, + ComponentPagination, + ConfirmService, + Notifier, + ScreenService, + hasMoreItems, + resetCurrentPage, + updatePaginationOnDelete +} from '@app/core' import { formatICU } from '@app/helpers' import { VideoChannel } from '@app/shared/shared-main/channel/video-channel.model' import { VideoChannelService } from '@app/shared/shared-main/channel/video-channel.service' @@ -12,12 +21,12 @@ import { Subject, first, map, switchMap } from 'rxjs' import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component' import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component' import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' -import { DeferLoadingDirective } from '../../shared/shared-main/common/defer-loading.directive' -import { InfiniteScrollerDirective } from '../../shared/shared-main/common/infinite-scroller.directive' -import { NumberFormatterPipe } from '../../shared/shared-main/common/number-formatter.pipe' import { DeleteButtonComponent } from '../../shared/shared-main/buttons/delete-button.component' import { EditButtonComponent } from '../../shared/shared-main/buttons/edit-button.component' import { ChannelsSetupMessageComponent } from '../../shared/shared-main/channel/channels-setup-message.component' +import { DeferLoadingDirective } from '../../shared/shared-main/common/defer-loading.directive' +import { InfiniteScrollerDirective } from '../../shared/shared-main/common/infinite-scroller.directive' +import { NumberFormatterPipe } from '../../shared/shared-main/common/number-formatter.pipe' type CustomChartData = (ChartData & { startDate: string, total: number }) @@ -75,7 +84,7 @@ export class MyVideoChannelsComponent { onSearch (search: string) { this.search = search - this.pagination.currentPage = 1 + resetCurrentPage(this.pagination) this.videoChannels = [] this.pagesDone.clear() @@ -105,6 +114,8 @@ export class MyVideoChannelsComponent { next: () => { this.videoChannels = this.videoChannels.filter(c => c.id !== videoChannel.id) this.notifier.success($localize`Video channel ${videoChannel.displayName} deleted.`) + + updatePaginationOnDelete(this.pagination) }, error: err => this.notifier.error(err.message) diff --git a/client/src/app/+my-library/my-follows/my-followers.component.ts b/client/src/app/+my-library/my-follows/my-followers.component.ts index 30ffce1c0..a89cd9c46 100644 --- a/client/src/app/+my-library/my-follows/my-followers.component.ts +++ b/client/src/app/+my-library/my-follows/my-followers.component.ts @@ -1,7 +1,8 @@ import { NgFor, NgIf } from '@angular/common' import { Component, OnInit } from '@angular/core' import { ActivatedRoute } from '@angular/router' -import { AuthService, ComponentPagination, Notifier } from '@app/core' +import { AuthService, ComponentPagination, Notifier, resetCurrentPage } from '@app/core' +import { formatICU } from '@app/helpers' import { UserSubscriptionService } from '@app/shared/shared-user-subscription/user-subscription.service' import { ActorFollow } from '@peertube/peertube-models' import { Subject } from 'rxjs' @@ -9,7 +10,6 @@ import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avat import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component' import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' import { InfiniteScrollerDirective } from '../../shared/shared-main/common/infinite-scroller.directive' -import { formatICU } from '@app/helpers' @Component({ templateUrl: './my-followers.component.html', @@ -68,7 +68,7 @@ export class MyFollowersComponent implements OnInit { onSearch (search: string) { this.search = search - this.pagination.currentPage = 1 + resetCurrentPage(this.pagination) this.loadFollowers(false) } diff --git a/client/src/app/+my-library/my-follows/my-subscriptions.component.ts b/client/src/app/+my-library/my-follows/my-subscriptions.component.ts index 1b3170518..9706be6da 100644 --- a/client/src/app/+my-library/my-follows/my-subscriptions.component.ts +++ b/client/src/app/+my-library/my-follows/my-subscriptions.component.ts @@ -1,16 +1,16 @@ -import { Subject } from 'rxjs' +import { NgFor, NgIf } from '@angular/common' import { Component } from '@angular/core' -import { ComponentPagination, Notifier } from '@app/core' -import { SubscribeButtonComponent } from '../../shared/shared-user-subscription/subscribe-button.component' import { RouterLink } from '@angular/router' -import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component' -import { InfiniteScrollerDirective } from '../../shared/shared-main/common/infinite-scroller.directive' -import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component' -import { NgIf, NgFor } from '@angular/common' -import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' +import { ComponentPagination, Notifier, resetCurrentPage } from '@app/core' +import { formatICU } from '@app/helpers' import { VideoChannel } from '@app/shared/shared-main/channel/video-channel.model' import { UserSubscriptionService } from '@app/shared/shared-user-subscription/user-subscription.service' -import { formatICU } from '@app/helpers' +import { Subject } from 'rxjs' +import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component' +import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component' +import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' +import { InfiniteScrollerDirective } from '../../shared/shared-main/common/infinite-scroller.directive' +import { SubscribeButtonComponent } from '../../shared/shared-user-subscription/subscribe-button.component' @Component({ templateUrl: './my-subscriptions.component.html', @@ -55,7 +55,7 @@ export class MySubscriptionsComponent { onSearch (search: string) { this.search = search - this.pagination.currentPage = 1 + resetCurrentPage(this.pagination) this.loadSubscriptions(false) } diff --git a/client/src/app/+my-library/my-history/my-history.component.ts b/client/src/app/+my-library/my-history/my-history.component.ts index b46510de6..e8fee5bf1 100644 --- a/client/src/app/+my-library/my-history/my-history.component.ts +++ b/client/src/app/+my-library/my-history/my-history.component.ts @@ -1,7 +1,15 @@ -import { NgIf } from '@angular/common' import { Component, OnInit, ViewChild } from '@angular/core' import { FormsModule } from '@angular/forms' -import { AuthService, ComponentPagination, ConfirmService, DisableForReuseHook, Notifier, User, UserService } from '@app/core' +import { + AuthService, + ComponentPagination, + ConfirmService, + DisableForReuseHook, + Notifier, + updatePaginationOnDelete, + User, + UserService +} from '@app/core' import { immutableAssign } from '@app/helpers' import { ButtonComponent } from '@app/shared/shared-main/buttons/button.component' import { UserHistoryService } from '@app/shared/shared-main/users/user-history.service' @@ -11,7 +19,6 @@ import { VideosSelectionComponent } from '@app/shared/shared-video-miniature/vid import { tap } from 'rxjs/operators' import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component' import { InputSwitchComponent } from '../../shared/shared-forms/input-switch.component' -import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' import { DeleteButtonComponent } from '../../shared/shared-main/buttons/delete-button.component' import { PeerTubeTemplateDirective } from '../../shared/shared-main/common/peertube-template.directive' @@ -21,8 +28,6 @@ import { PeerTubeTemplateDirective } from '../../shared/shared-main/common/peert standalone: true, imports: [ ButtonComponent, - GlobalIconComponent, - NgIf, AdvancedInputFilterComponent, InputSwitchComponent, FormsModule, @@ -132,6 +137,7 @@ export class MyHistoryComponent implements OnInit, DisableForReuseHook { .subscribe({ next: () => { this.videos = this.videos.filter(v => v.id !== video.id) + updatePaginationOnDelete(this.pagination) }, error: err => this.notifier.error(err.message) diff --git a/client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts b/client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts index e67e4ad70..45374c669 100644 --- a/client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts +++ b/client/src/app/+my-library/my-video-playlists/my-video-playlist-elements.component.ts @@ -2,7 +2,7 @@ import { CdkDrag, CdkDragDrop, CdkDropList } from '@angular/cdk/drag-drop' import { NgFor, NgIf } from '@angular/common' import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' -import { ComponentPagination, ConfirmService, HooksService, Notifier, ScreenService } from '@app/core' +import { ComponentPagination, ConfirmService, HooksService, Notifier, ScreenService, updatePaginationOnDelete } from '@app/core' import { ButtonComponent } from '@app/shared/shared-main/buttons/button.component' import { VideoShareComponent } from '@app/shared/shared-share-modal/video-share.component' import { VideoPlaylistElement } from '@app/shared/shared-video-playlist/video-playlist-element.model' @@ -121,6 +121,7 @@ export class MyVideoPlaylistElementsComponent implements OnInit, OnDestroy { const oldFirst = this.findFirst() this.playlistElements = this.playlistElements.filter(v => v.id !== element.id) + updatePaginationOnDelete(this.pagination) this.reorderClientPositions(oldFirst) } @@ -184,13 +185,12 @@ export class MyVideoPlaylistElementsComponent implements OnInit, OnDestroy { 'my-library', 'filter:api.my-library.video-playlist-elements.list.params', 'filter:api.my-library.video-playlist-elements.list.result' - ) - .subscribe(({ total, data }) => { - this.playlistElements = this.playlistElements.concat(data) - this.pagination.totalItems = total + ).subscribe(({ total, data }) => { + this.playlistElements = this.playlistElements.concat(data) + this.pagination.totalItems = total - this.onDataSubject.next(data) - }) + this.onDataSubject.next(data) + }) } private loadPlaylistInfo () { diff --git a/client/src/app/+my-library/my-video-playlists/my-video-playlists.component.ts b/client/src/app/+my-library/my-video-playlists/my-video-playlists.component.ts index 174734f57..cfd8edbce 100644 --- a/client/src/app/+my-library/my-video-playlists/my-video-playlists.component.ts +++ b/client/src/app/+my-library/my-video-playlists/my-video-playlists.component.ts @@ -1,7 +1,7 @@ import { NgFor, NgIf } from '@angular/common' import { Component } from '@angular/core' import { RouterLink } from '@angular/router' -import { AuthService, ComponentPagination, ConfirmService, Notifier } from '@app/core' +import { AuthService, ComponentPagination, ConfirmService, Notifier, resetCurrentPage, updatePaginationOnDelete } from '@app/core' import { formatICU } from '@app/helpers' import { VideoPlaylist } from '@app/shared/shared-video-playlist/video-playlist.model' import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service' @@ -61,8 +61,8 @@ export class MyVideoPlaylistsComponent { this.videoPlaylistService.removeVideoPlaylist(videoPlaylist) .subscribe({ next: () => { - this.videoPlaylists = this.videoPlaylists - .filter(p => p.id !== videoPlaylist.id) + this.videoPlaylists = this.videoPlaylists.filter(p => p.id !== videoPlaylist.id) + updatePaginationOnDelete(this.pagination) this.notifier.success($localize`Playlist ${videoPlaylist.displayName} deleted.`) }, @@ -85,7 +85,7 @@ export class MyVideoPlaylistsComponent { onSearch (search: string) { this.search = search - this.pagination.currentPage = 1 + resetCurrentPage(this.pagination) this.loadVideoPlaylists(true) } diff --git a/client/src/app/+my-library/my-videos/my-videos.component.ts b/client/src/app/+my-library/my-videos/my-videos.component.ts index 6337d4d67..011e1733a 100644 --- a/client/src/app/+my-library/my-videos/my-videos.component.ts +++ b/client/src/app/+my-library/my-videos/my-videos.component.ts @@ -2,7 +2,16 @@ import { NgIf } from '@angular/common' import { Component, OnInit, ViewChild } from '@angular/core' import { FormsModule } from '@angular/forms' import { ActivatedRoute, Router, RouterLink } from '@angular/router' -import { AuthService, ComponentPagination, ConfirmService, Notifier, ScreenService, ServerService, User } from '@app/core' +import { + AuthService, + ComponentPagination, + ConfirmService, + Notifier, + ScreenService, + ServerService, + updatePaginationOnDelete, + User +} from '@app/core' import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' import { formatICU, immutableAssign } from '@app/helpers' import { DropdownAction } from '@app/shared/shared-main/buttons/action-dropdown.component' @@ -256,6 +265,8 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook { private removeVideoFromArray (id: number) { this.videos = this.videos.filter(v => v.id !== id) + + updatePaginationOnDelete(this.pagination) } private buildActions () { diff --git a/client/src/app/+search/search.component.ts b/client/src/app/+search/search.component.ts index fa9dc8194..a3555b7c2 100644 --- a/client/src/app/+search/search.component.ts +++ b/client/src/app/+search/search.component.ts @@ -4,6 +4,7 @@ import { ActivatedRoute, Router, RouterLink } from '@angular/router' import { AuthService, HooksService, MetaService, Notifier, ServerService, User, UserService } from '@app/core' import { immutableAssign, SimpleMemoize } from '@app/helpers' import { validateHost } from '@app/shared/form-validators/host-validators' +import { GlobalIconComponent } from '@app/shared/shared-icons/global-icon.component' import { VideoChannel } from '@app/shared/shared-main/channel/video-channel.model' import { AlertComponent } from '@app/shared/shared-main/common/alert.component' import { Video } from '@app/shared/shared-main/video/video.model' @@ -21,7 +22,6 @@ import { SubscribeButtonComponent } from '../shared/shared-user-subscription/sub import { MiniatureDisplayOptions, VideoMiniatureComponent } from '../shared/shared-video-miniature/video-miniature.component' import { VideoPlaylistMiniatureComponent } from '../shared/shared-video-playlist/video-playlist-miniature.component' import { SearchFiltersComponent } from './search-filters.component' -import { GlobalIconComponent } from '@app/shared/shared-icons/global-icon.component' @Component({ selector: 'my-search', @@ -54,6 +54,8 @@ export class SearchComponent implements OnInit, OnDestroy { currentPage: 1, totalItems: null as number } + deletedVideos = 0 + advancedSearch: AdvancedSearch = new AdvancedSearch() isSearchFilterCollapsed = true currentSearch: string @@ -222,7 +224,10 @@ export class SearchComponent implements OnInit, OnDestroy { // Add VideoChannel/VideoPlaylist for typings, but the template already checks "video" argument is a video removeVideoFromArray (video: Video | VideoChannel | VideoPlaylist) { + const previous = this.results this.results = this.results.filter(r => !this.isVideo(r) || r.id !== video.id) + + if (previous.length !== this.results.length) this.deletedVideos++ } getLinkType (): LinkType { @@ -281,6 +286,7 @@ export class SearchComponent implements OnInit, OnDestroy { private resetPagination () { this.pagination.currentPage = 1 this.pagination.totalItems = null + this.deletedVideos = 0 this.results = [] } @@ -305,7 +311,7 @@ export class SearchComponent implements OnInit, OnDestroy { private getVideosObs () { const params = { search: this.currentSearch, - componentPagination: immutableAssign(this.pagination, { itemsPerPage: 10 }), + componentPagination: immutableAssign(this.pagination, { itemsPerPage: 10, itemsRemoved: this.deletedVideos }), advancedSearch: this.advancedSearch } diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts index 8c4d62d7d..f0316279e 100644 --- a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts +++ b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts @@ -1,13 +1,13 @@ -import { Subject, Subscription } from 'rxjs' +import { NgFor, NgIf } from '@angular/common' import { AfterViewInit, Component, OnDestroy, OnInit } from '@angular/core' -import { ComponentPagination, hasMoreItems, HooksService, ScreenService } from '@app/core' -import { VideoPlaylistMiniatureComponent } from '../../shared/shared-video-playlist/video-playlist-miniature.component' -import { InfiniteScrollerDirective } from '../../shared/shared-main/common/infinite-scroller.directive' -import { NgIf, NgFor } from '@angular/common' +import { ComponentPagination, hasMoreItems, HooksService, resetCurrentPage, ScreenService } from '@app/core' import { VideoChannel } from '@app/shared/shared-main/channel/video-channel.model' import { VideoChannelService } from '@app/shared/shared-main/channel/video-channel.service' import { VideoPlaylist } from '@app/shared/shared-video-playlist/video-playlist.model' import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service' +import { Subject, Subscription } from 'rxjs' +import { InfiniteScrollerDirective } from '../../shared/shared-main/common/infinite-scroller.directive' +import { VideoPlaylistMiniatureComponent } from '../../shared/shared-video-playlist/video-playlist-miniature.component' @Component({ selector: 'my-video-channel-playlists', @@ -46,7 +46,7 @@ export class VideoChannelPlaylistsComponent implements OnInit, AfterViewInit, On this.hooks.runAction('action:video-channel-playlists.video-channel.loaded', 'video-channel', { videoChannel }) this.videoPlaylists = [] - this.pagination.currentPage = 1 + resetCurrentPage(this.pagination) this.loadVideoPlaylists() }) } diff --git a/client/src/app/+videos/+video-watch/shared/player-widgets/video-watch-playlist.component.ts b/client/src/app/+videos/+video-watch/shared/player-widgets/video-watch-playlist.component.ts index f0fc359ca..3bafe0cf0 100644 --- a/client/src/app/+videos/+video-watch/shared/player-widgets/video-watch-playlist.component.ts +++ b/client/src/app/+videos/+video-watch/shared/player-widgets/video-watch-playlist.component.ts @@ -1,18 +1,26 @@ +import { NgClass, NgFor, NgIf } from '@angular/common' import { Component, EventEmitter, Input, Output } from '@angular/core' import { Router } from '@angular/router' -import { AuthService, ComponentPagination, HooksService, Notifier, SessionStorageService, UserService } from '@app/core' +import { + AuthService, + ComponentPagination, + HooksService, + Notifier, + SessionStorageService, + updatePaginationOnDelete, + UserService +} from '@app/core' import { isInViewport } from '@app/helpers' +import { VideoPlaylistElement } from '@app/shared/shared-video-playlist/video-playlist-element.model' +import { VideoPlaylist } from '@app/shared/shared-video-playlist/video-playlist.model' +import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service' +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap' +import { VideoPlaylistPrivacy } from '@peertube/peertube-models' import { getBoolOrDefault } from '@root-helpers/local-storage-utils' import { peertubeSessionStorage } from '@root-helpers/peertube-web-storage' -import { VideoPlaylistPrivacy } from '@peertube/peertube-models' -import { VideoPlaylistElementMiniatureComponent } from '../../../../shared/shared-video-playlist/video-playlist-element-miniature.component' import { GlobalIconComponent } from '../../../../shared/shared-icons/global-icon.component' -import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap' import { InfiniteScrollerDirective } from '../../../../shared/shared-main/common/infinite-scroller.directive' -import { NgIf, NgClass, NgFor } from '@angular/common' -import { VideoPlaylist } from '@app/shared/shared-video-playlist/video-playlist.model' -import { VideoPlaylistElement } from '@app/shared/shared-video-playlist/video-playlist-element.model' -import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service' +import { VideoPlaylistElementMiniatureComponent } from '../../../../shared/shared-video-playlist/video-playlist-element-miniature.component' @Component({ selector: 'my-video-watch-playlist', @@ -74,7 +82,7 @@ export class VideoWatchPlaylistComponent { onElementRemoved (playlistElement: VideoPlaylistElement) { this.playlistElements = this.playlistElements.filter(e => e.id !== playlistElement.id) - this.playlistPagination.totalItems-- + updatePaginationOnDelete(this.playlistPagination) } isPlaylistOwned () { diff --git a/client/src/app/core/rest/component-pagination.model.ts b/client/src/app/core/rest/component-pagination.model.ts index 59d70c1e8..56aa048a4 100644 --- a/client/src/app/core/rest/component-pagination.model.ts +++ b/client/src/app/core/rest/component-pagination.model.ts @@ -2,11 +2,12 @@ export interface ComponentPagination { currentPage: number itemsPerPage: number totalItems: number + itemsRemoved?: number } export type ComponentPaginationLight = Omit & { totalItems?: number } -export function hasMoreItems (componentPagination: ComponentPagination) { +export function hasMoreItems (componentPagination: ComponentPaginationLight) { // No results if (componentPagination.totalItems === 0) return false @@ -16,3 +17,16 @@ export function hasMoreItems (componentPagination: ComponentPagination) { const maxPage = componentPagination.totalItems / componentPagination.itemsPerPage return maxPage > componentPagination.currentPage } + +export function updatePaginationOnDelete (componentPagination: ComponentPagination, itemsDeleted = 1) { + componentPagination.totalItems -= itemsDeleted + + if (!componentPagination.itemsRemoved) componentPagination.itemsRemoved = 0 + + componentPagination.itemsRemoved += itemsDeleted +} + +export function resetCurrentPage (componentPagination: ComponentPaginationLight) { + componentPagination.currentPage = 1 + componentPagination.itemsRemoved = 0 +} diff --git a/client/src/app/core/rest/rest.service.ts b/client/src/app/core/rest/rest.service.ts index b8684627f..602f9dfa1 100644 --- a/client/src/app/core/rest/rest.service.ts +++ b/client/src/app/core/rest/rest.service.ts @@ -72,10 +72,11 @@ export class RestService { } componentToRestPagination (componentPagination: ComponentPaginationLight): RestPagination { - const start: number = (componentPagination.currentPage - 1) * componentPagination.itemsPerPage - const count: number = componentPagination.itemsPerPage + const { currentPage, itemsPerPage, itemsRemoved = 0 } = componentPagination - return { start, count } + const start = Math.max(0, (currentPage - 1) * itemsPerPage - itemsRemoved) + + return { start, count: itemsPerPage } } /* diff --git a/client/src/app/shared/shared-video-miniature/videos-list.component.html b/client/src/app/shared/shared-video-miniature/videos-list.component.html index bd70d3ae1..ce3dc3239 100644 --- a/client/src/app/shared/shared-video-miniature/videos-list.component.html +++ b/client/src/app/shared/shared-video-miniature/videos-list.component.html @@ -33,7 +33,7 @@ diff --git a/client/src/app/shared/shared-video-miniature/videos-list.component.ts b/client/src/app/shared/shared-video-miniature/videos-list.component.ts index 40e9e1368..3b1d3056a 100644 --- a/client/src/app/shared/shared-video-miniature/videos-list.component.ts +++ b/client/src/app/shared/shared-video-miniature/videos-list.component.ts @@ -3,12 +3,15 @@ import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, S import { ActivatedRoute } from '@angular/router' import { AuthService, + ComponentPagination, ComponentPaginationLight, Notifier, PeerTubeRouterService, ScreenService, User, - UserService + UserService, + resetCurrentPage, + updatePaginationOnDelete } from '@app/core' import { GlobalIconComponent, GlobalIconName } from '@app/shared/shared-icons/global-icon.component' import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@peertube/peertube-core-utils' @@ -112,9 +115,10 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy { private userSub: Subscription private resizeSub: Subscription - private pagination: ComponentPaginationLight = { + private pagination: ComponentPagination = { currentPage: 1, - itemsPerPage: 25 + itemsPerPage: 25, + totalItems: null } private groupedDateLabels: { [id in GroupDate]: string } @@ -276,12 +280,17 @@ export class VideosListComponent implements OnInit, OnChanges, OnDestroy { } reloadVideos () { - this.pagination.currentPage = 1 + resetCurrentPage(this.pagination) this.loadMoreVideos(true) } removeVideoFromArray (video: Video) { - this.videos = this.videos.filter(v => v.id !== video.id) + if (this.videos.some(v => v.id === video.id)) { + this.videos = this.videos.filter(v => v.id !== video.id) + + updatePaginationOnDelete(this.pagination) + } + this.highlightedLives = this.highlightedLives.filter(v => v.id !== video.id) } diff --git a/client/src/app/shared/shared-video-miniature/videos-selection.component.html b/client/src/app/shared/shared-video-miniature/videos-selection.component.html index 8ea03b127..722239c33 100644 --- a/client/src/app/shared/shared-video-miniature/videos-selection.component.html +++ b/client/src/app/shared/shared-video-miniature/videos-selection.component.html @@ -17,19 +17,16 @@ [displayVideoActions]="false" [user]="user" > - -
-
- - - -
-
- - + @if (isInSelectionMode() === false) { - + } + +
+ + + +
diff --git a/client/src/app/shared/shared-video-miniature/videos-selection.component.scss b/client/src/app/shared/shared-video-miniature/videos-selection.component.scss index ea6df643c..f029556f6 100644 --- a/client/src/app/shared/shared-video-miniature/videos-selection.component.scss +++ b/client/src/app/shared/shared-video-miniature/videos-selection.component.scss @@ -2,14 +2,10 @@ @use '_mixins' as *; .action-selection-mode { - display: flex; - justify-content: flex-end; - flex-grow: 1; -} - -.action-selection-mode-child { position: fixed; - display: flex; + bottom: 1rem; + + @include right(#{pvar(--x-margin-content)}); .action-button { display: block; @@ -45,10 +41,10 @@ } .checkbox-container { - display: none; + display: none !important; } .action-selection-mode { - display: none; // disable for small screens + display: none !important; // disable for small screens } } diff --git a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts index e9be233f5..5b42fa318 100644 --- a/client/src/app/shared/shared-video-miniature/videos-selection.component.ts +++ b/client/src/app/shared/shared-video-miniature/videos-selection.component.ts @@ -1,16 +1,16 @@ -import { Observable, Subject } from 'rxjs' +import { NgFor, NgIf, NgTemplateOutlet } from '@angular/common' import { AfterContentInit, Component, ContentChildren, EventEmitter, Input, Output, QueryList, TemplateRef } from '@angular/core' -import { ComponentPagination, Notifier, User } from '@app/core' -import { logger } from '@root-helpers/logger' +import { FormsModule } from '@angular/forms' +import { ComponentPagination, Notifier, resetCurrentPage, User } from '@app/core' import { objectKeysTyped } from '@peertube/peertube-core-utils' import { ResultList, VideosExistInPlaylists, VideoSortField } from '@peertube/peertube-models' -import { MiniatureDisplayOptions, VideoMiniatureComponent } from './video-miniature.component' -import { FormsModule } from '@angular/forms' +import { logger } from '@root-helpers/logger' +import { Observable, Subject } from 'rxjs' import { PeertubeCheckboxComponent } from '../shared-forms/peertube-checkbox.component' import { InfiniteScrollerDirective } from '../shared-main/common/infinite-scroller.directive' -import { NgIf, NgFor, NgTemplateOutlet } from '@angular/common' -import { Video } from '../shared-main/video/video.model' import { PeerTubeTemplateDirective } from '../shared-main/common/peertube-template.directive' +import { Video } from '../shared-main/video/video.model' +import { MiniatureDisplayOptions, VideoMiniatureComponent } from './video-miniature.component' export type SelectionType = { [ id: number ]: boolean } @@ -145,11 +145,7 @@ export class VideosSelectionComponent implements AfterContentInit { } reloadVideos () { - this.pagination.currentPage = 1 + resetCurrentPage(this.pagination) this.loadMoreVideos(true) } - - removeVideoFromArray (video: Video) { - this.videos = this.videos.filter(v => v.id !== video.id) - } }