1
0
Fork 0
-----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCAAdFiEExEqtY4NnkSypPt1XWDphLYkBWb4FAmdhNIQACgkQWDphLYkB
 Wb7/awgAu5KYKgoLw8+uPs5oVxXjpMk/3W3PIX+zmoUK4Z/EftPvDyzGkH1j7vKV
 ODUcbq/N/GNQmreKqXGITPAguuMUgZaeKAYkGzaJCLXO+vqc1WS/NcEV4L+PswVa
 Uz9j4YlI5fb4ydbHQyW654+VSKo//sePvHuCizLhs5wBUJvxjO0X5COAkQLQMYln
 RJdDzrgiFKi/qcL2mvw+yl8a1iXUDqNB2Ka4SKYMXh3XSBqBkZrjoQ5HMPGA4pqY
 Nqdv4OINBgTvn91tTi80/pZkD6ylpFj1BdsfYOPDP/b+AGiUuzPGYDCka5nDwJlS
 wyRG7roIzn/GRfRJUxMHgeiuQaN4cA==
 =34oR
 -----END PGP SIGNATURE-----
gpgsig -----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCAA1FiEEGCBYi9NGimfngx9dVTwOu+tdXwgFAmeSyfcXHGdpdEBrb3Rv
 dmFsZXhhcmlhbi5jb20ACgkQVTwOu+tdXwh0FQ/+Ks10+qDIufNBpskvhM8+oGq2
 fs9fryduoOwM3uM/JNKPWdT4hH3Iyu13YW0nELlZvsTdW0RD+onTD/hd3iZoib80
 XY3WJZqsQMXxSSHk9M7JoSPaZXWVGF9yWZWMVIKLaJGpmmuIfkFOgkxp4DB9fdPA
 Jw+TvTDhNVVx7OqKSI1G1WtWSAo0R8+NlhnMLr+kVdcK1R0CF9CXKafaZk83/kdr
 QrlS4V3xuqp8qoUiiD9/Vc+wcviCC38TumAozDE1V7/7GiUGNFrYUURhpXvfYGwp
 62v+J3kKmzi0KOJiPS6RKBiuC/fW1ytsjIqGrouNzwzu+G2bSgJFYogPro2wdJtY
 gMez9/n1bj5geiRdCmA93evL4964pWfw7J//EJxavSthvWywekWKGZK5tP2iZrgt
 12evAFzsOAN77SiBcXlNlFQwpRZ1nGe3yHSMukfm9qN3CJZnAIoMH7fNmwS18rVE
 4fWR5gcqyGy2b7hE80WT7oYxvQuzltNarGHVylBuxnAL3LfIPadZU7cJzQnMUYJg
 v2tJGf3G9CpdygQoYuJVB34fJw5ZYOlkByhbaiDGaBGxBdSetZoiZJB5Y1UpkLgd
 VbTShzYF5GHn04gi+G+gYuUxYmSw7ViZYKmDlb/6eUkstYRREdtobNKe/ivuWVu4
 QLwm9zVn5V2TKtGMbHg=
 =M0WB
 -----END PGP SIGNATURE-----

Merge tag 'v7.0.0' into changes

v7.0.0
This commit is contained in:
Alex Kotov 2025-01-24 03:00:06 +04:00
commit 3e5910a744
197 changed files with 97738 additions and 60934 deletions

View file

@ -1,6 +1,6 @@
# Changelog
## v7.0.0-rc.1
## v7.0.0
### IMPORTANT NOTES
@ -25,6 +25,7 @@
### Admin config (non-exhaustive)
* Ensure `instance.default_client_route` (in web admin -> `Configuration` -> `Basic` -> `Landing page`) has a correct path: `/videos/trending`, `/videos/local` and `/videos/recently-added` have been removed in favour of `/videos/browse`
* Add ability to configure STUN servers IPs: `webrtc.stun_servers`
* Remove `client.videos.miniature.display_author_avatar` config: author avatars are now always displayed
@ -56,6 +57,7 @@
* Add "skip menu" links
* Improve keyboard navigation
* Fix various screen readers issues
* Add Slovakian language support to the client
* SEO:
* Add instance avatar to OpenGraph tags
* Hide empty accounts/channels from sitemap [#6633](https://github.com/Chocobozzz/PeerTube/pull/6633)
@ -64,6 +66,7 @@
* Improve player control bar responsive
* Add refresh button to following list
* Clearer signup limit label
* Add `0.25` playback rate in player
### Bug fixes
@ -76,6 +79,10 @@
* Fix auto blacklisting unlisted videos
* Fix *ERR_BUFFER_OUT_OF_BOUNDS* error on some node version
* Add ability to set max channel sync in admin config
* Allow plugins to pass client params when listing videos (`filter:api.browse-videos.videos.list.params` hook)
* Respect user export expiration admin configuration
* Fix studio edition on an audio only file
* Fix embed crash on telegram web browser
## v6.3.3

View file

@ -17,6 +17,10 @@
"translation": "src/locale/angular.ar.xlf",
"baseHref": "/client/ar/"
},
"sk": {
"translation": "src/locale/angular.sk-SK.xlf",
"baseHref": "/client/sk-SK/"
},
"fa": {
"translation": "src/locale/angular.fa-IR.xlf",
"baseHref": "/client/fa-IR/"

View file

@ -211,7 +211,7 @@ export class VideoWatchPage {
async createReply (comment: string) {
const replyButton = await $('button.comment-action-reply')
await replyButton.waitForClickable()
await replyButton.scrollIntoView()
await replyButton.scrollIntoView({ block: 'center' })
await replyButton.click()
const textarea = await $('my-video-comment my-video-comment-add textarea')
@ -220,11 +220,12 @@ export class VideoWatchPage {
const confirmButton = await $('my-video-comment .comment-buttons .primary-button')
await confirmButton.waitForClickable()
await replyButton.scrollIntoView({ block: 'center' })
await confirmButton.click()
const createdComment = await $('.is-child .comment-html p')
await createdComment.waitForDisplayed()
return expect(await createdComment.getTagName()).toBe(comment)
return expect(await createdComment.getText()).toBe(comment)
}
}

View file

@ -1,6 +1,6 @@
{
"name": "peertube-client",
"version": "7.0.0-rc.1",
"version": "7.0.0",
"private": true,
"license": "AGPL-3.0",
"author": {
@ -18,8 +18,6 @@
"lint-scss": "stylelint 'src/**/*.scss'",
"eslint": "eslint",
"ng": "ng",
"webdriver-manager": "webdriver-manager",
"ngx-extractor": "ngx-extractor",
"stylelint": "stylelint"
},
"browser": {

View file

@ -32,6 +32,7 @@ my-global-icon {
left: 16px;
top: -24px;
width: 110px;
height: 110px;
&.icon-bottom {
top: 4px;

View file

@ -10,7 +10,7 @@
<div class="actor-info">
<div>
<div class="actor-display-name align-items-center">
<h1 i18n-title [title]="'Created on ' + (account.createdAt | date)">{{ account.displayName }}</h1>
<h1 i18n-title [title]="'Created on ' + (account.createdAt | ptDate)">{{ account.displayName }}</h1>
<my-user-moderation-dropdown
class="mx-3" [prependActions]="prependModerationActions"

View file

@ -1,4 +1,4 @@
import { DatePipe, NgClass, NgIf } from '@angular/common'
import { 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, MetaService, Notifier, RedirectService, RestExtractor, ScreenService, UserService } from '@app/core'
@ -7,6 +7,7 @@ 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/channel/video-channel.model'
import { VideoChannelService } from '@app/shared/shared-main/channel/video-channel.service'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { HorizontalMenuComponent, HorizontalMenuEntry } from '@app/shared/shared-main/menu/horizontal-menu.component'
import { VideoService } from '@app/shared/shared-main/video/video.service'
import { BlocklistService } from '@app/shared/shared-moderation/blocklist.service'
@ -41,7 +42,7 @@ import { SubscribeButtonComponent } from '../shared/shared-user-subscription/sub
SimpleSearchInputComponent,
RouterOutlet,
AccountReportComponent,
DatePipe,
PTDatePipe,
HorizontalMenuComponent
]
})

View file

@ -390,7 +390,7 @@
i18n-labelText labelText="Enable video transcription"
>
<ng-container ngProjectAs="description">
<span i18n>Automatically create a subtitle file of uploaded/imported VOD videos</span>
<span i18n><a href="https://docs.joinpeertube.org/admin/configuration#automatic-transcription" target="_blank">Automatically create subtitles</a> for uploaded/imported VOD videos</span>
</ng-container>
<ng-container ngProjectAs="extra">

View file

@ -56,6 +56,7 @@ input[type=checkbox] {
@include peertube-select-container($form-base-input-width);
}
my-select-checkbox,
my-select-options,
my-select-custom-value {
display: block;

View file

@ -482,7 +482,7 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
]).subscribe({
next: ([ languages, categories ]) => {
this.languageItems = languages.map(l => ({ label: l.label, id: l.id }))
this.categoryItems = categories.map(l => ({ label: l.label, id: l.id + '' }))
this.categoryItems = categories.map(l => ({ label: l.label, id: l.id }))
},
error: err => this.notifier.error(err.message)

View file

@ -60,7 +60,7 @@
</td>
<td>{{ follow.score }}</td>
<td>{{ follow.createdAt | date: 'short' }}</td>
<td>{{ follow.createdAt | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -1,18 +1,19 @@
import { SortMeta, SharedModule } from 'primeng/api'
import { NgIf } from '@angular/common'
import { Component, OnInit } from '@angular/core'
import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
import { formatICU } from '@app/helpers'
import { ActorFollow } from '@peertube/peertube-models'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { DeleteButtonComponent } from '../../../shared/shared-main/buttons/delete-button.component'
import { ButtonComponent } from '../../../shared/shared-main/buttons/button.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
import { NgIf, DatePipe } from '@angular/common'
import { TableModule } from 'primeng/table'
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
import { InstanceFollowService } from '@app/shared/shared-instance/instance-follow.service'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { ActorFollow } from '@peertube/peertube-models'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
import { ButtonComponent } from '../../../shared/shared-main/buttons/button.component'
import { DeleteButtonComponent } from '../../../shared/shared-main/buttons/delete-button.component'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
@Component({
selector: 'my-followers-list',
@ -30,7 +31,7 @@ import { InstanceFollowService } from '@app/shared/shared-instance/instance-foll
ButtonComponent,
DeleteButtonComponent,
AutoColspanDirective,
DatePipe
PTDatePipe
]
})
export class FollowersListComponent extends RestTable <ActorFollow> implements OnInit {

View file

@ -63,7 +63,7 @@
<span *ngIf="follow.state === 'rejected'" class="pt-badge badge-red" i18n>Rejected</span>
</td>
<td>{{ follow.createdAt | date: 'short' }}</td>
<td>{{ follow.createdAt | ptDate: 'short' }}</td>
<td>
<my-redundancy-checkbox
*ngIf="isInstanceFollowing(follow)"

View file

@ -1,8 +1,9 @@
import { DatePipe, NgIf } from '@angular/common'
import { NgIf } from '@angular/common'
import { Component, OnInit, ViewChild } from '@angular/core'
import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
import { formatICU } from '@app/helpers'
import { InstanceFollowService } from '@app/shared/shared-instance/instance-follow.service'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { ActorFollow } from '@peertube/peertube-models'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
@ -30,7 +31,7 @@ import { FollowModalComponent } from './follow-modal.component'
RedundancyCheckboxComponent,
AutoColspanDirective,
FollowModalComponent,
DatePipe,
PTDatePipe,
ButtonComponent
]
})

View file

@ -5,12 +5,12 @@
<div>
<span class="label">Created on</span>
<span>{{ redundancyElement.createdAt | date: 'medium' }}</span>
<span>{{ redundancyElement.createdAt | ptDate: 'medium' }}</span>
</div>
<div>
<span class="label">Expires on</span>
<span>{{ redundancyElement.expiresOn | date: 'medium' }}</span>
<span>{{ redundancyElement.expiresOn | ptDate: 'medium' }}</span>
</div>
<div>

View file

@ -1,14 +1,14 @@
import { Component, Input } from '@angular/core'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { FileRedundancyInformation, StreamingPlaylistRedundancyInformation } from '@peertube/peertube-models'
import { BytesPipe } from '../../../shared/shared-main/common/bytes.pipe'
import { DatePipe } from '@angular/common'
@Component({
selector: 'my-video-redundancy-information',
templateUrl: './video-redundancy-information.component.html',
styleUrls: [ './video-redundancy-information.component.scss' ],
standalone: true,
imports: [ DatePipe, BytesPipe ]
imports: [ PTDatePipe, BytesPipe ]
})
export class VideoRedundancyInformationComponent {
@Input() redundancyElement: FileRedundancyInformation | StreamingPlaylistRedundancyInformation

View file

@ -1,14 +1,14 @@
import { NgIf } from '@angular/common'
import { Component } from '@angular/core'
import { NgIf, DatePipe } from '@angular/common'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { ActorAvatarComponent } from '../../../shared/shared-actor-image/actor-avatar.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { SharedModule } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { GenericAccountBlocklistComponent } from '@app/shared/shared-moderation/account-blocklist.component'
import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.service'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { SharedModule } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { ActorAvatarComponent } from '../../../shared/shared-actor-image/actor-avatar.component'
import { AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
@Component({
selector: 'my-instance-account-blocklist',
@ -16,7 +16,6 @@ import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.
templateUrl: '../../../shared/shared-moderation/account-blocklist.component.html',
standalone: true,
imports: [
GlobalIconComponent,
TableModule,
SharedModule,
AdvancedInputFilterComponent,
@ -24,7 +23,7 @@ import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.
ActorAvatarComponent,
AutoColspanDirective,
NgIf,
DatePipe
PTDatePipe
]
})
export class InstanceAccountBlocklistComponent extends GenericAccountBlocklistComponent {

View file

@ -1,14 +1,15 @@
import { NgIf } from '@angular/common'
import { Component } from '@angular/core'
import { BatchDomainsModalComponent } from '../../../shared/shared-moderation/batch-domains-modal.component'
import { NgIf, DatePipe } from '@angular/common'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.service'
import { GenericServerBlocklistComponent } from '@app/shared/shared-moderation/server-blocklist.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { SharedModule } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
import { GenericServerBlocklistComponent } from '@app/shared/shared-moderation/server-blocklist.component'
import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.service'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { BatchDomainsModalComponent } from '../../../shared/shared-moderation/batch-domains-modal.component'
@Component({
selector: 'my-instance-server-blocklist',
@ -24,7 +25,7 @@ import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.
AutoColspanDirective,
NgIf,
BatchDomainsModalComponent,
DatePipe
PTDatePipe
]
})
export class InstanceServerBlocklistComponent extends GenericServerBlocklistComponent {

View file

@ -100,7 +100,7 @@
{{ registration.moderationResponse }}
</td>
<td class="c-hand" [pRowToggler]="registration">{{ registration.createdAt | date: 'short' }}</td>
<td class="c-hand" [pRowToggler]="registration">{{ registration.createdAt | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -1,20 +1,21 @@
import { SortMeta, SharedModule } from 'primeng/api'
import { NgClass, NgIf } from '@angular/common'
import { Component, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
import { formatICU } from '@app/helpers'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { UserRegistration, UserRegistrationState } from '@peertube/peertube-models'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
import { UserEmailInfoComponent } from '../../shared/user-email-info.component'
import { AdminRegistrationService } from './admin-registration.service'
import { ProcessRegistrationModalComponent } from './process-registration-modal.component'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { UserEmailInfoComponent } from '../../shared/user-email-info.component'
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
import { NgIf, NgClass, DatePipe } from '@angular/common'
import { TableModule } from 'primeng/table'
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
@Component({
selector: 'my-registration-list',
@ -34,7 +35,7 @@ import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.co
UserEmailInfoComponent,
AutoColspanDirective,
ProcessRegistrationModalComponent,
DatePipe
PTDatePipe
]
})
export class RegistrationListComponent extends RestTable <UserRegistration> implements OnInit {

View file

@ -62,7 +62,7 @@
</td>
<td>
{{ videoBlock.createdAt | date: 'short' }}
{{ videoBlock.createdAt | ptDate: 'short' }}
</td>
</tr>
</ng-template>

View file

@ -1,24 +1,25 @@
import { SortMeta, SharedModule } from 'primeng/api'
import { switchMap } from 'rxjs/operators'
import { environment } from 'src/environments/environment'
import { NgClass, NgIf } from '@angular/common'
import { Component, OnInit } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { VideoService } from '@app/shared/shared-main/video/video.service'
import { VideoBlockService } from '@app/shared/shared-moderation/video-block.service'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { buildVideoEmbedLink, decorateVideoLink } from '@peertube/peertube-core-utils'
import { VideoBlacklist, VideoBlacklistType, VideoBlacklistType_Type } from '@peertube/peertube-models'
import { buildVideoOrPlaylistEmbed } from '@root-helpers/video'
import { EmbedComponent } from '../../../shared/shared-main/video/embed.component'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { VideoCellComponent } from '../../../shared/shared-tables/video-cell.component'
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
import { NgIf, NgClass, DatePipe } from '@angular/common'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { switchMap } from 'rxjs/operators'
import { environment } from 'src/environments/environment'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
import { VideoService } from '@app/shared/shared-main/video/video.service'
import { VideoBlockService } from '@app/shared/shared-moderation/video-block.service'
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { EmbedComponent } from '../../../shared/shared-main/video/embed.component'
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
import { VideoCellComponent } from '../../../shared/shared-tables/video-cell.component'
@Component({
selector: 'my-video-block-list',
@ -38,7 +39,7 @@ import { VideoBlockService } from '@app/shared/shared-moderation/video-block.ser
VideoCellComponent,
AutoColspanDirective,
EmbedComponent,
DatePipe
PTDatePipe
]
})
export class VideoBlockListComponent extends RestTable implements OnInit {

View file

@ -6,7 +6,7 @@
formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
autocomplete="new-password"
>
<button class="btn btn-outline-secondary" (click)="togglePasswordVisibility()" type="button">
<button class="btn" (click)="togglePasswordVisibility()" type="button">
@if (showPassword) {
<ng-container i18n>Hide</ng-container>
} @else {

View file

@ -142,9 +142,9 @@
<span *ngIf="user.pluginAuth" [ngbTooltip]="user.pluginAuth">{{ user.pluginAuth }}</span>
</td>
<td *ngIf="isSelected('createdAt')" [title]="user.createdAt">{{ user.createdAt | date: 'short' }}</td>
<td *ngIf="isSelected('createdAt')" [title]="user.createdAt">{{ user.createdAt | ptDate: 'short' }}</td>
<td *ngIf="isSelected('lastLoginDate')" [title]="user.lastLoginDate">{{ user.lastLoginDate | date: 'short' }}</td>
<td *ngIf="isSelected('lastLoginDate')" [title]="user.lastLoginDate">{{ user.lastLoginDate | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -1,14 +1,16 @@
import { DatePipe, NgClass, NgIf } from '@angular/common'
import { NgClass, 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, ConfirmService, LocalStorageService, Notifier, RestPagination, RestTable } from '@app/core'
import { formatICU, getAPIHost } from '@app/helpers'
import { Actor } from '@app/shared/shared-main/account/actor.model'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { ProgressBarComponent } from '@app/shared/shared-main/common/progress-bar.component'
import { BlocklistService } from '@app/shared/shared-moderation/blocklist.service'
import { UserBanModalComponent } from '@app/shared/shared-moderation/user-ban-modal.component'
import { UserAdminService } from '@app/shared/shared-users/user-admin.service'
import { NgbDropdown, NgbDropdownItem, NgbDropdownMenu, NgbDropdownToggle, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { NgbDropdown, NgbDropdownMenu, NgbDropdownToggle, NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { User, UserRole, UserRoleType } from '@peertube/peertube-models'
import { logger } from '@root-helpers/logger'
import { SharedModule, SortMeta } from 'primeng/api'
@ -18,9 +20,9 @@ import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../../s
import { PeertubeCheckboxComponent } from '../../../../shared/shared-forms/peertube-checkbox.component'
import { SelectCheckboxComponent } from '../../../../shared/shared-forms/select/select-checkbox.component'
import { GlobalIconComponent } from '../../../../shared/shared-icons/global-icon.component'
import { ActionDropdownComponent, DropdownAction } from '../../../../shared/shared-main/buttons/action-dropdown.component'
import { AutoColspanDirective } from '../../../../shared/shared-main/common/auto-colspan.directive'
import { BytesPipe } from '../../../../shared/shared-main/common/bytes.pipe'
import { ActionDropdownComponent, DropdownAction } from '../../../../shared/shared-main/buttons/action-dropdown.component'
import {
AccountMutedStatus,
UserModerationDisplayType,
@ -28,7 +30,6 @@ import {
} from '../../../../shared/shared-moderation/user-moderation-dropdown.component'
import { TableExpanderIconComponent } from '../../../../shared/shared-tables/table-expander-icon.component'
import { UserEmailInfoComponent } from '../../../shared/user-email-info.component'
import { ProgressBarComponent } from '@app/shared/shared-main/common/progress-bar.component'
type UserForList = User & {
rawVideoQuota: number
@ -53,7 +54,6 @@ type UserForList = User & {
NgbDropdown,
NgbDropdownToggle,
NgbDropdownMenu,
NgbDropdownItem,
SelectCheckboxComponent,
FormsModule,
PeertubeCheckboxComponent,
@ -65,7 +65,7 @@ type UserForList = User & {
UserEmailInfoComponent,
AutoColspanDirective,
UserBanModalComponent,
DatePipe,
PTDatePipe,
BytesPipe,
ProgressBarComponent
]

View file

@ -1,13 +1,13 @@
import { Observable } from 'rxjs'
import { catchError, switchMap } from 'rxjs/operators'
import { HttpClient, HttpParams } from '@angular/common/http'
import { Injectable } from '@angular/core'
import { RestExtractor, RestPagination, RestService } from '@app/core'
import { ResultList, VideoInclude, VideoPrivacy } from '@peertube/peertube-models'
import { getAllPrivacies } from '@peertube/peertube-core-utils'
import { VideoService, CommonVideoParams } from '@app/shared/shared-main/video/video.service'
import { Video } from '@app/shared/shared-main/video/video.model'
import { AdvancedInputFilter } from '@app/shared/shared-forms/advanced-input-filter.component'
import { Video } from '@app/shared/shared-main/video/video.model'
import { CommonVideoParams, VideoService } from '@app/shared/shared-main/video/video.service'
import { getAllPrivacies, omit } from '@peertube/peertube-core-utils'
import { ResultList, VideoInclude, VideoPrivacy } from '@peertube/peertube-models'
import { Observable } from 'rxjs'
import { catchError, switchMap } from 'rxjs/operators'
@Injectable()
export class VideoAdminService {
@ -25,7 +25,7 @@ export class VideoAdminService {
const { pagination, search } = options
let params = new HttpParams()
params = this.videoService.buildCommonVideosParams({ params, ...options })
params = this.videoService.buildCommonVideosParams({ params, ...omit(options, [ 'search', 'pagination' ]) })
params = params.set('start', pagination.start.toString())
.set('count', pagination.count.toString())

View file

@ -106,7 +106,7 @@
</td>
<td>
{{ video.publishedAt | date: 'short' }}
{{ video.publishedAt | ptDate: 'short' }}
</td>
</tr>

View file

@ -15,10 +15,10 @@ my-embed {
display: flex;
my-global-icon {
width: 16px;
position: relative;
top: -2px;
@include global-icon-size(16px);
@include margin-left(3px);
}
}

View file

@ -1,8 +1,9 @@
import { DatePipe, NgClass, NgFor, NgIf } from '@angular/common'
import { NgClass, NgFor, NgIf } from '@angular/common'
import { Component, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router, RouterLink } from '@angular/router'
import { AuthService, ConfirmService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
import { formatICU } from '@app/helpers'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { VideoCaptionService } from '@app/shared/shared-main/video-caption/video-caption.service'
import { VideoDetails } from '@app/shared/shared-main/video/video-details.model'
import { VideoFileTokenService } from '@app/shared/shared-main/video/video-file-token.service'
@ -19,10 +20,10 @@ import { TableModule, TableRowExpandEvent } from 'primeng/table'
import { finalize } from 'rxjs/operators'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../../../shared/shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../../../shared/shared-icons/global-icon.component'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { BytesPipe } from '../../../shared/shared-main/common/bytes.pipe'
import { ActionDropdownComponent, DropdownAction } from '../../../shared/shared-main/buttons/action-dropdown.component'
import { ButtonComponent } from '../../../shared/shared-main/buttons/button.component'
import { AutoColspanDirective } from '../../../shared/shared-main/common/auto-colspan.directive'
import { BytesPipe } from '../../../shared/shared-main/common/bytes.pipe'
import { EmbedComponent } from '../../../shared/shared-main/video/embed.component'
import { TableExpanderIconComponent } from '../../../shared/shared-tables/table-expander-icon.component'
import { VideoCellComponent } from '../../../shared/shared-tables/video-cell.component'
@ -54,7 +55,7 @@ import { VideoAdminService } from './video-admin.service'
NgFor,
EmbedComponent,
VideoBlockComponent,
DatePipe,
PTDatePipe,
RouterLink,
BytesPipe
]

View file

@ -16,11 +16,13 @@
}
@if (search && !isSearching) {
<my-global-icon iconName="search"></my-global-icon>
<div>
<my-global-icon iconName="search"></my-global-icon>
<ng-container i18n>
{{ pagination.totalItems }} {pagination.totalItems, plural, =1 {result} other {results}} for "{{ search }}"
</ng-container>
<ng-container i18n>
{{ pagination.totalItems }} {pagination.totalItems, plural, =1 {result} other {results}} for "{{ search }}"
</ng-container>
</div>
}
<div class="search-bar">

View file

@ -41,7 +41,7 @@ export class JobsComponent extends RestTable implements OnInit {
private static LS_STATE = 'jobs-list-state'
private static LS_TYPE = 'jobs-list-type'
jobState?: JobStateClient
jobState: JobStateClient = 'all'
jobStates: JobStateClient[] = [ 'all', 'active', 'completed', 'failed', 'waiting', 'delayed' ]
jobStateItems: SelectOptionsItem[] = this.jobStates.map(s => ({
id: s,
@ -176,10 +176,10 @@ export class JobsComponent extends RestTable implements OnInit {
private loadJobStateAndType () {
const state = peertubeLocalStorage.getItem(JobsComponent.LS_STATE)
if (state) this.jobState = state as JobState
if (state && state !== 'undefined') this.jobState = state as JobState
const jobType = peertubeLocalStorage.getItem(JobsComponent.LS_TYPE)
if (jobType) this.jobType = jobType as JobType
if (jobType && jobType !== 'undefined') this.jobType = jobType as JobType
}
private saveJobStateAndType () {

View file

@ -16,7 +16,7 @@
<my-select-options inputId="log-start-date" [items]="timeChoices" [(ngModel)]="startDate" (ngModelChange)="refresh()">
<ng-template ptTemplate="item" let-item>
{{ item.label }} ({{ item.id | date: item.dateFormat }} - <span i18n>now</span>)
{{ item.label }} ({{ item.id | ptDate: item.dateFormat }} - <span i18n>now</span>)
</ng-template>
</my-select-options>
</div>

View file

@ -1,9 +1,9 @@
import { DatePipe, NgClass, NgFor, NgIf } from '@angular/common'
import { NgClass, NgFor, NgIf } from '@angular/common'
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { LocalStorageService, Notifier } from '@app/core'
import { SelectOptionsComponent } from '@app/shared/shared-forms/select/select-options.component'
import { GlobalIconComponent } from '@app/shared/shared-icons/global-icon.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { PeerTubeTemplateDirective } from '@app/shared/shared-main/common/peertube-template.directive'
import { ServerLogLevel } from '@peertube/peertube-models'
import { SelectTagsComponent } from '../../../shared/shared-forms/select/select-tags.component'
@ -23,9 +23,8 @@ import { LogsService } from './logs.service'
NgClass,
SelectTagsComponent,
ButtonComponent,
DatePipe,
PTDatePipe,
CopyButtonComponent,
GlobalIconComponent,
SelectOptionsComponent,
PeerTubeTemplateDirective
]

View file

@ -32,9 +32,9 @@
<td>{{ runner.ip }}</td>
<td>{{ runner.lastContact | date: 'short' }}</td>
<td>{{ runner.lastContact | ptDate: 'short' }}</td>
<td>{{ runner.createdAt | date: 'short' }}</td>
<td>{{ runner.createdAt | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -1,29 +1,25 @@
import { SortMeta, SharedModule } from 'primeng/api'
import { Component, OnInit } from '@angular/core'
import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
import { Runner } from '@peertube/peertube-models'
import { RunnerService } from '../runner.service'
import { DatePipe } from '@angular/common'
import { AutoColspanDirective } from '../../../../shared/shared-main/common/auto-colspan.directive'
import { ActionDropdownComponent, DropdownAction } from '../../../../shared/shared-main/buttons/action-dropdown.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { Runner } from '@peertube/peertube-models'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { RouterLink } from '@angular/router'
import { GlobalIconComponent } from '../../../../shared/shared-icons/global-icon.component'
import { ActionDropdownComponent, DropdownAction } from '../../../../shared/shared-main/buttons/action-dropdown.component'
import { AutoColspanDirective } from '../../../../shared/shared-main/common/auto-colspan.directive'
import { RunnerService } from '../runner.service'
@Component({
selector: 'my-runner-list',
templateUrl: './runner-list.component.html',
standalone: true,
imports: [
GlobalIconComponent,
RouterLink,
TableModule,
SharedModule,
NgbTooltip,
ActionDropdownComponent,
AutoColspanDirective,
DatePipe
PTDatePipe
]
})
export class RunnerListComponent extends RestTable <Runner> implements OnInit {

View file

@ -41,7 +41,7 @@
></my-copy-button>
</td>
<td>{{ registrationToken.createdAt | date: 'short' }}</td>
<td>{{ registrationToken.createdAt | ptDate: 'short' }}</td>
<td>{{ registrationToken.registeredRunnersCount }}</td>
</tr>

View file

@ -1,17 +1,17 @@
import { SortMeta, SharedModule } from 'primeng/api'
import { Component, OnInit } from '@angular/core'
import { RouterLink } from '@angular/router'
import { ConfirmService, Notifier, RestPagination, RestTable } from '@app/core'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { RunnerRegistrationToken } from '@peertube/peertube-models'
import { RunnerService } from '../runner.service'
import { DatePipe } from '@angular/common'
import { AutoColspanDirective } from '../../../../shared/shared-main/common/auto-colspan.directive'
import { CopyButtonComponent } from '../../../../shared/shared-main/buttons/copy-button.component'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { GlobalIconComponent } from '../../../../shared/shared-icons/global-icon.component'
import { ActionDropdownComponent, DropdownAction } from '../../../../shared/shared-main/buttons/action-dropdown.component'
import { ButtonComponent } from '../../../../shared/shared-main/buttons/button.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { TableModule } from 'primeng/table'
import { RouterLink } from '@angular/router'
import { GlobalIconComponent } from '../../../../shared/shared-icons/global-icon.component'
import { CopyButtonComponent } from '../../../../shared/shared-main/buttons/copy-button.component'
import { AutoColspanDirective } from '../../../../shared/shared-main/common/auto-colspan.directive'
import { RunnerService } from '../runner.service'
@Component({
selector: 'my-runner-registration-token-list',
@ -28,7 +28,7 @@ import { GlobalIconComponent } from '../../../../shared/shared-icons/global-icon
ActionDropdownComponent,
CopyButtonComponent,
AutoColspanDirective,
DatePipe
PTDatePipe
]
})
export class RunnerRegistrationTokenListComponent extends RestTable <RunnerRegistrationToken> implements OnInit {

View file

@ -1,21 +1,20 @@
import { NgIf } from '@angular/common'
import { Component } from '@angular/core'
import { NgIf, DatePipe } from '@angular/common'
import { AutoColspanDirective } from '../../shared/shared-main/common/auto-colspan.directive'
import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component'
import { SharedModule } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { GenericAccountBlocklistComponent } from '@app/shared/shared-moderation/account-blocklist.component'
import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.service'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { SharedModule } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component'
import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component'
import { AutoColspanDirective } from '../../shared/shared-main/common/auto-colspan.directive'
@Component({
selector: 'my-account-blocklist',
templateUrl: '../../shared/shared-moderation/account-blocklist.component.html',
standalone: true,
imports: [
GlobalIconComponent,
TableModule,
SharedModule,
AdvancedInputFilterComponent,
@ -23,7 +22,7 @@ import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.
ActorAvatarComponent,
AutoColspanDirective,
NgIf,
DatePipe
PTDatePipe
]
})
export class MyAccountBlocklistComponent extends GenericAccountBlocklistComponent {

View file

@ -1,14 +1,15 @@
import { NgIf } from '@angular/common'
import { Component } from '@angular/core'
import { BatchDomainsModalComponent } from '../../shared/shared-moderation/batch-domains-modal.component'
import { NgIf, DatePipe } from '@angular/common'
import { AutoColspanDirective } from '../../shared/shared-main/common/auto-colspan.directive'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component'
import { SharedModule } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { BlocklistComponentType } from '@app/shared/shared-moderation/blocklist.service'
import { GenericServerBlocklistComponent } from '@app/shared/shared-moderation/server-blocklist.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { SharedModule } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component'
import { AutoColspanDirective } from '../../shared/shared-main/common/auto-colspan.directive'
import { BatchDomainsModalComponent } from '../../shared/shared-moderation/batch-domains-modal.component'
@Component({
selector: 'my-account-server-blocklist',
@ -24,7 +25,7 @@ import { GenericServerBlocklistComponent } from '@app/shared/shared-moderation/s
AutoColspanDirective,
NgIf,
BatchDomainsModalComponent,
DatePipe
PTDatePipe
]
})
export class MyAccountServerBlocklistComponent extends GenericServerBlocklistComponent {

View file

@ -46,7 +46,7 @@
</tr>
<tr *ngFor="let export of userExports">
<td>{{ export.createdAt | date: 'medium' }}</td>
<td>{{ export.createdAt | ptDate: 'medium' }}</td>
<td>{{ export.state.label }}</td>
<td>
@ -54,7 +54,7 @@
</td>
<td>
<ng-container *ngIf="export.expiresOn">{{ export.expiresOn | date: 'medium' }}</ng-container>
<ng-container *ngIf="export.expiresOn">{{ export.expiresOn | ptDate: 'medium' }}</ng-container>
</td>
<td>

View file

@ -1,8 +1,9 @@
import { DatePipe, NgFor, NgIf } from '@angular/common'
import { NgFor, NgIf } from '@angular/common'
import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { AuthService, ServerService } from '@app/core'
import { AlertComponent } from '@app/shared/shared-main/common/alert.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
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'
@ -16,7 +17,7 @@ import { UserImportExportService } from './user-import-export.service'
templateUrl: './my-account-export.component.html',
styleUrls: [ './my-account-export.component.scss' ],
standalone: true,
imports: [ NgIf, NgFor, GlobalIconComponent, PeertubeCheckboxComponent, FormsModule, DatePipe, BytesPipe, AlertComponent ]
imports: [ NgIf, NgFor, GlobalIconComponent, PeertubeCheckboxComponent, FormsModule, PTDatePipe, BytesPipe, AlertComponent ]
})
export class MyAccountExportComponent implements OnInit {
@ViewChild('exportModal', { static: true }) exportModal: NgbModal

View file

@ -39,7 +39,7 @@
<div class="mb-3" *ngIf="latestImport">
<div>
<strong>Latest import on:</strong> {{ latestImport.createdAt | date: 'medium' }}
<strong>Latest import on:</strong> {{ latestImport.createdAt | ptDate: 'medium' }}
</div>
<div>

View file

@ -1,10 +1,11 @@
import { DatePipe, NgIf } from '@angular/common'
import { 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 { AlertComponent } from '@app/shared/shared-main/common/alert.component'
import { BytesPipe } from '@app/shared/shared-main/common/bytes.pipe'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { HttpStatusCode, UserImport, UserImportState } from '@peertube/peertube-models'
import { UploadState, UploaderX, UploadxService } from 'ngx-uploadx'
@ -17,7 +18,7 @@ import { UserImportExportService } from './user-import-export.service'
templateUrl: './my-account-import.component.html',
styleUrls: [ './my-account-import.component.scss' ],
standalone: true,
imports: [ NgIf, UploadProgressComponent, NgbTooltip, DatePipe, AlertComponent ]
imports: [ NgIf, UploadProgressComponent, NgbTooltip, PTDatePipe, AlertComponent ]
})
export class MyAccountImportComponent implements OnInit, OnDestroy, CanComponentDeactivate {
@Input() videoQuotaUsed: number

View file

@ -39,7 +39,7 @@
<my-video-cell [video]="videoChangeOwnership.video"></my-video-cell>
</td>
<td>{{ videoChangeOwnership.createdAt | date: 'short' }}</td>
<td>{{ videoChangeOwnership.createdAt | ptDate: 'short' }}</td>
<td>
<span class="pt-badge"

View file

@ -1,16 +1,16 @@
import { DatePipe, NgClass, NgIf } from '@angular/common'
import { NgClass, NgIf } from '@angular/common'
import { Component, OnInit, ViewChild } from '@angular/core'
import { Notifier, RestPagination, RestTable } from '@app/core'
import { Account } from '@app/shared/shared-main/account/account.model'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { VideoOwnershipService } from '@app/shared/shared-main/video/video-ownership.service'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { VideoChangeOwnership, VideoChangeOwnershipStatus, VideoChangeOwnershipStatusType } from '@peertube/peertube-models'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { ActorAvatarComponent } from '../../shared/shared-actor-image/actor-avatar.component'
import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component'
import { AutoColspanDirective } from '../../shared/shared-main/common/auto-colspan.directive'
import { ButtonComponent } from '../../shared/shared-main/buttons/button.component'
import { AutoColspanDirective } from '../../shared/shared-main/common/auto-colspan.directive'
import { VideoCellComponent } from '../../shared/shared-tables/video-cell.component'
import { MyAcceptOwnershipComponent } from './my-accept-ownership/my-accept-ownership.component'
@ -18,7 +18,6 @@ import { MyAcceptOwnershipComponent } from './my-accept-ownership/my-accept-owne
templateUrl: './my-ownership.component.html',
standalone: true,
imports: [
GlobalIconComponent,
TableModule,
SharedModule,
NgbTooltip,
@ -28,7 +27,7 @@ import { MyAcceptOwnershipComponent } from './my-accept-ownership/my-accept-owne
NgClass,
AutoColspanDirective,
MyAcceptOwnershipComponent,
DatePipe,
PTDatePipe,
VideoCellComponent
]
})

View file

@ -70,8 +70,8 @@
</span>
</td>
<td>{{ videoChannelSync.createdAt | date: 'short' }}</td>
<td>{{ videoChannelSync.lastSyncAt | date: 'short' }}</td>
<td>{{ videoChannelSync.createdAt | ptDate: 'short' }}</td>
<td>{{ videoChannelSync.lastSyncAt | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -1,10 +1,11 @@
import { DatePipe, NgClass, NgIf } from '@angular/common'
import { NgClass, NgIf } from '@angular/common'
import { Component, OnInit } from '@angular/core'
import { RouterLink } from '@angular/router'
import { AuthService, Notifier, RestPagination, RestTable, ServerService } from '@app/core'
import { VideoChannelSyncService } from '@app/shared/shared-main/channel/video-channel-sync.service'
import { VideoChannelService } from '@app/shared/shared-main/channel/video-channel.service'
import { AlertComponent } from '@app/shared/shared-main/common/alert.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { HTMLServerConfig, VideoChannelSync, VideoChannelSyncState, VideoChannelSyncStateType } from '@peertube/peertube-models'
import { SharedModule, SortMeta } from 'primeng/api'
@ -27,7 +28,7 @@ import { ActionDropdownComponent, DropdownAction } from '../../shared/shared-mai
ActionDropdownComponent,
ActorAvatarComponent,
NgClass,
DatePipe,
PTDatePipe,
AlertComponent
]
})

View file

@ -55,7 +55,7 @@
</span>
</td>
<td>{{ videoImport.createdAt | date: 'short' }}</td>
<td>{{ videoImport.createdAt | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -1,28 +1,25 @@
import { SortMeta, SharedModule } from 'primeng/api'
import { NgClass, NgIf } from '@angular/common'
import { Component, OnInit } from '@angular/core'
import { Notifier, RestPagination, RestTable } from '@app/core'
import { VideoImport, VideoImportState, VideoImportStateType } from '@peertube/peertube-models'
import { AutoColspanDirective } from '../../shared/shared-main/common/auto-colspan.directive'
import { EditButtonComponent } from '../../shared/shared-main/buttons/edit-button.component'
import { DeleteButtonComponent } from '../../shared/shared-main/buttons/delete-button.component'
import { ButtonComponent } from '../../shared/shared-main/buttons/button.component'
import { TableExpanderIconComponent } from '../../shared/shared-tables/table-expander-icon.component'
import { NgIf, NgClass, DatePipe } from '@angular/common'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { TableModule } from 'primeng/table'
import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component'
import { RouterLink } from '@angular/router'
import { GlobalIconComponent } from '../../shared/shared-icons/global-icon.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { VideoImportService } from '@app/shared/shared-main/video/video-import.service'
import { Video } from '@app/shared/shared-main/video/video.model'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { VideoImport, VideoImportState, VideoImportStateType } from '@peertube/peertube-models'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { AdvancedInputFilterComponent } from '../../shared/shared-forms/advanced-input-filter.component'
import { ButtonComponent } from '../../shared/shared-main/buttons/button.component'
import { DeleteButtonComponent } from '../../shared/shared-main/buttons/delete-button.component'
import { EditButtonComponent } from '../../shared/shared-main/buttons/edit-button.component'
import { AutoColspanDirective } from '../../shared/shared-main/common/auto-colspan.directive'
import { TableExpanderIconComponent } from '../../shared/shared-tables/table-expander-icon.component'
@Component({
templateUrl: './my-video-imports.component.html',
styleUrls: [ './my-video-imports.component.scss' ],
standalone: true,
imports: [
GlobalIconComponent,
RouterLink,
AdvancedInputFilterComponent,
TableModule,
SharedModule,
@ -34,7 +31,7 @@ import { Video } from '@app/shared/shared-main/video/video.model'
EditButtonComponent,
NgClass,
AutoColspanDirective,
DatePipe
PTDatePipe
]
})
export class MyVideoImportsComponent extends RestTable implements OnInit {

View file

@ -64,7 +64,7 @@
<div class="actor-info">
<div>
<div class="actor-display-name">
<h1 i18n-title [title]="'Channel created on ' + (videoChannel.createdAt | date)">{{ videoChannel.displayName }}</h1>
<h1 i18n-title [title]="'Channel created on ' + (videoChannel.createdAt | ptDate)">{{ videoChannel.displayName }}</h1>
</div>
<div class="actor-handle">

View file

@ -1,10 +1,11 @@
import { DatePipe, NgClass, NgIf, NgTemplateOutlet } from '@angular/common'
import { NgClass, NgIf, NgTemplateOutlet } from '@angular/common'
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, RouterLink, RouterOutlet } from '@angular/router'
import { AuthService, Hotkey, HotkeysService, MarkdownService, MetaService, RestExtractor, ScreenService } from '@app/core'
import { Account } from '@app/shared/shared-main/account/account.model'
import { VideoChannel } from '@app/shared/shared-main/channel/video-channel.model'
import { VideoChannelService } from '@app/shared/shared-main/channel/video-channel.service'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { HorizontalMenuComponent, HorizontalMenuEntry } from '@app/shared/shared-main/menu/horizontal-menu.component'
import { VideoService } from '@app/shared/shared-main/video/video.service'
import { BlocklistService } from '@app/shared/shared-moderation/blocklist.service'
@ -35,7 +36,7 @@ import { AccountBlockBadgesComponent } from '../shared/shared-moderation/account
HorizontalMenuComponent,
RouterOutlet,
SupportModalComponent,
DatePipe
PTDatePipe
]
})
export class VideoChannelsComponent implements OnInit, OnDestroy {

View file

@ -212,7 +212,7 @@
[href]="videoCaption.captionPath"
>{{ getCaptionLabel(videoCaption) }}</a>
<div i18n class="caption-entry-state">Already uploaded on {{ videoCaption.updatedAt | date }} &#10004;</div>
<div i18n class="caption-entry-state">Already uploaded on {{ videoCaption.updatedAt | ptDate }} &#10004;</div>
<my-edit-button i18n-label label="Edit" class="me-2" (click)="openEditCaptionModal(videoCaption)"></my-edit-button>
<my-delete-button label (click)="deleteCaption(videoCaption)"></my-delete-button>

View file

@ -82,12 +82,6 @@ p-calendar {
.p-calendar {
width: 100%;
}
.p-inputtext {
color: #000;
@include peertube-input-text(100%);
}
}
}
@ -98,6 +92,11 @@ p-calendar {
grid-gap: 30px;
}
.col-video-edit {
max-width: 100%;
min-width: 1px;
}
.hide-chapter-label {
height: 0;
opacity: 0;

View file

@ -1,4 +1,4 @@
import { DatePipe, NgClass, NgFor, NgIf, NgTemplateOutlet } from '@angular/common'
import { NgClass, NgFor, NgIf, NgTemplateOutlet } from '@angular/common'
import {
ChangeDetectorRef,
Component,
@ -12,6 +12,7 @@ import {
booleanAttribute
} from '@angular/core'
import { AbstractControl, FormArray, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms'
import { RouterLink } from '@angular/router'
import { ConfirmService, HooksService, PluginService, ServerService } from '@app/core'
import { removeElementFromArray } from '@app/helpers'
import { BuildFormArgument, BuildFormValidator } from '@app/shared/form-validators/form-validator.model'
@ -34,6 +35,7 @@ import {
import { FormReactiveErrors, FormReactiveValidationMessages } from '@app/shared/shared-forms/form-reactive.service'
import { FormValidatorService } from '@app/shared/shared-forms/form-validator.service'
import { AlertComponent } from '@app/shared/shared-main/common/alert.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { InstanceService } from '@app/shared/shared-main/instance/instance.service'
import { VideoCaptionEdit, VideoCaptionWithPathEdit } from '@app/shared/shared-main/video-caption/video-caption-edit.model'
import { VideoChaptersEdit } from '@app/shared/shared-main/video/video-chapters-edit.model'
@ -64,7 +66,6 @@ import { DynamicFormFieldComponent } from '../../../shared/shared-forms/dynamic-
import { InputTextComponent } from '../../../shared/shared-forms/input-text.component'
import { MarkdownTextareaComponent } from '../../../shared/shared-forms/markdown-textarea.component'
import { PeertubeCheckboxComponent } from '../../../shared/shared-forms/peertube-checkbox.component'
import { PreviewUploadComponent } from '../../../shared/shared-forms/preview-upload.component'
import { SelectChannelComponent } from '../../../shared/shared-forms/select/select-channel.component'
import { SelectOptionsComponent } from '../../../shared/shared-forms/select/select-options.component'
import { SelectTagsComponent } from '../../../shared/shared-forms/select/select-tags.component'
@ -82,7 +83,6 @@ import { VideoCaptionEditModalContentComponent } from './caption/video-caption-e
import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service'
import { ThumbnailManagerComponent } from './thumbnail-manager/thumbnail-manager.component'
import { VideoEditType } from './video-edit.type'
import { RouterLink } from '@angular/router'
type PluginField = {
pluginInfo: PluginInfo
@ -123,10 +123,9 @@ type PluginField = {
DeleteButtonComponent,
EmbedComponent,
LiveDocumentationLinkComponent,
PreviewUploadComponent,
NgbNavOutlet,
VideoCaptionAddModalComponent,
DatePipe,
PTDatePipe,
ThumbnailManagerComponent,
EditButtonComponent,
ButtonComponent,

View file

@ -1,5 +1,5 @@
<my-alert rounded="false" type="primary" i18n *ngIf="hasVideoScheduledPublication()">
This video will be published on {{ video.scheduledUpdate.updateAt | date: 'full' }}.
This video will be published on {{ video.scheduledUpdate.updateAt | ptDate: 'full' }}.
</my-alert>
<my-alert rounded="false" type="primary" i18n *ngIf="isWaitingForLive()">

View file

@ -1,7 +1,8 @@
import { DatePipe, NgIf } from '@angular/common'
import { NgIf } from '@angular/common'
import { Component, Input } from '@angular/core'
import { AuthUser } from '@app/core'
import { AlertComponent } from '@app/shared/shared-main/common/alert.component'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { VideoDetails } from '@app/shared/shared-main/video/video-details.model'
import { VideoPrivacy, VideoState } from '@peertube/peertube-models'
@ -10,7 +11,7 @@ import { VideoPrivacy, VideoState } from '@peertube/peertube-models'
templateUrl: './video-alert.component.html',
standalone: true,
styles: `my-alert { text-align: center }`,
imports: [ NgIf, DatePipe, AlertComponent ]
imports: [ NgIf, PTDatePipe, AlertComponent ]
})
export class VideoAlertComponent {
@Input() user: AuthUser

View file

@ -30,12 +30,12 @@
<div *ngIf="!!video.inputFileUpdatedAt" class="attribute attribute-re-uploaded-on">
<span i18n class="attribute-label">Video re-upload</span>
<span class="attribute-value">{{ video.inputFileUpdatedAt | date: 'short' }}</span>
<span class="attribute-value">{{ video.inputFileUpdatedAt | ptDate: 'short' }}</span>
</div>
<div *ngIf="!!video.originallyPublishedAt" class="attribute attribute-originally-published-at">
<span i18n class="attribute-label">Originally published</span>
<span class="attribute-value">{{ video.originallyPublishedAt | date: 'shortDate' }}</span>
<span class="attribute-value">{{ video.originallyPublishedAt | ptDate: 'shortDate' }}</span>
</div>
<div class="attribute attribute-category">

View file

@ -1,7 +1,8 @@
import { DatePipe, NgFor, NgIf } from '@angular/common'
import { NgFor, NgIf } from '@angular/common'
import { Component, Input, OnChanges } from '@angular/core'
import { RouterLink } from '@angular/router'
import { HooksService } from '@app/core'
import { PTDatePipe } from '@app/shared/shared-main/common/date.pipe'
import { TimeDurationFormatterPipe } from '@app/shared/shared-main/date/time-duration-formatter.pipe'
import { VideoDetails } from '@app/shared/shared-main/video/video-details.model'
import { GlobalIconComponent } from '../../../../shared/shared-icons/global-icon.component'
@ -18,7 +19,7 @@ type PluginMetadata = {
templateUrl: './video-attributes.component.html',
styleUrls: [ './video-attributes.component.scss' ],
standalone: true,
imports: [ NgIf, RouterLink, GlobalIconComponent, NgFor, DatePipe, TimeDurationFormatterPipe ]
imports: [ NgIf, RouterLink, GlobalIconComponent, NgFor, TimeDurationFormatterPipe, PTDatePipe ]
})
export class VideoAttributesComponent implements OnChanges {
@Input() video: VideoDetails

View file

@ -12,10 +12,6 @@
@include peertube-word-wrap;
::ng-deep {
a {
text-decoration: none;
}
p:last-child {
margin-bottom: 0;
}

View file

@ -41,7 +41,6 @@
<my-video-playlist-element-miniature
[playlistElement]="playlistElement" [playlist]="playlist" [owned]="isPlaylistOwned()" (elementRemoved)="onElementRemoved($event)"
[playing]="currentPlaylistPosition === playlistElement.position" [accountLink]="false" [position]="playlistElement.position"
[touchScreenEditButton]="true"
></my-video-playlist-element-miniature>
</div>
</div>

View file

@ -11,7 +11,6 @@ import {
ScreenService,
ScrollService,
ServerService,
ThemeService,
User,
UserLocalStorageService
} from '@app/core'
@ -93,7 +92,6 @@ export class AppComponent implements OnInit, AfterViewInit {
private domSanitizer: DomSanitizer,
private screenService: ScreenService,
private hotkeysService: HotkeysService,
private themeService: ThemeService,
private hooks: HooksService,
private location: PlatformLocation,
private modalService: NgbModal,
@ -115,7 +113,6 @@ export class AppComponent implements OnInit, AfterViewInit {
this.serverConfig = this.serverService.getHTMLConfig()
this.hooks.runAction('action:application.init', 'common')
this.themeService.initialize()
this.authService.loadClientCredentials()

View file

@ -81,7 +81,7 @@ export class PluginService implements ClientHook {
initializePlugins () {
this.pluginsManager.loadPluginsList(this.server.getHTMLConfig())
this.pluginsManager.ensurePluginsAreLoaded('common')
return this.pluginsManager.ensurePluginsAreLoaded('common')
}
initializeCustomModal (customModal: CustomModalComponent) {

View file

@ -188,21 +188,36 @@ export class ThemeService {
this.oldInjectedProperties = []
const toProcess: { prefix: string, invertIfDark: boolean, fallbacks?: Record<string, string> }[] = [
{ prefix: 'primary', invertIfDark: true },
{ prefix: 'bg-secondary', invertIfDark: true },
{ prefix: 'fg', invertIfDark: true, fallbacks: { '--fg-300': '--greyForegroundColor' } }
]
const darkTheme = this.isDarkTheme(computedStyle)
if (darkTheme) {
debugLogger('Detected dark theme')
const isGlobalDarkTheme = () => {
return this.isDarkTheme({
fg: computedStyle.getPropertyValue('--fg') || computedStyle.getPropertyValue('--mainForegroundColor'),
bg: computedStyle.getPropertyValue('--bg') || computedStyle.getPropertyValue('--mainBackgroundColor'),
isDarkVar: computedStyle.getPropertyValue('--is-dark')
})
}
for (const { prefix, invertIfDark, fallbacks = {} } of toProcess) {
const isMenuDarkTheme = () => {
return this.isDarkTheme({
fg: computedStyle.getPropertyValue('--menu-fg'),
bg: computedStyle.getPropertyValue('--menu-bg'),
isDarkVar: computedStyle.getPropertyValue('--is-menu-dark')
})
}
const toProcess = [
{ prefix: 'primary', invertIfDark: true, step: 5, darkTheme: isGlobalDarkTheme },
{ prefix: 'on-primary', invertIfDark: true, step: 0, darkTheme: isGlobalDarkTheme },
{ prefix: 'bg-secondary', invertIfDark: true, step: 5, darkTheme: isGlobalDarkTheme },
{ prefix: 'fg', invertIfDark: true, fallbacks: { '--fg-300': '--greyForegroundColor' }, step: 5, darkTheme: isGlobalDarkTheme },
{ prefix: 'menu-fg', invertIfDark: true, step: 5, darkTheme: isMenuDarkTheme },
{ prefix: 'menu-bg', invertIfDark: true, step: 5, darkTheme: isMenuDarkTheme }
] as { prefix: string, invertIfDark: boolean, step: number, darkTheme: () => boolean, fallbacks?: Record<string, string> }[]
for (const { prefix, invertIfDark, step, darkTheme, fallbacks = {} } of toProcess) {
const mainColor = computedStyle.getPropertyValue('--' + prefix)
const darkInverter = invertIfDark && darkTheme
const darkInverter = invertIfDark && darkTheme()
? -1
: 1
@ -227,7 +242,7 @@ export class ThemeService {
const existingValue = computedStyle.getPropertyValue(key)
if (!existingValue || existingValue === '0') {
const newLuminance = this.buildNewLuminance(lastColorHSL, j, darkInverter)
const newLuminance = this.buildNewLuminance(lastColorHSL, j * step, darkInverter)
const newColorHSL = { ...lastColorHSL, l: newLuminance }
const newColorStr = this.toHSLStr(newColorHSL)
@ -253,28 +268,31 @@ export class ThemeService {
}
}
document.body.dataset.bsTheme = darkTheme
document.body.dataset.bsTheme = isGlobalDarkTheme()
? 'dark'
: ''
}
private buildNewLuminance (base: { l: number }, factor: number, darkInverter: number) {
return Math.max(Math.min(100, Math.round(base.l + (factor * 5 * -1 * darkInverter))), 0)
return Math.max(Math.min(100, Math.round(base.l + (factor * -1 * darkInverter))), 0)
}
private toHSLStr (c: { h: number, s: number, l: number, a: number }) {
return `hsl(${Math.round(c.h)} ${Math.round(c.s)}% ${Math.round(c.l)}% / ${Math.round(c.a)})`
}
private isDarkTheme (computedStyle: CSSStyleDeclaration) {
const deprecatedFG = computedStyle.getPropertyValue('--mainForegroundColor')
const deprecatedBG = computedStyle.getPropertyValue('--mainBackgroundColor')
private isDarkTheme (options: {
fg: string
bg: string
isDarkVar: string
}) {
const { fg, bg, isDarkVar } = options
if (computedStyle.getPropertyValue('--is-dark') === '1') {
if (isDarkVar === '1') {
return true
} else if (deprecatedFG && deprecatedBG) {
} else if (fg && bg) {
try {
if (getLuminance(parse(deprecatedBG)) < getLuminance(parse(deprecatedFG))) {
if (getLuminance(parse(bg)) < getLuminance(parse(fg))) {
return true
}
} catch (err) {
@ -331,6 +349,7 @@ export class ThemeService {
private removeThemeFromLocalStorageIfNeeded (themes: ServerConfigTheme[]) {
if (!this.themeFromLocalStorage) return
if (this.internalThemes.includes(this.themeFromLocalStorage.name)) return
const loadedTheme = themes.find(t => t.name === this.themeFromLocalStorage.name)
if (!loadedTheme || loadedTheme.version !== this.themeFromLocalStorage.version) {

View file

@ -1,15 +1,18 @@
<div class="root" [hidden]="!loaded || (loggedIn && !user.account)">
<div class="root">
<a class="peertube-title" [routerLink]="getDefaultRoute()" [queryParams]="getDefaultRouteQuery()">
<span class="icon-logo"></span>
<span class="instance-name">{{ instanceName }}</span>
</a>
<my-search-typeahead></my-search-typeahead>
<my-search-typeahead [hidden]="!isLoaded()"></my-search-typeahead>
<div class="d-flex align-items-center buttons-container">
<div class="d-flex align-items-center buttons-container" [hidden]="!isLoaded()">
@if (!loggedIn) {
<my-button theme="tertiary" rounded="true" class="margin-button settings-button" icon="cog" (click)="openQuickSettings()"></my-button>
<my-button
i18n-title title="Open settings modal"
theme="tertiary" rounded="true" class="margin-button settings-button" icon="cog" (click)="openQuickSettings()"
></my-button>
<a *ngIf="isRegistrationAllowed()" routerLink="/signup" class="peertube-button-link secondary-button w-100 ellipsis margin-button create-account-button">
<my-signup-label [requiresApproval]="requiresApproval"></my-signup-label>
@ -85,4 +88,4 @@
</div>
<my-language-chooser #languageChooserModal></my-language-chooser>
<my-quick-settings #quickSettingsModal></my-quick-settings>
<my-quick-settings #quickSettingsModal (openLanguageModal)="languageChooserModal.show()"></my-quick-settings>

View file

@ -25,6 +25,7 @@
color: inherit !important;
display: flex;
align-items: center;
min-height: 46px; // Prevent layout shifting when waiting for the right part of the header to load
@include padding-left(18px);
@include margin-right(0.5rem);
@ -51,6 +52,7 @@
my-search-typeahead {
max-width: 270px;
width: 100%;
@include margin-right(1.5rem);
}

View file

@ -62,8 +62,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
currentInterfaceLanguage: string
loaded = false
private serverConfig: ServerConfig
private quickSettingsModalSub: Subscription
@ -93,6 +91,10 @@ export class HeaderComponent implements OnInit, OnDestroy {
return this.serverService.getHTMLConfig().instance.name
}
isLoaded () {
return this.serverConfig && (!this.loggedIn || !!this.user?.account)
}
isInMobileView () {
return this.screenService.isInMobileView()
}
@ -125,8 +127,6 @@ export class HeaderComponent implements OnInit, OnDestroy {
this.quickSettingsModalSub = this.modalService.openQuickSettingsSubject
.subscribe(() => this.openQuickSettings())
this.loaded = true
}
ngOnDestroy () {

View file

@ -23,7 +23,7 @@
</a>
} @else {
<div
ngbDropdown autoClose="outside" placement="bottom" container="body" dropdownClass="dropdown-notifications"
ngbDropdown autoClose="outside" placement="bottom-end auto" container="body" dropdownClass="dropdown-notifications"
#dropdown="ngbDropdown" (openChange)="$event === true ? onDropdownShown() : onDropdownHidden()"
>
<button

View file

@ -5,16 +5,8 @@
scrollbar-color: auto;
}
.notification-inbox-dropdown.hidden {
display: none;
}
::ng-deep {
.dropdown-notifications {
max-width: none;
top: -6px !important;
left: 7px !important;
.dropdown-menu {
padding: 0;
font-size: 14px;
@ -95,5 +87,6 @@
line-height: 16px;
padding: 0 3px;
min-width: 16px;
}
}

View file

@ -6,7 +6,7 @@ import { GlobalIconComponent } from '@app/shared/shared-icons/global-icon.compon
import { LoaderComponent } from '@app/shared/shared-main/common/loader.component'
import { UserNotificationService } from '@app/shared/shared-main/users/user-notification.service'
import { UserNotificationsComponent } from '@app/shared/standalone-notifications/user-notifications.component'
import { NgbDropdown, NgbDropdownModule, NgbPopoverModule } from '@ng-bootstrap/ng-bootstrap'
import { NgbDropdown, NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap'
import { Subject, Subscription } from 'rxjs'
import { filter } from 'rxjs/operators'
@ -17,7 +17,6 @@ import { filter } from 'rxjs/operators'
standalone: true,
imports: [
CommonModule,
NgbPopoverModule,
UserNotificationsComponent,
GlobalIconComponent,
LoaderComponent,

View file

@ -1,9 +1,16 @@
<ng-template #moreInfoButton>
<my-button i18n class="mt-2 d-block" theme="secondary" icon="help" i18n-ariaLabel aria-label="More info" i18n ptRouterLink="/about" ptRouterLinkActive="active">
@if (!collapsed) {
More info
}
</my-button>
<div class="more-info-btn-container">
<a
class="more-info-btn peertube-button-link peertube-button-icon mt-2 d-block" [ngClass]="{ 'icon-only': collapsed }"
routerLink="/about" i18n-title title="More info" routerLinkActive="active"
>
<my-global-icon iconName="help"></my-global-icon>
@if (!collapsed) {
More info
}
</a>
</div>
</ng-template>
<div class="menu-container" [ngClass]="{ collapsed: collapsed, 'logged-in': loggedIn }">
@ -20,11 +27,11 @@
<div class="toggle-menu-container">
@if (collapsed) {
<button type="button" class="button-unstyle toggle-menu" i18n-title title="Display the lateral bar" (click)="toggleMenu()">
<button type="button" class="button-unstyle toggle-menu" i18n-title title="Display the lateral menu" (click)="toggleMenu()">
<my-global-icon class="transform-rotate-180" iconName="chevron-left"></my-global-icon>
</button>
} @else {
<button type="button" class="button-unstyle toggle-menu" i18n-title title= "Hide the lateral bar" (click)="toggleMenu()">
<button type="button" class="button-unstyle toggle-menu" i18n-title title= "Hide the lateral menu" (click)="toggleMenu()">
<my-global-icon iconName="chevron-left"></my-global-icon>
</button>
}
@ -47,13 +54,13 @@
<ul class="ul-unstyle">
<li *ngFor="let link of menuSection.links">
@if (link.isPrimaryButton === true) {
<my-button class="d-block menu-button" [ngClass]="link.ngClass" theme="primary" [icon]="link.icon" [ariaLabel]="link.label" [ptRouterLink]="link.path">
<my-button class="d-block menu-button" [ngClass]="link.ngClass" theme="primary" [icon]="link.icon" [title]="link.label" [ptRouterLink]="link.path">
@if (!collapsed) {
{{ link.label }}
}
</my-button>
} @else {
<a class="menu-link ellipsis" [routerLink]="link.path" routerLinkActive="active" [ngClass]="link.ngClass">
<a class="menu-link ellipsis" [routerLink]="link.path" routerLinkActive="active" [ngClass]="link.ngClass" [title]="link.label">
<my-global-icon *ngIf="link.icon" [iconName]="link.icon" [ngClass]="link.iconClass" aria-hidden="true"></my-global-icon>
<span [ngClass]="{ 'visually-hidden': collapsed }">{{ link.label }}</span>
</a>

View file

@ -23,11 +23,11 @@
}
.toggle-menu {
color: pvar-fallback(--menu-fg, --fg-200);
color: pvar(--menu-fg-300);
width: 24px;
height: 24px;
border-radius: 100%;
background-color: pvar-fallback(--menu-bg, --bg-secondary-500);
background-color: pvar(--menu-bg-550);
@include button-with-icon(20px, 0, 0, 1px);
@ -82,14 +82,14 @@
padding-top: 1.5rem;
padding-bottom: 1.5rem;
border-radius: 14px;
background-color: pvar-fallback(--menu-bg, --bg-secondary-400);
background-color: pvar(--menu-bg);
}
.menu-link,
.menu-button,
.block-title,
.about .description,
.about my-button {
.about .more-info-btn-container {
@include padding-left(var(--co-menu-x-padding));
@include padding-right(var(--co-menu-x-padding));
}
@ -103,7 +103,92 @@
display: block;
height: 2px;
margin: 1rem var(--co-menu-x-padding);
background: pvar(--bg-secondary-500);
background: pvar(--menu-bg-600);
}
}
.block-title {
font-weight: $font-bold;
color: pvar(--menu-fg-450);
font-size: 14px;
margin-bottom: 0.5rem;
max-width: 180px;
@include ellipsis;
}
.menu-link {
display: flex;
align-items: center;
white-space: normal;
word-break: break-word;
transition: background-color .1s ease-in-out;
width: 100%;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
@include disable-default-a-behaviour;
&:hover,
&:focus-visible {
opacity: 1;
background-color: pvar(--menu-bg-550);
}
my-global-icon {
width: 22px;
height: 22px;
line-height: 22px;
position: relative;
top: -1px;
+ *:not(.visually-hidden) {
@include margin-left(12px);
}
}
}
.menu-button {
margin-top: 0.5rem;
}
.about {
.description {
font-size: 14px;
color: pvar(--menu-fg-300);
}
}
.more-info-btn {
@include secondary-button(
$fg: pvar(--menu-fg),
$active-bg: pvar(--menu-bg-600),
$hover-bg: pvar(--menu-bg-550),
$border-color: pvar(--menu-bg-600)
)
}
.more-info-btn,
.menu-link {
my-global-icon {
color: pvar(--secondary-icon-color);
}
&.active {
font-weight: $font-bold;
my-global-icon {
color: pvar(--menu-fg-600);
}
}
}
.menu-link {
color: pvar(--menu-fg);
&.active {
background-color: pvar(--menu-bg-600);
}
}
@ -116,9 +201,7 @@
margin: 1rem auto;
}
}
}
.collapsed {
.main-menu-wrapper {
max-height: 100%;
}
@ -135,73 +218,19 @@
text-align: center;
}
.menu-link {
.menu-link,
.more-info-btn {
border: 0 !important;
justify-content: center;
}
}
.block-title {
font-weight: $font-bold;
color: pvar-fallback(--menu-fg, --fg-350);
font-size: 14px;
margin-bottom: 0.5rem;
max-width: 180px;
@include ellipsis;
}
.menu-link {
display: flex;
align-items: center;
color: pvar-fallback(--menu-fg, --fg-400);
white-space: normal;
word-break: break-word;
transition: background-color .1s ease-in-out;
width: 100%;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
@include disable-default-a-behaviour;
&:hover,
&:focus-visible {
background-color: pvar-fallback(--menu-fg, --bg-secondary-450);
}
&.active {
background-color: pvar-fallback(--menu-fg, --bg-secondary-500);
}
my-global-icon {
width: 22px;
height: 22px;
line-height: 22px;
position: relative;
top: -1px;
color: pvar-fallback(--menu-fg, --secondary-icon-color);
+ *:not(.visually-hidden) {
@include margin-left(12px);
&:not(.active) {
my-global-icon {
color: pvar(--menu-fg-400);
}
}
}
}
.menu-button {
margin-top: 0.5rem;
}
.about {
.description {
font-size: 14px;
color: pvar-fallback(--menu-fg, --fg-200)
}
}
my-button[theme=secondary] ::ng-deep my-global-icon {
color: pvar(--secondary-icon-color) !important;
}
.menu-overlay {
background-color: #000;
width: 100vw;
@ -239,7 +268,7 @@ my-button[theme=secondary] ::ng-deep my-global-icon {
--menu-margin-left: 0;
border-radius: 0;
background-color: pvar-fallback(--menu-bg, --bg-secondary-400);
background-color: pvar(--menu-bg);
overflow: auto;
.main-menu-wrapper {

View file

@ -23,5 +23,7 @@
*ngIf="!isUserLoggedIn()"
[user]="user" [userInformationLoaded]="userInformationLoaded" [reactiveUpdate]="true" [notifyOnUpdate]="true"
></my-user-interface-settings>
<my-button class="mt-2" theme="secondary" icon="language" (click)="changeLanguage()">Change interface language</my-button>
</div>
</ng-template>

View file

@ -1,8 +1,9 @@
import { CommonModule } from '@angular/common'
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'
import { Component, EventEmitter, OnDestroy, OnInit, Output, ViewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { AuthService, AuthStatus, LocalStorageService, User, UserService } from '@app/core'
import { GlobalIconComponent } from '@app/shared/shared-icons/global-icon.component'
import { ButtonComponent } from '@app/shared/shared-main/buttons/button.component'
import { AlertComponent } from '@app/shared/shared-main/common/alert.component'
import { UserInterfaceSettingsComponent } from '@app/shared/shared-user-settings/user-interface-settings.component'
import { UserVideoSettingsComponent } from '@app/shared/shared-user-settings/user-video-settings.component'
@ -15,13 +16,22 @@ import { filter } from 'rxjs/operators'
selector: 'my-quick-settings',
templateUrl: './quick-settings-modal.component.html',
standalone: true,
imports: [ CommonModule, GlobalIconComponent, UserVideoSettingsComponent, UserInterfaceSettingsComponent, AlertComponent ]
imports: [
CommonModule,
GlobalIconComponent,
UserVideoSettingsComponent,
UserInterfaceSettingsComponent,
AlertComponent,
ButtonComponent
]
})
export class QuickSettingsModalComponent implements OnInit, OnDestroy {
private static readonly QUERY_MODAL_NAME = 'quick-settings'
@ViewChild('modal', { static: true }) modal: NgbModal
@Output() openLanguageModal = new EventEmitter<void>()
user: User
userInformationLoaded = new ReplaySubject<boolean>(1)
@ -83,6 +93,11 @@ export class QuickSettingsModalComponent implements OnInit, OnDestroy {
this.setModalQuery('add')
}
changeLanguage () {
this.openedModal.close()
this.openLanguageModal.emit()
}
private setModalQuery (type: 'add' | 'remove') {
const modal = type === 'add'
? QuickSettingsModalComponent.QUERY_MODAL_NAME

View file

@ -44,7 +44,7 @@
<div class="d-flex" *ngIf="abuse.updatedAt">
<span class="moderation-expanded-label" i18n>Updated</span>
<time class="moderation-expanded-text abuse-details-date-updated">{{ abuse.updatedAt | date: 'medium' }}</time>
<time class="moderation-expanded-text abuse-details-date-updated">{{ abuse.updatedAt | ptDate: 'medium' }}</time>
</div>
<!-- report text -->

View file

@ -1,19 +1,20 @@
import { NgFor, NgIf } from '@angular/common'
import { Component, Input, OnInit } from '@angular/core'
import { RouterLink } from '@angular/router'
import { durationToString } from '@app/helpers'
import { AbusePredefinedReasonsString } from '@peertube/peertube-models'
import { ProcessedAbuse } from './processed-abuse.model'
import { EmbedComponent } from '../shared-main/video/embed.component'
import { GlobalIconComponent } from '../shared-icons/global-icon.component'
import { ActorAvatarComponent } from '../shared-actor-image/actor-avatar.component'
import { RouterLink } from '@angular/router'
import { NgIf, NgFor, DatePipe } from '@angular/common'
import { GlobalIconComponent } from '../shared-icons/global-icon.component'
import { PTDatePipe } from '../shared-main/common/date.pipe'
import { EmbedComponent } from '../shared-main/video/embed.component'
import { ProcessedAbuse } from './processed-abuse.model'
@Component({
selector: 'my-abuse-details',
templateUrl: './abuse-details.component.html',
styleUrls: [ '../shared-moderation/moderation.scss', './abuse-details.component.scss' ],
standalone: true,
imports: [ NgIf, RouterLink, ActorAvatarComponent, GlobalIconComponent, NgFor, EmbedComponent, DatePipe ]
imports: [ NgIf, RouterLink, ActorAvatarComponent, GlobalIconComponent, NgFor, EmbedComponent, PTDatePipe ]
})
export class AbuseDetailsComponent implements OnInit {
@Input() abuse: ProcessedAbuse

View file

@ -118,7 +118,7 @@
</ng-container>
<td class="c-hand" [pRowToggler]="abuse">{{ abuse.createdAt | date: 'short' }}</td>
<td class="c-hand" [pRowToggler]="abuse">{{ abuse.createdAt | ptDate: 'short' }}</td>
<td class="c-hand abuse-states" [pRowToggler]="abuse">
<div *ngIf="isAbuseAccepted(abuse)" [title]="abuse.state.label" class="pt-badge badge-success">

View file

@ -10,17 +10,18 @@
.abuse-messages {
my-global-icon {
width: 22px;
position: relative;
top: -2px;
top: -1px;
@include global-icon-size(22px);
@include margin-left(3px);
}
}
.table-video-text my-global-icon,
my-video-cell my-global-icon {
width: 15px;
position: relative;
top: -2px;
@include global-icon-size(15px);
}

View file

@ -1,33 +1,34 @@
import debug from 'debug'
import { SortMeta, SharedModule } from 'primeng/api'
import { NgClass, NgIf } from '@angular/common'
import { Component, Input, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } from '@app/core'
import { formatICU } from '@app/helpers'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { AbuseState, AbuseStateType, AdminAbuse } from '@peertube/peertube-models'
import { logger } from '@root-helpers/logger'
import { AbuseMessageModalComponent } from './abuse-message-modal.component'
import { ModerationCommentModalComponent } from './moderation-comment-modal.component'
import { ProcessedAbuse } from './processed-abuse.model'
import { AbuseDetailsComponent } from './abuse-details.component'
import { AutoColspanDirective } from '../shared-main/common/auto-colspan.directive'
import { GlobalIconComponent } from '../shared-icons/global-icon.component'
import { VideoCellComponent } from '../shared-tables/video-cell.component'
import { ActorAvatarComponent } from '../shared-actor-image/actor-avatar.component'
import { ActionDropdownComponent, DropdownAction } from '../shared-main/buttons/action-dropdown.component'
import { TableExpanderIconComponent } from '../shared-tables/table-expander-icon.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { NgIf, NgClass, DatePipe } from '@angular/common'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../shared-forms/advanced-input-filter.component'
import debug from 'debug'
import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { Video } from '../shared-main/video/video.model'
import { Actor } from '../shared-main/account/actor.model'
import { VideoService } from '../shared-main/video/video.service'
import { ActorAvatarComponent } from '../shared-actor-image/actor-avatar.component'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../shared-icons/global-icon.component'
import { Account } from '../shared-main/account/account.model'
import { Actor } from '../shared-main/account/actor.model'
import { ActionDropdownComponent, DropdownAction } from '../shared-main/buttons/action-dropdown.component'
import { AutoColspanDirective } from '../shared-main/common/auto-colspan.directive'
import { PTDatePipe } from '../shared-main/common/date.pipe'
import { Video } from '../shared-main/video/video.model'
import { VideoService } from '../shared-main/video/video.service'
import { AbuseService } from '../shared-moderation/abuse.service'
import { BlocklistService } from '../shared-moderation/blocklist.service'
import { VideoBlockService } from '../shared-moderation/video-block.service'
import { TableExpanderIconComponent } from '../shared-tables/table-expander-icon.component'
import { VideoCellComponent } from '../shared-tables/video-cell.component'
import { VideoCommentService } from '../shared-video-comment/video-comment.service'
import { formatICU } from '@app/helpers'
import { AbuseDetailsComponent } from './abuse-details.component'
import { AbuseMessageModalComponent } from './abuse-message-modal.component'
import { ModerationCommentModalComponent } from './moderation-comment-modal.component'
import { ProcessedAbuse } from './processed-abuse.model'
const debugLogger = debug('peertube:moderation:AbuseListTableComponent')
@ -52,7 +53,7 @@ const debugLogger = debug('peertube:moderation:AbuseListTableComponent')
AbuseDetailsComponent,
ModerationCommentModalComponent,
AbuseMessageModalComponent,
DatePipe
PTDatePipe
]
})
export class AbuseListTableComponent extends RestTable implements OnInit {

View file

@ -21,7 +21,7 @@
<div class="bubble">
<div class="content" [innerHTML]="message.messageHtml"></div>
<div class="date">{{ message.createdAt | date }}</div>
<div class="date">{{ message.createdAt | ptDate }}</div>
</div>
</div>
</div>

View file

@ -54,11 +54,11 @@ textarea {
&.by-me {
.bubble {
color: pvar(--on-primary);
color: pvar(--on-primary-400);
background-color: pvar(--primary-400);
.date {
color: pvar(--on-primary);
color: pvar(--on-primary-400);
}
}
}

View file

@ -1,15 +1,16 @@
import { NgClass, NgFor, NgIf } from '@angular/common'
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { AuthService, HtmlRendererService, Notifier } from '@app/core'
import { FormReactive } from '@app/shared/shared-forms/form-reactive'
import { FormReactiveService } from '@app/shared/shared-forms/form-reactive.service'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap/modal/modal-ref'
import { logger } from '@root-helpers/logger'
import { AbuseMessage, UserAbuse } from '@peertube/peertube-models'
import { logger } from '@root-helpers/logger'
import { ABUSE_MESSAGE_VALIDATOR } from '../form-validators/abuse-validators'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { GlobalIconComponent } from '../shared-icons/global-icon.component'
import { NgIf, NgFor, NgClass, DatePipe } from '@angular/common'
import { PTDatePipe } from '../shared-main/common/date.pipe'
import { AbuseService } from '../shared-moderation/abuse.service'
@Component({
@ -17,7 +18,7 @@ import { AbuseService } from '../shared-moderation/abuse.service'
templateUrl: './abuse-message-modal.component.html',
styleUrls: [ './abuse-message-modal.component.scss' ],
standalone: true,
imports: [ NgIf, GlobalIconComponent, NgFor, NgClass, FormsModule, ReactiveFormsModule, DatePipe ]
imports: [ NgIf, GlobalIconComponent, NgFor, NgClass, FormsModule, ReactiveFormsModule, PTDatePipe ]
})
export class AbuseMessageModalComponent extends FormReactive implements OnInit {
@ViewChild('modal', { static: true }) modal: NgbModal

View file

@ -27,7 +27,7 @@
<div class="d-flex align-items-center item-label">
<img *ngIf="item.imageUrl" alt="" class="me-2" [src]="item.imageUrl" />
<span [ngClass]="item.classes">{{ item.label }}</span>
<span class="ellipsis" [ngClass]="item.classes">{{ item.label }}</span>
</div>
<span *ngIf="description" class="muted">{{ description }}</span>

View file

@ -1,12 +1,17 @@
:host ::ng-deep {
svg {
vertical-align: bottom;
width: inherit;
height: inherit;
}
:host {
display: inline-block;
height: 24px;
width: 24px;
.feather-flag {
margin-left: -1px;
::ng-deep {
svg {
vertical-align: bottom;
width: inherit;
height: inherit;
}
.feather-flag {
margin-left: -1px;
}
}
}

View file

@ -1,5 +1,6 @@
<button
class="btn btn-outline-secondary copy-button"
type="button"
class="btn copy-button"
(click)="copy()"
[title]="title" [ngClass]="{ 'is-input-group': isInputGroup, 'with-border': withBorder }"
>

View file

@ -11,10 +11,6 @@ button:not(.with-border, .is-input-group) {
}
my-global-icon {
width: 15px;
line-height: 15px;
height: 15px;
display: inline-block;
@include global-icon-size(15px);
@include margin-right(5px);
}

View file

@ -2,7 +2,7 @@
@use '_mixins' as *;
my-global-icon {
width: 32px;
display: inline-block;
margin-bottom: 0.75rem;
@include global-icon-size(32px);
}

View file

@ -0,0 +1,31 @@
import { DatePipe } from '@angular/common'
import { Inject, LOCALE_ID, Pipe, PipeTransform } from '@angular/core'
// Re-implementation of the angular date pipe that use the web browser locale to display dates
@Pipe({
name: 'ptDate',
standalone: true,
pure: true
})
export class PTDatePipe implements PipeTransform {
private angularPipe: DatePipe
private customLocaleId: string
constructor (@Inject(LOCALE_ID) localeId: string) {
if (navigator.language.includes('-') && navigator.language.split('-')[0] === localeId.split('-')[0]) {
this.customLocaleId = navigator.language
} else {
this.customLocaleId = localeId
}
this.angularPipe = new DatePipe(localeId)
}
transform (value: Date | string | number | null | undefined, format?: string): string {
if (format === 'short') return new Date(value).toLocaleString(this.customLocaleId)
if (format === 'shortDate') return new Date(value).toLocaleDateString(this.customLocaleId)
return this.angularPipe.transform(value, format)
}
}

View file

@ -91,7 +91,7 @@ h1 {
&.active,
&.child-active {
color: pvar(--on-primary) !important;
color: pvar(--on-primary-450) !important;
background-color: pvar(--primary-450);
opacity: .9;
}

View file

@ -30,8 +30,5 @@ input {
}
.form-control-clear my-global-icon {
width: 20px;
height: 20px;
line-height: 20px;
display: inline-block;
@include global-icon-size(20px);
}

View file

@ -51,6 +51,7 @@ export type CommonVideoParams = {
isLive?: boolean
skipCount?: boolean
nsfw?: BooleanBothQuery
search?: string
}
@Injectable()
@ -180,15 +181,12 @@ export class VideoService {
getAccountVideos (parameters: CommonVideoParams & {
account: Pick<Account, 'nameWithHost'>
search?: string
}): Observable<ResultList<Video>> {
const { account, search } = parameters
const { account } = parameters
let params = new HttpParams()
params = this.buildCommonVideosParams({ params, ...parameters })
if (search) params = params.set('search', search)
return this.authHttp
.get<ResultList<Video>>(AccountService.BASE_ACCOUNT_URL + account.nameWithHost + '/videos', { params })
.pipe(
@ -550,7 +548,10 @@ export class VideoService {
privacyOneOf,
skipCount,
isLive,
nsfw
nsfw,
search,
...otherOptions
} = options
const pagination = videoPagination
@ -568,6 +569,9 @@ export class VideoService {
if (languageOneOf !== undefined) newParams = this.restService.addArrayParams(newParams, 'languageOneOf', languageOneOf)
if (categoryOneOf !== undefined) newParams = this.restService.addArrayParams(newParams, 'categoryOneOf', categoryOneOf)
if (privacyOneOf !== undefined) newParams = this.restService.addArrayParams(newParams, 'privacyOneOf', privacyOneOf)
if (search) newParams = newParams.set('search', search)
newParams = this.restService.addObjectParams(newParams, otherOptions)
return newParams
}

View file

@ -37,7 +37,7 @@
</a>
</td>
<td>{{ accountBlock.createdAt | date: 'short' }}</td>
<td>{{ accountBlock.createdAt | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -39,7 +39,7 @@
<my-global-icon iconName="external-link"></my-global-icon>
</a>
</td>
<td>{{ serverBlock.createdAt | date: 'short' }}</td>
<td>{{ serverBlock.createdAt | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -1,14 +1,18 @@
<form (ngSubmit)="updateDetails()" [formGroup]="form">
<div class="form-group">
<div class="anchor" id="video-sensitive-content-policy"></div> <!-- video-sensitive-content-policy anchor -->
<label i18n for="nsfwPolicy">Default policy on videos containing sensitive content</label>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
With <strong>Hide</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video.
</ng-container>
</ng-template>
</my-help>
<div class="pt-label-container">
<label i18n for="nsfwPolicy">Default policy on videos containing sensitive content</label>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
With <strong>Hide</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video.
</ng-container>
</ng-template>
</my-help>
</div>
<div class="peertube-select-container">
<select id="nsfwPolicy" formControlName="nsfwPolicy" class="form-control">
@ -22,12 +26,15 @@
<div class="form-group">
<div class="anchor" id="video-languages-subtitles"></div> <!-- video-languages-subtitles anchor -->
<label i18n for="videoLanguages">Only display videos in the following languages/subtitles</label>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>In Recently added, Trending, Local, Most liked and Search pages</ng-container>
</ng-template>
</my-help>
<div class="pt-label-container">
<label i18n for="videoLanguages">Only display videos in the following languages/subtitles</label>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>In Recently added, Trending, Local, Most liked and Search pages</ng-container>
</ng-template>
</my-help>
</div>
<div>
<my-select-languages inputId="videoLanguages" [maxLanguages]="20" formControlName="videoLanguages"></my-select-languages>

View file

@ -96,7 +96,7 @@
}
</td>
<td class="c-hand" [pRowToggler]="videoComment">{{ videoComment.createdAt | date: 'short' }}</td>
<td class="c-hand" [pRowToggler]="videoComment">{{ videoComment.createdAt | ptDate: 'short' }}</td>
</tr>
</ng-template>

View file

@ -1,4 +1,4 @@
import { DatePipe, NgClass, NgIf } from '@angular/common'
import { NgClass, NgIf } from '@angular/common'
import { Component, Input, OnInit } from '@angular/core'
import { ActivatedRoute, Router, RouterLink } from '@angular/router'
import { AuthService, ConfirmService, MarkdownService, Notifier, RestPagination, RestTable } from '@app/core'
@ -12,11 +12,10 @@ import { SharedModule, SortMeta } from 'primeng/api'
import { TableModule } from 'primeng/table'
import { ActorAvatarComponent } from '../shared-actor-image/actor-avatar.component'
import { AdvancedInputFilter, AdvancedInputFilterComponent } from '../shared-forms/advanced-input-filter.component'
import { GlobalIconComponent } from '../shared-icons/global-icon.component'
import { AutoColspanDirective } from '../shared-main/common/auto-colspan.directive'
import { ActionDropdownComponent, DropdownAction } from '../shared-main/buttons/action-dropdown.component'
import { ButtonComponent } from '../shared-main/buttons/button.component'
import { FeedComponent } from '../shared-main/feeds/feed.component'
import { AutoColspanDirective } from '../shared-main/common/auto-colspan.directive'
import { PTDatePipe } from '../shared-main/common/date.pipe'
import { TableExpanderIconComponent } from '../shared-tables/table-expander-icon.component'
@Component({
@ -25,8 +24,6 @@ import { TableExpanderIconComponent } from '../shared-tables/table-expander-icon
styleUrls: [ '../shared-moderation/moderation.scss', './video-comment-list-admin-owner.component.scss' ],
standalone: true,
imports: [
GlobalIconComponent,
FeedComponent,
TableModule,
SharedModule,
NgIf,
@ -38,7 +35,7 @@ import { TableExpanderIconComponent } from '../shared-tables/table-expander-icon
NgClass,
ActorAvatarComponent,
AutoColspanDirective,
DatePipe,
PTDatePipe,
RouterLink
]
})

View file

@ -41,8 +41,8 @@
<span i18n class="pt-badge badge-success" *ngIf="!getErrorLabel(session)">Success</span>
<span class="pt-badge badge-danger" *ngIf="getErrorLabel(session)">{{ getErrorLabel(session) }}</span>
<span i18n>Started on {{ session.startDate | date:'medium' }}</span>
<span i18n *ngIf="session.endDate">Ended on {{ session.endDate | date:'medium' }}</span>
<span i18n>Started on {{ session.startDate | ptDate:'medium' }}</span>
<span i18n *ngIf="session.endDate">Ended on {{ session.endDate | ptDate:'medium' }}</span>
<a i18n *ngIf="session.replayVideo" [routerLink]="getVideoUrl(session.replayVideo)" target="_blank">Go to replay</a>
<span i18n *ngIf="isReplayBeingProcessed(session)">Replay is being processed...</span>
</div>

View file

@ -1,4 +1,4 @@
import { DatePipe, NgFor, NgIf } from '@angular/common'
import { NgFor, NgIf } from '@angular/common'
import { Component, ElementRef, ViewChild } from '@angular/core'
import { RouterLink } from '@angular/router'
import { Video } from '@app/shared/shared-main/video/video.model'
@ -8,6 +8,7 @@ import { InputTextComponent } from '../shared-forms/input-text.component'
import { GlobalIconComponent } from '../shared-icons/global-icon.component'
import { EditButtonComponent } from '../shared-main/buttons/edit-button.component'
import { AlertComponent } from '../shared-main/common/alert.component'
import { PTDatePipe } from '../shared-main/common/date.pipe'
import { LiveDocumentationLinkComponent } from './live-documentation-link.component'
import { LiveVideoService } from './live-video.service'
@ -24,7 +25,7 @@ import { LiveVideoService } from './live-video.service'
NgFor,
RouterLink,
EditButtonComponent,
DatePipe,
PTDatePipe,
AlertComponent
],
providers: [ LiveVideoService ]

View file

@ -1,6 +1,6 @@
import { NgFor, NgIf } from '@angular/common'
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
import { NgbNav, NgbNavContent, NgbNavItem, NgbNavLink, NgbNavLinkBase, NgbNavOutlet } from '@ng-bootstrap/ng-bootstrap'
import { NgbNavModule } from '@ng-bootstrap/ng-bootstrap'
import { VideoCaption } from '@peertube/peertube-models'
import { logger } from '@root-helpers/logger'
import { InputTextComponent } from '../../shared-forms/input-text.component'
@ -13,12 +13,7 @@ import { InputTextComponent } from '../../shared-forms/input-text.component'
NgIf,
NgFor,
InputTextComponent,
NgbNav,
NgbNavItem,
NgbNavLink,
NgbNavLinkBase,
NgbNavContent,
NgbNavOutlet
NgbNavModule
]
})
export class SubtitleFilesDownloadComponent implements OnInit {

View file

@ -9,10 +9,10 @@
}
my-global-icon[iconName=shield] {
width: 16px;
position: relative;
top: -2px;
top: -1px;
@include global-icon-size(16px);
@include margin-left(10px);
}

View file

@ -1,15 +1,10 @@
import { KeyValuePipe, NgClass, NgFor, NgIf, NgTemplateOutlet } from '@angular/common'
import { KeyValuePipe, NgFor, NgIf, NgTemplateOutlet } from '@angular/common'
import { Component, EventEmitter, Inject, Input, LOCALE_ID, OnInit, Output } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { AlertComponent } from '@app/shared/shared-main/common/alert.component'
import {
NgbCollapse,
NgbNav,
NgbNavContent,
NgbNavItem,
NgbNavLink,
NgbNavLinkBase,
NgbNavOutlet,
NgbNavModule,
NgbTooltip
} from '@ng-bootstrap/ng-bootstrap'
import { objectKeysTyped, pick } from '@peertube/peertube-core-utils'
@ -38,18 +33,12 @@ type FileMetadata = { [key: string]: { label: string, value: string | number } }
FormsModule,
GlobalIconComponent,
NgFor,
NgbNav,
NgbNavItem,
NgbNavLink,
NgbNavLinkBase,
NgbNavContent,
NgbNavModule,
InputTextComponent,
NgbNavOutlet,
NgbCollapse,
KeyValuePipe,
NgbTooltip,
NgTemplateOutlet,
NgClass,
AlertComponent
]
})

Some files were not shown because too many files have changed in this diff Show more