8c9f9df11c
- Il background refresh al riavvio ora non riattiva il filtro comunità se comunitaEnabled è false nelle impostazioni, evitando di restringere silenziosamente il bacino dei canti. - Invertita la logica di deduplicazione: in caso di canto duplicato (validato + non validato), ora vince la versione validata (ufficiale del catalogo).
233 lines
8.5 KiB
TypeScript
233 lines
8.5 KiB
TypeScript
import { Injectable, signal, inject, effect } from '@angular/core';
|
|
import { HttpClient, HttpRequest, HttpEventType, HttpResponse } from '@angular/common/http';
|
|
import { SettingsService } from './settings.service';
|
|
import { Canto } from './canti.service';
|
|
|
|
export interface ParrocchiaItem {
|
|
id_parrocchia: number;
|
|
nome: string;
|
|
codice: string;
|
|
mail: string;
|
|
guid_parrocchia: string;
|
|
}
|
|
|
|
export interface ParrocchiaCantiItem {
|
|
id_parrocchia: number;
|
|
id_canti: number;
|
|
num_canto: number;
|
|
}
|
|
|
|
export interface CantiSettingsItem {
|
|
id_canti: number;
|
|
speed: number;
|
|
tonalita: number;
|
|
}
|
|
|
|
export interface GetAllAppTablesResponse {
|
|
parrocchia?: { data: ParrocchiaItem[] };
|
|
parrocchia_canti?: { data: ParrocchiaCantiItem[] };
|
|
canti_settings?: { data: CantiSettingsItem[] };
|
|
}
|
|
|
|
@Injectable({
|
|
providedIn: 'root'
|
|
})
|
|
export class ComunitaService {
|
|
private http = inject(HttpClient);
|
|
private settingsService = inject(SettingsService);
|
|
|
|
public comunitaCode = signal<string>('');
|
|
public comunitaNome = signal<string>('');
|
|
public comunitaMail = signal<string>('');
|
|
public comunitaCantiIds = signal<(number | string)[]>([]);
|
|
public comunitaCantiInfo = signal<ParrocchiaCantiItem[]>([]);
|
|
public comunitaCantiSettings = signal<CantiSettingsItem[]>([]);
|
|
public comunitaCantiPersonali = signal<Canto[]>([]);
|
|
public isFilterActive = signal<boolean>(false);
|
|
public loading = signal<boolean>(false);
|
|
public loadingProgress = signal<number>(0);
|
|
|
|
constructor() {
|
|
const savedCode = localStorage.getItem('comunita-code');
|
|
const savedNome = localStorage.getItem('comunita-nome');
|
|
const savedMail = localStorage.getItem('comunita-mail');
|
|
const savedCanti = localStorage.getItem('comunita-canti-ids');
|
|
const savedInfo = localStorage.getItem('comunita-canti-info');
|
|
const savedSettings = localStorage.getItem('comunita-canti-settings');
|
|
const savedCantiPersonali = localStorage.getItem('comunita-canti-personali');
|
|
const savedFilterActive = localStorage.getItem('comunita-filter-active') === 'true';
|
|
|
|
if (savedCode) {
|
|
this.comunitaCode.set(savedCode);
|
|
// Run background refresh 1 second after startup to fetch any new custom canti or updates
|
|
// but only if the community feature is enabled in settings
|
|
setTimeout(() => {
|
|
if (!this.settingsService.comunitaEnabled()) {
|
|
// Community is disabled: skip refresh to avoid re-enabling the filter
|
|
return;
|
|
}
|
|
this.setComunitaCode(savedCode).catch(err => {
|
|
console.warn('Failed background community refresh at startup:', err);
|
|
});
|
|
}, 1000);
|
|
}
|
|
if (savedNome) this.comunitaNome.set(savedNome);
|
|
if (savedMail) this.comunitaMail.set(savedMail);
|
|
if (savedCanti) {
|
|
try { this.comunitaCantiIds.set(JSON.parse(savedCanti)); } catch (e) {}
|
|
}
|
|
if (savedInfo) {
|
|
try { this.comunitaCantiInfo.set(JSON.parse(savedInfo)); } catch (e) {}
|
|
}
|
|
if (savedSettings) {
|
|
try { this.comunitaCantiSettings.set(JSON.parse(savedSettings)); } catch (e) {}
|
|
}
|
|
if (savedCantiPersonali) {
|
|
try { this.comunitaCantiPersonali.set(JSON.parse(savedCantiPersonali)); } catch (e) {}
|
|
}
|
|
this.isFilterActive.set(savedFilterActive);
|
|
|
|
effect(() => {
|
|
localStorage.setItem('comunita-code', this.comunitaCode());
|
|
localStorage.setItem('comunita-nome', this.comunitaNome());
|
|
localStorage.setItem('comunita-mail', this.comunitaMail());
|
|
localStorage.setItem('comunita-canti-ids', JSON.stringify(this.comunitaCantiIds()));
|
|
localStorage.setItem('comunita-canti-info', JSON.stringify(this.comunitaCantiInfo()));
|
|
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());
|
|
});
|
|
|
|
effect(() => {
|
|
if (!this.settingsService.comunitaEnabled()) {
|
|
this.isFilterActive.set(false);
|
|
}
|
|
});
|
|
}
|
|
|
|
private fetchWithProgress<T>(url: string): Promise<T> {
|
|
return new Promise<T>((resolve, reject) => {
|
|
const req = new HttpRequest('GET', url, {
|
|
reportProgress: true,
|
|
responseType: 'json'
|
|
});
|
|
|
|
this.http.request<T>(req).subscribe({
|
|
next: (event) => {
|
|
if (event.type === HttpEventType.DownloadProgress) {
|
|
if (event.total && event.total > 0) {
|
|
const pct = Math.round((event.loaded / event.total) * 100);
|
|
this.loadingProgress.set(pct);
|
|
} else {
|
|
// No Content-Length header — simulate gradual progress up to 85%
|
|
const simulated = Math.min(85, this.loadingProgress() + 12);
|
|
this.loadingProgress.set(simulated);
|
|
}
|
|
} else if (event instanceof HttpResponse) {
|
|
this.loadingProgress.set(100);
|
|
resolve(event.body as T);
|
|
}
|
|
},
|
|
error: (err) => reject(err)
|
|
});
|
|
});
|
|
}
|
|
|
|
async setComunitaCode(code: string): Promise<boolean> {
|
|
const trimmedCode = code.trim();
|
|
if (!trimmedCode) {
|
|
this.comunitaCode.set('');
|
|
this.comunitaNome.set('');
|
|
this.comunitaMail.set('');
|
|
this.comunitaCantiIds.set([]);
|
|
this.comunitaCantiInfo.set([]);
|
|
this.comunitaCantiSettings.set([]);
|
|
this.comunitaCantiPersonali.set([]);
|
|
this.isFilterActive.set(false);
|
|
return true;
|
|
}
|
|
|
|
this.loading.set(true);
|
|
this.loadingProgress.set(0);
|
|
|
|
// 1. Try to fetch from the actual production API
|
|
try {
|
|
const url = `https://libretto.mmcinet.eu/canti/api/v3/get_all_app_tables?uuid=pwa-cc-uuid&email=&platform=browser&version=1.0&gruppo=${trimmedCode}&all_song=false&t=${Date.now()}`;
|
|
const data = await this.fetchWithProgress<GetAllAppTablesResponse>(url);
|
|
|
|
if (data && data.parrocchia?.data && data.parrocchia.data.length > 0) {
|
|
const parrocchia = data.parrocchia.data[0];
|
|
const cantiList = data.parrocchia_canti?.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 || '',
|
|
nonValidato: true
|
|
}));
|
|
|
|
this.comunitaCode.set(trimmedCode);
|
|
this.comunitaNome.set(parrocchia.nome || `Comunità ${trimmedCode}`);
|
|
this.comunitaMail.set(parrocchia.mail || '');
|
|
this.comunitaCantiInfo.set(cantiList);
|
|
this.comunitaCantiIds.set(cantiList.map(c => c.id_canti));
|
|
this.comunitaCantiSettings.set(settingsList);
|
|
this.comunitaCantiPersonali.set(mappedCantiPersonali);
|
|
this.isFilterActive.set(true);
|
|
this.loading.set(false);
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.warn('Failed to fetch from production API, trying fallback...', err);
|
|
this.loadingProgress.set(0);
|
|
}
|
|
|
|
// 2. Fallback to static community JSON
|
|
try {
|
|
const isProduction = window.location.hostname.includes('canticristiani.it');
|
|
const origin = isProduction ? window.location.origin : 'https://www.canticristiani.it';
|
|
const fallbackUrl = `${origin}/api/comunita_${trimmedCode}.json?t=${Date.now()}`;
|
|
|
|
interface StaticComunitaData {
|
|
id_comunita: string;
|
|
nome_comunita: string;
|
|
canti: (number | string)[];
|
|
}
|
|
|
|
const staticData = await this.fetchWithProgress<StaticComunitaData>(fallbackUrl);
|
|
if (staticData && staticData.canti) {
|
|
this.comunitaCode.set(trimmedCode);
|
|
this.comunitaNome.set(staticData.nome_comunita || `Comunità ${trimmedCode}`);
|
|
this.comunitaCantiIds.set(staticData.canti);
|
|
|
|
const mockInfo = staticData.canti.map((id, index) => ({
|
|
id_parrocchia: 1,
|
|
id_canti: Number(id),
|
|
num_canto: index + 1
|
|
}));
|
|
|
|
this.comunitaCantiInfo.set(mockInfo);
|
|
this.comunitaCantiSettings.set([]);
|
|
this.comunitaCantiPersonali.set([]);
|
|
this.isFilterActive.set(true);
|
|
this.loading.set(false);
|
|
return true;
|
|
}
|
|
} catch (err) {
|
|
console.error('All community fetch strategies failed:', err);
|
|
}
|
|
|
|
this.loading.set(false);
|
|
return false;
|
|
}
|
|
}
|