]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
allow muting from the miniature options
authorRigel Kent <sendmemail@rigelk.eu>
Sun, 28 Jun 2020 14:38:51 +0000 (16:38 +0200)
committerRigel Kent <sendmemail@rigelk.eu>
Sun, 28 Jun 2020 14:55:17 +0000 (16:55 +0200)
initial implementation with a listing refresh except on search results

client/src/app/+my-account/my-account-settings/my-account-settings.component.html
client/src/app/+videos/+video-watch/recommendations/recommended-videos.component.html
client/src/app/shared/shared-moderation/blocklist.service.ts
client/src/app/shared/shared-video-miniature/abstract-video-list.html
client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts
client/src/app/shared/shared-video-miniature/video-miniature.component.html
client/src/app/shared/shared-video-miniature/video-miniature.component.ts
server/models/video/video-comment.ts

index 26096da028debe0b244a57d8bbe1a9de4ac4dc9d..185f132751529c7df52246f5ee8188d524037730 100644 (file)
@@ -1,11 +1,18 @@
 <h1 class="sr-only" i18n>Settings</h1>
-<div class="form-row"> <!-- profile grid -->
+<div class="form-row"> <!-- preview -->
+  <div class="form-group col-12 col-lg-4 col-xl-3"></div>
+
+  <div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
+    <my-actor-avatar-info [actor]="user.account" (avatarChange)="onAvatarChange($event)"></my-actor-avatar-info>
+  </div>
+</div>
+
+<div class="form-row"> <!-- profile settings grid -->
   <div class="form-group col-12 col-lg-4 col-xl-3">
-    <h2 i18n class="account-title">PROFILE</h2>
+    <h2 i18n class="account-title">PROFILE SETTINGS</h2>
   </div>
 
   <div class="form-group form-group-right col-12 col-lg-8 col-xl-9">
-    <my-actor-avatar-info [actor]="user.account" (avatarChange)="onAvatarChange($event)"></my-actor-avatar-info>
 
     <div class="user-quota mb-3">
       <div>
index 0467cabf5810cda7c9ae1cd2b4f15ba917c4c709..1ab1b73435de4cdd78b485869a2c7c45f2d17fc3 100644 (file)
@@ -15,7 +15,7 @@
     <ng-container *ngFor="let video of (videos$ | async); let i = index; let length = count">
       <my-video-miniature
         [displayOptions]="displayOptions" [video]="video" [user]="userMiniature"
-        (videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()">
+        (videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()" (videoAccountMuted)="onVideoRemoved()">
       </my-video-miniature>
 
       <hr *ngIf="!playlist && i == 0 && length > 1" />
index 0caa927828ccccea62d7b0b48b8381c09da139f5..de677a77b18ccde9d87470ab02495d1da8262128 100644 (file)
@@ -39,14 +39,14 @@ export class BlocklistService {
                )
   }
 
-  blockAccountByUser (account: Account) {
+  blockAccountByUser (account: Pick<Account, 'nameWithHost'>) {
     const body = { accountName: account.nameWithHost }
 
     return this.authHttp.post(BlocklistService.BASE_USER_BLOCKLIST_URL + '/accounts', body)
                .pipe(catchError(err => this.restExtractor.handleError(err)))
   }
 
-  unblockAccountByUser (account: Account) {
+  unblockAccountByUser (account: Pick<Account, 'nameWithHost'>) {
     const path = BlocklistService.BASE_USER_BLOCKLIST_URL + '/accounts/' + account.nameWithHost
 
     return this.authHttp.delete(path)
@@ -102,14 +102,14 @@ export class BlocklistService {
                )
   }
 
-  blockAccountByInstance (account: Account) {
+  blockAccountByInstance (account: Pick<Account, 'nameWithHost'>) {
     const body = { accountName: account.nameWithHost }
 
     return this.authHttp.post(BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/accounts', body)
                .pipe(catchError(err => this.restExtractor.handleError(err)))
   }
 
-  unblockAccountByInstance (account: Account) {
+  unblockAccountByInstance (account: Pick<Account, 'nameWithHost'>) {
     const path = BlocklistService.BASE_SERVER_BLOCKLIST_URL + '/accounts/' + account.nameWithHost
 
     return this.authHttp.delete(path)
index 1e919ee720be64816dfb30845bbe0c2a8491ddf0..9df0b56521f991e3dbc0f95e89bd51e5622baf47 100644 (file)
@@ -41,6 +41,7 @@
           [video]="video" [user]="userMiniature" [ownerDisplayType]="ownerDisplayType"
           [displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
           (videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
+          (videoAccountMuted)="reloadVideos()"
         >
         </my-video-miniature>
       </div>
index db8d1c309e79fd0b03df11688d98e5faeed338d0..9bd0741dfbcc4eda6463858c76eb6d70f151f5e7 100644 (file)
@@ -1,10 +1,10 @@
 import { Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core'
 import { AuthService, ConfirmService, Notifier, ScreenService } from '@app/core'
-import { VideoBlockComponent, VideoBlockService, VideoReportComponent } from '@app/shared/shared-moderation'
+import { VideoBlockComponent, VideoBlockService, VideoReportComponent, BlocklistService } from '@app/shared/shared-moderation'
 import { NgbDropdown } from '@ng-bootstrap/ng-bootstrap'
 import { I18n } from '@ngx-translate/i18n-polyfill'
 import { VideoCaption } from '@shared/models'
-import { DropdownAction, DropdownButtonSize, DropdownDirection, RedundancyService, Video, VideoDetails, VideoService } from '../shared-main'
+import { DropdownAction, DropdownButtonSize, DropdownDirection, RedundancyService, Video, VideoDetails, VideoService, Actor } from '../shared-main'
 import { VideoAddToPlaylistComponent } from '../shared-video-playlist'
 import { VideoDownloadComponent } from './video-download.component'
 
@@ -16,6 +16,7 @@ export type VideoActionsDisplayType = {
   delete?: boolean
   report?: boolean
   duplicate?: boolean
+  mute?: boolean
 }
 
 @Component({
@@ -41,7 +42,8 @@ export class VideoActionsDropdownComponent implements OnChanges {
     blacklist: true,
     delete: true,
     report: true,
-    duplicate: true
+    duplicate: true,
+    mute: true
   }
   @Input() placement = 'left'
 
@@ -54,6 +56,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
   @Output() videoRemoved = new EventEmitter()
   @Output() videoUnblocked = new EventEmitter()
   @Output() videoBlocked = new EventEmitter()
+  @Output() videoAccountMuted = new EventEmitter()
   @Output() modalOpened = new EventEmitter()
 
   videoActions: DropdownAction<{ video: Video }>[][] = []
@@ -64,6 +67,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
     private authService: AuthService,
     private notifier: Notifier,
     private confirmService: ConfirmService,
+    private blocklistService: BlocklistService,
     private videoBlocklistService: VideoBlockService,
     private screenService: ScreenService,
     private videoService: VideoService,
@@ -142,6 +146,10 @@ export class VideoActionsDropdownComponent implements OnChanges {
     return this.video.canBeDuplicatedBy(this.user)
   }
 
+  isVideoAccountMutable () {
+    return this.video.account.id !== this.user.account.id
+  }
+
   /* Action handlers */
 
   async unblockVideo () {
@@ -152,18 +160,19 @@ export class VideoActionsDropdownComponent implements OnChanges {
     const res = await this.confirmService.confirm(confirmMessage, this.i18n('Unblock'))
     if (res === false) return
 
-    this.videoBlocklistService.unblockVideo(this.video.id).subscribe(
-      () => {
-        this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: this.video.name }))
+    this.videoBlocklistService.unblockVideo(this.video.id)
+        .subscribe(
+          () => {
+            this.notifier.success(this.i18n('Video {{name}} unblocked.', { name: this.video.name }))
 
-        this.video.blacklisted = false
-        this.video.blockedReason = null
+            this.video.blacklisted = false
+            this.video.blockedReason = null
 
-        this.videoUnblocked.emit()
-      },
+            this.videoUnblocked.emit()
+          },
 
-      err => this.notifier.error(err.message)
-    )
+          err => this.notifier.error(err.message)
+        )
   }
 
   async removeVideo () {
@@ -186,14 +195,29 @@ export class VideoActionsDropdownComponent implements OnChanges {
 
   duplicateVideo () {
     this.redundancyService.addVideoRedundancy(this.video)
-      .subscribe(
-        () => {
-          const message = this.i18n('This video will be duplicated by your instance.')
-          this.notifier.success(message)
-        },
+        .subscribe(
+          () => {
+            const message = this.i18n('This video will be duplicated by your instance.')
+            this.notifier.success(message)
+          },
 
-        err => this.notifier.error(err.message)
-      )
+          err => this.notifier.error(err.message)
+        )
+  }
+
+  muteVideoAccount () {
+    const params = { nameWithHost: Actor.CREATE_BY_STRING(this.video.account.name, this.video.account.host) }
+
+    this.blocklistService.blockAccountByUser(params)
+        .subscribe(
+          () => {
+            this.notifier.success(this.i18n('Account {{nameWithHost}} muted.', params))
+
+            this.videoAccountMuted.emit()
+          },
+
+          err => this.notifier.error(err.message)
+        )
   }
 
   onVideoBlocked () {
@@ -218,7 +242,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
           iconName: 'playlist-add'
         }
       ],
-      [
+      [ // actions regarding the video
         {
           label: this.i18n('Download'),
           handler: () => this.showDownloadModal(),
@@ -254,15 +278,21 @@ export class VideoActionsDropdownComponent implements OnChanges {
           handler: () => this.removeVideo(),
           isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.delete && this.isVideoRemovable(),
           iconName: 'delete'
-        }
-      ],
-      [
+        },
         {
           label: this.i18n('Report'),
           handler: () => this.showReportModal(),
           isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.report,
           iconName: 'alert'
         }
+      ],
+      [ // actions regarding the account/its server
+        {
+          label: this.i18n('Mute account'),
+          handler: () => this.muteVideoAccount(),
+          isDisplayed: () => this.authService.isLoggedIn() && this.displayOptions.mute && this.isVideoAccountMutable(),
+          iconName: 'no'
+        }
       ]
     ]
   }
index 82afc866f7c16bee802425e95f69dcab91c8018e..e5d91e69a26e62b616e399ac4dc5f10621e49cd8 100644 (file)
@@ -59,7 +59,7 @@
       <!-- FIXME: remove bottom placement when overflow is fixed in bootstrap dropdown: https://github.com/ng-bootstrap/ng-bootstrap/issues/3495 -->
       <my-video-actions-dropdown
         *ngIf="showActions" [video]="video" [displayOptions]="videoActionsDisplayOptions" placement="bottom-left bottom-right left auto"
-        (videoRemoved)="onVideoRemoved()" (videoBlocked)="onVideoBlocked()" (videoUnblocked)="onVideoUnblocked()"
+        (videoRemoved)="onVideoRemoved()" (videoBlocked)="onVideoBlocked()" (videoUnblocked)="onVideoUnblocked()" (videoAccountMuted)="onVideoAccountMuted()"
       ></my-video-actions-dropdown>
     </div>
   </div>
index 6f32977b347957cf48d500c422cac08d5ec5ebfb..e1adbb6adbb9ae14cb4859262ff90d44c19eec27 100644 (file)
@@ -60,6 +60,7 @@ export class VideoMiniatureComponent implements OnInit {
   @Output() videoBlocked = new EventEmitter()
   @Output() videoUnblocked = new EventEmitter()
   @Output() videoRemoved = new EventEmitter()
+  @Output() videoAccountMuted = new EventEmitter()
 
   videoActionsDisplayOptions: VideoActionsDisplayType = {
     playlist: true,
@@ -68,7 +69,8 @@ export class VideoMiniatureComponent implements OnInit {
     blacklist: true,
     delete: true,
     report: true,
-    duplicate: true
+    duplicate: true,
+    mute: true
   }
   showActions = false
   serverConfig: ServerConfig
@@ -206,6 +208,10 @@ export class VideoMiniatureComponent implements OnInit {
     this.videoRemoved.emit()
   }
 
+  onVideoAccountMuted () {
+    this.videoAccountMuted.emit()
+  }
+
   isUserLoggedIn () {
     return this.authService.isLoggedIn()
   }
index c465eb3e706585533c4bf5742f1b0610e4b52311..90625d987a9f6436ecf125f3360ee9a8fe544a1b 100644 (file)
@@ -444,11 +444,11 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
     }
     const accountWhere = accountId
       ? {
-          [Op.and]: {
-            ...accountExclusion,
-            [Op.eq]: accountId
-          }
+        [Op.and]: {
+          ...accountExclusion,
+          [Op.eq]: accountId
         }
+      }
       : accountExclusion
 
     const videoChannelWhere = videoChannelId ? { id: videoChannelId } : undefined