feat: condivisione e importazione automatica del codice comunità nelle playlist con priorità tonalità e autoscroll e rifinitura UI
This commit is contained in:
@@ -160,7 +160,7 @@
|
||||
|
||||
<!-- Active Playlist Actions -->
|
||||
<div class="selection-pill glass" *ngIf="playlistService.activeListName() && !playlistService.selectionMode()">
|
||||
<ion-button fill="clear" color="secondary" (click)="editPlaylist()" class="mini-action-btn" *ngIf="!isComunitaPlaylist()">
|
||||
<ion-button fill="clear" color="secondary" (click)="editPlaylist()" class="mini-action-btn" *ngIf="!isComunitaPlaylist() && isActivePlaylistSaved()">
|
||||
<ion-icon slot="icon-only" name="create-outline"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button fill="clear" color="secondary" (click)="shareActivePlaylist()" class="mini-action-btn">
|
||||
|
||||
@@ -174,7 +174,7 @@ ion-title {
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
gap: 12px;
|
||||
padding: 16px 0 4px 24px; // Reduced padding to bring search bar closer
|
||||
padding: 16px 0 16px 24px; // Spacing adjusted for search bar breathing room
|
||||
}
|
||||
|
||||
.header-logo {
|
||||
@@ -318,7 +318,7 @@ ion-title {
|
||||
.search-wrapper-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 16px 8px 16px;
|
||||
padding: 6px 16px 8px 16px; // Added slight top padding for search bar breathing room
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
|
||||
@@ -131,9 +131,9 @@ export class HomePage implements OnDestroy {
|
||||
...this.comunitaService.comunitaCantiPersonali()
|
||||
];
|
||||
|
||||
// Filter to only community canti
|
||||
// Filter to only community canti, but preserve canti that are in the active playlist
|
||||
list = list.filter(c => {
|
||||
return comunitaIds.includes(c.id_canti) || comunitaIds.includes(c.id);
|
||||
return comunitaIds.includes(c.id_canti) || comunitaIds.includes(c.id) || activeIds.includes(c.id);
|
||||
});
|
||||
|
||||
// Deduplicate: parish-customized versions take precedence
|
||||
@@ -144,7 +144,7 @@ export class HomePage implements OnDestroy {
|
||||
if (!existing) {
|
||||
seen.set(key, canto);
|
||||
} else {
|
||||
if (!existing.nonValidato && canto.nonValidato) {
|
||||
if (!existing.isPersonal && canto.isPersonal) {
|
||||
seen.set(key, canto);
|
||||
}
|
||||
}
|
||||
@@ -253,6 +253,9 @@ export class HomePage implements OnDestroy {
|
||||
});
|
||||
|
||||
public visibleCanti = computed(() => {
|
||||
if (this.playlistService.selectionMode() && !this.isAddingSongs()) {
|
||||
return this.filteredCanti();
|
||||
}
|
||||
return this.filteredCanti().slice(0, this.limit());
|
||||
});
|
||||
|
||||
@@ -393,15 +396,70 @@ export class HomePage implements OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
handleImport(base64: string) {
|
||||
async handleImport(base64: string) {
|
||||
try {
|
||||
const decoded = decodeURIComponent(escape(atob(base64)));
|
||||
const json = JSON.parse(decoded);
|
||||
|
||||
if (json && json.comunitaCode) {
|
||||
// 1. Abilita la funzionalità comunità nelle impostazioni
|
||||
this.settingsService.comunitaEnabled.set(true);
|
||||
localStorage.setItem('comunita-enabled', 'true');
|
||||
|
||||
// 2. Mostra un overlay di caricamento premium con indicatore di progresso
|
||||
const loading = await this.loadingCtrl.create({
|
||||
message: 'Attivazione comunità: Caricamento 0%',
|
||||
cssClass: 'premium-loading',
|
||||
spinner: 'crescent'
|
||||
});
|
||||
await loading.present();
|
||||
|
||||
// Iscrizione agli aggiornamenti di progresso
|
||||
let progressInterval: any = null;
|
||||
progressInterval = setInterval(() => {
|
||||
const pct = this.comunitaService.loadingProgress();
|
||||
loading.message = `Attivazione comunità: Caricamento ${pct}%`;
|
||||
if (pct >= 100) {
|
||||
clearInterval(progressInterval);
|
||||
}
|
||||
}, 100);
|
||||
|
||||
const success = await this.comunitaService.setComunitaCode(json.comunitaCode);
|
||||
clearInterval(progressInterval);
|
||||
await loading.dismiss();
|
||||
|
||||
if (success) {
|
||||
const toast = await this.toastCtrl.create({
|
||||
message: `Comunità attivata: ${this.comunitaService.comunitaNome()}`,
|
||||
duration: 2500,
|
||||
color: 'success',
|
||||
position: 'bottom'
|
||||
});
|
||||
await toast.present();
|
||||
} else {
|
||||
const toast = await this.toastCtrl.create({
|
||||
message: 'Codice comunità non trovato o errore di connessione.',
|
||||
duration: 3000,
|
||||
color: 'danger',
|
||||
position: 'bottom'
|
||||
});
|
||||
await toast.present();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.playlistService.processImportJson(json)) {
|
||||
this.limit.set(50); // Mostra più canti inizialmente per le playlist speciali
|
||||
this.router.navigate([], { queryParams: { import: null }, queryParamsHandling: 'merge' });
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to import playlist', e);
|
||||
const toast = await this.toastCtrl.create({
|
||||
message: 'Errore durante l\'importazione della playlist.',
|
||||
duration: 3000,
|
||||
color: 'danger',
|
||||
position: 'bottom'
|
||||
});
|
||||
await toast.present();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -847,21 +905,25 @@ export class HomePage implements OnDestroy {
|
||||
if (data.startsWith('canti:')) {
|
||||
const parts = data.replace('canti:', '').split(':');
|
||||
let idsStr = '';
|
||||
let playlistName = 'Lista Parrocchiale';
|
||||
if (parts.length > 1) {
|
||||
this.playlistService.activeListName.set(parts[0]);
|
||||
playlistName = parts[0];
|
||||
idsStr = parts[1];
|
||||
} else {
|
||||
this.playlistService.activeListName.set('Lista Parrocchiale');
|
||||
idsStr = parts[0];
|
||||
}
|
||||
|
||||
const ids = idsStr.split(',').map(id => id.trim());
|
||||
this.playlistService.activeListIds.set(ids);
|
||||
this.playlistService.activeListName.set(playlistName);
|
||||
this.limit.set(50); // Show more initially for special lists
|
||||
|
||||
// Clear other filters to avoid confusion
|
||||
this.selectedLiturgico.set(null);
|
||||
this.selectedTematico.set(null);
|
||||
|
||||
// Automatically save to the device!
|
||||
this.playlistService.savePlaylist(playlistName, ids);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -936,6 +998,12 @@ export class HomePage implements OnDestroy {
|
||||
return !!id && id.startsWith('comunita_');
|
||||
}
|
||||
|
||||
isActivePlaylistSaved(): boolean {
|
||||
const id = this.playlistService.activePlaylistId();
|
||||
if (!id) return false;
|
||||
return this.playlistService.playlists().some(p => p.id === id);
|
||||
}
|
||||
|
||||
clearSpecialList(event?: Event) {
|
||||
if (event) event.stopPropagation();
|
||||
this.playlistService.activeListIds.set([]);
|
||||
@@ -955,7 +1023,12 @@ export class HomePage implements OnDestroy {
|
||||
shareActivePlaylist() {
|
||||
const ids = this.playlistService.activeListIds();
|
||||
const name = this.playlistService.activeListName() || 'Playlist';
|
||||
this.playlistService.sharePlaylistQR(ids, name);
|
||||
|
||||
const id = this.playlistService.activePlaylistId();
|
||||
const pl = this.playlistService.playlists().find(p => p.id === id);
|
||||
const songSettings = pl ? pl.songSettings : undefined;
|
||||
|
||||
this.playlistService.sharePlaylistQR(ids, name, songSettings);
|
||||
}
|
||||
|
||||
async importPlaylist() {
|
||||
|
||||
Reference in New Issue
Block a user