269 lines
7.3 KiB
TypeScript
269 lines
7.3 KiB
TypeScript
import { Component, HostListener, OnInit, ViewChild } from '@angular/core';
|
|
import { HeaderComponent } from '../../shared/components/header/header.component';
|
|
import { HeroBannerComponent } from './hero-banner/hero-banner.component';
|
|
import { CategoriesComponent } from './categories/categories.component';
|
|
import { VideoService } from '../../services/video.service';
|
|
import { CommonModule } from '@angular/common';
|
|
import { VideoPlayerComponent } from './video-player/video-player.component';
|
|
import { BtnSmallComponent } from '../../shared/components/buttons/btn-small/btn-small.component';
|
|
import { UploadVideoComponent } from './upload-video/upload-video.component';
|
|
import { UserService } from '../../services/user.service';
|
|
import { ResolutionService } from '../../services/resolution.service';
|
|
import { Video } from '../../interfaces/video.interface';
|
|
|
|
@Component({
|
|
selector: 'app-home',
|
|
standalone: true,
|
|
imports: [
|
|
CommonModule,
|
|
HeaderComponent,
|
|
HeroBannerComponent,
|
|
CategoriesComponent,
|
|
VideoPlayerComponent,
|
|
BtnSmallComponent,
|
|
UploadVideoComponent,
|
|
],
|
|
templateUrl: './home.component.html',
|
|
styleUrl: './home.component.scss',
|
|
})
|
|
export class HomeComponent implements OnInit {
|
|
@ViewChild(VideoPlayerComponent) videoPlayer!: VideoPlayerComponent;
|
|
|
|
videos: Video[] = [];
|
|
currentVideo: Video | null = null;
|
|
favoriteVideos: number[] = [];
|
|
watchedVideos: number[] = [];
|
|
|
|
playVideo: string = '';
|
|
isLoading: boolean = true;
|
|
uploadVideoOverview: boolean = false;
|
|
|
|
availableResolutions: string[];
|
|
currentResolution: string;
|
|
videoIsUploaded: { [resolution: string]: boolean };
|
|
|
|
private readonly SCREEN_WIDTH_THRESHOLD = 600;
|
|
|
|
/**
|
|
* Initializes the HomeComponent with the VideoService, UserService and ResolutionService.
|
|
* Get the available resolutions, current resolution, and video upload status.
|
|
*/
|
|
constructor(
|
|
private videoService: VideoService,
|
|
public userService: UserService,
|
|
private resolutionService: ResolutionService
|
|
) {
|
|
this.availableResolutions =
|
|
this.resolutionService.getAvailableResolutions();
|
|
this.currentResolution = this.resolutionService.getDefaultResolution();
|
|
this.videoIsUploaded = this.resolutionService.initVideoIsUploaded();
|
|
}
|
|
|
|
/**
|
|
* Lifecycle hook: Called once the component is initialized.
|
|
* Initializes the component by loading user data and videos.
|
|
*/
|
|
async ngOnInit(): Promise<void> {
|
|
await this.initializeComponent();
|
|
}
|
|
|
|
/**
|
|
* Determines whether the screen is considered wide.
|
|
*/
|
|
get isWideScreenView(): boolean {
|
|
return window.innerWidth > this.SCREEN_WIDTH_THRESHOLD;
|
|
}
|
|
|
|
/**
|
|
* Initializes the component by loading user data and videos.
|
|
*/
|
|
private async initializeComponent(): Promise<void> {
|
|
await this.fetchAllVideos();
|
|
await this.loadUserVideoPreferences();
|
|
this.autoSelectRandomVideoIfWideScreen();
|
|
}
|
|
|
|
/**
|
|
* Fetches all available videos from the server.
|
|
*/
|
|
private async fetchAllVideos(): Promise<void> {
|
|
this.isLoading = true;
|
|
try {
|
|
this.videos = await this.videoService.getAllVideos();
|
|
} finally {
|
|
this.isLoading = false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads the user's liked and watched video IDs.
|
|
*/
|
|
private async loadUserVideoPreferences(): Promise<void> {
|
|
try {
|
|
const { liked_videos, watched_videos } =
|
|
await this.userService.getUserVideoPreferences();
|
|
this.favoriteVideos = liked_videos;
|
|
this.watchedVideos = watched_videos;
|
|
} catch (error) {
|
|
console.error('Failed to load user video preferences:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Automatically selects a random video if screen is wide and no video is selected.
|
|
*/
|
|
private autoSelectRandomVideoIfWideScreen(): void {
|
|
if (this.isWideScreenView && !this.currentVideo) {
|
|
this.selectRandomVideoAsCurrent();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called when favorite videos change.
|
|
*/
|
|
onFavoriteVideoChange(favorites: number[]): void {
|
|
this.favoriteVideos = favorites;
|
|
this.updateLikedVideos();
|
|
}
|
|
|
|
/**
|
|
* Called when watched videos change.
|
|
*/
|
|
onWatchedVideoChange(watched: number[]): void {
|
|
this.watchedVideos = watched;
|
|
this.updateWatchedVideos();
|
|
}
|
|
|
|
/**
|
|
* Updates user's watched videos in the backend.
|
|
*/
|
|
private updateWatchedVideos(): void {
|
|
const body = { watched_videos: this.watchedVideos };
|
|
this.userService.updateWatchedVideos(body);
|
|
}
|
|
|
|
/**
|
|
* Updates user's liked videos in the backend.
|
|
*/
|
|
private updateLikedVideos(): void {
|
|
const body = {
|
|
liked_videos: this.favoriteVideos,
|
|
};
|
|
this.userService.updateLikedVideos(body);
|
|
}
|
|
|
|
/**
|
|
* Updates current video after refresh.
|
|
*/
|
|
onRefreshPage(updatedVideos: Video[] | undefined): void {
|
|
this.currentVideo = null;
|
|
setTimeout(() => {
|
|
this.currentVideo =
|
|
updatedVideos && updatedVideos.length > 0 ? updatedVideos[0] : null;
|
|
}, 0);
|
|
}
|
|
|
|
/**
|
|
* Called when the video list changes.
|
|
*/
|
|
onVideosChange(updatedVideos: Video[]): void {
|
|
if (this.isWideScreenView) {
|
|
this.selectRandomVideoAsCurrent();
|
|
} else {
|
|
this.currentVideo = updatedVideos[0] || null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called after a video upload is completed.
|
|
*/
|
|
onVideoUploaded(video: Video): void {
|
|
this.currentVideo = null;
|
|
setTimeout(() => {
|
|
this.currentVideo = video;
|
|
this.videos.push(video);
|
|
}, 1);
|
|
}
|
|
|
|
/**
|
|
* Handles resolution switching.
|
|
*/
|
|
changeResolution(resolution: string): void {
|
|
if (this.videoPlayer && this.videoIsUploaded[resolution]) {
|
|
this.videoPlayer.switchResolution(resolution);
|
|
this.currentResolution = resolution;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if any resolution is unavailable.
|
|
*/
|
|
isAnyResolutionUnavailable(): boolean {
|
|
return this.availableResolutions.some(
|
|
(resolution) => !this.videoIsUploaded[resolution]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Sets the current video to the given video ID.
|
|
*/
|
|
openCurrentVideo(video: Video): void {
|
|
this.currentVideo = video;
|
|
}
|
|
|
|
/**
|
|
* Selects a random video from the list as current video.
|
|
*/
|
|
private selectRandomVideoAsCurrent(): void {
|
|
const randomIndex = Math.floor(Math.random() * this.videos.length);
|
|
this.currentVideo = this.videos[randomIndex] || null;
|
|
}
|
|
|
|
/**
|
|
* Plays a video by path and sets resolution to default.
|
|
*/
|
|
playVideoPath(videoPath: string): void {
|
|
this.currentResolution = this.resolutionService.getDefaultResolution();
|
|
this.playVideo = videoPath;
|
|
}
|
|
|
|
/**
|
|
* Closes the currently playing video.
|
|
*/
|
|
closeVideo(): void {
|
|
this.playVideo = '';
|
|
}
|
|
|
|
/**
|
|
* Updates the state of uploaded resolutions.
|
|
*/
|
|
onVideoIsUploadedChange(newStatus: { [resolution: string]: boolean }): void {
|
|
this.videoIsUploaded = newStatus;
|
|
}
|
|
|
|
/**
|
|
* Toggles the upload video UI overview.
|
|
*/
|
|
toggleUploadVideoOverview(value: boolean): void {
|
|
this.uploadVideoOverview = value;
|
|
}
|
|
|
|
/**
|
|
* Listens for window resize events and triggers the screen size check.
|
|
*
|
|
* @param event The resize event triggered when the window is resized.
|
|
*/
|
|
@HostListener('window:resize', ['$event'])
|
|
onResize(event: Event): void {
|
|
this.checkScreenSize();
|
|
}
|
|
|
|
/**
|
|
* Checks the screen size and selects a random video if wide screen and no video is selected.
|
|
*/
|
|
private checkScreenSize(): void {
|
|
if (this.isWideScreenView && !this.currentVideo) {
|
|
this.selectRandomVideoAsCurrent();
|
|
}
|
|
}
|
|
}
|