Ottimizzazione UI player, rotazione head tilt invertita, prefisso playlist in Home e implementazione Identity QR modal e interceptor API

This commit is contained in:
David Frassi
2026-06-12 17:13:46 +02:00
parent 4d1883a45d
commit d023bb7d3f
31 changed files with 1706 additions and 160 deletions
@@ -0,0 +1,41 @@
<ion-header class="ion-no-border">
<ion-toolbar class="bg-gradient">
<ion-title class="outfit-font">QR Code di Ripristino</ion-title>
<ion-buttons slot="end">
<ion-button (click)="dismiss()">
<ion-icon name="close-outline" slot="icon-only" color="secondary"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content class="bg-gradient ion-padding">
<div class="qr-container">
<p class="description outfit-font">
Salva questo QR Code (fai uno screenshot o scaricalo) per ripristinare il tuo account e le tue comunità se cambi dispositivo o reinstalli l'applicazione.
</p>
<div class="qr-card glass">
<div class="qr-wrapper" *ngIf="qrCodeUrl">
<img [src]="qrCodeUrl" alt="QR Code di Ripristino" class="qr-image" />
</div>
<div class="uuid-box">
<span class="uuid-label outfit-font">Codice Identificativo:</span>
<span class="uuid-text select-all outfit-font">{{ userUuid }}</span>
</div>
</div>
<div class="actions-wrapper">
<ion-button expand="block" fill="solid" color="secondary" class="outfit-font action-btn" (click)="copyToClipboard()">
<ion-icon name="copy-outline" slot="start"></ion-icon>
Copia Codice Testuale
</ion-button>
<a *ngIf="qrCodeUrl" [href]="qrCodeUrl" download="ripristino-identita-canti.png" class="download-btn outfit-font">
<ion-icon name="download-outline"></ion-icon>
Scarica Immagine QR
</a>
</div>
</div>
</ion-content>
@@ -0,0 +1,121 @@
.qr-container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 16px 8px;
text-align: center;
min-height: 100%;
}
.description {
font-size: 0.95rem;
line-height: 1.5;
color: var(--ion-text-color);
opacity: 0.9;
margin-bottom: 24px;
max-width: 320px;
}
.qr-card {
padding: 24px;
border-radius: 24px;
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
margin-bottom: 24px;
width: 100%;
max-width: 340px;
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.15);
}
.qr-wrapper {
background: white;
padding: 12px;
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
width: 220px;
height: 220px;
box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.05);
.qr-image {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.uuid-box {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
width: 100%;
padding-top: 8px;
border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.uuid-label {
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--ion-color-secondary);
font-weight: 600;
}
.uuid-text {
font-size: 0.8rem;
color: var(--ion-text-color);
word-break: break-all;
opacity: 0.85;
font-family: monospace;
user-select: all;
background: rgba(var(--ion-text-color-rgb, 255, 255, 255), 0.04);
padding: 6px 10px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.04);
}
.actions-wrapper {
display: flex;
flex-direction: column;
gap: 12px;
width: 100%;
max-width: 340px;
}
.action-btn {
margin: 0;
--border-radius: 14px;
--box-shadow: 0 4px 16px rgba(var(--ion-color-secondary-rgb), 0.2);
font-weight: 600;
height: 48px;
}
.download-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
text-decoration: none;
background: rgba(255, 255, 255, 0.06);
color: var(--ion-text-color);
border: 1px solid rgba(255, 255, 255, 0.1);
padding: 12px;
border-radius: 14px;
font-size: 0.9rem;
font-weight: 600;
transition: all 0.2s ease;
ion-icon {
font-size: 1.2rem;
color: var(--ion-color-secondary);
}
&:active {
background: rgba(255, 255, 255, 0.12);
}
}
@@ -0,0 +1,58 @@
import { Component, OnInit, inject, Input } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IonicModule, ModalController, ToastController } from '@ionic/angular';
import * as QRCode from 'qrcode';
@Component({
selector: 'app-identity-qr-modal',
templateUrl: './identity-qr-modal.component.html',
styleUrls: ['./identity-qr-modal.component.scss'],
standalone: true,
imports: [CommonModule, IonicModule]
})
export class IdentityQrModalComponent implements OnInit {
private modalCtrl = inject(ModalController);
private toastCtrl = inject(ToastController);
@Input() userUuid!: string;
public qrCodeUrl: string = '';
ngOnInit() {
this.generateQr();
}
async generateQr() {
try {
this.qrCodeUrl = await QRCode.toDataURL(this.userUuid, {
errorCorrectionLevel: 'H',
margin: 2,
width: 400,
color: {
dark: '#1e293b', // Slate 800 for premium dark aesthetic contrast
light: '#ffffff'
}
});
} catch (err) {
console.error('Failed to generate QR Code:', err);
}
}
async copyToClipboard() {
try {
await navigator.clipboard.writeText(this.userUuid);
const toast = await this.toastCtrl.create({
message: 'Codice copiato negli appunti!',
duration: 2000,
color: 'success',
position: 'bottom'
});
await toast.present();
} catch (err) {
console.error('Failed to copy text:', err);
}
}
dismiss() {
this.modalCtrl.dismiss();
}
}