mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 22:26:16 -08:00
131 lines
4.5 KiB
TypeScript
131 lines
4.5 KiB
TypeScript
import {
|
|
Component,
|
|
ElementRef,
|
|
inject,
|
|
Input,
|
|
OnChanges,
|
|
SimpleChanges,
|
|
ViewChild,
|
|
} from '@angular/core';
|
|
import { FormsModule } from '@angular/forms';
|
|
import { MatButtonModule } from '@angular/material/button';
|
|
import { MatIconModule } from '@angular/material/icon';
|
|
import { MatSliderModule } from '@angular/material/slider';
|
|
import { Store } from '@ngrx/store';
|
|
import { ChannelActions } from 'm3u-state';
|
|
|
|
@Component({
|
|
selector: 'app-audio-player',
|
|
template: `
|
|
<div id="audio-player">
|
|
<div class="radio-logo">
|
|
<img [src]="icon" alt="radio icon" />
|
|
</div>
|
|
<audio preload="metadata" autoplay #audio>
|
|
<source [src]="url" />
|
|
</audio>
|
|
<div class="controls">
|
|
<button mat-icon-button (click)="switchChannel('previous')">
|
|
<mat-icon>skip_previous</mat-icon>
|
|
</button>
|
|
|
|
@if (playState === 'paused') {
|
|
<button
|
|
class="icon-button-large"
|
|
mat-icon-button
|
|
(click)="play()"
|
|
>
|
|
<mat-icon>play_arrow</mat-icon>
|
|
</button>
|
|
}
|
|
@if (playState === 'play') {
|
|
<button
|
|
class="icon-button-large"
|
|
mat-icon-button
|
|
(click)="stop()"
|
|
>
|
|
<mat-icon>pause</mat-icon>
|
|
</button>
|
|
}
|
|
<button mat-icon-button (click)="switchChannel('next')">
|
|
<mat-icon>skip_next</mat-icon>
|
|
</button>
|
|
</div>
|
|
<div class="volume-panel">
|
|
@if (playState === 'play') {
|
|
<div class="playing">
|
|
<span class="playing-bar playing-bar1"></span>
|
|
<span class="playing-bar playing-bar2"></span>
|
|
<span class="playing-bar playing-bar3"></span>
|
|
</div>
|
|
}
|
|
@if (playState === 'paused') {
|
|
<div class="playing">
|
|
<span class="playing-bar-stopped playing-bar1"></span>
|
|
<span class="playing-bar-stopped playing-bar2"></span>
|
|
<span class="playing-bar-stopped playing-bar3"></span>
|
|
</div>
|
|
}
|
|
<mat-slider min="0" max="1" step="0.1" color="accent">
|
|
<input matSliderThumb [(ngModel)]="audio.volume" />
|
|
</mat-slider>
|
|
<button mat-icon-button (click)="mute()">
|
|
@if (audio.volume > 0 && !audio.muted) {
|
|
<mat-icon>volume_up</mat-icon>
|
|
}
|
|
@if (audio.volume === 0 || audio.muted) {
|
|
<mat-icon>volume_off</mat-icon>
|
|
}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`,
|
|
styleUrls: ['./audio-player.component.scss'],
|
|
imports: [MatSliderModule, MatIconModule, MatButtonModule, FormsModule],
|
|
})
|
|
export class AudioPlayerComponent implements OnChanges {
|
|
@Input() icon!: string;
|
|
@Input({ required: true }) url!: string;
|
|
|
|
playState: 'play' | 'paused' = 'paused';
|
|
|
|
fallbackVolume!: number;
|
|
|
|
@ViewChild('audio', { static: true }) audio!: ElementRef<HTMLAudioElement>;
|
|
|
|
private store = inject(Store);
|
|
|
|
ngOnChanges(changes: SimpleChanges): void {
|
|
this.audio.nativeElement.src = changes['url'].currentValue;
|
|
this.audio.nativeElement.load();
|
|
this.play();
|
|
}
|
|
|
|
play() {
|
|
const playPromise = this.audio.nativeElement.play();
|
|
if (playPromise !== undefined) {
|
|
playPromise.catch((error) => {
|
|
console.log(error);
|
|
});
|
|
}
|
|
this.playState = 'play';
|
|
}
|
|
|
|
stop() {
|
|
this.audio.nativeElement.pause();
|
|
this.playState = 'paused';
|
|
}
|
|
|
|
mute() {
|
|
this.audio.nativeElement.muted = !this.audio.nativeElement.muted;
|
|
if (this.audio.nativeElement.muted) {
|
|
this.fallbackVolume = this.audio.nativeElement.volume;
|
|
this.audio.nativeElement.volume = 0;
|
|
} else this.audio.nativeElement.volume = this.fallbackVolume;
|
|
}
|
|
|
|
switchChannel(direction: 'next' | 'previous') {
|
|
this.store.dispatch(ChannelActions.setAdjacentChannelAsActive({ direction }));
|
|
}
|
|
}
|