canti primo tag
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
import { Component, OnInit, OnDestroy, signal, computed, inject } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { CantiService, Canto } from '../../services/canti.service';
|
||||
import { LyricsParserService, ParsedSection } from '../../services/lyrics-parser.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-display',
|
||||
templateUrl: './display.page.html',
|
||||
styleUrls: ['./display.page.scss'],
|
||||
standalone: false
|
||||
})
|
||||
export class DisplayPage implements OnInit, OnDestroy {
|
||||
public canto = signal<Canto | null>(null);
|
||||
public showChords = signal<boolean>(false);
|
||||
public fontSize = signal<number>(1.0);
|
||||
public currentLineIndex = signal<number>(0);
|
||||
|
||||
public parsedSections = computed<ParsedSection[]>(() => {
|
||||
const c = this.canto();
|
||||
if (!c) return [];
|
||||
if (this.showChords() && c.accordi) {
|
||||
return this.lyricsParser.parseAccordi(c.accordi);
|
||||
}
|
||||
return this.lyricsParser.parseText(c.testo);
|
||||
});
|
||||
|
||||
/** Get the current line text and surrounding lines from flat index */
|
||||
public displayLines = computed(() => {
|
||||
const sections = this.parsedSections();
|
||||
const idx = this.currentLineIndex();
|
||||
const allLines: { text: string; segments: any[]; sectionType: string }[] = [];
|
||||
|
||||
for (const section of sections) {
|
||||
for (const line of section.lines) {
|
||||
allLines.push({ text: line.text, segments: line.segments, sectionType: section.type });
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
prev: idx > 0 ? allLines[idx - 1] : null,
|
||||
current: allLines[idx] || null,
|
||||
next: idx < allLines.length - 1 ? allLines[idx + 1] : null
|
||||
};
|
||||
});
|
||||
|
||||
private channel = new BroadcastChannel('karaoke_sync');
|
||||
|
||||
private readonly MIN_FONT = 0.6;
|
||||
private readonly MAX_FONT = 5.0;
|
||||
private initialPinchDistance: number | null = null;
|
||||
private initialFontSize: number = 1.0;
|
||||
|
||||
private route = inject(ActivatedRoute);
|
||||
private cantiService = inject(CantiService);
|
||||
private lyricsParser = inject(LyricsParserService);
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
this.route.queryParams.subscribe(params => {
|
||||
const id = params['id'];
|
||||
if (id) {
|
||||
const found = this.cantiService.getCantoById(id);
|
||||
if (found) this.canto.set(found);
|
||||
}
|
||||
});
|
||||
|
||||
this.channel.onmessage = (event) => {
|
||||
if (event.data.type === 'SYNC_INDEX') {
|
||||
this.currentLineIndex.set(event.data.index);
|
||||
}
|
||||
if (event.data.type === 'SYNC_CANTO') {
|
||||
const found = this.cantiService.getCantoById(event.data.id);
|
||||
if (found) this.canto.set(found);
|
||||
}
|
||||
if (event.data.type === 'SYNC_CHORDS') {
|
||||
this.showChords.set(event.data.showChords);
|
||||
}
|
||||
if (event.data.type === 'SYNC_FONT') {
|
||||
this.fontSize.set(event.data.fontSize);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.channel.close();
|
||||
}
|
||||
|
||||
// --- Touch Gestures for Pinch-to-Zoom ---
|
||||
onTouchStart(event: TouchEvent) {
|
||||
if (event.touches.length === 2) {
|
||||
this.initialPinchDistance = this.getDistance(event.touches[0], event.touches[1]);
|
||||
this.initialFontSize = this.fontSize();
|
||||
}
|
||||
}
|
||||
|
||||
onTouchMove(event: TouchEvent) {
|
||||
if (event.touches.length === 2 && this.initialPinchDistance !== null) {
|
||||
event.preventDefault(); // Prevent browser zoom/scroll
|
||||
const currentDistance = this.getDistance(event.touches[0], event.touches[1]);
|
||||
const ratio = currentDistance / this.initialPinchDistance;
|
||||
let newSize = this.initialFontSize * ratio;
|
||||
|
||||
// Clamp values
|
||||
newSize = Math.max(this.MIN_FONT, Math.min(this.MAX_FONT, newSize));
|
||||
|
||||
if (Math.abs(newSize - this.fontSize()) > 0.01) {
|
||||
this.fontSize.set(newSize);
|
||||
// Sync back to player if display is touched
|
||||
this.channel.postMessage({ type: 'SYNC_FONT', fontSize: this.fontSize() });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onTouchEnd() {
|
||||
this.initialPinchDistance = null;
|
||||
}
|
||||
|
||||
private getDistance(t1: Touch, t2: Touch): number {
|
||||
return Math.sqrt(Math.pow(t1.clientX - t2.clientX, 2) + Math.pow(t1.clientY - t2.clientY, 2));
|
||||
}
|
||||
// ----------------------------------------
|
||||
}
|
||||
Reference in New Issue
Block a user