feat: condivisione e importazione automatica del codice comunità nelle playlist con priorità tonalità e autoscroll e rifinitura UI
This commit is contained in:
@@ -11,11 +11,30 @@
|
||||
<div class="scanner-container">
|
||||
<zxing-scanner
|
||||
[formats]="allowedFormats"
|
||||
[device]="currentDevice"
|
||||
(camerasFound)="onCamerasFound($event)"
|
||||
(scanSuccess)="onCodeResult($event)">
|
||||
</zxing-scanner>
|
||||
|
||||
<div class="scan-overlay">
|
||||
<div class="scan-frame"></div>
|
||||
<p class="scan-text">Inquadra il QR Code della tua parrocchia</p>
|
||||
</div>
|
||||
|
||||
<!-- Pulsante premium per cambiare fotocamera -->
|
||||
<div class="camera-toggle-container" *ngIf="availableDevices.length > 1">
|
||||
<button (click)="toggleCamera()" class="camera-toggle-btn">
|
||||
<ion-icon name="camera-reverse-outline"></ion-icon>
|
||||
<span>Cambia fotocamera</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Messaggio di aiuto per utenti iPad in modalità desktop -->
|
||||
<div class="ipad-warning-container" *ngIf="showIpadWarning">
|
||||
<ion-icon name="information-circle-outline"></ion-icon>
|
||||
<p>
|
||||
Su iPad, se non vedi lo switch fotocamera, tocca l'icona <strong>"aA"</strong> in alto nella barra di Safari e seleziona <strong>"Richiedi sito mobile"</strong>.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
@@ -55,6 +55,91 @@
|
||||
padding: 0 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.camera-toggle-container {
|
||||
position: absolute;
|
||||
bottom: 50px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.camera-toggle-btn {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||
color: white;
|
||||
padding: 12px 24px;
|
||||
border-radius: 30px;
|
||||
font-family: 'Outfit', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);
|
||||
cursor: pointer;
|
||||
transition: background 0.2s, transform 0.2s, box-shadow 0.2s;
|
||||
outline: none;
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background: rgba(255, 255, 255, 0.35);
|
||||
transform: scale(0.96);
|
||||
box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.37);
|
||||
}
|
||||
|
||||
ion-icon {
|
||||
font-size: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.ipad-warning-container {
|
||||
position: absolute;
|
||||
bottom: 40px;
|
||||
left: 24px;
|
||||
right: 24px;
|
||||
background: rgba(0, 0, 0, 0.75);
|
||||
backdrop-filter: blur(12px);
|
||||
-webkit-backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
border-radius: 14px;
|
||||
padding: 14px 18px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
color: white;
|
||||
z-index: 10;
|
||||
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.5);
|
||||
|
||||
ion-icon {
|
||||
font-size: 24px;
|
||||
color: var(--ion-color-secondary);
|
||||
flex-shrink: 0;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
font-family: 'Outfit', sans-serif;
|
||||
font-size: 0.82rem;
|
||||
line-height: 1.45;
|
||||
font-weight: 500;
|
||||
text-align: left;
|
||||
|
||||
strong {
|
||||
color: var(--ion-color-secondary);
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scan {
|
||||
|
||||
@@ -16,6 +16,39 @@ export class QrScannerComponent {
|
||||
private modalCtrl = inject(ModalController);
|
||||
public allowedFormats = [BarcodeFormat.QR_CODE];
|
||||
|
||||
public availableDevices: MediaDeviceInfo[] = [];
|
||||
public currentDevice: MediaDeviceInfo | undefined = undefined;
|
||||
|
||||
onCamerasFound(devices: MediaDeviceInfo[]) {
|
||||
this.availableDevices = devices;
|
||||
if (devices && devices.length > 0) {
|
||||
// Cerca la fotocamera posteriore (etichette contenenti 'back', 'rear', 'environment', 'posteriore')
|
||||
const backCamera = devices.find(d => {
|
||||
const label = d.label.toLowerCase();
|
||||
return label.includes('back') ||
|
||||
label.includes('rear') ||
|
||||
label.includes('environment') ||
|
||||
label.includes('posteriore');
|
||||
});
|
||||
this.currentDevice = backCamera || devices[0];
|
||||
}
|
||||
}
|
||||
|
||||
toggleCamera() {
|
||||
if (this.availableDevices.length <= 1) return;
|
||||
const currentIndex = this.availableDevices.findIndex(d => d.deviceId === this.currentDevice?.deviceId);
|
||||
const nextIndex = (currentIndex + 1) % this.availableDevices.length;
|
||||
this.currentDevice = this.availableDevices[nextIndex];
|
||||
}
|
||||
|
||||
get showIpadWarning(): boolean {
|
||||
const isIPadDesktop =
|
||||
/Macintosh/.test(navigator.userAgent) &&
|
||||
navigator.maxTouchPoints !== undefined &&
|
||||
navigator.maxTouchPoints > 1;
|
||||
return isIPadDesktop && this.availableDevices.length <= 1;
|
||||
}
|
||||
|
||||
onCodeResult(result: string) {
|
||||
if (result) {
|
||||
this.modalCtrl.dismiss(result);
|
||||
|
||||
Reference in New Issue
Block a user