chore: save current changes

This commit is contained in:
David Frassi
2026-06-06 08:19:08 +02:00
parent e7e43468b3
commit 4d1883a45d
23 changed files with 1028 additions and 327 deletions
+5 -2
View File
@@ -5,7 +5,10 @@
<img src="assets/icon/favicon.png" class="header-logo">
<div class="header-text-group">
<span class="app-name">{{ appName }}</span>
<span class="version-badge">v{{ version }}</span>
<span class="version-badge" (click)="checkForAppUpdate($event)" style="cursor: pointer; display: inline-flex; align-items: center; gap: 4px;">
v{{ version }}
<ion-icon name="refresh-outline" style="font-size: 0.9em;"></ion-icon>
</span>
</div>
</div>
</ion-title>
@@ -283,7 +286,7 @@
<!-- Selection Area -->
<div class="selection-column" (click)="playlistService.toggleSongSelection(canto.id); $event.stopPropagation()">
<span class="canto-number" [class.selected-number]="playlistService.selectedIds().has(canto.id)">
{{ canto.id.startsWith('my_') ? 'M' : canto.id_canti }}
{{ canto.id.startsWith('my_') ? getMySongNumber(canto) : canto.id_canti }}
</span>
</div>
+123
View File
@@ -16,6 +16,9 @@ import { QrScannerComponent } from '../components/qr-scanner/qr-scanner.componen
import { CantiLettureService } from '../services/canti-letture.service';
import { ComunitaService } from '../services/comunita.service';
import { environment } from '../../environments/environment';
import { SwUpdate, VersionReadyEvent } from '@angular/service-worker';
import { filter, first } from 'rxjs/operators';
import { showFullscreenUpdateOverlay } from '../app.component';
@Component({
selector: 'app-home',
@@ -67,9 +70,123 @@ export class HomePage implements OnDestroy {
private alertCtrl = inject(AlertController);
private toastCtrl = inject(ToastController);
private loadingCtrl = inject(LoadingController);
private swUpdate = inject(SwUpdate);
private firstInteraction = true;
async checkForAppUpdate(event?: Event) {
if (event) event.stopPropagation();
if (!this.swUpdate.isEnabled) {
const toast = await this.toastCtrl.create({
message: 'Aggiornamenti non supportati su questo browser.',
duration: 3000,
color: 'medium'
});
await toast.present();
return;
}
const toastLoading = await this.toastCtrl.create({
message: 'Ricerca aggiornamenti in corso...',
duration: 1500,
color: 'secondary'
});
await toastLoading.present();
const updateAvailable = await this.performUpdateCheck();
if (!updateAvailable) {
const toast = await this.toastCtrl.create({
message: 'L\'applicazione è già aggiornata all\'ultima versione.',
duration: 3000,
color: 'success'
});
await toast.present();
}
}
private async performUpdateCheck(): Promise<boolean> {
try {
if ('serviceWorker' in navigator) {
const registration = await navigator.serviceWorker.ready;
await registration.update();
}
if (this.swUpdate.isEnabled) {
const swFoundUpdate = await this.swUpdate.checkForUpdate();
if (swFoundUpdate) {
await this.applyUpdateAndReload();
return true;
}
}
const versionMismatch = await this.checkVersionJson();
if (versionMismatch) {
await this.applyUpdateAndReload();
return true;
}
return false;
} catch (err) {
console.error('[PWA-Update] Update check failed from home:', err);
const toast = await this.toastCtrl.create({
message: 'Errore durante la ricerca di aggiornamenti.',
duration: 3000,
color: 'danger'
});
await toast.present();
return false;
}
}
private async applyUpdateAndReload() {
const overlay = showFullscreenUpdateOverlay();
let activated = false;
const activateAndReload = async () => {
if (activated) return;
activated = true;
try {
if (this.swUpdate.isEnabled) {
await this.swUpdate.activateUpdate();
}
} catch (e) {
console.warn('[PWA-Update] activateUpdate failed:', e);
}
overlay.finish();
setTimeout(() => {
window.location.replace(window.location.origin + window.location.pathname + '?update=' + Date.now());
}, 600);
};
if (this.swUpdate.isEnabled) {
this.swUpdate.versionUpdates
.pipe(
filter((evt): evt is VersionReadyEvent => evt.type === 'VERSION_READY'),
first()
)
.subscribe(() => {
activateAndReload();
});
}
setTimeout(() => {
activateAndReload();
}, 6000);
}
private async checkVersionJson(): Promise<boolean> {
try {
const response = await fetch(`/version.json?cb=${Date.now()}`, { cache: 'no-store' });
if (!response.ok) return false;
const data = await response.json();
return data.version !== VERSION;
} catch (err) {
return false;
}
}
onInteraction() {
if (this.firstInteraction) {
this.firstInteraction = false;
@@ -1104,6 +1221,12 @@ export class HomePage implements OnDestroy {
return info && info.num_canto ? info.num_canto.toString() : null;
}
getMySongNumber(canto: any): number {
if (!canto || !canto.id) return 0;
const index = this.myCantiService.myCanti().findIndex(c => c.id === canto.id);
return index !== -1 ? index + 1 : 0;
}
toggleComunitaFilter() {
if (!this.comunitaService.comunitaCode()) {
this.promptComunitaCode();