Optimize caption edit modal

This commit is contained in:
Chocobozzz 2024-11-08 10:31:19 +01:00
parent 6e2f86e1b3
commit 857507dd1d
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
6 changed files with 78 additions and 74 deletions

View File

@ -42,72 +42,78 @@
</div>
<div class="text-start segments pe-2 ps-2" [hidden]="rawEdition">
<div class="pt-1 pb-1 mb-3" *ngFor="let segment of segments">
@if (segmentToUpdate === segment) {
<div role="form">
<div class="d-flex flex-wrap ">
<div>
<label class="visually-hidden" i18n for="segmentStart">Segment start timestamp</label>
@for (segment of segments; track segment.id) {
<div class="pt-1 pb-1 mb-3">
@if (segmentToUpdate === segment) {
<div role="form">
<div class="d-flex flex-wrap ">
<div>
<label class="visually-hidden" i18n for="segmentStart">Segment start timestamp</label>
<my-timestamp-input
class="me-1"
inputName="segmentStart" [disableBorder]="false" [maxTimestamp]="publishedVideo.duration * 1000" mask="99:99:99.999"
[(ngModel)]="segment.startMs" [parser]="timestampParser" [formatter]="timestampFormatter"
></my-timestamp-input>
<my-timestamp-input
class="me-1"
inputName="segmentStart" [disableBorder]="false" [maxTimestamp]="publishedVideo.duration * 1000" mask="99:99:99.999"
[(ngModel)]="segment.startMs" [parser]="timestampParser" [formatter]="timestampFormatter"
></my-timestamp-input>
<my-button *ngIf="publishedVideo" icon="clock-arrow-down" i18n-title title="Use video current time as start time" (click)="videoTimeForSegmentStart(segment)">
</my-button>
<my-button *ngIf="publishedVideo" icon="clock-arrow-down" i18n-title title="Use video current time as start time" (click)="videoTimeForSegmentStart(segment)">
</my-button>
</div>
<my-global-icon class="d-inline-block ms-2 me-2" iconName="move-right"></my-global-icon>
<div>
<label class="visually-hidden" i18n for="segmentEnd">Segment end timestamp</label>
<my-timestamp-input
class="me-1"
inputName="segmentEnd" [disableBorder]="false" [maxTimestamp]="publishedVideo.duration * 1000" mask="99:99:99.999"
[(ngModel)]="segment.endMs" [parser]="timestampParser" [formatter]="timestampFormatter"
></my-timestamp-input>
<my-button *ngIf="publishedVideo" icon="clock-arrow-down" i18n-title title="Use video current time as end time" (click)="videoTimeForSegmentEnd(segment)">
</my-button>
</div>
</div>
<my-global-icon class="d-inline-block ms-2 me-2" iconName="move-right"></my-global-icon>
<div class="d-flex mt-2">
<div class="form-group w-100">
<label class="visually-hidden" i18n for="segment-edition">Segment end timestamp</label>
<div>
<label class="visually-hidden" i18n for="segmentEnd">Segment end timestamp</label>
<textarea id="segment-edition" name="segment-edition" class="form-control fs-7" [(ngModel)]="segment.text"></textarea>
<my-timestamp-input
class="me-1"
inputName="segmentEnd" [disableBorder]="false" [maxTimestamp]="publishedVideo.duration * 1000" mask="99:99:99.999"
[(ngModel)]="segment.endMs" [parser]="timestampParser" [formatter]="timestampFormatter"
></my-timestamp-input>
<div *ngIf="segmentEditionError" class="form-error" role="alert">{{ segmentEditionError }}</div>
</div>
<my-button *ngIf="publishedVideo" icon="clock-arrow-down" i18n-title title="Use video current time as end time" (click)="videoTimeForSegmentEnd(segment)">
</my-button>
<div class="d-flex flex-column ms-3">
<my-button i18n-title title="Save" icon="tick" (click)="onEditionSaved(segment)"></my-button>
<my-button class="mt-3" i18n-title title="Revert" icon="undo" (click)="onEditionCanceled(segment)"></my-button>
</div>
</div>
</div>
<div class="d-flex mt-2">
<div class="form-group w-100">
<label class="visually-hidden" i18n for="segment-edition">Segment end timestamp</label>
<textarea id="segment-edition" name="segment-edition" class="form-control fs-7" [(ngModel)]="segment.text"></textarea>
<div *ngIf="segmentEditionError" class="form-error" role="alert">{{ segmentEditionError }}</div>
} @else {
<div class="d-flex">
<div
class="flex-grow-1 segment-text ps-1 pe-1" role="button" tabindex="0" i18n-title title="Jump to this segment"
(keyup.enter)="onSegmentClick($event, segment)" (click)="onSegmentClick($event, segment)"
[ngClass]="{ active: segment === activeSegment }"
>
<strong class="segment-start me-2 d-block">{{ segment.startFormatted }} -> {{ segment.endFormatted }}</strong>
<span class="segment-text fs-7">{{ segment.text }}</span>
</div>
<div class="d-flex flex-column ms-3">
<my-button i18n-title title="Save" icon="tick" (click)="onEditionSaved(segment)"></my-button>
<my-button class="mt-3" i18n-title title="Revert" icon="undo" (click)="onEditionCanceled(segment)"></my-button>
</div>
<div class="d-flex flex-column ms-3" [ngClass]="{ 'opacity-0': !!segmentToUpdate }">
@defer (on viewport) {
<my-edit-button i18n-title title="Edit this segment" (click)="updateSegment(segment)"></my-edit-button>
<my-delete-button class="mt-1" i18n-title title="Delete this segment" (click)="deleteSegment(segment)"></my-delete-button>
} @placeholder {
<div style="height: 100%; width: 40px"></div>
}
</div>
</div>
</div>
} @else {
<div class="d-flex">
<div
class="flex-grow-1 segment-text ps-1 pe-1" role="button" tabindex="0" i18n-title title="Jump to this segment"
(keyup.enter)="onSegmentClick($event, segment)" (click)="onSegmentClick($event, segment)"
[ngClass]="getSegmentClasses(segment)"
>
<strong class="segment-start me-2 d-block">{{ segment.startFormatted }} -> {{ segment.endFormatted }}</strong>
<span class="segment-text fs-7" [innerHTML]="segment.text | nl2br"></span>
</div>
<div class="d-flex flex-column ms-3" [ngClass]="{ 'opacity-0': !!segmentToUpdate }">
<my-edit-button i18n-title title="Edit this segment" (click)="updateSegment(segment)"></my-edit-button>
<my-delete-button class="mt-1" i18n-title title="Delete this segment" (click)="deleteSegment(segment)"></my-delete-button>
</div>
</div>
}
</div>
}
</div>
}
</div>
</div>
</div>

View File

@ -14,6 +14,8 @@
}
.segment-text {
white-space: pre-wrap;
&.active,
&:hover {
background: pvar(--mainBackgroundHoverColor);

View File

@ -330,13 +330,9 @@ export class VideoCaptionEditModalContentComponent extends FormReactive implemen
this.openedModal.close()
}
getSegmentClasses (segment: Segment) {
return { active: this.activeSegment === segment, ['segment-' + segment.id]: true }
}
private scrollToSegment (segment: Segment) {
setTimeout(() => {
const element = document.querySelector<HTMLElement>('.segment-' + segment.id)
const element = document.querySelector<HTMLElement>(`.segments > div:nth-child(${parseInt(segment.id) + 1})`)
if (!element) return
element.scrollIntoView({ behavior: 'smooth', block: 'center' })

View File

@ -1,10 +1,10 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges, OnInit, booleanAttribute } from '@angular/core'
import { NgClass, NgIf, NgTemplateOutlet } from '@angular/common'
import { ChangeDetectionStrategy, Component, Input, OnChanges, booleanAttribute } from '@angular/core'
import { RouterLink } from '@angular/router'
import { GlobalIconName } from '@app/shared/shared-icons/global-icon.component'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { GlobalIconComponent } from '../../shared-icons/global-icon.component'
import { LoaderComponent } from '../common/loader.component'
import { RouterLink } from '@angular/router'
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
import { NgIf, NgClass, NgTemplateOutlet } from '@angular/common'
@Component({
selector: 'my-button',
@ -15,7 +15,7 @@ import { NgIf, NgClass, NgTemplateOutlet } from '@angular/common'
imports: [ NgIf, NgClass, NgbTooltip, NgTemplateOutlet, RouterLink, LoaderComponent, GlobalIconComponent ]
})
export class ButtonComponent implements OnInit, OnChanges {
export class ButtonComponent implements OnChanges {
@Input() label = ''
@Input() theme: 'orange' | 'grey' = 'grey'
@Input() icon: GlobalIconName
@ -27,15 +27,13 @@ export class ButtonComponent implements OnInit, OnChanges {
classes: { [id: string]: boolean } = {}
ngOnInit () {
this.buildClasses()
}
ngOnChanges () {
this.buildClasses()
}
private buildClasses () {
console.log('build classes')
this.classes = {
'peertube-button': !this.ptRouterLink,
'peertube-button-link': !!this.ptRouterLink,

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'
import { ButtonComponent } from './button.component'
@Component({
@ -11,15 +11,16 @@ import { ButtonComponent } from './button.component'
></my-button>
`,
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ ButtonComponent ]
})
export class DeleteButtonComponent implements OnInit {
export class DeleteButtonComponent implements OnChanges {
@Input() label: string
@Input() title: string
@Input() responsiveLabel = false
@Input() disabled: boolean
ngOnInit () {
ngOnChanges () {
if (this.label === undefined && !this.title) {
this.title = $localize`Delete`
}

View File

@ -1,4 +1,4 @@
import { Component, Input, OnInit } from '@angular/core'
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core'
import { ButtonComponent } from './button.component'
@Component({
@ -10,15 +10,16 @@ import { ButtonComponent } from './button.component'
></my-button>
`,
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [ ButtonComponent ]
})
export class EditButtonComponent implements OnInit {
export class EditButtonComponent implements OnChanges {
@Input() label: string
@Input() title: string
@Input() ptRouterLink: string[] | string = []
@Input() responsiveLabel = false
ngOnInit () {
ngOnChanges () {
// <my-edit-button /> No label
if (this.label === undefined && !this.title) {
this.title = $localize`Update`