diff --git a/client/src/app/shared/shared-icons/global-icon.component.ts b/client/src/app/shared/shared-icons/global-icon.component.ts
index 3235c9fac..8ac0d02f0 100644
--- a/client/src/app/shared/shared-icons/global-icon.component.ts
+++ b/client/src/app/shared/shared-icons/global-icon.component.ts
@@ -77,7 +77,8 @@ const icons = {
'message-circle': require('!!raw-loader?!../../../assets/images/feather/message-circle.svg').default,
'codesandbox': require('!!raw-loader?!../../../assets/images/feather/codesandbox.svg').default,
'award': require('!!raw-loader?!../../../assets/images/feather/award.svg').default,
- 'stats': require('!!raw-loader?!../../../assets/images/feather/stats.svg').default
+ 'stats': require('!!raw-loader?!../../../assets/images/feather/stats.svg').default,
+ 'shield': require('!!raw-loader?!../../../assets/images/misc/shield.svg').default
}
export type GlobalIconName = keyof typeof icons
diff --git a/client/src/app/shared/shared-main/buttons/action-dropdown.component.html b/client/src/app/shared/shared-main/buttons/action-dropdown.component.html
index d4aa9f380..f2ea57e61 100644
--- a/client/src/app/shared/shared-main/buttons/action-dropdown.component.html
+++ b/client/src/app/shared/shared-main/buttons/action-dropdown.component.html
@@ -19,7 +19,16 @@
- {{ action.label }}
+
+ {{ action.label }}
+
+
+
+
{{ action.description }}
diff --git a/client/src/app/shared/shared-main/buttons/action-dropdown.component.scss b/client/src/app/shared/shared-main/buttons/action-dropdown.component.scss
index 8e5bb266f..05777a7db 100644
--- a/client/src/app/shared/shared-main/buttons/action-dropdown.component.scss
+++ b/client/src/app/shared/shared-main/buttons/action-dropdown.component.scss
@@ -82,3 +82,11 @@
@include ellipsis;
}
}
+
+.owner-moderator-privilege {
+ margin: 0 !important;
+
+ @include margin-left(1rem !important);
+
+ width: 13px !important;
+}
diff --git a/client/src/app/shared/shared-main/buttons/action-dropdown.component.ts b/client/src/app/shared/shared-main/buttons/action-dropdown.component.ts
index 3e5e8a5fe..ff707c43d 100644
--- a/client/src/app/shared/shared-main/buttons/action-dropdown.component.ts
+++ b/client/src/app/shared/shared-main/buttons/action-dropdown.component.ts
@@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, Input } from '@angular/core'
import { Params, RouterLink } from '@angular/router'
import { GlobalIconName } from '@app/shared/shared-icons/global-icon.component'
import { GlobalIconComponent } from '../../shared-icons/global-icon.component'
-import { NgbDropdown, NgbDropdownToggle, NgbDropdownMenu } from '@ng-bootstrap/ng-bootstrap'
+import { NgbDropdown, NgbDropdownToggle, NgbDropdownMenu, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { NgIf, NgClass, NgFor, NgTemplateOutlet } from '@angular/common'
export type DropdownAction = {
@@ -19,6 +19,8 @@ export type DropdownAction = {
class?: string[]
isHeader?: boolean
+
+ ownerOrModeratorPrivilege?: () => string
}
export type DropdownButtonSize = 'normal' | 'small'
@@ -31,7 +33,18 @@ export type DropdownDirection = 'horizontal' | 'vertical'
templateUrl: './action-dropdown.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
- imports: [ NgIf, NgbDropdown, NgbDropdownToggle, NgClass, GlobalIconComponent, NgbDropdownMenu, NgFor, RouterLink, NgTemplateOutlet ]
+ imports: [
+ NgIf,
+ NgbTooltip,
+ NgbDropdown,
+ NgbDropdownToggle,
+ NgClass,
+ GlobalIconComponent,
+ NgbDropdownMenu,
+ NgFor,
+ RouterLink,
+ NgTemplateOutlet
+ ]
})
export class ActionDropdownComponent {
diff --git a/client/src/app/shared/shared-main/video/video.model.ts b/client/src/app/shared/shared-main/video/video.model.ts
index 730f51f8e..0a5b9c361 100644
--- a/client/src/app/shared/shared-main/video/video.model.ts
+++ b/client/src/app/shared/shared-main/video/video.model.ts
@@ -236,8 +236,18 @@ export class Video implements VideoServerModel {
this.isUpdatableBy(user)
}
+ // ---------------------------------------------------------------------------
+
+ isOwner (user: AuthUser) {
+ return user && this.isLocal === true && this.account.name === user.username
+ }
+
+ hasSeeAllVideosRight (user: AuthUser) {
+ return user && user.hasRight(UserRight.SEE_ALL_VIDEOS)
+ }
+
isOwnerOrHasSeeAllVideosRight (user: AuthUser) {
- return user && this.isLocal === true && (this.account.name === user.username || user.hasRight(UserRight.SEE_ALL_VIDEOS))
+ return this.isOwner(user) || this.hasSeeAllVideosRight(user)
}
canRemoveOneFile (user: AuthUser) {
diff --git a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts
index 89b2ead45..1a0372c5d 100644
--- a/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts
+++ b/client/src/app/shared/shared-video-miniature/video-actions-dropdown.component.ts
@@ -205,9 +205,7 @@ export class VideoActionsDropdownComponent implements OnChanges {
return this.video.isLiveInfoAvailableBy(this.user)
}
- isVideoDownloadable () {
- if (this.video.isOwnerOrHasSeeAllVideosRight(this.user)) return true
-
+ isVideoDownloadableByAnonymous () {
return (
this.video &&
this.video.isLive !== true &&
@@ -373,8 +371,17 @@ export class VideoActionsDropdownComponent implements OnChanges {
{
label: $localize`Download`,
handler: () => this.showDownloadModal(),
- isDisplayed: () => this.displayOptions.download && this.isVideoDownloadable(),
- iconName: 'download'
+ isDisplayed: () => {
+ if (!this.displayOptions.download) return false
+
+ return this.isVideoDownloadableByAnonymous() || this.video.isOwnerOrHasSeeAllVideosRight(this.user)
+ },
+ iconName: 'download',
+ ownerOrModeratorPrivilege: () => {
+ if (this.isVideoDownloadableByAnonymous()) return undefined
+
+ return $localize`This option is visible only to you`
+ }
},
{
label: $localize`Display live information`,
diff --git a/client/src/assets/images/misc/shield.svg b/client/src/assets/images/misc/shield.svg
new file mode 100644
index 000000000..b6ef58229
--- /dev/null
+++ b/client/src/assets/images/misc/shield.svg
@@ -0,0 +1,6 @@
+