feat: integrato il supporto ai canti personalizzati (non validati) della parrocchia

- Recuperato il campo 'canti_personali' dalle tabelle dell'API parrocchiale.
- Mappato ed integrato il segnale 'comunitaCantiPersonali' in locale e salvato su localStorage.
- Permesso il caricamento e l'interrogazione corretta dei brani custom in HomePage, PlayerPage, DisplayPage, YoutubePlayerService e MediaSessionService.
- Risolto il disallineamento per cui la parrocchia 123456 mostrava 196 brani anziché 208.
This commit is contained in:
David Frassi
2026-05-20 12:11:05 +02:00
parent d83a5db65a
commit 19993a0051
7 changed files with 54 additions and 3 deletions
+8 -1
View File
@@ -117,6 +117,9 @@ export class HomePage implements OnDestroy {
const comunitaCode = this.comunitaService.comunitaCode(); const comunitaCode = this.comunitaService.comunitaCode();
const comunitaIds = this.comunitaService.comunitaCantiIds(); const comunitaIds = this.comunitaService.comunitaCantiIds();
if (comunitaCode && this.comunitaService.isFilterActive()) { if (comunitaCode && this.comunitaService.isFilterActive()) {
// Include parish custom/unvalidated canti
list = [...list, ...this.comunitaService.comunitaCantiPersonali()];
list = list.filter(c => { list = list.filter(c => {
return comunitaIds.includes(c.id_canti) || comunitaIds.includes(c.id); return comunitaIds.includes(c.id_canti) || comunitaIds.includes(c.id);
}); });
@@ -329,7 +332,11 @@ export class HomePage implements OnDestroy {
} }
findCanto(id: string) { findCanto(id: string) {
return [...this.cantiService.canti(), ...this.myCantiService.myCanti()].find(c => c.id === id); return [
...this.cantiService.canti(),
...this.myCantiService.myCanti(),
...this.comunitaService.comunitaCantiPersonali()
].find(c => c.id === id);
} }
getPlayingCanto() { getPlayingCanto() {
+7 -1
View File
@@ -2,6 +2,7 @@ import { Component, OnInit, OnDestroy, signal, computed, effect, inject } from '
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { CantiService, Canto } from '../../services/canti.service'; import { CantiService, Canto } from '../../services/canti.service';
import { LyricsParserService, ParsedSection } from '../../services/lyrics-parser.service'; import { LyricsParserService, ParsedSection } from '../../services/lyrics-parser.service';
import { ComunitaService } from '../../services/comunita.service';
@Component({ @Component({
selector: 'app-display', selector: 'app-display',
@@ -54,13 +55,18 @@ export class DisplayPage implements OnInit, OnDestroy {
private route = inject(ActivatedRoute); private route = inject(ActivatedRoute);
private cantiService = inject(CantiService); private cantiService = inject(CantiService);
private lyricsParser = inject(LyricsParserService); private lyricsParser = inject(LyricsParserService);
private comunitaService = inject(ComunitaService);
constructor() { constructor() {
effect(() => { effect(() => {
const id = this.activeSongId(); const id = this.activeSongId();
const allCanti = this.cantiService.canti(); const allCanti = this.cantiService.canti();
const comunitaCantiPers = this.comunitaService.comunitaCantiPersonali();
if (id) { if (id) {
const found = allCanti.find(c => c.id === id); let found = allCanti.find(c => c.id === id);
if (!found) {
found = comunitaCantiPers.find(c => c.id === id);
}
if (found) { if (found) {
this.canto.set(found); this.canto.set(found);
} }
+4
View File
@@ -160,12 +160,16 @@ export class PlayerPage implements OnInit, AfterViewInit, OnDestroy {
const id = this.activeSongId(); const id = this.activeSongId();
const allCanti = this.cantiService.canti(); const allCanti = this.cantiService.canti();
const myCantiList = this.myCantiService.myCanti(); const myCantiList = this.myCantiService.myCanti();
const comunitaCantiPers = this.comunitaService.comunitaCantiPersonali();
if (id) { if (id) {
let found = allCanti.find(c => c.id === id); let found = allCanti.find(c => c.id === id);
if (!found) { if (!found) {
found = myCantiList.find(c => c.id === id); found = myCantiList.find(c => c.id === id);
} }
if (!found) {
found = comunitaCantiPers.find(c => c.id === id);
}
if (found) { if (found) {
const current = this.canto(); const current = this.canto();
+24
View File
@@ -1,6 +1,7 @@
import { Injectable, signal, inject, effect } from '@angular/core'; import { Injectable, signal, inject, effect } from '@angular/core';
import { HttpClient, HttpRequest, HttpEventType, HttpResponse } from '@angular/common/http'; import { HttpClient, HttpRequest, HttpEventType, HttpResponse } from '@angular/common/http';
import { SettingsService } from './settings.service'; import { SettingsService } from './settings.service';
import { Canto } from './canti.service';
export interface ParrocchiaItem { export interface ParrocchiaItem {
id_parrocchia: number; id_parrocchia: number;
@@ -41,6 +42,7 @@ export class ComunitaService {
public comunitaCantiIds = signal<(number | string)[]>([]); public comunitaCantiIds = signal<(number | string)[]>([]);
public comunitaCantiInfo = signal<ParrocchiaCantiItem[]>([]); public comunitaCantiInfo = signal<ParrocchiaCantiItem[]>([]);
public comunitaCantiSettings = signal<CantiSettingsItem[]>([]); public comunitaCantiSettings = signal<CantiSettingsItem[]>([]);
public comunitaCantiPersonali = signal<Canto[]>([]);
public isFilterActive = signal<boolean>(false); public isFilterActive = signal<boolean>(false);
public loading = signal<boolean>(false); public loading = signal<boolean>(false);
public loadingProgress = signal<number>(0); public loadingProgress = signal<number>(0);
@@ -52,6 +54,7 @@ export class ComunitaService {
const savedCanti = localStorage.getItem('comunita-canti-ids'); const savedCanti = localStorage.getItem('comunita-canti-ids');
const savedInfo = localStorage.getItem('comunita-canti-info'); const savedInfo = localStorage.getItem('comunita-canti-info');
const savedSettings = localStorage.getItem('comunita-canti-settings'); const savedSettings = localStorage.getItem('comunita-canti-settings');
const savedCantiPersonali = localStorage.getItem('comunita-canti-personali');
const savedFilterActive = localStorage.getItem('comunita-filter-active') === 'true'; const savedFilterActive = localStorage.getItem('comunita-filter-active') === 'true';
if (savedCode) this.comunitaCode.set(savedCode); if (savedCode) this.comunitaCode.set(savedCode);
@@ -66,6 +69,9 @@ export class ComunitaService {
if (savedSettings) { if (savedSettings) {
try { this.comunitaCantiSettings.set(JSON.parse(savedSettings)); } catch (e) {} try { this.comunitaCantiSettings.set(JSON.parse(savedSettings)); } catch (e) {}
} }
if (savedCantiPersonali) {
try { this.comunitaCantiPersonali.set(JSON.parse(savedCantiPersonali)); } catch (e) {}
}
this.isFilterActive.set(savedFilterActive); this.isFilterActive.set(savedFilterActive);
effect(() => { effect(() => {
@@ -75,6 +81,7 @@ export class ComunitaService {
localStorage.setItem('comunita-canti-ids', JSON.stringify(this.comunitaCantiIds())); localStorage.setItem('comunita-canti-ids', JSON.stringify(this.comunitaCantiIds()));
localStorage.setItem('comunita-canti-info', JSON.stringify(this.comunitaCantiInfo())); localStorage.setItem('comunita-canti-info', JSON.stringify(this.comunitaCantiInfo()));
localStorage.setItem('comunita-canti-settings', JSON.stringify(this.comunitaCantiSettings())); localStorage.setItem('comunita-canti-settings', JSON.stringify(this.comunitaCantiSettings()));
localStorage.setItem('comunita-canti-personali', JSON.stringify(this.comunitaCantiPersonali()));
localStorage.setItem('comunita-filter-active', this.isFilterActive().toString()); localStorage.setItem('comunita-filter-active', this.isFilterActive().toString());
}); });
@@ -122,6 +129,7 @@ export class ComunitaService {
this.comunitaCantiIds.set([]); this.comunitaCantiIds.set([]);
this.comunitaCantiInfo.set([]); this.comunitaCantiInfo.set([]);
this.comunitaCantiSettings.set([]); this.comunitaCantiSettings.set([]);
this.comunitaCantiPersonali.set([]);
this.isFilterActive.set(false); this.isFilterActive.set(false);
return true; return true;
} }
@@ -139,12 +147,27 @@ export class ComunitaService {
const cantiList = data.parrocchia_canti?.data || []; const cantiList = data.parrocchia_canti?.data || [];
const settingsList = data.canti_settings?.data || []; const settingsList = data.canti_settings?.data || [];
// Parse canti_personali (custom unvalidated community canti)
const cantiPersonaliList = (data as any).canti_personali?.data || [];
const mappedCantiPersonali = cantiPersonaliList.map((cp: any) => ({
id: cp.id_canti.toString(),
id_canti: cp.id_canti,
titolo: cp.titolo,
testo: cp.accordi || '',
accordi: cp.accordi || '',
autore: cp.autore || '',
link_youtube: cp.link_youtube || '',
id_momenti: [],
data_update: cp.data_update || ''
}));
this.comunitaCode.set(trimmedCode); this.comunitaCode.set(trimmedCode);
this.comunitaNome.set(parrocchia.nome || `Comunità ${trimmedCode}`); this.comunitaNome.set(parrocchia.nome || `Comunità ${trimmedCode}`);
this.comunitaMail.set(parrocchia.mail || ''); this.comunitaMail.set(parrocchia.mail || '');
this.comunitaCantiInfo.set(cantiList); this.comunitaCantiInfo.set(cantiList);
this.comunitaCantiIds.set(cantiList.map(c => c.id_canti)); this.comunitaCantiIds.set(cantiList.map(c => c.id_canti));
this.comunitaCantiSettings.set(settingsList); this.comunitaCantiSettings.set(settingsList);
this.comunitaCantiPersonali.set(mappedCantiPersonali);
this.isFilterActive.set(true); this.isFilterActive.set(true);
this.loading.set(false); this.loading.set(false);
return true; return true;
@@ -180,6 +203,7 @@ export class ComunitaService {
this.comunitaCantiInfo.set(mockInfo); this.comunitaCantiInfo.set(mockInfo);
this.comunitaCantiSettings.set([]); this.comunitaCantiSettings.set([]);
this.comunitaCantiPersonali.set([]);
this.isFilterActive.set(true); this.isFilterActive.set(true);
this.loading.set(false); this.loading.set(false);
return true; return true;
@@ -1,6 +1,7 @@
import { Injectable, inject } from '@angular/core'; import { Injectable, inject } from '@angular/core';
import { CantiService } from './canti.service'; import { CantiService } from './canti.service';
import { MyCantiService } from './my-canti.service'; import { MyCantiService } from './my-canti.service';
import { ComunitaService } from './comunita.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -8,6 +9,7 @@ import { MyCantiService } from './my-canti.service';
export class MediaSessionService { export class MediaSessionService {
private cantiService = inject(CantiService); private cantiService = inject(CantiService);
private myCantiService = inject(MyCantiService); private myCantiService = inject(MyCantiService);
private comunitaService = inject(ComunitaService);
public updateMetadata(cantoId: string) { public updateMetadata(cantoId: string) {
if (!('mediaSession' in navigator)) return; if (!('mediaSession' in navigator)) return;
@@ -16,6 +18,9 @@ export class MediaSessionService {
if (!canto) { if (!canto) {
canto = this.myCantiService.myCanti().find(c => c.id === cantoId); canto = this.myCantiService.myCanti().find(c => c.id === cantoId);
} }
if (!canto) {
canto = this.comunitaService.comunitaCantiPersonali().find(c => c.id === cantoId);
}
if (!canto) return; if (!canto) return;
const thumb = this.cantiService.getYoutubeThumb(canto.link_youtube) || 'assets/icons/icon-512x512.png'; const thumb = this.cantiService.getYoutubeThumb(canto.link_youtube) || 'assets/icons/icon-512x512.png';
@@ -4,6 +4,7 @@ import { SettingsService } from './settings.service';
import { MediaSessionService } from './media-session.service'; import { MediaSessionService } from './media-session.service';
import { MyCantiService } from './my-canti.service'; import { MyCantiService } from './my-canti.service';
import { ConnectivityService } from './connectivity.service'; import { ConnectivityService } from './connectivity.service';
import { ComunitaService } from './comunita.service';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@@ -14,6 +15,7 @@ export class YoutubePlayerService {
private mediaSessionService = inject(MediaSessionService); private mediaSessionService = inject(MediaSessionService);
private myCantiService = inject(MyCantiService); private myCantiService = inject(MyCantiService);
private connectivityService = inject(ConnectivityService); private connectivityService = inject(ConnectivityService);
private comunitaService = inject(ComunitaService);
public isPlayerSupported = computed<boolean>(() => { public isPlayerSupported = computed<boolean>(() => {
// Check if offline // Check if offline
@@ -128,6 +130,9 @@ export class YoutubePlayerService {
if (!canto) { if (!canto) {
canto = this.myCantiService.myCanti().find(c => c.id === cantoId); canto = this.myCantiService.myCanti().find(c => c.id === cantoId);
} }
if (!canto) {
canto = this.comunitaService.comunitaCantiPersonali().find(c => c.id === cantoId);
}
if (!canto) return; if (!canto) return;
const videoId = this.cantiService.getYoutubeId(canto.link_youtube); const videoId = this.cantiService.getYoutubeId(canto.link_youtube);
+1 -1
View File
@@ -1 +1 @@
export const VERSION = '2026.05.18.1750'; export const VERSION = '2026.05.20.1128';