chore: update Angular cache and TypeScript build info
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, inject, signal } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { LikesService } from '../../../../services/likes.service';
|
||||
import { finalize } from 'rxjs';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { AuthService } from '../../../../services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-like-button',
|
||||
standalone: true,
|
||||
imports: [CommonModule, HttpClientModule],
|
||||
// Le service est déjà fourni via providedIn: 'root' dans le service
|
||||
template: `
|
||||
<button
|
||||
(click)="onClick($event)"
|
||||
[class.text-red-500]="isLiked()"
|
||||
[class.text-slate-400]="!isLiked()"
|
||||
[class.hover\:text-red-500]="!isLiked()"
|
||||
[disabled]="isLoading() || !isAuthenticated()"
|
||||
class="transition-colors duration-200 p-1 rounded-full hover:bg-slate-700/50 flex items-center justify-center"
|
||||
[attr.aria-label]="!isAuthenticated() ? 'Connectez-vous pour aimer' : (isLiked() ? 'Retirer des vidéos aimées' : 'Ajouter aux vidéos aimées')"
|
||||
[attr.aria-pressed]="isLiked()"
|
||||
>
|
||||
@if (isLoading()) {
|
||||
<svg class="animate-spin h-5 w-5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
|
||||
</svg>
|
||||
<span class="sr-only">Chargement...</span>
|
||||
} @else {
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
[attr.aria-hidden]="true"
|
||||
>
|
||||
<path
|
||||
[attr.d]="isLiked() ? 'M12 21.35l-1.45-1.32C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3c1.74 0 3.41.81 4.5 2.09C13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78-3.4 6.86-8.55 11.54L12 21.35z' : 'M16.5 3c-1.74 0-3.41.81-4.5 2.09C10.91 3.81 9.24 3 7.5 3 4.42 3 2 5.42 2 8.5c0 3.78 3.4 6.86 8.55 11.54L12 21.35l1.45-1.32C18.6 15.36 22 12.28 22 8.5 22 5.42 19.58 3 16.5 3zm-4.4 15.55l-.1.1-.1-.1C7.14 14.24 4 11.39 4 8.5 4 6.5 5.5 5 7.5 5c1.54 0 3.04.99 3.57 2.36h1.87C13.46 5.99 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5 0 2.89-3.14 5.74-7.9 10.05z'"
|
||||
/>
|
||||
</svg>
|
||||
<span class="sr-only">{{ isLiked() ? 'Retirer des vidéos aimées' : 'Ajouter aux vidéos aimées' }}</span>
|
||||
}
|
||||
</button>
|
||||
`,
|
||||
styles: [
|
||||
`
|
||||
:host {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
button {
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
button:disabled {
|
||||
opacity: 0.7;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
button:not(:disabled):hover {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
padding: 0;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: nowrap;
|
||||
border-width: 0;
|
||||
}
|
||||
`
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class LikeButtonComponent implements OnInit, OnDestroy, OnChanges {
|
||||
private likesService = inject(LikesService);
|
||||
private auth = inject(AuthService);
|
||||
|
||||
@Input() provider = 'youtube';
|
||||
|
||||
private _videoId = '';
|
||||
|
||||
@Input()
|
||||
set videoId(value: string) {
|
||||
if (this._videoId !== value) {
|
||||
this._videoId = value;
|
||||
this.checkLikeStatus();
|
||||
}
|
||||
}
|
||||
|
||||
get videoId(): string {
|
||||
return this._videoId;
|
||||
}
|
||||
|
||||
isLiked = signal<boolean>(false);
|
||||
isLoading = signal<boolean>(true);
|
||||
isAuthenticated = signal<boolean>(false);
|
||||
private destroyRef = false;
|
||||
|
||||
ngOnInit() {
|
||||
// Vérifie le statut du like à l'initialisation
|
||||
this.isAuthenticated.set(!!this.auth.currentUser());
|
||||
this.checkLikeStatus();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
// Vérifie le statut du like lorsque les propriétés d'entrée changent
|
||||
if (changes['videoId'] && !changes['videoId'].firstChange) {
|
||||
this.checkLikeStatus();
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroyRef = true;
|
||||
}
|
||||
|
||||
onClick(event: MouseEvent) {
|
||||
try { event.preventDefault(); event.stopPropagation(); } catch {}
|
||||
// Re-evaluate auth state on interaction (in case it changed)
|
||||
this.isAuthenticated.set(!!this.auth.currentUser());
|
||||
if (!this.isAuthenticated()) return;
|
||||
this.toggleLike();
|
||||
}
|
||||
|
||||
checkLikeStatus() {
|
||||
if (!this.videoId) {
|
||||
this.isLoading.set(false);
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading.set(true);
|
||||
try {
|
||||
this.likesService.isLiked(this.provider, this.videoId)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
if (!this.destroyRef) {
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
})
|
||||
)
|
||||
.subscribe({
|
||||
next: (response: { liked: boolean }) => {
|
||||
if (!this.destroyRef) {
|
||||
this.isLiked.set(response.liked);
|
||||
}
|
||||
},
|
||||
error: (err: any) => {
|
||||
console.error('Erreur lors de la vérification du like:', err);
|
||||
if (!this.destroyRef) {
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la vérification du like:', error);
|
||||
if (!this.destroyRef) {
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toggleLike() {
|
||||
if (this.isLoading() || !this.videoId) return;
|
||||
|
||||
this.isLoading.set(true);
|
||||
|
||||
try {
|
||||
if (this.isLiked()) {
|
||||
this.likesService.unlike(this.provider, this.videoId)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
if (!this.destroyRef) {
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
})
|
||||
)
|
||||
.subscribe({
|
||||
next: (response: { removed: boolean }) => {
|
||||
if (!this.destroyRef) {
|
||||
this.isLiked.set(false);
|
||||
}
|
||||
},
|
||||
error: (err: any) => {
|
||||
console.error('Erreur lors du retrait du like:', err);
|
||||
if (!this.destroyRef) {
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.likesService.like(this.provider, this.videoId)
|
||||
.pipe(
|
||||
finalize(() => {
|
||||
if (!this.destroyRef) {
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
})
|
||||
)
|
||||
.subscribe({
|
||||
next: () => {
|
||||
if (!this.destroyRef) {
|
||||
this.isLiked.set(true);
|
||||
}
|
||||
},
|
||||
error: (err: any) => {
|
||||
console.error('Erreur lors de l\'ajout du like:', err);
|
||||
if (!this.destroyRef) {
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Erreur lors de la gestion du like:', error);
|
||||
if (!this.destroyRef) {
|
||||
this.isLoading.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user