gestione comunità
This commit is contained in:
@@ -4,10 +4,19 @@
|
||||
<div class="offline-badge-header" *ngIf="!connectivityService.isOnline()">
|
||||
<ion-icon name="cloud-offline-outline"></ion-icon>
|
||||
</div>
|
||||
<ion-button fill="clear" (click)="toggleChords()" style="margin: 0; --padding-start: 6px; --padding-end: 6px;">
|
||||
<ion-icon slot="icon-only"
|
||||
[name]="showChords() ? 'musical-notes-outline' : 'text-outline'"
|
||||
[color]="showChords() ? 'secondary' : 'medium'"
|
||||
style="font-size: 1.3rem;">
|
||||
</ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title class="outfit-font wrapped-title">
|
||||
<div class="title-main" [style.fontSize.rem]="fontSize() * 1.1">
|
||||
<span class="canto-number" *ngIf="canto()?.id_canti">{{ canto()?.id_canti }}</span>
|
||||
<span class="canto-number" *ngIf="canto()?.id_canti" [style.color]="getCommunitySongNumber(canto()) !== null ? 'var(--ion-color-secondary)' : ''">
|
||||
{{ getCommunitySongNumber(canto()) || canto()?.id_canti }}
|
||||
</span>
|
||||
<span class="title-text">{{ canto()?.titolo || 'Player' }}</span>
|
||||
</div>
|
||||
</ion-title>
|
||||
|
||||
@@ -11,6 +11,8 @@ import { ConnectivityService } from '../../services/connectivity.service';
|
||||
import { PlaylistService } from '../../services/playlist.service';
|
||||
import { YoutubePlayerService } from '../../services/youtube-player.service';
|
||||
import { MyCantiService } from '../../services/my-canti.service';
|
||||
import { ComunitaService } from '../../services/comunita.service';
|
||||
import { StatsService } from '../../services/stats.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-player',
|
||||
@@ -103,11 +105,15 @@ export class PlayerPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
public settingsService = inject(SettingsService);
|
||||
public connectivityService = inject(ConnectivityService);
|
||||
public playlistService = inject(PlaylistService);
|
||||
public comunitaService = inject(ComunitaService);
|
||||
private myCantiService = inject(MyCantiService);
|
||||
private statsService = inject(StatsService);
|
||||
private gestureCtrl = inject(GestureController);
|
||||
private el = inject(ElementRef);
|
||||
private sanitizer = inject(DomSanitizer);
|
||||
|
||||
private songStartTime: number = 0;
|
||||
|
||||
constructor() {
|
||||
// Sync mode from global settings
|
||||
effect(() => {
|
||||
@@ -195,9 +201,24 @@ export class PlayerPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
}
|
||||
|
||||
if (found) {
|
||||
this.logPreviousSongTime();
|
||||
this.canto.set(found);
|
||||
this.songStartTime = Date.now();
|
||||
this.cantiService.getStorage()?.set('last_song_id', id);
|
||||
this.channel.postMessage({ type: 'SYNC_CANTO', id: found.id });
|
||||
|
||||
// Set custom community transposition if active
|
||||
if (this.comunitaService.comunitaCode() && this.comunitaService.isFilterActive()) {
|
||||
const settings = this.comunitaService.comunitaCantiSettings();
|
||||
const songSetting = settings.find(s => s.id_canti === found.id_canti || s.id_canti === Number(found.id));
|
||||
if (songSetting && songSetting.tonalita !== undefined) {
|
||||
this.transposeAmount.set(songSetting.tonalita);
|
||||
} else {
|
||||
this.transposeAmount.set(0);
|
||||
}
|
||||
} else {
|
||||
this.transposeAmount.set(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -243,11 +264,21 @@ export class PlayerPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
transposeUp() {
|
||||
this.transposeAmount.update(v => v + 1);
|
||||
this.channel.postMessage({ type: 'SYNC_TRANSPOSE', amount: this.transposeAmount() });
|
||||
|
||||
const c = this.canto();
|
||||
if (c) {
|
||||
this.statsService.updateSongSettings(c.id_canti, this.transposeAmount());
|
||||
}
|
||||
}
|
||||
|
||||
transposeDown() {
|
||||
this.transposeAmount.update(v => v - 1);
|
||||
this.channel.postMessage({ type: 'SYNC_TRANSPOSE', amount: this.transposeAmount() });
|
||||
|
||||
const c = this.canto();
|
||||
if (c) {
|
||||
this.statsService.updateSongSettings(c.id_canti, this.transposeAmount());
|
||||
}
|
||||
}
|
||||
|
||||
zoomIn() {
|
||||
@@ -485,7 +516,25 @@ export class PlayerPage implements OnInit, AfterViewInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
getCommunitySongNumber(canto: any): string | null {
|
||||
if (!canto) return null;
|
||||
if (!this.comunitaService.comunitaCode() || !this.comunitaService.isFilterActive()) return null;
|
||||
const cantiInfo = this.comunitaService.comunitaCantiInfo();
|
||||
const info = cantiInfo.find(x => x.id_canti === canto.id_canti || x.id_canti === Number(canto.id));
|
||||
return info && info.num_canto ? info.num_canto.toString() : null;
|
||||
}
|
||||
|
||||
private logPreviousSongTime() {
|
||||
const c = this.canto();
|
||||
if (c && this.songStartTime > 0) {
|
||||
const timeSpent = (Date.now() - this.songStartTime) / 1000;
|
||||
this.statsService.logSongView(c.id_canti, timeSpent);
|
||||
this.songStartTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.logPreviousSongTime();
|
||||
this.audioEngine.stopListening();
|
||||
this.channel.close();
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
</div>
|
||||
<div class="song-info">
|
||||
<span class="canto-number">{{ song.id_canti }}</span>
|
||||
<span class="song-title">{{ song.titolo }}</span>
|
||||
<span class="song-title">
|
||||
<span *ngIf="getCommunitySongNumber(song)" style="color: var(--ion-color-secondary); font-weight: 600; margin-right: 6px;">{{ getCommunitySongNumber(song) }}</span>{{ song.titolo }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="example-custom-placeholder" *cdkDragPlaceholder></div>
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component, inject, computed } from '@angular/core';
|
||||
import { PlaylistService } from '../../services/playlist.service';
|
||||
import { CantiService } from '../../services/canti.service';
|
||||
import { ComunitaService } from '../../services/comunita.service';
|
||||
import { CdkDragDrop, moveItemInArray } from '@angular/cdk/drag-drop';
|
||||
import { AlertController, ToastController, ModalController } from '@ionic/angular';
|
||||
import { Router } from '@angular/router';
|
||||
@@ -14,6 +15,7 @@ import { Router } from '@angular/router';
|
||||
export class PlaylistPage {
|
||||
public playlistService = inject(PlaylistService);
|
||||
public cantiService = inject(CantiService);
|
||||
public comunitaService = inject(ComunitaService);
|
||||
private alertCtrl = inject(AlertController);
|
||||
private toastCtrl = inject(ToastController);
|
||||
private router = inject(Router);
|
||||
@@ -177,4 +179,11 @@ export class PlaylistPage {
|
||||
});
|
||||
await toast.present();
|
||||
}
|
||||
|
||||
getCommunitySongNumber(song: any): string | null {
|
||||
if (!this.comunitaService.comunitaCode() || !this.comunitaService.isFilterActive()) return null;
|
||||
const cantiInfo = this.comunitaService.comunitaCantiInfo();
|
||||
const info = cantiInfo.find(x => x.id_canti === song.id_canti || x.id_canti === Number(song.id));
|
||||
return info && info.num_canto ? info.num_canto.toString() : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,37 +61,31 @@
|
||||
</ion-item>
|
||||
</div>
|
||||
|
||||
<!-- Messa di Riferimento Selection -->
|
||||
<!-- Comunità -->
|
||||
<div class="settings-group glass ion-margin-bottom">
|
||||
<div class="group-header ion-padding-start ion-padding-top">
|
||||
<h2 class="outfit-font settings-group-title">
|
||||
Messa di Riferimento (Suggeriti)
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<div class="select-item-container ion-padding-horizontal ion-padding-bottom">
|
||||
<div class="select-label-row">
|
||||
<ion-icon name="calendar-outline" color="secondary" class="select-icon"></ion-icon>
|
||||
<div class="select-text-group">
|
||||
<h2 class="settings-item-title outfit-font">Seleziona Messa</h2>
|
||||
<p class="settings-item-subtitle outfit-font">Scegli la messa per i canti consigliati</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="select-box-wrapper">
|
||||
<ion-select [value]="cantiLettureService.selectedMassDate()"
|
||||
(ionChange)="onMassChange($event)"
|
||||
interface="action-sheet"
|
||||
class="custom-select-block"
|
||||
placeholder="Seleziona una messa...">
|
||||
<ion-select-option *ngFor="let mass of cantiLettureService.availableMasses()" [value]="mass.date">
|
||||
{{ mass.formattedLabel }}
|
||||
</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
</div>
|
||||
<ion-item class="transparent-item" lines="none">
|
||||
<ion-icon name="people-outline" slot="start" color="secondary"></ion-icon>
|
||||
<ion-label class="outfit-font">
|
||||
<h2 class="settings-item-title">Comunità</h2>
|
||||
<p class="settings-item-subtitle">Mostra il filtro Comunità nella home</p>
|
||||
</ion-label>
|
||||
<ion-toggle slot="end" [checked]="settingsService.comunitaEnabled()" (ionChange)="settingsService.toggleComunitaEnabled()" color="secondary"></ion-toggle>
|
||||
</ion-item>
|
||||
</div>
|
||||
|
||||
<!-- Invio Dati Statistici -->
|
||||
<div class="settings-group glass ion-margin-bottom">
|
||||
<ion-item class="transparent-item" lines="none">
|
||||
<ion-icon name="analytics-outline" slot="start" color="secondary"></ion-icon>
|
||||
<ion-label class="outfit-font">
|
||||
<h2 class="settings-item-title">Invio dati statistici</h2>
|
||||
<p class="settings-item-subtitle">Invia statistiche di utilizzo e tonalità</p>
|
||||
</ion-label>
|
||||
<ion-toggle slot="end" [checked]="settingsService.invioDatiStatistici()" (ionChange)="settingsService.toggleInvioDatiStatistici()" color="secondary"></ion-toggle>
|
||||
</ion-item>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Display Mode Section -->
|
||||
<div class="settings-group glass ion-margin-bottom">
|
||||
<div class="group-header ion-padding-start ion-padding-top">
|
||||
@@ -117,6 +111,8 @@
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="settings-group glass ion-margin-top" *ngIf="settingsService.showEditor()">
|
||||
<ion-item class="transparent-item" lines="none" (click)="myCantiService.sendAllMyCanti()" detail="true" button *ngIf="myCantiService.myCanti().length > 0">
|
||||
<ion-icon name="send-outline" slot="start" color="secondary"></ion-icon>
|
||||
@@ -185,6 +181,23 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legend-item">
|
||||
<div style="display: flex; flex-direction: column; gap: 4px; align-items: center;">
|
||||
<div class="legend-icon-wrapper">
|
||||
<ion-icon name="text-outline" color="medium"></ion-icon>
|
||||
</div>
|
||||
<div class="legend-icon-wrapper">
|
||||
<ion-icon name="musical-notes-outline" color="secondary"></ion-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="legend-text" style="padding-top: 6px;">
|
||||
<h4 class="outfit-font">Testo / Accordi (icona in alto a destra)</h4>
|
||||
<p class="outfit-font">
|
||||
Alterna la visualizzazione tra solo testo e testo con accordi. L'icona con la <strong>T</strong> (grigia) indica la modalità testo; l'icona con le note musicali (arancione) indica la modalità accordi. Un tocco cambia modalità all'istante.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="legend-item">
|
||||
<div class="legend-icon-wrapper">
|
||||
<ion-icon name="arrow-up-circle" color="secondary"></ion-icon>
|
||||
|
||||
@@ -11,6 +11,7 @@ import { Router } from '@angular/router';
|
||||
|
||||
import { MyCantiService } from '../../services/my-canti.service';
|
||||
import { CantiLettureService } from '../../services/canti-letture.service';
|
||||
import { ComunitaService } from '../../services/comunita.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-settings',
|
||||
@@ -26,6 +27,7 @@ export class SettingsPage {
|
||||
public connectivityService = inject(ConnectivityService);
|
||||
public playlistService = inject(PlaylistService);
|
||||
public cantiLettureService = inject(CantiLettureService);
|
||||
public comunitaService = inject(ComunitaService);
|
||||
private swUpdate = inject(SwUpdate);
|
||||
private toastCtrl = inject(ToastController);
|
||||
private modalCtrl = inject(ModalController);
|
||||
@@ -47,6 +49,13 @@ export class SettingsPage {
|
||||
async fullRefresh() {
|
||||
// 1. Refresh JSON data
|
||||
this.cantiService.refresh();
|
||||
|
||||
// 2. Refresh liturgical readings JSON
|
||||
try {
|
||||
await this.cantiLettureService.fetchData();
|
||||
} catch (err) {
|
||||
console.error('Failed to refresh liturgical readings:', err);
|
||||
}
|
||||
|
||||
// 2. Check for Service Worker updates
|
||||
if (this.swUpdate.isEnabled) {
|
||||
@@ -77,5 +86,4 @@ export class SettingsPage {
|
||||
});
|
||||
await toast.present();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user