modifiche face offline e 2 secondi di attesa
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, ViewChild, ElementRef, inject } from '@angular/core';
|
||||
import { Component, OnInit, OnDestroy, ViewChild, ElementRef, inject } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { IonicModule, ToastController, IonTextarea, PopoverController, NavController, AlertController } from '@ionic/angular';
|
||||
@@ -9,6 +9,7 @@ import { PlaylistService } from '../../services/playlist.service';
|
||||
import { ThemeService } from '../../services/theme.service';
|
||||
import { ActivatedRoute, RouterModule, Router } from '@angular/router';
|
||||
import { LyricsParserService, ParsedSection } from '../../services/lyrics-parser.service';
|
||||
import { YoutubePlayerService } from '../../services/youtube-player.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-propose-canto',
|
||||
@@ -17,8 +18,9 @@ import { LyricsParserService, ParsedSection } from '../../services/lyrics-parser
|
||||
standalone: true,
|
||||
imports: [CommonModule, FormsModule, IonicModule, RouterModule]
|
||||
})
|
||||
export class ProposeCantoPage implements OnInit {
|
||||
@ViewChild('contentTextarea', { static: false }) contentTextarea!: IonTextarea;
|
||||
export class ProposeCantoPage implements OnInit, OnDestroy {
|
||||
@ViewChild('nativeTextarea', { static: false }) nativeTextarea!: ElementRef<HTMLTextAreaElement>;
|
||||
|
||||
@ViewChild('cameraInput', { static: false }) cameraInput!: ElementRef;
|
||||
@ViewChild('fileInput', { static: false }) fileInput!: ElementRef;
|
||||
|
||||
@@ -31,12 +33,154 @@ export class ProposeCantoPage implements OnInit {
|
||||
private router = inject(Router);
|
||||
public lyricsParser = inject(LyricsParserService);
|
||||
private alertCtrl = inject(AlertController);
|
||||
public youtubePlayerService = inject(YoutubePlayerService);
|
||||
|
||||
showChordsPreview: boolean = true;
|
||||
activeTab: string = 'editor';
|
||||
transposeAmount: number = 0;
|
||||
|
||||
get highlightedHtml(): string {
|
||||
if (!this.content) return '';
|
||||
|
||||
let escaped = this.content
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
|
||||
escaped = escaped.replace(/\[([^\]]+)\]/g, (match, chord) => {
|
||||
const transposed = this.transposeAmount !== 0
|
||||
? this.lyricsParser.transposeChord(chord, this.transposeAmount)
|
||||
: chord;
|
||||
return `<span class="editor-chord">[${transposed}]</span>`;
|
||||
});
|
||||
|
||||
const lines = escaped.split('\n');
|
||||
let htmlLines: string[] = [];
|
||||
let inChorus = false;
|
||||
let inVerse = false;
|
||||
let inVerseNum = false;
|
||||
|
||||
for (const line of lines) {
|
||||
const trimmed = line.trim();
|
||||
|
||||
let currentInChorus = inChorus;
|
||||
let currentInVerse = inVerse;
|
||||
let currentInVerseNum = inVerseNum;
|
||||
|
||||
let isTagLine = false;
|
||||
let processedContent = line;
|
||||
|
||||
if (trimmed === '{start_chorus}' || trimmed === '{soc}') {
|
||||
inChorus = true;
|
||||
currentInChorus = true;
|
||||
isTagLine = true;
|
||||
processedContent = `<span class="editor-tag">${line}</span>`;
|
||||
} else if (trimmed === '{end_chorus}' || trimmed === '{eoc}') {
|
||||
inChorus = false;
|
||||
currentInChorus = true;
|
||||
isTagLine = true;
|
||||
processedContent = `<span class="editor-tag">${line}</span>`;
|
||||
} else if (trimmed === '{start_verse}' || trimmed === '{sov}') {
|
||||
inVerse = true;
|
||||
currentInVerse = true;
|
||||
isTagLine = true;
|
||||
processedContent = `<span class="editor-tag">${line}</span>`;
|
||||
} else if (trimmed === '{end_verse}' || trimmed === '{eov}') {
|
||||
inVerse = false;
|
||||
currentInVerse = true;
|
||||
isTagLine = true;
|
||||
processedContent = `<span class="editor-tag">${line}</span>`;
|
||||
} else if (trimmed === '{start_verse_num}') {
|
||||
inVerseNum = true;
|
||||
currentInVerseNum = true;
|
||||
isTagLine = true;
|
||||
processedContent = `<span class="editor-tag">${line}</span>`;
|
||||
} else if (trimmed === '{end_verse_num}') {
|
||||
inVerseNum = false;
|
||||
currentInVerseNum = true;
|
||||
isTagLine = true;
|
||||
processedContent = `<span class="editor-tag">${line}</span>`;
|
||||
} else if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
||||
isTagLine = true;
|
||||
processedContent = `<span class="editor-tag">${line}</span>`;
|
||||
}
|
||||
|
||||
let classes = ['editor-line'];
|
||||
if (currentInChorus) classes.push('chorus');
|
||||
if (currentInVerse) classes.push('verse');
|
||||
if (currentInVerseNum) classes.push('verse-num');
|
||||
if (isTagLine) classes.push('tag-line');
|
||||
|
||||
const finalContent = processedContent || '​';
|
||||
htmlLines.push(`<div class="${classes.join(' ')}">${finalContent}</div>`);
|
||||
}
|
||||
|
||||
return htmlLines.join('\n');
|
||||
}
|
||||
|
||||
|
||||
|
||||
get parsedSections(): ParsedSection[] {
|
||||
return this.lyricsParser.parseAccordi(this.content);
|
||||
const sections = this.lyricsParser.parseAccordi(this.content);
|
||||
if (this.showChordsPreview && this.transposeAmount !== 0) {
|
||||
return this.lyricsParser.transposeSections(sections, this.transposeAmount);
|
||||
}
|
||||
return sections;
|
||||
}
|
||||
|
||||
transposeUp() {
|
||||
this.transposeAmount = (this.transposeAmount + 1) > 12 ? -11 : this.transposeAmount + 1;
|
||||
}
|
||||
|
||||
transposeDown() {
|
||||
this.transposeAmount = (this.transposeAmount - 1) < -12 ? 11 : this.transposeAmount - 1;
|
||||
}
|
||||
|
||||
setDefaultTonalita() {
|
||||
if (this.transposeAmount === 0 || !this.content) return;
|
||||
const chordRegex = /\[([^\]]+)\]/g;
|
||||
this.content = this.content.replace(chordRegex, (match, chord) => {
|
||||
const transposed = this.lyricsParser.transposeChord(chord, this.transposeAmount);
|
||||
return `[${transposed}]`;
|
||||
});
|
||||
this.transposeAmount = 0;
|
||||
}
|
||||
|
||||
isAudioLoaded(): boolean {
|
||||
return !!this.youtubeLink && this.cantiService.getYoutubeId(this.youtubeLink) !== null;
|
||||
}
|
||||
|
||||
loadedYoutubeLink: string = '';
|
||||
|
||||
loadEditorAudio() {
|
||||
if (!this.youtubeLink) return;
|
||||
const videoId = this.cantiService.getYoutubeId(this.youtubeLink);
|
||||
if (videoId) {
|
||||
this.youtubePlayerService.initPlayer(this.editId || 'editing_song', 0, undefined, undefined, this.youtubeLink);
|
||||
this.loadedYoutubeLink = this.youtubeLink;
|
||||
}
|
||||
}
|
||||
|
||||
togglePlayPause() {
|
||||
const currentId = this.editId || 'editing_song';
|
||||
const isLoaded = this.youtubePlayerService.currentCantoId() === currentId && this.loadedYoutubeLink === this.youtubeLink;
|
||||
if (!isLoaded && this.youtubeLink) {
|
||||
this.loadEditorAudio();
|
||||
} else {
|
||||
this.youtubePlayerService.togglePlayPause();
|
||||
}
|
||||
}
|
||||
|
||||
onSeek(event: any) {
|
||||
const value = event.detail.value;
|
||||
this.youtubePlayerService.seekTo(value);
|
||||
}
|
||||
|
||||
formatSeconds(seconds: number): string {
|
||||
if (isNaN(seconds)) return '0:00';
|
||||
const mins = Math.floor(seconds / 60);
|
||||
const secs = Math.floor(seconds % 60);
|
||||
return `${mins}:${secs < 10 ? '0' : ''}${secs}`;
|
||||
}
|
||||
|
||||
toggleChordsPreview() {
|
||||
@@ -164,8 +308,12 @@ export class ProposeCantoPage implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.youtubePlayerService.stop();
|
||||
}
|
||||
|
||||
async insertText(tag: string) {
|
||||
const input = await this.contentTextarea.getInputElement();
|
||||
const input = this.nativeTextarea.nativeElement;
|
||||
const start = input.selectionStart || 0;
|
||||
const end = input.selectionEnd || 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user