From e3fb8a09f8cc6862a7d9988db665015ec1eb1197 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Thu, 30 May 2024 09:20:12 +0200 Subject: [PATCH] My account/library get user simplification --- .../src/app/+accounts/accounts.component.ts | 55 ++++++------ .../my-account-applications.component.ts | 1 + .../my-account-auto-tag-policies.component.ts | 5 +- .../my-account-export.component.ts | 19 ++-- .../my-account-import-export.component.ts | 16 ++-- .../my-account-import.component.ts | 24 +++-- .../my-account-change-email.component.ts | 6 +- .../my-account-change-password.component.ts | 4 +- .../my-account-danger-zone.component.ts | 2 +- .../my-account-email-preferences.component.ts | 10 +-- ...ount-notification-preferences.component.ts | 12 ++- .../my-account-profile.component.ts | 16 ++-- .../my-account-settings.component.html | 10 +-- .../my-account-settings.component.ts | 2 +- .../my-account-two-factor-button.component.ts | 12 +-- .../my-account-two-factor.component.ts | 10 +-- .../app/+my-account/my-account.component.ts | 1 - client/src/app/+my-account/routes.ts | 4 + .../my-follows/my-followers.component.ts | 40 ++++----- .../app/+my-library/my-library.component.ts | 11 +-- .../my-videos/my-videos.component.ts | 88 +++++++++---------- client/src/app/+my-library/routes.ts | 4 + .../+video-edit/video-add.component.html | 2 +- client/src/app/core/routing/user.resolver.ts | 11 +++ .../shared-main/users/user-quota.component.ts | 20 +++-- .../user-interface-settings.component.ts | 2 +- 26 files changed, 184 insertions(+), 203 deletions(-) create mode 100644 client/src/app/core/routing/user.resolver.ts diff --git a/client/src/app/+accounts/accounts.component.ts b/client/src/app/+accounts/accounts.component.ts index c5b1e185f..afc99b0b8 100644 --- a/client/src/app/+accounts/accounts.component.ts +++ b/client/src/app/+accounts/accounts.component.ts @@ -1,26 +1,26 @@ -import { Subscription } from 'rxjs' -import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators' +import { DatePipe, NgClass, NgIf } from '@angular/common' import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core' import { ActivatedRoute, Router, RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router' import { AuthService, MarkdownService, Notifier, RedirectService, RestExtractor, ScreenService, UserService } from '@app/core' -import { HttpStatusCode, User, UserRight } from '@peertube/peertube-models' -import { SimpleSearchInputComponent } from '../shared/shared-main/misc/simple-search-input.component' -import { ListOverflowComponent, ListOverflowItem } from '../shared/shared-main/misc/list-overflow.component' -import { SubscribeButtonComponent } from '../shared/shared-user-subscription/subscribe-button.component' -import { CopyButtonComponent } from '../shared/shared-main/buttons/copy-button.component' -import { AccountBlockBadgesComponent } from '../shared/shared-moderation/account-block-badges.component' -import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap' -import { UserModerationDropdownComponent } from '../shared/shared-moderation/user-moderation-dropdown.component' -import { ActorAvatarComponent } from '../shared/shared-actor-image/actor-avatar.component' -import { NgIf, NgClass, DatePipe } from '@angular/common' +import { Account } from '@app/shared/shared-main/account/account.model' import { AccountService } from '@app/shared/shared-main/account/account.service' import { DropdownAction } from '@app/shared/shared-main/buttons/action-dropdown.component' +import { VideoChannel } from '@app/shared/shared-main/video-channel/video-channel.model' import { VideoChannelService } from '@app/shared/shared-main/video-channel/video-channel.service' import { VideoService } from '@app/shared/shared-main/video/video.service' -import { Account } from '@app/shared/shared-main/account/account.model' -import { VideoChannel } from '@app/shared/shared-main/video-channel/video-channel.model' import { BlocklistService } from '@app/shared/shared-moderation/blocklist.service' import { AccountReportComponent } from '@app/shared/shared-moderation/report-modals' +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap' +import { HttpStatusCode, User, UserRight } from '@peertube/peertube-models' +import { Subscription } from 'rxjs' +import { catchError, distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators' +import { ActorAvatarComponent } from '../shared/shared-actor-image/actor-avatar.component' +import { CopyButtonComponent } from '../shared/shared-main/buttons/copy-button.component' +import { ListOverflowComponent, ListOverflowItem } from '../shared/shared-main/misc/list-overflow.component' +import { SimpleSearchInputComponent } from '../shared/shared-main/misc/simple-search-input.component' +import { AccountBlockBadgesComponent } from '../shared/shared-moderation/account-block-badges.component' +import { UserModerationDropdownComponent } from '../shared/shared-moderation/user-moderation-dropdown.component' +import { SubscribeButtonComponent } from '../shared/shared-user-subscription/subscribe-button.component' @Component({ templateUrl: './accounts.component.html', @@ -208,24 +208,19 @@ export class AccountsComponent implements OnInit, OnDestroy { this.prependModerationActions = [] if (!this.authService.isLoggedIn()) return + if (this.isManageable()) return - this.authService.userInformationLoaded.subscribe( - () => { - if (this.isManageable()) return - - // It's not our account, we can report it - this.prependModerationActions = [ - { - label: $localize`Report`, - isHeader: true - }, - { - label: $localize`Report this account`, - handler: () => this.showReportModal() - } - ] + // It's not our account, we can report it + this.prependModerationActions = [ + { + label: $localize`Report`, + isHeader: true + }, + { + label: $localize`Report this account`, + handler: () => this.showReportModal() } - ) + ] } private loadAccountVideosCount () { diff --git a/client/src/app/+my-account/my-account-applications/my-account-applications.component.ts b/client/src/app/+my-account/my-account-applications/my-account-applications.component.ts index 97e8c11e4..e308681ef 100644 --- a/client/src/app/+my-account/my-account-applications/my-account-applications.component.ts +++ b/client/src/app/+my-account/my-account-applications/my-account-applications.component.ts @@ -29,6 +29,7 @@ export class MyAccountApplicationsComponent implements OnInit { ngOnInit () { this.feedUrl = this.baseURL + this.scopedTokensService.getScopedTokens() .subscribe({ next: tokens => this.regenApplications(tokens), diff --git a/client/src/app/+my-account/my-account-auto-tag-policies/my-account-auto-tag-policies.component.ts b/client/src/app/+my-account/my-account-auto-tag-policies/my-account-auto-tag-policies.component.ts index 3c8978058..13c04abd9 100644 --- a/client/src/app/+my-account/my-account-auto-tag-policies/my-account-auto-tag-policies.component.ts +++ b/client/src/app/+my-account/my-account-auto-tag-policies/my-account-auto-tag-policies.component.ts @@ -5,7 +5,6 @@ import { PeertubeCheckboxComponent } from '@app/shared/shared-forms/peertube-che import { GlobalIconComponent } from '@app/shared/shared-icons/global-icon.component' import { AutomaticTagAvailableType } from '@peertube/peertube-models' import { forkJoin } from 'rxjs' -import { first } from 'rxjs/operators' import { AutomaticTagService } from './automatic-tag.service' @Component({ @@ -29,9 +28,7 @@ export class MyAccountAutoTagPoliciesComponent implements OnInit { } ngOnInit () { - this.authService.userInformationLoaded - .pipe(first()) - .subscribe(() => this.loadAvailableTags()) + this.loadAvailableTags() } getLabelText (tag: { name: string, type: AutomaticTagAvailableType }) { diff --git a/client/src/app/+my-account/my-account-import-export/my-account-export.component.ts b/client/src/app/+my-account/my-account-import-export/my-account-export.component.ts index a9a3d2fa9..2539496be 100644 --- a/client/src/app/+my-account/my-account-import-export/my-account-export.component.ts +++ b/client/src/app/+my-account/my-account-import-export/my-account-export.component.ts @@ -1,14 +1,14 @@ +import { DatePipe, NgFor, NgIf } from '@angular/common' import { Component, Input, OnInit, ViewChild } from '@angular/core' -import { AuthService, ServerService } from '@app/core' -import { PeerTubeProblemDocument, ServerErrorCode, UserExport, UserExportState } from '@peertube/peertube-models' -import { UserImportExportService } from './user-import-export.service' -import { concatMap, first, from, of, switchMap, toArray } from 'rxjs' -import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' -import { BytesPipe } from '../../shared/shared-main/angular/bytes.pipe' import { FormsModule } from '@angular/forms' +import { AuthService, ServerService } from '@app/core' +import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' +import { PeerTubeProblemDocument, ServerErrorCode, UserExport, UserExportState } from '@peertube/peertube-models' +import { concatMap, from, of, switchMap, toArray } from 'rxjs' import { PeertubeCheckboxComponent } from '../../shared/shared-forms/peertube-checkbox.component' import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' -import { NgIf, NgFor, DatePipe } from '@angular/common' +import { BytesPipe } from '../../shared/shared-main/angular/bytes.pipe' +import { UserImportExportService } from './user-import-export.service' @Component({ selector: 'my-account-export', @@ -41,9 +41,8 @@ export class MyAccountExportComponent implements OnInit { ngOnInit () { this.archiveWeightEstimation = this.videoQuotaUsed - this.authService.userInformationLoaded - .pipe(first()) - .subscribe(() => this.reloadUserExports()) + + this.reloadUserExports() } isExportEnabled () { diff --git a/client/src/app/+my-account/my-account-import-export/my-account-import-export.component.ts b/client/src/app/+my-account/my-account-import-export/my-account-import-export.component.ts index 4dcee52c8..3a3491eda 100644 --- a/client/src/app/+my-account/my-account-import-export/my-account-import-export.component.ts +++ b/client/src/app/+my-account/my-account-import-export/my-account-import-export.component.ts @@ -1,9 +1,8 @@ import { Component, OnInit, ViewChild } from '@angular/core' -import { AuthService, CanComponentDeactivate, UserService } from '@app/core' -import { MyAccountImportComponent } from './my-account-import.component' -import { first } from 'rxjs' -import { MyAccountExportComponent } from './my-account-export.component' +import { CanComponentDeactivate, UserService } from '@app/core' import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' +import { MyAccountExportComponent } from './my-account-export.component' +import { MyAccountImportComponent } from './my-account-import.component' @Component({ selector: 'my-account-import-export', @@ -17,17 +16,12 @@ export class MyAccountImportExportComponent implements OnInit, CanComponentDeact videoQuotaUsed: number constructor ( - private authService: AuthService, private userService: UserService ) {} ngOnInit () { - this.authService.userInformationLoaded - .pipe(first()) - .subscribe(() => { - this.userService.getMyVideoQuotaUsed() - .subscribe(res => this.videoQuotaUsed = res.videoQuotaUsed) - }) + this.userService.getMyVideoQuotaUsed() + .subscribe(res => this.videoQuotaUsed = res.videoQuotaUsed) } canDeactivate () { diff --git a/client/src/app/+my-account/my-account-import-export/my-account-import.component.ts b/client/src/app/+my-account/my-account-import-export/my-account-import.component.ts index 154d2e788..cd2c796d3 100644 --- a/client/src/app/+my-account/my-account-import-export/my-account-import.component.ts +++ b/client/src/app/+my-account/my-account-import-export/my-account-import.component.ts @@ -1,15 +1,15 @@ -import { Component, Input, OnDestroy, OnInit } from '@angular/core' -import { AuthService, ServerService, CanComponentDeactivate, Notifier } from '@app/core' -import { Subscription, first, switchMap } from 'rxjs' -import { UserImportExportService } from './user-import-export.service' +import { DatePipe, NgIf } from '@angular/common' import { HttpErrorResponse } from '@angular/common/http' +import { Component, Input, OnDestroy, OnInit } from '@angular/core' +import { AuthService, CanComponentDeactivate, Notifier, ServerService } from '@app/core' import { buildHTTPErrorResponse, genericUploadErrorHandler, getUploadXRetryConfig } from '@app/helpers' -import { HttpStatusCode, UserImport, UserImportState } from '@peertube/peertube-models' -import { UploadxService, UploadState, UploaderX } from 'ngx-uploadx' -import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap' -import { UploadProgressComponent } from '../../shared/standalone-upload/upload-progress.component' -import { NgIf, DatePipe } from '@angular/common' import { BytesPipe } from '@app/shared/shared-main/angular/bytes.pipe' +import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap' +import { HttpStatusCode, UserImport, UserImportState } from '@peertube/peertube-models' +import { UploadState, UploaderX, UploadxService } from 'ngx-uploadx' +import { Subscription } from 'rxjs' +import { UploadProgressComponent } from '../../shared/standalone-upload/upload-progress.component' +import { UserImportExportService } from './user-import-export.service' @Component({ selector: 'my-account-import', @@ -43,11 +43,7 @@ export class MyAccountImportComponent implements OnInit, OnDestroy, CanComponent ) {} ngOnInit () { - this.authService.userInformationLoaded - .pipe( - first(), - switchMap(() => this.userImportExportService.getLatestImport({ userId: this.authService.getUser().id })) - ) + this.userImportExportService.getLatestImport({ userId: this.authService.getUser().id }) .subscribe(res => this.latestImport = res) this.uploadServiceSubscription = this.resumableUploadService.events diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts b/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts index c33de1496..9d3cfeef4 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-change-email/my-account-change-email.component.ts @@ -18,9 +18,9 @@ import { InputTextComponent } from '../../../shared/shared-forms/input-text.comp imports: [ NgIf, FormsModule, ReactiveFormsModule, NgClass, InputTextComponent ] }) export class MyAccountChangeEmailComponent extends FormReactive implements OnInit { - error: string = null - success: string = null - user: User = null + error: string + success: string + user: User constructor ( protected formReactiveService: FormReactiveService, diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts index 8806341a4..d13332477 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts @@ -21,8 +21,8 @@ import { NgIf } from '@angular/common' imports: [ NgIf, FormsModule, ReactiveFormsModule, InputTextComponent ] }) export class MyAccountChangePasswordComponent extends FormReactive implements OnInit { - error: string = null - user: User = null + error: string + user: User constructor ( protected formReactiveService: FormReactiveService, diff --git a/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts b/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts index 64f73512e..7f135d01c 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-danger-zone/my-account-danger-zone.component.ts @@ -8,7 +8,7 @@ import { AuthService, ConfirmService, Notifier, RedirectService, User, UserServi standalone: true }) export class MyAccountDangerZoneComponent { - @Input() user: User = null + @Input() user: User constructor ( private authService: AuthService, diff --git a/client/src/app/+my-account/my-account-settings/my-account-email-preferences/my-account-email-preferences.component.ts b/client/src/app/+my-account/my-account-settings/my-account-email-preferences/my-account-email-preferences.component.ts index ab0019f7c..520c69896 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-email-preferences/my-account-email-preferences.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-email-preferences/my-account-email-preferences.component.ts @@ -1,11 +1,10 @@ -import { Subject } from 'rxjs' import { Component, Input, OnInit } from '@angular/core' +import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { Notifier, UserService } from '@app/core' import { FormReactive } from '@app/shared/shared-forms/form-reactive' import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service' import { User, UserUpdateMe } from '@peertube/peertube-models' import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube-checkbox.component' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' @Component({ selector: 'my-account-email-preferences', @@ -15,8 +14,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms' imports: [ FormsModule, ReactiveFormsModule, PeertubeCheckboxComponent ] }) export class MyAccountEmailPreferencesComponent extends FormReactive implements OnInit { - @Input() user: User = null - @Input() userInformationLoaded: Subject + @Input() user: User constructor ( protected formReactiveService: FormReactiveService, @@ -31,9 +29,7 @@ export class MyAccountEmailPreferencesComponent extends FormReactive implements 'email-public': null }) - this.userInformationLoaded.subscribe(() => { - this.form.patchValue({ 'email-public': this.user.emailPublic }) - }) + this.form.patchValue({ 'email-public': this.user.emailPublic }) } updateEmailPublic () { diff --git a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts index 4fa2ed6d7..69a1b0882 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-notification-preferences/my-account-notification-preferences.component.ts @@ -1,13 +1,12 @@ -import { debounce } from 'lodash-es' -import { Subject } from 'rxjs' +import { NgFor, NgIf } from '@angular/common' import { Component, Input, OnInit } from '@angular/core' +import { FormsModule } from '@angular/forms' import { Notifier, ServerService, User } from '@app/core' +import { UserNotificationService } from '@app/shared/shared-main/users/user-notification.service' import { objectKeysTyped } from '@peertube/peertube-core-utils' import { UserNotificationSetting, UserNotificationSettingValue, UserRight, UserRightType } from '@peertube/peertube-models' -import { FormsModule } from '@angular/forms' +import { debounce } from 'lodash-es' import { InputSwitchComponent } from '../../../shared/shared-forms/input-switch.component' -import { NgIf, NgFor } from '@angular/common' -import { UserNotificationService } from '@app/shared/shared-main/users/user-notification.service' @Component({ selector: 'my-account-notification-preferences', @@ -18,7 +17,6 @@ import { UserNotificationService } from '@app/shared/shared-main/users/user-noti }) export class MyAccountNotificationPreferencesComponent implements OnInit { @Input() user: User - @Input() userInformationLoaded: Subject notificationSettingGroups: { label: string, keys: (keyof UserNotificationSetting)[] }[] = [] emailNotifications: { [ id in keyof UserNotificationSetting ]?: boolean } = {} @@ -111,7 +109,7 @@ export class MyAccountNotificationPreferencesComponent implements OnInit { const serverConfig = this.serverService.getHTMLConfig() this.emailEnabled = serverConfig.email.enabled - this.userInformationLoaded.subscribe(() => this.loadNotificationSettings()) + this.loadNotificationSettings() } hasUserRight (field: keyof UserNotificationSetting) { diff --git a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts index 44e3b3d9c..5db3f35de 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts @@ -1,11 +1,10 @@ -import { Subject } from 'rxjs' +import { NgClass, NgIf } from '@angular/common' import { Component, Input, OnInit } from '@angular/core' +import { FormsModule, ReactiveFormsModule } from '@angular/forms' import { Notifier, User, UserService } from '@app/core' import { USER_DESCRIPTION_VALIDATOR, USER_DISPLAY_NAME_REQUIRED_VALIDATOR } from '@app/shared/form-validators/user-validators' import { FormReactive } from '@app/shared/shared-forms/form-reactive' import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service' -import { FormsModule, ReactiveFormsModule } from '@angular/forms' -import { NgIf, NgClass } from '@angular/common' @Component({ selector: 'my-account-profile', @@ -16,7 +15,6 @@ import { NgIf, NgClass } from '@angular/common' }) export class MyAccountProfileComponent extends FormReactive implements OnInit { @Input() user: User = null - @Input() userInformationLoaded: Subject error: string = null @@ -36,12 +34,10 @@ export class MyAccountProfileComponent extends FormReactive implements OnInit { }) this.form.controls['username'].disable() - this.userInformationLoaded.subscribe(() => { - this.form.patchValue({ - 'username': this.user.username, - 'display-name': this.user.account.displayName, - 'description': this.user.account.description - }) + this.form.patchValue({ + 'username': this.user.username, + 'display-name': this.user.account.displayName, + 'description': this.user.account.description }) } diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-settings.component.html index f192e56d7..8e7a9a946 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.html +++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.html @@ -13,9 +13,9 @@ (avatarChange)="onAvatarChange($event)" (avatarDelete)="onAvatarDelete()" > - + - + @@ -47,7 +47,7 @@
- +
@@ -67,7 +67,7 @@
- +
@@ -77,7 +77,7 @@
- +
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts index 544265bc5..522efd287 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts @@ -39,7 +39,7 @@ import { ActorAvatarEditComponent } from '../../shared/shared-actor-image-edit/a ] }) export class MyAccountSettingsComponent implements OnInit, AfterViewChecked { - user: User = null + user: User private lastScrollHash: string diff --git a/client/src/app/+my-account/my-account-settings/my-account-two-factor/my-account-two-factor-button.component.ts b/client/src/app/+my-account/my-account-settings/my-account-two-factor/my-account-two-factor-button.component.ts index d9aaa58cc..eb34dc09b 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-two-factor/my-account-two-factor-button.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-two-factor/my-account-two-factor-button.component.ts @@ -1,9 +1,8 @@ -import { Subject } from 'rxjs' +import { NgIf } from '@angular/common' import { Component, Input, OnInit } from '@angular/core' import { AuthService, ConfirmService, Notifier, User } from '@app/core' -import { ButtonComponent } from '../../../shared/shared-main/buttons/button.component' -import { NgIf } from '@angular/common' import { TwoFactorService } from '@app/shared/shared-users/two-factor.service' +import { ButtonComponent } from '../../../shared/shared-main/buttons/button.component' @Component({ selector: 'my-account-two-factor-button', @@ -12,8 +11,7 @@ import { TwoFactorService } from '@app/shared/shared-users/two-factor.service' imports: [ NgIf, ButtonComponent ] }) export class MyAccountTwoFactorButtonComponent implements OnInit { - @Input() user: User = null - @Input() userInformationLoaded: Subject + @Input() user: User twoFactorEnabled = false @@ -26,9 +24,7 @@ export class MyAccountTwoFactorButtonComponent implements OnInit { } ngOnInit () { - this.userInformationLoaded.subscribe(() => { - this.twoFactorEnabled = this.user.twoFactorEnabled - }) + this.twoFactorEnabled = this.user.twoFactorEnabled } async disableTwoFactor () { diff --git a/client/src/app/+my-account/my-account-settings/my-account-two-factor/my-account-two-factor.component.ts b/client/src/app/+my-account/my-account-settings/my-account-two-factor/my-account-two-factor.component.ts index b98ec7cf8..22cbb5ec9 100644 --- a/client/src/app/+my-account/my-account-settings/my-account-two-factor/my-account-two-factor.component.ts +++ b/client/src/app/+my-account/my-account-settings/my-account-two-factor/my-account-two-factor.component.ts @@ -1,14 +1,14 @@ +import { NgIf } from '@angular/common' import { Component, OnInit } from '@angular/core' import { FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms' import { Router } from '@angular/router' import { AuthService, Notifier, User } from '@app/core' import { USER_EXISTING_PASSWORD_VALIDATOR, USER_OTP_TOKEN_VALIDATOR } from '@app/shared/form-validators/user-validators' import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service' +import { TwoFactorService } from '@app/shared/shared-users/two-factor.service' import { QRCodeModule } from 'angularx-qrcode' import { InputTextComponent } from '../../../shared/shared-forms/input-text.component' -import { NgIf } from '@angular/common' import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component' -import { TwoFactorService } from '@app/shared/shared-users/two-factor.service' @Component({ selector: 'my-account-two-factor', @@ -49,11 +49,9 @@ export class MyAccountTwoFactorComponent implements OnInit { this.buildPasswordForm() this.buildOTPForm() - this.auth.userInformationLoaded.subscribe(() => { - this.user = this.auth.getUser() + this.user = this.auth.getUser() - this.twoFactorAlreadyEnabled = this.user.twoFactorEnabled - }) + this.twoFactorAlreadyEnabled = this.user.twoFactorEnabled } requestTwoFactor () { diff --git a/client/src/app/+my-account/my-account.component.ts b/client/src/app/+my-account/my-account.component.ts index 696896627..7374bb977 100644 --- a/client/src/app/+my-account/my-account.component.ts +++ b/client/src/app/+my-account/my-account.component.ts @@ -5,7 +5,6 @@ import { AuthUser, PluginService, ScreenService } from '@app/core' import { TopMenuDropdownComponent, TopMenuDropdownParam } from '../shared/shared-main/misc/top-menu-dropdown.component' @Component({ - selector: 'my-my-account', templateUrl: './my-account.component.html', styleUrls: [ './my-account.component.scss' ], standalone: true, diff --git a/client/src/app/+my-account/routes.ts b/client/src/app/+my-account/routes.ts index 6c2a1e1e8..8a3bb209b 100644 --- a/client/src/app/+my-account/routes.ts +++ b/client/src/app/+my-account/routes.ts @@ -20,6 +20,7 @@ import { MyAccountSettingsComponent } from './my-account-settings/my-account-set import { MyAccountTwoFactorComponent } from './my-account-settings/my-account-two-factor/my-account-two-factor.component' import { MyAccountWatchedWordsListComponent } from './my-account-watched-words-list/my-account-watched-words-list.component' import { MyAccountComponent } from './my-account.component' +import { userResolver } from '@app/core/routing/user.resolver' export default [ { @@ -35,6 +36,9 @@ export default [ BulkService, WatchedWordsListService ], + resolve: { + user: userResolver + }, canActivateChild: [ LoginGuard ], children: [ { 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 b8c12a2d7..7b1a8edc8 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,14 +1,14 @@ -import { Subject } from 'rxjs' +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 { ActorFollow } from '@peertube/peertube-models' -import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component' -import { InfiniteScrollerDirective } from '../../shared/shared-main/angular/infinite-scroller.directive' -import { AdvancedInputFilter, 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 { UserSubscriptionService } from '@app/shared/shared-user-subscription/user-subscription.service' +import { ActorFollow } from '@peertube/peertube-models' +import { Subject } from 'rxjs' +import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component' +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/angular/infinite-scroller.directive' @Component({ templateUrl: './my-followers.component.html', @@ -42,21 +42,19 @@ export class MyFollowersComponent implements OnInit { this.search = this.route.snapshot.queryParams['search'] } - this.auth.userInformationLoaded.subscribe(() => { - const channelFilters = this.auth.getUser().videoChannels.map(c => { - return { - value: 'channel:' + c.name, - label: c.name - } - }) - - this.inputFilters = [ - { - title: $localize`Channel filters`, - children: channelFilters - } - ] + const channelFilters = this.auth.getUser().videoChannels.map(c => { + return { + value: 'channel:' + c.name, + label: c.name + } }) + + this.inputFilters = [ + { + title: $localize`Channel filters`, + children: channelFilters + } + ] } onNearOfBottom () { diff --git a/client/src/app/+my-library/my-library.component.ts b/client/src/app/+my-library/my-library.component.ts index d3a5b2aea..ba35731ee 100644 --- a/client/src/app/+my-library/my-library.component.ts +++ b/client/src/app/+my-library/my-library.component.ts @@ -1,9 +1,9 @@ +import { NgClass } from '@angular/common' import { Component, OnInit } from '@angular/core' +import { RouterOutlet } from '@angular/router' import { AuthService, AuthUser, ScreenService, ServerService } from '@app/core' import { HTMLServerConfig } from '@peertube/peertube-models' -import { TopMenuDropdownParam, TopMenuDropdownComponent } from '../shared/shared-main/misc/top-menu-dropdown.component' -import { RouterOutlet } from '@angular/router' -import { NgClass } from '@angular/common' +import { TopMenuDropdownComponent, TopMenuDropdownParam } from '../shared/shared-main/misc/top-menu-dropdown.component' @Component({ templateUrl: './my-library.component.html', @@ -31,10 +31,7 @@ export class MyLibraryComponent implements OnInit { this.serverConfig = this.serverService.getHTMLConfig() this.user = this.authService.getUser() - - this.authService.userInformationLoaded.subscribe( - () => this.buildMenu() - ) + this.buildMenu() } isVideoImportEnabled () { 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 a3d6e9ee0..cb58ee6c6 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 @@ -1,30 +1,30 @@ -import { uniqBy } from 'lodash-es' -import { concat, Observable } from 'rxjs' -import { tap, toArray } from 'rxjs/operators' +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 { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook' -import { immutableAssign, formatICU } from '@app/helpers' -import { VideoChannel, VideoExistInPlaylist, VideosExistInPlaylists, VideoSortField } from '@peertube/peertube-models' -import { VideoChangeOwnershipComponent } from './modals/video-change-ownership.component' -import { - VideoActionsDisplayType, - VideoActionsDropdownComponent -} from '../../shared/shared-video-miniature/video-actions-dropdown.component' -import { EditButtonComponent } from '../../shared/shared-main/buttons/edit-button.component' -import { PeerTubeTemplateDirective } from '../../shared/shared-main/angular/peertube-template.directive' -import { FormsModule } from '@angular/forms' -import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component' -import { NgIf } from '@angular/common' -import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' +import { formatICU, immutableAssign } from '@app/helpers' import { DropdownAction } from '@app/shared/shared-main/buttons/action-dropdown.component' import { Video } from '@app/shared/shared-main/video/video.model' import { VideoService } from '@app/shared/shared-main/video/video.service' import { LiveStreamInformationComponent } from '@app/shared/shared-video-live/live-stream-information.component' import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature/video-miniature.component' -import { VideosSelectionComponent, SelectionType } from '@app/shared/shared-video-miniature/videos-selection.component' +import { SelectionType, VideosSelectionComponent } from '@app/shared/shared-video-miniature/videos-selection.component' import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service' +import { VideoChannel, VideoExistInPlaylist, VideosExistInPlaylists, VideoSortField } from '@peertube/peertube-models' +import { uniqBy } from 'lodash-es' +import { concat, Observable } from 'rxjs' +import { tap, toArray } from 'rxjs/operators' +import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component' +import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component' +import { PeerTubeTemplateDirective } from '../../shared/shared-main/angular/peertube-template.directive' +import { EditButtonComponent } from '../../shared/shared-main/buttons/edit-button.component' +import { + VideoActionsDisplayType, + VideoActionsDropdownComponent +} from '../../shared/shared-video-miniature/video-actions-dropdown.component' +import { VideoChangeOwnershipComponent } from './modals/video-change-ownership.component' @Component({ templateUrl: './my-videos.component.html', @@ -121,36 +121,34 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook { this.search = this.route.snapshot.queryParams['search'] } - this.authService.userInformationLoaded.subscribe(() => { - this.user = this.authService.getUser() - this.userChannels = this.user.videoChannels + this.user = this.authService.getUser() + this.userChannels = this.user.videoChannels - const channelFilters = [ ...this.userChannels ] - .sort((a, b) => a.displayName.localeCompare(b.displayName)) - .map(c => { - return { - value: 'channel:' + c.name, - label: c.displayName - } - }) - - this.inputFilters = [ - { - title: $localize`Advanced filters`, - children: [ - { - value: 'isLive:true', - label: $localize`Only live videos` - } - ] - }, - - { - title: $localize`Channel filters`, - children: channelFilters + const channelFilters = [ ...this.userChannels ] + .sort((a, b) => a.displayName.localeCompare(b.displayName)) + .map(c => { + return { + value: 'channel:' + c.name, + label: c.displayName } - ] - }) + }) + + this.inputFilters = [ + { + title: $localize`Advanced filters`, + children: [ + { + value: 'isLive:true', + label: $localize`Only live videos` + } + ] + }, + + { + title: $localize`Channel filters`, + children: channelFilters + } + ] } onSearch (search: string) { diff --git a/client/src/app/+my-library/routes.ts b/client/src/app/+my-library/routes.ts index 5a12fa144..7d1d87563 100644 --- a/client/src/app/+my-library/routes.ts +++ b/client/src/app/+my-library/routes.ts @@ -19,6 +19,7 @@ import { UserSubscriptionService } from '@app/shared/shared-user-subscription/us import { LiveVideoService } from '@app/shared/shared-video-live/live-video.service' import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service' import { AbuseService } from '@app/shared/shared-moderation/abuse.service' +import { userResolver } from '@app/core/routing/user.resolver' export default [ { @@ -32,6 +33,9 @@ export default [ LiveVideoService, UserSubscriptionService ], + resolve: { + user: userResolver + }, canActivateChild: [ LoginGuard ], children: [ { diff --git a/client/src/app/+videos/+video-edit/video-add.component.html b/client/src/app/+videos/+video-edit/video-add.component.html index bd35516ab..7f60f47e3 100644 --- a/client/src/app/+videos/+video-edit/video-add.component.html +++ b/client/src/app/+videos/+video-edit/video-add.component.html @@ -38,7 +38,7 @@
- +
Import {{ videoName }} diff --git a/client/src/app/core/routing/user.resolver.ts b/client/src/app/core/routing/user.resolver.ts new file mode 100644 index 000000000..3fea47dcd --- /dev/null +++ b/client/src/app/core/routing/user.resolver.ts @@ -0,0 +1,11 @@ +import { inject } from '@angular/core' +import { ResolveFn } from '@angular/router' +import { first, map } from 'rxjs' +import { AuthService, AuthUser } from '../auth' + +export const userResolver: ResolveFn = () => { + const auth = inject(AuthService) + + return auth.userInformationLoaded + .pipe(first(), map(() => auth.getUser())) +} diff --git a/client/src/app/shared/shared-main/users/user-quota.component.ts b/client/src/app/shared/shared-main/users/user-quota.component.ts index 98d4a79eb..fbe413880 100644 --- a/client/src/app/shared/shared-main/users/user-quota.component.ts +++ b/client/src/app/shared/shared-main/users/user-quota.component.ts @@ -1,8 +1,8 @@ -import { Subject } from 'rxjs' -import { Component, Input, OnInit } from '@angular/core' -import { User, UserService } from '@app/core' import { NgIf } from '@angular/common' +import { Component, OnInit } from '@angular/core' +import { AuthService, UserService } from '@app/core' import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap' +import { first } from 'rxjs' import { BytesPipe } from '../angular/bytes.pipe' @Component({ @@ -14,9 +14,6 @@ import { BytesPipe } from '../angular/bytes.pipe' }) export class UserQuotaComponent implements OnInit { - @Input() user: User = null - @Input() userInformationLoaded: Subject - userVideoQuota = '0' userVideoQuotaUsed = 0 userVideoQuotaPercentage = 15 @@ -25,10 +22,17 @@ export class UserQuotaComponent implements OnInit { userVideoQuotaUsedDaily = 0 userVideoQuotaDailyPercentage = 15 - constructor (private userService: UserService) { } + constructor ( + private userService: UserService, + private auth: AuthService + ) { } + + get user () { + return this.auth.getUser() + } ngOnInit () { - this.userInformationLoaded.subscribe( + this.auth.userInformationLoaded.pipe(first()).subscribe( () => { if (this.user.videoQuota !== -1) { this.userVideoQuota = new BytesPipe().transform(this.user.videoQuota, 0).toString() diff --git a/client/src/app/shared/shared-user-settings/user-interface-settings.component.ts b/client/src/app/shared/shared-user-settings/user-interface-settings.component.ts index 3214439dc..4ea58b555 100644 --- a/client/src/app/shared/shared-user-settings/user-interface-settings.component.ts +++ b/client/src/app/shared/shared-user-settings/user-interface-settings.component.ts @@ -16,7 +16,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms' imports: [ FormsModule, ReactiveFormsModule, NgFor, NgIf ] }) export class UserInterfaceSettingsComponent extends FormReactive implements OnInit, OnDestroy { - @Input() user: User = null + @Input() user: User @Input() reactiveUpdate = false @Input() notifyOnUpdate = true @Input() userInformationLoaded: Subject