blrec/webapp/src/app/tasks/task-item/task-item.component.ts
2022-08-24 11:57:41 +08:00

240 lines
6.6 KiB
TypeScript

import {
Component,
OnChanges,
OnDestroy,
Input,
HostBinding,
SimpleChanges,
ChangeDetectionStrategy,
ChangeDetectorRef,
} from '@angular/core';
import { HttpErrorResponse } from '@angular/common/http';
import { BreakpointObserver } from '@angular/cdk/layout';
import { Subject, zip } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
import { NzMessageService } from 'ng-zorro-antd/message';
import { NzModalService } from 'ng-zorro-antd/modal';
import { retry } from '../../shared/rx-operators';
import { breakpoints } from '../shared/breakpoints';
import { SettingService } from '../../settings/shared/services/setting.service';
import { RunningStatus, TaskData } from '../shared/task.model';
import { TaskManagerService } from '../shared/services/task-manager.service';
import {
TaskOptions,
GlobalTaskSettings,
TaskOptionsIn,
} from '../../settings/shared/setting.model';
import { TaskSettingsService } from '../shared/services/task-settings.service';
@Component({
selector: 'app-task-item',
templateUrl: './task-item.component.html',
styleUrls: ['./task-item.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TaskItemComponent implements OnChanges, OnDestroy {
@Input() data!: TaskData;
@HostBinding('class.stopped') stopped = false;
taskOptions?: TaskOptions;
globalSettings?: GlobalTaskSettings;
destroyed = new Subject<void>();
useDrawer = false;
menuDrawerVisible = false;
switchPending = false;
settingsDialogVisible = false;
readonly RunningStatus = RunningStatus;
constructor(
breakpointObserver: BreakpointObserver,
private changeDetector: ChangeDetectorRef,
private message: NzMessageService,
private modal: NzModalService,
private settingService: SettingService,
private taskManager: TaskManagerService,
private appTaskSettings: TaskSettingsService
) {
breakpointObserver
.observe(breakpoints[0])
.pipe(takeUntil(this.destroyed))
.subscribe((state) => {
this.useDrawer = state.matches;
changeDetector.markForCheck();
});
}
get roomId() {
return this.data.room_info.room_id;
}
get toggleRecorderForbidden() {
return !this.data.task_status.monitor_enabled;
}
get showInfoPanel() {
return Boolean(this.appTaskSettings.getSettings(this.roomId).showInfoPanel);
}
set showInfoPanel(value: boolean) {
this.appTaskSettings.updateSettings(this.roomId, { showInfoPanel: value });
}
ngOnChanges(changes: SimpleChanges): void {
console.debug('[ngOnChanges]', this.roomId, changes);
this.stopped =
this.data.task_status.running_status === RunningStatus.STOPPED;
}
ngOnDestroy() {
this.destroyed.next();
this.destroyed.complete();
}
updateTaskInfo(): void {
this.taskManager.updateTaskInfo(this.roomId).subscribe();
}
toggleRecorder(): void {
if (this.toggleRecorderForbidden) {
return;
}
if (this.switchPending) {
return;
}
this.switchPending = true;
if (this.data.task_status.recorder_enabled) {
this.taskManager
.disableRecorder(this.roomId)
.subscribe(() => (this.switchPending = false));
} else {
this.taskManager
.enableRecorder(this.roomId)
.subscribe(() => (this.switchPending = false));
}
}
removeTask(): void {
this.taskManager.removeTask(this.roomId).subscribe();
}
startTask(): void {
if (this.data.task_status.running_status === RunningStatus.STOPPED) {
this.taskManager.startTask(this.roomId).subscribe();
} else {
this.message.warning('任务运行中,忽略操作。');
}
}
stopTask(force: boolean = false): void {
if (this.data.task_status.running_status === RunningStatus.STOPPED) {
this.message.warning('任务处于停止状态,忽略操作。');
return;
}
if (
force &&
this.data.task_status.running_status == RunningStatus.RECORDING
) {
this.modal.confirm({
nzTitle: '确定要强制停止任务?',
nzContent: '正在录制的文件会被强行中断!确定要放弃正在录制的文件?',
nzOnOk: () =>
new Promise((resolve, reject) => {
this.taskManager
.stopTask(this.roomId, force)
.subscribe(resolve, reject);
}),
});
} else {
this.taskManager.stopTask(this.roomId).subscribe();
}
}
disableRecorder(force: boolean = false): void {
if (!this.data.task_status.recorder_enabled) {
this.message.warning('录制处于关闭状态,忽略操作。');
return;
}
if (
force &&
this.data.task_status.running_status == RunningStatus.RECORDING
) {
this.modal.confirm({
nzTitle: '确定要强制停止录制?',
nzContent: '正在录制的文件会被强行中断!确定要放弃正在录制的文件?',
nzOnOk: () =>
new Promise((resolve, reject) => {
this.taskManager
.disableRecorder(this.roomId, force)
.subscribe(resolve, reject);
}),
});
} else {
this.taskManager.disableRecorder(this.roomId).subscribe();
}
}
openSettingsDialog(): void {
zip(
this.settingService.getTaskOptions(this.roomId),
this.settingService.getSettings([
'output',
'biliApi',
'header',
'danmaku',
'recorder',
'postprocessing',
])
).subscribe(
([taskOptions, globalSettings]) => {
this.taskOptions = taskOptions;
this.globalSettings = globalSettings;
this.settingsDialogVisible = true;
this.changeDetector.markForCheck();
},
(error: HttpErrorResponse) => {
this.message.error(`获取任务设置出错: ${error.message}`);
}
);
}
cleanSettingsData(): void {
delete this.taskOptions;
delete this.globalSettings;
this.changeDetector.markForCheck();
}
changeTaskOptions(options: TaskOptionsIn): void {
this.settingService
.changeTaskOptions(this.roomId, options)
.pipe(retry(3, 300))
.subscribe(
(options) => {
this.message.success('修改任务设置成功');
},
(error: HttpErrorResponse) => {
this.message.error(`修改任务设置出错: ${error.message}`);
}
);
}
cutStream(): void {
if (this.data.task_status.running_status === RunningStatus.RECORDING) {
this.taskManager
.canCutStream(this.roomId)
.subscribe((ableToCutStream) => {
if (ableToCutStream) {
this.taskManager.cutStream(this.roomId).subscribe();
}
});
}
}
}