Compare commits
64 Commits
ebf73be72a
...
docker
| Author | SHA1 | Date | |
|---|---|---|---|
| e18a09e1da | |||
| f3262a0497 | |||
| 690f7e636a | |||
| 5b95f18889 | |||
| 45dd205270 | |||
| 0764b0b625 | |||
| 8befcb8abf | |||
| 89aed8a458 | |||
| ae861e78d2 | |||
| 77eb9943d0 | |||
| a0ec72f6c0 | |||
| 21a1d57cab | |||
| 2833cd0487 | |||
| 865bfa2752 | |||
| 70ed8f0a61 | |||
| ed42a41bcd | |||
| 6a3f931431 | |||
| ef1bc92e67 | |||
| 343f171d6a | |||
| 61f0945db2 | |||
| 29724f5baf | |||
| 009fa51155 | |||
| 7b405ed78e | |||
| 79756d878d | |||
| 551697d98d | |||
| 3db0d946b7 | |||
| d08e54657a | |||
| b810c7f76b | |||
| 95018e0d65 | |||
| df9b63dd41 | |||
| 7a01251258 | |||
| 56484e0bec | |||
| c199e542ba | |||
| d99b5ec923 | |||
| 6795282993 | |||
| 62d5cebf9c | |||
| ee67bedc31 | |||
| f124f2e4e8 | |||
| 570c2e53d6 | |||
| 4bfcf147b4 | |||
| c37b5b9f1e | |||
|
|
29a567bb1d | ||
|
|
f017ec0364 | ||
|
|
6036896f7d | ||
|
|
8717a3b6ef | ||
|
|
967005b96a | ||
|
|
59d7e0c41f | ||
|
|
daf9ea31fc | ||
|
|
cb30e1fb08 | ||
|
|
717dc44b3b | ||
|
|
fef7b909e7 | ||
|
|
139a9d62b7 | ||
|
|
4e16f50aeb | ||
|
|
db1d99d424 | ||
|
|
114697a1b2 | ||
|
|
995732f379 | ||
|
|
28ef09d91f | ||
|
|
b12b57be81 | ||
|
|
8bc123ff85 | ||
|
|
9b38adfd5f | ||
|
|
6558ac6512 | ||
|
|
1a5611cc60 | ||
|
|
c910117171 | ||
|
|
ded7d3882b |
87
Mimante/.dockerignore
Normal file
@@ -0,0 +1,87 @@
|
||||
**Dockerignore file**
|
||||
|
||||
# Build artifacts
|
||||
**/bin/
|
||||
**/obj/
|
||||
**/out/
|
||||
**/publish/
|
||||
|
||||
# User-specific files
|
||||
*.user
|
||||
*.suo
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# IDE files
|
||||
.vs/
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# NuGet packages
|
||||
*.nupkg
|
||||
*.snupkg
|
||||
**/packages/*
|
||||
!**/packages/build/
|
||||
|
||||
# Test results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# Data and databases (exclude from image)
|
||||
**/data/*.db
|
||||
**/data/*.db-shm
|
||||
**/data/*.db-wal
|
||||
**/data/backups/
|
||||
**/data/logs/
|
||||
|
||||
# Git files
|
||||
.git
|
||||
.gitignore
|
||||
.gitattributes
|
||||
.github/
|
||||
|
||||
# CI/CD files
|
||||
.gitea/
|
||||
|
||||
# Documentation
|
||||
*.md
|
||||
!README.md
|
||||
|
||||
# Docker files
|
||||
Dockerfile*
|
||||
docker-compose*
|
||||
.dockerignore
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.*
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.temp
|
||||
*.cache
|
||||
*.bak
|
||||
*.log
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
92
Mimante/.env.example
Normal file
@@ -0,0 +1,92 @@
|
||||
# AutoBidder Environment Variables
|
||||
# Copia questo file in .env e configura i valori
|
||||
|
||||
# === ASP.NET Core Configuration ===
|
||||
ASPNETCORE_ENVIRONMENT=Production
|
||||
ASPNETCORE_URLS=http://+:8080
|
||||
|
||||
# === AUTENTICAZIONE APPLICAZIONE (SICUREZZA) ===
|
||||
# Username amministratore
|
||||
ADMIN_USERNAME=admin
|
||||
|
||||
# Password amministratore (OBBLIGATORIO in produzione!)
|
||||
# REQUISITI: min 12 caratteri, maiuscole, minuscole, numeri, simboli
|
||||
# Esempio: Admin@SecurePass2024!
|
||||
ADMIN_PASSWORD=
|
||||
|
||||
# === NOTA: SESSIONE BIDOO ===
|
||||
# Non servono credenziali Bidoo!
|
||||
# Il cookie di sessione Bidoo viene configurato manualmente
|
||||
# dall'interfaccia web in Settings ? Sessione Bidoo
|
||||
|
||||
# === PostgreSQL Database (Statistiche) ===
|
||||
# Username PostgreSQL
|
||||
POSTGRES_USER=autobidder
|
||||
|
||||
# Password PostgreSQL (CAMBIA IN PRODUZIONE!)
|
||||
POSTGRES_PASSWORD=autobidder_password
|
||||
|
||||
# Database name
|
||||
POSTGRES_DB=autobidder_stats
|
||||
|
||||
# Usa PostgreSQL per statistiche (true/false)
|
||||
USE_POSTGRES=true
|
||||
|
||||
# === Application Settings ===
|
||||
# Logging level (Debug, Information, Warning, Error)
|
||||
LOG_LEVEL=Information
|
||||
|
||||
# Porta applicazione (default: 8080 container, mappata su host)
|
||||
APP_PORT=5000
|
||||
|
||||
# === Database Configuration ===
|
||||
# Path database SQLite locale (default: /app/data/autobidder.db in container)
|
||||
# DATABASE_PATH=/app/data/autobidder.db
|
||||
|
||||
# Giorni di retention backup database (default: 30)
|
||||
DB_BACKUP_RETENTION_DAYS=30
|
||||
|
||||
# Auto-ottimizzazione database (VACUUM automatico)
|
||||
DB_AUTO_OPTIMIZE=true
|
||||
|
||||
# === Logging ===
|
||||
# Livello log: Trace, Debug, Information, Warning, Error, Critical
|
||||
LOG_LEVEL=Information
|
||||
|
||||
# Livello log Microsoft: Trace, Debug, Information, Warning, Error, Critical
|
||||
LOG_LEVEL_MICROSOFT=Warning
|
||||
|
||||
# Livello log Entity Framework: Trace, Debug, Information, Warning, Error, Critical
|
||||
LOG_LEVEL_EF=Warning
|
||||
|
||||
# === Application Settings ===
|
||||
# Numero massimo connessioni concorrenti HTTP
|
||||
# MAX_HTTP_CONNECTIONS=10
|
||||
|
||||
# Timeout richieste HTTP (secondi)
|
||||
# HTTP_TIMEOUT=30
|
||||
|
||||
# === Backup Configuration ===
|
||||
# Directory backup (default: /app/data/backups)
|
||||
# BACKUP_DIR=/app/data/backups
|
||||
|
||||
# Numero giorni backup da mantenere
|
||||
# BACKUP_RETENTION_DAYS=30
|
||||
|
||||
# === Security ===
|
||||
# Chiave segreta per DataProtection (genera random se non specificato)
|
||||
# DATA_PROTECTION_KEY=your-random-key-here
|
||||
|
||||
# === Monitoring ===
|
||||
# Abilita metriche Prometheus (true/false)
|
||||
# ENABLE_METRICS=false
|
||||
|
||||
# Porta metriche (se ENABLE_METRICS=true)
|
||||
# METRICS_PORT=9090
|
||||
|
||||
# === Advanced ===
|
||||
# Numero thread worker per polling aste
|
||||
# AUCTION_WORKER_THREADS=4
|
||||
|
||||
# Intervallo pulizia cache (minuti)
|
||||
# CACHE_CLEANUP_INTERVAL=60
|
||||
71
Mimante/.gitea/workflows/backup.yml
Normal file
@@ -0,0 +1,71 @@
|
||||
name: Database Backup
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Esegui backup ogni giorno alle 2:00 AM UTC
|
||||
- cron: '0 2 * * *'
|
||||
workflow_dispatch: # Permette trigger manuale
|
||||
|
||||
jobs:
|
||||
backup-database:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Execute remote backup
|
||||
uses: appleboy/ssh-action@master
|
||||
with:
|
||||
host: ${{ secrets.DEPLOY_HOST }}
|
||||
username: ${{ secrets.DEPLOY_USER }}
|
||||
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
script: |
|
||||
echo "??? Starting database backup..."
|
||||
|
||||
cd /opt/autobidder
|
||||
|
||||
# Directory backup
|
||||
BACKUP_DIR="./data/backups"
|
||||
mkdir -p $BACKUP_DIR
|
||||
|
||||
# Timestamp
|
||||
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# Backup database
|
||||
if [ -f ./data/autobidder.db ]; then
|
||||
echo "?? Backing up autobidder.db..."
|
||||
cp ./data/autobidder.db $BACKUP_DIR/autobidder_backup_$TIMESTAMP.db
|
||||
|
||||
# Verifica backup
|
||||
if [ -f $BACKUP_DIR/autobidder_backup_$TIMESTAMP.db ]; then
|
||||
SIZE=$(du -h $BACKUP_DIR/autobidder_backup_$TIMESTAMP.db | cut -f1)
|
||||
echo "? Backup created successfully: $SIZE"
|
||||
else
|
||||
echo "? Backup failed!"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "?? Database file not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Cleanup backup vecchi (mantieni ultimi 30 giorni)
|
||||
echo "?? Cleaning up old backups..."
|
||||
find $BACKUP_DIR -name "autobidder_backup_*.db" -mtime +30 -delete
|
||||
|
||||
# Conta backup rimanenti
|
||||
BACKUP_COUNT=$(find $BACKUP_DIR -name "autobidder_backup_*.db" | wc -l)
|
||||
echo "?? Total backups: $BACKUP_COUNT"
|
||||
|
||||
# Mostra dimensione totale backup
|
||||
TOTAL_SIZE=$(du -sh $BACKUP_DIR | cut -f1)
|
||||
echo "?? Total backup size: $TOTAL_SIZE"
|
||||
|
||||
echo "?? Backup completed successfully!"
|
||||
|
||||
- name: Backup summary
|
||||
if: always()
|
||||
run: |
|
||||
if [ "${{ job.status }}" == "success" ]; then
|
||||
echo "? Database backup SUCCESSFUL"
|
||||
else
|
||||
echo "? Database backup FAILED"
|
||||
fi
|
||||
222
Mimante/.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,222 @@
|
||||
name: Build and Deploy AutoBidder
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- docker
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
workflow_dispatch: # Permette trigger manuale
|
||||
|
||||
env:
|
||||
DOTNET_VERSION: '8.0.x'
|
||||
REGISTRY: ${{ secrets.GITEA_REGISTRY }}
|
||||
|
||||
jobs:
|
||||
# Job 1: Build e Test .NET
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Fetch completo per analisi
|
||||
|
||||
- name: Set up .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: ${{ env.DOTNET_VERSION }}
|
||||
|
||||
- name: Cache NuGet packages
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nuget-
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build
|
||||
run: dotnet build --configuration Release --no-restore
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test --no-restore --verbosity normal --logger "console;verbosity=detailed"
|
||||
continue-on-error: true
|
||||
|
||||
- name: Publish artifacts
|
||||
run: dotnet publish --configuration Release --no-build --output ./publish
|
||||
|
||||
- name: Upload publish artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: publish-artifacts
|
||||
path: ./publish
|
||||
retention-days: 7
|
||||
|
||||
# Job 2: Build e Push Docker Image
|
||||
build-docker:
|
||||
needs: build-and-test
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Log in to Gitea Container Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.GITEA_USERNAME }}
|
||||
password: ${{ secrets.GITEA_PASSWORD }}
|
||||
|
||||
- name: Extract metadata for Docker
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/autobidder
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=ref,event=pr
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=sha,prefix=,format=short
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
labels: |
|
||||
org.opencontainers.image.title=AutoBidder
|
||||
org.opencontainers.image.description=Sistema automatizzato gestione aste Blazor
|
||||
org.opencontainers.image.vendor=Alby96
|
||||
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=${{ env.REGISTRY }}/autobidder:buildcache
|
||||
cache-to: type=registry,ref=${{ env.REGISTRY }}/autobidder:buildcache,mode=max
|
||||
build-args: |
|
||||
BUILD_DATE=${{ github.event.head_commit.timestamp }}
|
||||
VCS_REF=${{ github.sha }}
|
||||
VERSION=${{ steps.meta.outputs.version }}
|
||||
|
||||
# Job 3: Security Scan (opzionale)
|
||||
security-scan:
|
||||
needs: build-docker
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
continue-on-error: true
|
||||
|
||||
steps:
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
with:
|
||||
image-ref: ${{ env.REGISTRY }}/autobidder:latest
|
||||
format: 'sarif'
|
||||
output: 'trivy-results.sarif'
|
||||
|
||||
- name: Upload Trivy results
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
if: always()
|
||||
with:
|
||||
sarif_file: 'trivy-results.sarif'
|
||||
|
||||
# Job 4: Deploy su Server
|
||||
deploy:
|
||||
needs: build-docker
|
||||
runs-on: ubuntu-latest
|
||||
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/docker') && github.event_name == 'push'
|
||||
environment:
|
||||
name: production
|
||||
url: https://${{ secrets.DEPLOY_HOST }}:5001
|
||||
|
||||
steps:
|
||||
- name: Deploy to server
|
||||
uses: appleboy/ssh-action@master
|
||||
with:
|
||||
host: ${{ secrets.DEPLOY_HOST }}
|
||||
username: ${{ secrets.DEPLOY_USER }}
|
||||
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
script: |
|
||||
echo "?? Starting deployment..."
|
||||
|
||||
# Vai alla directory deploy
|
||||
cd /opt/autobidder || exit 1
|
||||
|
||||
# Carica variabili ambiente
|
||||
if [ -f .env ]; then
|
||||
export $(cat .env | grep -v '^#' | xargs)
|
||||
fi
|
||||
|
||||
# Login al registry
|
||||
echo "$GITEA_PASSWORD" | docker login $GITEA_REGISTRY -u $GITEA_USERNAME --password-stdin
|
||||
|
||||
# Backup database prima del deploy
|
||||
echo "?? Creating database backup..."
|
||||
if [ -f data/autobidder.db ]; then
|
||||
mkdir -p data/backups
|
||||
cp data/autobidder.db data/backups/autobidder_predeploy_$(date +%Y%m%d_%H%M%S).db
|
||||
fi
|
||||
|
||||
# Pull nuova immagine
|
||||
echo "?? Pulling latest image..."
|
||||
docker-compose pull
|
||||
|
||||
# Stop vecchi container
|
||||
echo "?? Stopping old containers..."
|
||||
docker-compose down
|
||||
|
||||
# Start nuovi container
|
||||
echo "?? Starting new containers..."
|
||||
docker-compose up -d
|
||||
|
||||
# Attendi healthcheck
|
||||
echo "?? Waiting for healthcheck..."
|
||||
sleep 15
|
||||
|
||||
# Verifica status
|
||||
echo "?? Container status:"
|
||||
docker-compose ps
|
||||
|
||||
# Verifica healthcheck
|
||||
if docker inspect --format='{{.State.Health.Status}}' autobidder | grep -q "healthy"; then
|
||||
echo "? Deploy successful! Container is healthy."
|
||||
else
|
||||
echo "?? Warning: Container may not be healthy yet. Check logs."
|
||||
fi
|
||||
|
||||
# Mostra ultimi log
|
||||
echo "?? Recent logs:"
|
||||
docker-compose logs --tail=30
|
||||
|
||||
echo "?? Deployment completed!"
|
||||
|
||||
- name: Notify deployment status
|
||||
if: always()
|
||||
run: |
|
||||
if [ "${{ job.status }}" == "success" ]; then
|
||||
echo "? Deployment SUCCESSFUL"
|
||||
else
|
||||
echo "? Deployment FAILED"
|
||||
fi
|
||||
|
||||
# Job 5: Cleanup (rimuove vecchie immagini dal registry)
|
||||
cleanup:
|
||||
needs: deploy
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- name: Cleanup old images
|
||||
run: |
|
||||
echo "?? Cleanup task completed (manual cleanup required on Gitea)"
|
||||
70
Mimante/.gitea/workflows/health-check.yml
Normal file
@@ -0,0 +1,70 @@
|
||||
name: Health Check Monitor
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Verifica ogni ora
|
||||
- cron: '0 * * * *'
|
||||
workflow_dispatch: # Permette trigger manuale
|
||||
|
||||
jobs:
|
||||
health-check:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check application health
|
||||
uses: appleboy/ssh-action@master
|
||||
with:
|
||||
host: ${{ secrets.DEPLOY_HOST }}
|
||||
username: ${{ secrets.DEPLOY_USER }}
|
||||
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
script: |
|
||||
echo "?? Health Check Starting..."
|
||||
|
||||
# Verifica container running
|
||||
if ! docker ps | grep -q "autobidder"; then
|
||||
echo "? Container NOT running!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verifica Docker healthcheck
|
||||
HEALTH_STATUS=$(docker inspect --format='{{.State.Health.Status}}' autobidder 2>/dev/null || echo "unknown")
|
||||
echo "Docker Health: $HEALTH_STATUS"
|
||||
|
||||
if [ "$HEALTH_STATUS" != "healthy" ]; then
|
||||
echo "?? Container not healthy!"
|
||||
echo "Recent logs:"
|
||||
docker logs autobidder --tail=50
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test HTTP endpoint
|
||||
if curl -f -s http://localhost:5000/health > /dev/null; then
|
||||
echo "? HTTP endpoint: OK"
|
||||
else
|
||||
echo "? HTTP endpoint: FAILED"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Verifica database
|
||||
cd /opt/autobidder
|
||||
if [ -f ./data/autobidder.db ]; then
|
||||
DB_SIZE=$(du -h ./data/autobidder.db | cut -f1)
|
||||
echo "?? Database size: $DB_SIZE"
|
||||
else
|
||||
echo "?? Database file not found!"
|
||||
fi
|
||||
|
||||
# Verifica risorse container
|
||||
echo "?? Container resources:"
|
||||
docker stats autobidder --no-stream --format " CPU: {{.CPUPerc}}\n Memory: {{.MemUsage}}"
|
||||
|
||||
echo "? All health checks passed!"
|
||||
|
||||
- name: Health check summary
|
||||
if: always()
|
||||
run: |
|
||||
if [ "${{ job.status }}" == "success" ]; then
|
||||
echo "? Health check PASSED"
|
||||
else
|
||||
echo "? Health check FAILED - Check server status!"
|
||||
fi
|
||||
97
Mimante/.github/workflows/ci-cd.yml
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
name: AutoBidder CI/CD
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ main, docker ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
|
||||
env:
|
||||
REGISTRY: 192.168.30.23/Alby96
|
||||
IMAGE_NAME: autobidder
|
||||
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build
|
||||
run: dotnet build --configuration Release --no-restore
|
||||
|
||||
- name: Test
|
||||
run: dotnet test --no-restore --verbosity normal
|
||||
continue-on-error: true
|
||||
|
||||
- name: Publish
|
||||
run: dotnet publish --configuration Release --no-build --output ./publish
|
||||
|
||||
docker-build-push:
|
||||
needs: build-and-test
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Login to Gitea Registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ secrets.GITEA_REGISTRY }}
|
||||
username: ${{ secrets.GITEA_USERNAME }}
|
||||
password: ${{ secrets.GITEA_PASSWORD }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=ref,event=branch
|
||||
type=sha
|
||||
type=raw,value=latest,enable={{is_default_branch}}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
|
||||
cache-to: type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
|
||||
|
||||
deploy:
|
||||
needs: docker-build-push
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/docker' || github.ref == 'refs/heads/main'
|
||||
|
||||
steps:
|
||||
- name: Deploy to server
|
||||
uses: appleboy/ssh-action@master
|
||||
with:
|
||||
host: ${{ secrets.DEPLOY_HOST }}
|
||||
username: ${{ secrets.DEPLOY_USER }}
|
||||
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
||||
script: |
|
||||
cd /opt/autobidder
|
||||
source .env
|
||||
echo "$GITEA_PASSWORD" | docker login $GITEA_REGISTRY -u $GITEA_USERNAME --password-stdin
|
||||
docker-compose pull
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
sleep 10
|
||||
docker-compose ps
|
||||
docker-compose logs --tail=30
|
||||
456
Mimante/.gitignore
vendored
Normal file
@@ -0,0 +1,456 @@
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.rsuser
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Mono auto generated files
|
||||
mono_crash.*
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
[Ll]ogs/
|
||||
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUnit
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
nunit-*.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
# ASP.NET Scaffolding
|
||||
ScaffoldingReadMe.txt
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_h.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*_wpftmp.csproj
|
||||
*.log
|
||||
*.tlog
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Coverlet is a free, cross platform Code Coverage Tool
|
||||
coverage*.json
|
||||
coverage*.xml
|
||||
coverage*.info
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# NuGet Symbol Packages
|
||||
*.snupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
*.appxbundle
|
||||
*.appxupload
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!?*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
*- [Bb]ackup.rdl
|
||||
*- [Bb]ackup ([0-9]).rdl
|
||||
*- [Bb]ackup ([0-9][0-9]).rdl
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio 6 auto-generated project file (contains which files were open etc.)
|
||||
*.vbp
|
||||
|
||||
# Visual Studio 6 workspace and project file (working project files containing files to include in project)
|
||||
*.dsw
|
||||
*.dsp
|
||||
|
||||
# Visual Studio 6 technical files
|
||||
*.ncb
|
||||
*.aps
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# CodeRush personal settings
|
||||
.cr/personal
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
# Local History for Visual Studio
|
||||
.localhistory/
|
||||
|
||||
# Visual Studio History (VSHistory) files
|
||||
.vshistory/
|
||||
|
||||
# BeatPulse healthcheck temp database
|
||||
healthchecksdb
|
||||
|
||||
# Backup folder for Package Reference Convert tool in Visual Studio 2017
|
||||
MigrationBackup/
|
||||
|
||||
# Ionide (cross platform F# VS Code tools) working folder
|
||||
.ionide/
|
||||
|
||||
# Fody - auto-generated XML schema
|
||||
FodyWeavers.xsd
|
||||
|
||||
# VS Code files for those working on multiple tools
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Windows Installer files from build outputs
|
||||
*.cab
|
||||
*.msi
|
||||
*.msix
|
||||
*.msm
|
||||
*.msp
|
||||
|
||||
# JetBrains Rider
|
||||
*.sln.iml
|
||||
.idea/
|
||||
|
||||
# ============================================
|
||||
# AutoBidder Specific
|
||||
# ============================================
|
||||
|
||||
# Database files (local development)
|
||||
*.db
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
data/*.db
|
||||
data/*.db-*
|
||||
|
||||
# Backups (keep structure, ignore files)
|
||||
data/backups/*.db
|
||||
data/backups/*.json
|
||||
|
||||
# Logs
|
||||
logs/*.log
|
||||
logs/*.txt
|
||||
*.log
|
||||
|
||||
# Environment files with secrets
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Certificates and keys
|
||||
*.pfx
|
||||
*.key
|
||||
*.crt
|
||||
*.pem
|
||||
cert/*
|
||||
!cert/.gitkeep
|
||||
|
||||
# Docker volumes data
|
||||
test-data/
|
||||
|
||||
# Published artifacts
|
||||
publish/
|
||||
PublishProfiles/
|
||||
|
||||
# Temp directories
|
||||
temp/
|
||||
tmp/
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Keep important empty directories
|
||||
!data/.gitkeep
|
||||
!data/backups/.gitkeep
|
||||
!logs/.gitkeep
|
||||
!cert/.gitkeep
|
||||
36
Mimante/App.razor
Normal file
@@ -0,0 +1,36 @@
|
||||
<CascadingAuthenticationState>
|
||||
<Router AppAssembly="@typeof(App).Assembly">
|
||||
<Found Context="routeData">
|
||||
<AuthorizeRouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)">
|
||||
<NotAuthorized>
|
||||
@if (context.User.Identity?.IsAuthenticated != true)
|
||||
{
|
||||
<RedirectToLogin />
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>Non sei autorizzato ad accedere a questa risorsa.</p>
|
||||
}
|
||||
</NotAuthorized>
|
||||
</AuthorizeRouteView>
|
||||
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
|
||||
</Found>
|
||||
<NotFound>
|
||||
<PageTitle>Non trovato</PageTitle>
|
||||
<LayoutView Layout="@typeof(MainLayout)">
|
||||
<div style="padding: 2rem; text-align: center;">
|
||||
<svg style="width: 64px; height: 64px; margin-bottom: 1rem; opacity: 0.5;" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<line x1="12" y1="8" x2="12" y2="12"></line>
|
||||
<line x1="12" y1="16" x2="12.01" y2="16"></line>
|
||||
</svg>
|
||||
<h1 style="font-size: 1.5rem; margin-bottom: 0.5rem;">Pagina non trovata</h1>
|
||||
<p style="color: var(--text-muted);">Spiacenti, non c'è nulla a questo indirizzo.</p>
|
||||
<a href="/" style="color: var(--primary-color); text-decoration: none; margin-top: 1rem; display: inline-block;">
|
||||
?? Torna alla Home
|
||||
</a>
|
||||
</div>
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
</CascadingAuthenticationState>
|
||||
@@ -4,6 +4,26 @@
|
||||
xmlns:local="clr-namespace:Mimante"
|
||||
StartupUri="MainWindow.xaml">
|
||||
<Application.Resources>
|
||||
|
||||
<ResourceDictionary>
|
||||
<!-- Stile pulsanti globale -->
|
||||
<Style x:Key="SmallButtonStyle" TargetType="Button">
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
CornerRadius="12"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Configuration;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Windows;
|
||||
|
||||
|
||||
157
Mimante/AutoBidder.csproj
Normal file
@@ -0,0 +1,157 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<AssemblyName>AutoBidder</AssemblyName>
|
||||
<RootNamespace>AutoBidder</RootNamespace>
|
||||
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||
<DockerfileContext>.</DockerfileContext>
|
||||
<DockerfileFile>Dockerfile</DockerfileFile>
|
||||
|
||||
<!-- Versioning per Docker & Gitea Registry -->
|
||||
<!-- v1.3.0: Database management + bug fixes (duplicates, race conditions, warnings) -->
|
||||
<Version>1.3.0</Version>
|
||||
<AssemblyVersion>1.3.0.0</AssemblyVersion>
|
||||
<FileVersion>1.3.0.0</FileVersion>
|
||||
<InformationalVersion>1.3.0</InformationalVersion>
|
||||
|
||||
<!-- Metadata immagine Docker -->
|
||||
<ContainerImageName>autobidder</ContainerImageName>
|
||||
<ContainerImageTag>$(Version)</ContainerImageTag>
|
||||
<!-- CORRETTO: Convenzione Gitea {registro}/{proprietario}/{immagine} -->
|
||||
<ContainerRegistry>gitea.encke-hake.ts.net/alby96</ContainerRegistry>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- Exclude WPF files from compilation -->
|
||||
<Compile Remove=".github\**" />
|
||||
<Compile Remove=".vscode\**" />
|
||||
<Compile Remove="obj\**" />
|
||||
<Compile Remove="Controls\**" />
|
||||
<Compile Remove="Dialogs\**" />
|
||||
<Compile Remove="Core\**" />
|
||||
<Compile Remove="MainWindow.xaml.cs" />
|
||||
<Compile Remove="App.xaml.cs" />
|
||||
<Compile Remove="AssemblyInfo.cs" />
|
||||
<Compile Remove="ViewModels\**" />
|
||||
<Compile Remove="Utilities\NumericTextBoxHelper.cs" />
|
||||
<Compile Remove="Utilities\BooleanToOpacityConverter.cs" />
|
||||
<Compile Remove="Utilities\RelayCommand.cs" />
|
||||
|
||||
<Content Remove=".github\**" />
|
||||
<Content Remove=".vscode\**" />
|
||||
<Content Remove="obj\**" />
|
||||
<Content Remove="Controls\**" />
|
||||
<Content Remove="Dialogs\**" />
|
||||
<Content Remove="**\*.xaml" />
|
||||
|
||||
<EmbeddedResource Remove=".github\**" />
|
||||
<EmbeddedResource Remove=".vscode\**" />
|
||||
<EmbeddedResource Remove="obj\**" />
|
||||
<EmbeddedResource Remove="Controls\**" />
|
||||
<EmbeddedResource Remove="Dialogs\**" />
|
||||
|
||||
<None Remove=".github\**" />
|
||||
<None Remove=".vscode\**" />
|
||||
<None Remove="obj\**" />
|
||||
<None Remove="Controls\**" />
|
||||
<None Remove="Dialogs\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Icon\favicon.ico" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.0" />
|
||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="Icon\favicon.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include=".gitea\workflows\backup.yml" />
|
||||
<None Include=".gitea\workflows\deploy.yml" />
|
||||
<None Include=".gitea\workflows\health-check.yml" />
|
||||
<None Include=".github\workflows\ci-cd.yml" />
|
||||
<None Include="Dockerfile" />
|
||||
<None Include=".dockerignore" />
|
||||
<None Include="Properties\PublishProfiles\GiteaRegistry-Versioned.pubxml.user" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- ============================================ -->
|
||||
<!-- POST-BUILD TARGET: Push automatico su Gitea -->
|
||||
<!-- con versionamento da <Version> della solution -->
|
||||
<!-- ============================================ -->
|
||||
<Target Name="PushDockerImageToGitea" AfterTargets="Publish" Condition="'$(PushToGiteaRegistry)' == 'true'">
|
||||
<PropertyGroup>
|
||||
<GiteaRegistry>gitea.encke-hake.ts.net/alby96</GiteaRegistry>
|
||||
<LocalImageName>autobidder</LocalImageName>
|
||||
<GiteaImageLatest>$(GiteaRegistry)/$(LocalImageName):latest</GiteaImageLatest>
|
||||
<GiteaImageVersion>$(GiteaRegistry)/$(LocalImageName):$(Version)</GiteaImageVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="+-------------------------------------------------------------------+" />
|
||||
<Message Importance="high" Text="¦ POST-BUILD: Pubblicazione su Gitea Container Registry ¦" />
|
||||
<Message Importance="high" Text="+-------------------------------------------------------------------+" />
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="?? Solution Version: $(Version)" />
|
||||
<Message Importance="high" Text="?? Local Image: $(LocalImageName):latest" />
|
||||
<Message Importance="high" Text="??? Target Tags:" />
|
||||
<Message Importance="high" Text=" • $(GiteaImageLatest)" />
|
||||
<Message Importance="high" Text=" • $(GiteaImageVersion)" />
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="-------------------------------------------------------------------" />
|
||||
<Message Importance="high" Text="??? Tagging images..." />
|
||||
<Message Importance="high" Text="-------------------------------------------------------------------" />
|
||||
|
||||
<!-- Tag immagine locale per Gitea (latest) -->
|
||||
<Exec Command="docker tag $(LocalImageName):latest $(GiteaImageLatest)" />
|
||||
<Message Importance="high" Text="? Tagged: $(GiteaImageLatest)" />
|
||||
|
||||
<!-- Tag immagine locale per Gitea (versione solution) -->
|
||||
<Exec Command="docker tag $(LocalImageName):latest $(GiteaImageVersion)" />
|
||||
<Message Importance="high" Text="? Tagged: $(GiteaImageVersion)" />
|
||||
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="-------------------------------------------------------------------" />
|
||||
<Message Importance="high" Text="?? Pushing to Gitea Registry..." />
|
||||
<Message Importance="high" Text="-------------------------------------------------------------------" />
|
||||
|
||||
<!-- Push latest -->
|
||||
<Exec Command="docker push $(GiteaImageLatest)" />
|
||||
<Message Importance="high" Text="? Pushed: $(GiteaImageLatest)" />
|
||||
|
||||
<!-- Push version -->
|
||||
<Exec Command="docker push $(GiteaImageVersion)" />
|
||||
<Message Importance="high" Text="? Pushed: $(GiteaImageVersion)" />
|
||||
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="+-------------------------------------------------------------------+" />
|
||||
<Message Importance="high" Text="¦ ? PUBBLICAZIONE COMPLETATA CON SUCCESSO! ¦" />
|
||||
<Message Importance="high" Text="+-------------------------------------------------------------------+" />
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="?? Visualizza su Gitea:" />
|
||||
<Message Importance="high" Text=" https://gitea.encke-hake.ts.net/Alby96/-/packages/container/autobidder" />
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="?? Tag pubblicati:" />
|
||||
<Message Importance="high" Text=" • latest (sempre aggiornato all'ultima versione)" />
|
||||
<Message Importance="high" Text=" • $(Version) (versione solution corrente)" />
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="?? Pull command:" />
|
||||
<Message Importance="high" Text=" docker pull $(GiteaImageLatest)" />
|
||||
<Message Importance="high" Text=" docker pull $(GiteaImageVersion)" />
|
||||
<Message Importance="high" Text="" />
|
||||
<Message Importance="high" Text="-------------------------------------------------------------------" />
|
||||
<Message Importance="high" Text="" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
49
Mimante/AutoBidder.sln
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 18
|
||||
VisualStudioVersion = 18.0.11217.181 d18.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoBidder", "AutoBidder.csproj", "{9BBAEF93-DF66-432C-9349-459E272D6538}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|ARM = Release|ARM
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|ARM.ActiveCfg = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|ARM.Build.0 = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|ARM64.ActiveCfg = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|ARM64.Build.0 = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|ARM.ActiveCfg = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|ARM.Build.0 = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|ARM64.ActiveCfg = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|ARM64.Build.0 = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|x64.Build.0 = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{9BBAEF93-DF66-432C-9349-459E272D6538}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {1C55CA56-D270-4D9A-91DA-410BF131E905}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
964
Mimante/Controls/AuctionMonitorControl.xaml
Normal file
@@ -0,0 +1,964 @@
|
||||
<UserControl x:Class="AutoBidder.Controls.AuctionMonitorControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:util="clr-namespace:AutoBidder.Utilities"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="800" d:DesignWidth="1200"
|
||||
Background="#1E1E1E">
|
||||
|
||||
<UserControl.Resources>
|
||||
<!-- Converters -->
|
||||
<util:BooleanToOpacityConverter x:Key="BoolToOpacity"/>
|
||||
|
||||
<!-- Rounded Button Style -->
|
||||
<Style x:Key="RoundedButton" TargetType="Button">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
CornerRadius="8"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Setter Property="Padding" Value="15,10"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
</Style>
|
||||
|
||||
<!-- Small Rounded Button -->
|
||||
<Style x:Key="SmallRoundedButton" TargetType="Button" BasedOn="{StaticResource RoundedButton}">
|
||||
<Setter Property="Padding" Value="12,6"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
</Style>
|
||||
|
||||
<!-- Card Style -->
|
||||
<Style x:Key="CardBorder" TargetType="Border">
|
||||
<Setter Property="Background" Value="#252526"/>
|
||||
<Setter Property="BorderBrush" Value="#3E3E42"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Margin" Value="5"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header - COMPATTO SU 3 RIGHE -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="15,8" BorderBrush="#3E3E42" BorderThickness="0,0,0,1">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Riga 1: Solo Puntate -->
|
||||
<StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,0,3">
|
||||
<TextBlock Text="Puntate: "
|
||||
Foreground="#999999"
|
||||
FontSize="13"
|
||||
Margin="0,0,5,0"/>
|
||||
|
||||
<!-- 🎯 StackPanel per includere indicatore limite -->
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock x:Name="RemainingBidsText"
|
||||
Text="0"
|
||||
Foreground="#00D800"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"
|
||||
Margin="0,0,0,0"/>
|
||||
|
||||
<!-- 🎯 Indicatore limite minimo puntate (solo numero tra parentesi) -->
|
||||
<TextBlock x:Name="MinBidsLimitIndicator"
|
||||
Text="(20)"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"
|
||||
Margin="5,0,0,0"
|
||||
VerticalAlignment="Center"
|
||||
Visibility="Collapsed"
|
||||
ToolTip="Limite minimo puntate attivo"/>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Riga 2: Solo Credito Shop -->
|
||||
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,0,0,3">
|
||||
<TextBlock Text="Credito Shop: "
|
||||
Foreground="#999999"
|
||||
FontSize="12"
|
||||
Margin="0,0,5,0"/>
|
||||
<TextBlock x:Name="ShopCreditText"
|
||||
Text="EUR 0.00"
|
||||
Foreground="#00D800"
|
||||
FontSize="12"
|
||||
FontWeight="Bold"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Riga 3: Solo Aste vinte -->
|
||||
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Left">
|
||||
<TextBlock Text="Aste vinte da confermare: "
|
||||
Foreground="#999999"
|
||||
FontSize="12"
|
||||
Margin="0,0,5,0"/>
|
||||
<TextBlock x:Name="BannerAsteDaRiscattare"
|
||||
Text="0"
|
||||
Foreground="#FFB700"
|
||||
FontSize="12"
|
||||
FontWeight="Bold"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Control Buttons (Right) - Su tutte e 3 le righe -->
|
||||
<StackPanel Grid.Row="0" Grid.RowSpan="3" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<Button x:Name="StartButton"
|
||||
Content="Avvia Tutti"
|
||||
Background="#00D800"
|
||||
Style="{StaticResource RoundedButton}"
|
||||
Margin="5,0"
|
||||
Click="StartButton_Click"/>
|
||||
|
||||
<Button x:Name="PauseAllButton"
|
||||
Content="Pausa Tutti"
|
||||
Background="#FFB700"
|
||||
Style="{StaticResource RoundedButton}"
|
||||
Margin="5,0"
|
||||
Click="PauseAllButton_Click"/>
|
||||
|
||||
<Button x:Name="StopButton"
|
||||
Content="Ferma Tutti"
|
||||
Background="#E81123"
|
||||
Style="{StaticResource RoundedButton}"
|
||||
Margin="5,0"
|
||||
Click="StopButton_Click"/>
|
||||
|
||||
<!-- Separator -->
|
||||
<Border Width="1"
|
||||
Background="#3E3E42"
|
||||
Margin="10,5"/>
|
||||
|
||||
<!-- Export Button -->
|
||||
<Button x:Name="ExportButton"
|
||||
Content="Esporta"
|
||||
Background="#007ACC"
|
||||
Style="{StaticResource RoundedButton}"
|
||||
Margin="5,0"
|
||||
Click="ExportButton_Click"
|
||||
ToolTip="Esporta dati aste monitorate"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Main Layout: 2 rows -->
|
||||
<Grid Grid.Row="1" Margin="5">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="5"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- TOP ROW: Auction Grid (2/3) + Global Log (1/3) -->
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
<ColumnDefinition Width="5"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- TOP LEFT: Auction Grid -->
|
||||
<Border Grid.Column="0" Style="{StaticResource CardBorder}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Grid Header -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="10,8" CornerRadius="4,4,0,0">
|
||||
<Grid>
|
||||
<TextBlock x:Name="MonitorateTitle"
|
||||
Text="Aste monitorate: 0"
|
||||
Foreground="#00D800"
|
||||
FontSize="14"
|
||||
FontWeight="Bold"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Content="Aggiungi"
|
||||
x:Name="AddUrlButton"
|
||||
Background="#007ACC"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="10,5"
|
||||
FontSize="11"
|
||||
Margin="3,0"
|
||||
Click="AddUrlButton_Click"
|
||||
ToolTip="Aggiungi nuova asta"/>
|
||||
|
||||
<!-- NUOVO: Pulsanti per riordinare le aste (senza emoji) -->
|
||||
<Button Content="Sposta Su"
|
||||
x:Name="MoveUpButton"
|
||||
Background="#9B4F96"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="10,5"
|
||||
FontSize="11"
|
||||
Margin="3,0"
|
||||
Click="MoveUpButton_Click"
|
||||
ToolTip="Sposta l'asta selezionata verso l'alto"/>
|
||||
|
||||
<Button Content="Sposta Giù"
|
||||
x:Name="MoveDownButton"
|
||||
Background="#9B4F96"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="10,5"
|
||||
FontSize="11"
|
||||
Margin="3,0"
|
||||
Click="MoveDownButton_Click"
|
||||
ToolTip="Sposta l'asta selezionata verso il basso"/>
|
||||
|
||||
<Button Content="Rimuovi"
|
||||
x:Name="RemoveUrlButton"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="10,5"
|
||||
FontSize="11"
|
||||
Margin="3,0"
|
||||
Click="RemoveUrlButton_Click"
|
||||
ToolTip="Rimuovi asta selezionata"/>
|
||||
|
||||
<Button Content="Rimuovi Tutte"
|
||||
x:Name="RemoveAllButton"
|
||||
Background="#E81123"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="10,5"
|
||||
FontSize="11"
|
||||
Margin="3,0"
|
||||
Click="RemoveAllButton_Click"
|
||||
ToolTip="Rimuovi tutte le aste monitorate"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Auction DataGrid -->
|
||||
<DataGrid Grid.Row="1"
|
||||
x:Name="MultiAuctionsGrid"
|
||||
AutoGenerateColumns="False"
|
||||
SelectionMode="Single"
|
||||
CanUserAddRows="False"
|
||||
IsReadOnly="True"
|
||||
GridLinesVisibility="Horizontal"
|
||||
HeadersVisibility="Column"
|
||||
Background="#1E1E1E"
|
||||
Foreground="#CCCCCC"
|
||||
RowBackground="#1E1E1E"
|
||||
AlternatingRowBackground="#252526"
|
||||
BorderThickness="0"
|
||||
SelectionChanged="MultiAuctionsGrid_SelectionChanged"
|
||||
PreviewKeyDown="MultiAuctionsGrid_PreviewKeyDown"
|
||||
Focusable="True"
|
||||
FocusVisualStyle="{x:Null}">
|
||||
<DataGrid.ColumnHeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="Background" Value="#2D2D30"/>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Padding" Value="8,6"/>
|
||||
<Setter Property="BorderThickness" Value="0,0,1,1"/>
|
||||
<Setter Property="BorderBrush" Value="#3E3E42"/>
|
||||
<Setter Property="FontSize" Value="11"/>
|
||||
</Style>
|
||||
</DataGrid.ColumnHeaderStyle>
|
||||
<DataGrid.CellStyle>
|
||||
<Style TargetType="DataGridCell">
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Padding" Value="8,4"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="FontSize" Value="11"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="#094771"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGrid.CellStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="ID" Binding="{Binding AuctionId}" Width="90"/>
|
||||
<DataGridTextColumn Header="Asta" Binding="{Binding Name}" Width="2*"/>
|
||||
<DataGridTextColumn Header="Latenza" Binding="{Binding LatencyDisplay}" Width="70"/>
|
||||
<DataGridTextColumn Header="Stato" Binding="{Binding StatusDisplay}" Width="100"/>
|
||||
<DataGridTextColumn Header="Timer" Binding="{Binding TimerDisplay}" Width="90"/>
|
||||
<DataGridTextColumn Header="Prezzo" Binding="{Binding PriceDisplay}" Width="70"/>
|
||||
<DataGridTextColumn Header="Ultimo" Binding="{Binding LastBidder}" Width="110"/>
|
||||
<DataGridTextColumn Header="Clicks" Binding="{Binding MyClicks}" Width="60"/>
|
||||
<DataGridTemplateColumn Header="Azioni" Width="260">
|
||||
<DataGridTemplateColumn.CellTemplate>
|
||||
<DataTemplate>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<Button Content="Avvia"
|
||||
Command="{Binding DataContext.GridStartCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
IsEnabled="{Binding CanStart}"
|
||||
Opacity="{Binding CanStart, Converter={StaticResource BoolToOpacity}}"
|
||||
Background="#00D800"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="6,3"
|
||||
FontSize="10"
|
||||
Margin="1"/>
|
||||
<Button Content="Pausa"
|
||||
Command="{Binding DataContext.GridPauseCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
IsEnabled="{Binding CanPause}"
|
||||
Opacity="{Binding CanPause, Converter={StaticResource BoolToOpacity}}"
|
||||
Background="#FFB700"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="6,3"
|
||||
FontSize="10"
|
||||
Margin="1"/>
|
||||
<Button Content="Ferma"
|
||||
Command="{Binding DataContext.GridStopCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
IsEnabled="{Binding CanStop}"
|
||||
Opacity="{Binding CanStop, Converter={StaticResource BoolToOpacity}}"
|
||||
Background="#E81123"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="6,3"
|
||||
FontSize="10"
|
||||
Margin="1"/>
|
||||
<Button Content="Punta"
|
||||
Command="{Binding DataContext.GridBidCommand, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
CommandParameter="{Binding}"
|
||||
IsEnabled="{Binding CanBid}"
|
||||
Opacity="{Binding CanBid, Converter={StaticResource BoolToOpacity}}"
|
||||
Background="#9B4F96"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="6,3"
|
||||
FontSize="10"
|
||||
Margin="1"/>
|
||||
</StackPanel>
|
||||
</DataTemplate>
|
||||
</DataGridTemplateColumn.CellTemplate>
|
||||
</DataGridTemplateColumn>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Vertical Splitter -->
|
||||
<GridSplitter Grid.Column="1"
|
||||
Width="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="#3E3E42"
|
||||
ResizeBehavior="PreviousAndNext"/>
|
||||
|
||||
<!-- TOP RIGHT: Global Log -->
|
||||
<Border Grid.Column="2" Style="{StaticResource CardBorder}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="10,8" CornerRadius="4,4,0,0">
|
||||
<Grid>
|
||||
<TextBlock Text="Log Globale"
|
||||
Foreground="#00D800"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"
|
||||
VerticalAlignment="Center"/>
|
||||
<Button x:Name="ClearGlobalLogButton"
|
||||
Content="Pulisci"
|
||||
HorizontalAlignment="Right"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="8,4"
|
||||
FontSize="10"
|
||||
Click="ClearGlobalLogButton_Click"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Log Box -->
|
||||
<RichTextBox Grid.Row="1"
|
||||
x:Name="LogBox"
|
||||
IsReadOnly="True"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
Background="#1E1E1E"
|
||||
Foreground="#00D800"
|
||||
BorderThickness="0"
|
||||
FontFamily="Consolas"
|
||||
FontSize="10"
|
||||
Padding="8"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!-- Horizontal Splitter -->
|
||||
<GridSplitter Grid.Row="1"
|
||||
Height="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Stretch"
|
||||
Background="#3E3E42"
|
||||
ResizeBehavior="PreviousAndNext"/>
|
||||
|
||||
<!-- BOTTOM ROW: Settings (1/3) + Bidders (1/3) + Auction Log (1/3) -->
|
||||
<Grid Grid.Row="2">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="5"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="5"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- BOTTOM LEFT: Settings (Impostazioni) -->
|
||||
<Border Grid.Column="0" Style="{StaticResource CardBorder}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="10,8" CornerRadius="4,4,0,0">
|
||||
<TextBlock Text="Impostazioni"
|
||||
Foreground="#00D800"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"/>
|
||||
</Border>
|
||||
|
||||
<!-- Settings Content -->
|
||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="10">
|
||||
<TextBlock x:Name="SelectedAuctionName"
|
||||
Text="Seleziona un'asta"
|
||||
Foreground="White"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"
|
||||
Margin="0,0,0,8"/>
|
||||
|
||||
<TextBox x:Name="SelectedAuctionUrl"
|
||||
IsReadOnly="True"
|
||||
Background="#1E1E1E"
|
||||
Foreground="#999999"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="1"
|
||||
Padding="6"
|
||||
FontSize="10"
|
||||
Margin="0,0,0,8"
|
||||
TextWrapping="Wrap"
|
||||
MaxHeight="50"/>
|
||||
|
||||
<!-- Pulsanti azione asta - RIORDINATI E FUNZIONANTI -->
|
||||
<Grid Margin="0,0,0,15">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Riga 1: Browser -->
|
||||
<Button Grid.Row="0" Grid.Column="0"
|
||||
x:Name="OpenAuctionInternalButton"
|
||||
Content="Browser Interno"
|
||||
Background="#007ACC"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="8,5"
|
||||
FontSize="10"
|
||||
Margin="0,0,2,3"
|
||||
ToolTip="Apri asta nel browser integrato"
|
||||
Click="OpenAuctionInternalButton_Click"/>
|
||||
|
||||
<Button Grid.Row="0" Grid.Column="1"
|
||||
x:Name="OpenAuctionExternalButton"
|
||||
Content="Browser Esterno"
|
||||
Background="#0078D7"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="8,5"
|
||||
FontSize="10"
|
||||
Margin="2,0,0,3"
|
||||
ToolTip="Apri asta nel browser predefinito di sistema"
|
||||
Click="OpenAuctionExternalButton_Click"/>
|
||||
|
||||
<!-- Riga 2: Azioni -->
|
||||
<Button Grid.Row="1" Grid.Column="0"
|
||||
x:Name="CopyAuctionUrlButton"
|
||||
Content="Copia URL"
|
||||
Background="#9B4F96"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="8,5"
|
||||
FontSize="10"
|
||||
Margin="0,0,2,0"
|
||||
ToolTip="Copia URL negli appunti"
|
||||
Click="CopyAuctionUrlButton_Click"/>
|
||||
|
||||
<Button Grid.Row="1" Grid.Column="1"
|
||||
x:Name="ExportAuctionButton"
|
||||
Content="Esporta"
|
||||
Background="#106EBE"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="8,5"
|
||||
FontSize="10"
|
||||
Margin="2,0,0,0"
|
||||
ToolTip="Esporta dati asta"
|
||||
Click="ExportAuctionButton_Click"/>
|
||||
</Grid>
|
||||
|
||||
<!-- NUOVA SEZIONE: Info Prodotto - SEZIONE FISSA -->
|
||||
<Border BorderBrush="#3E3E42"
|
||||
BorderThickness="1"
|
||||
Background="#2D2D30"
|
||||
Padding="10"
|
||||
CornerRadius="4"
|
||||
Margin="0,0,0,10">
|
||||
<StackPanel>
|
||||
<!-- Header fisso -->
|
||||
<TextBlock Text="Informazioni Prodotto"
|
||||
FontWeight="Bold"
|
||||
FontSize="12"
|
||||
Foreground="#CCCCCC"
|
||||
Margin="0,0,0,10"/>
|
||||
|
||||
<!-- Dati Prodotto -->
|
||||
<Grid x:Name="ProductInfoGrid" Margin="0,0,0,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Valore -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="Valore:"
|
||||
FontWeight="Bold"
|
||||
Foreground="#CCCCCC"
|
||||
FontSize="11"
|
||||
Margin="0,3"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1"
|
||||
x:Name="ProductBuyNowPriceText"
|
||||
Text="-"
|
||||
Foreground="#007ACC"
|
||||
FontSize="11"
|
||||
FontWeight="Bold"
|
||||
Margin="5,3"/>
|
||||
|
||||
<!-- Extra (Spedizione/Transazione) -->
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
Text="Extra:"
|
||||
FontWeight="Bold"
|
||||
Foreground="#CCCCCC"
|
||||
FontSize="11"
|
||||
Margin="0,3"
|
||||
ToolTip="Spese di spedizione o transazione"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1"
|
||||
x:Name="ProductShippingCostText"
|
||||
Text="-"
|
||||
Foreground="#FFB700"
|
||||
FontSize="11"
|
||||
Margin="5,3"/>
|
||||
|
||||
<!-- Limite Vincita -->
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
Text="Limite:"
|
||||
FontWeight="Bold"
|
||||
Foreground="#CCCCCC"
|
||||
FontSize="11"
|
||||
Margin="0,3"/>
|
||||
<TextBlock Grid.Row="2" Grid.Column="1"
|
||||
x:Name="ProductWinLimitText"
|
||||
Text="-"
|
||||
Foreground="#999999"
|
||||
FontSize="11"
|
||||
TextWrapping="Wrap"
|
||||
Margin="5,3"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Pulsante Applica Limiti -->
|
||||
<Button x:Name="RefreshProductInfoButton"
|
||||
Content="Applica Limiti Suggeriti"
|
||||
Background="#007ACC"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Padding="10,6"
|
||||
FontSize="11"
|
||||
Margin="0,0,0,0"
|
||||
Click="RefreshProductInfoButton_Click"
|
||||
ToolTip="Calcola e applica limiti Max EUR e Max Clicks basati sul valore del prodotto"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- Settings Grid - Campi aggiornati -->
|
||||
<Grid Margin="0,0,0,8">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
<ColumnDefinition Width="15"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="100"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Row 1: Anticipo ms -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Anticipo (ms):" Foreground="#CCCCCC" FontSize="11" Margin="0,6" VerticalAlignment="Center" ToolTip="Millisecondi prima della scadenza per puntare"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" x:Name="SelectedBidBeforeDeadlineMs" Background="#1E1E1E" Foreground="White" BorderBrush="#3E3E42" Padding="6" Margin="5,6" FontSize="11" TextChanged="SelectedBidBeforeDeadlineMs_TextChanged"/>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="3" Text="Min EUR:" Foreground="#CCCCCC" FontSize="11" Margin="0,6" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="4" x:Name="SelectedMinPrice" Background="#1E1E1E" Foreground="White" BorderBrush="#3E3E42" Padding="6" Margin="5,6" FontSize="11" TextChanged="SelectedMinPrice_TextChanged"/>
|
||||
|
||||
<!-- Row 2 -->
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Max EUR:" Foreground="#CCCCCC" FontSize="11" Margin="0,6" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1" x:Name="SelectedMaxPrice" Background="#1E1E1E" Foreground="White" BorderBrush="#3E3E42" Padding="6" Margin="5,6" FontSize="11" TextChanged="SelectedMaxPrice_TextChanged"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="3" Text="Max Clicks:" Foreground="#CCCCCC" FontSize="11" Margin="0,6" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="4" x:Name="SelectedMaxClicks" Background="#1E1E1E" Foreground="White" BorderBrush="#3E3E42" Padding="6" Margin="5,6" FontSize="11" TextChanged="SelectedMaxClicks_TextChanged"/>
|
||||
|
||||
<!-- Row 3: Check Auction Open -->
|
||||
<CheckBox Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="5"
|
||||
x:Name="SelectedCheckAuctionOpen"
|
||||
Content="Verifica stato asta prima di puntare"
|
||||
Foreground="#CCCCCC"
|
||||
FontSize="11"
|
||||
Margin="0,10,0,0"
|
||||
Checked="SelectedCheckAuctionOpen_Changed"
|
||||
Unchecked="SelectedCheckAuctionOpen_Changed"
|
||||
ToolTip="Aggiunge una chiamata API extra per verificare che l'asta sia ancora aperta"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- Footer Button (bottom like other panels) -->
|
||||
<Button Grid.Row="2"
|
||||
x:Name="ResetSettingsButton"
|
||||
Content="Reset"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Margin="5"
|
||||
Click="ResetSettingsButton_Click"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Vertical Splitter 1 -->
|
||||
<GridSplitter Grid.Column="1"
|
||||
Width="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="#3E3E42"
|
||||
ResizeBehavior="PreviousAndNext"/>
|
||||
|
||||
<!-- BOTTOM CENTER: Tab Control (Utenti + Storia Puntate) -->
|
||||
<Border Grid.Column="2" Style="{StaticResource CardBorder}">
|
||||
<TabControl Background="#252526" BorderThickness="0">
|
||||
<TabControl.Resources>
|
||||
<!-- Tab Header Style -->
|
||||
<Style TargetType="TabItem">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="TabItem">
|
||||
<Border Name="Border"
|
||||
Background="#2D2D30"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="0,0,1,0"
|
||||
Padding="15,8">
|
||||
<ContentPresenter x:Name="ContentSite"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"
|
||||
ContentSource="Header"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter TargetName="Border" Property="Background" Value="#094771"/>
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="Border" Property="Background" Value="#3E3E42"/>
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
</Style>
|
||||
</TabControl.Resources>
|
||||
|
||||
<!-- Tab 1: Utenti -->
|
||||
<TabItem Header="Utenti">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="10,8">
|
||||
<TextBlock x:Name="SelectedAuctionBiddersCount"
|
||||
Text="Utenti: 0"
|
||||
Foreground="#00D800"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"/>
|
||||
</Border>
|
||||
|
||||
<!-- Bidders Grid -->
|
||||
<DataGrid Grid.Row="1"
|
||||
x:Name="SelectedAuctionBiddersGrid"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
Background="#1E1E1E"
|
||||
Foreground="#CCCCCC"
|
||||
RowBackground="#1E1E1E"
|
||||
AlternatingRowBackground="#252526"
|
||||
GridLinesVisibility="None"
|
||||
HeadersVisibility="Column"
|
||||
BorderThickness="0"
|
||||
FontSize="11">
|
||||
<DataGrid.ColumnHeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="Background" Value="#2D2D30"/>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="Padding" Value="8,5"/>
|
||||
<Setter Property="FontSize" Value="11"/>
|
||||
</Style>
|
||||
</DataGrid.ColumnHeaderStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Utente" Binding="{Binding Username}" Width="*"/>
|
||||
<DataGridTextColumn Header="Punt." Binding="{Binding BidCount}" Width="50"/>
|
||||
<DataGridTextColumn Header="Ultima" Binding="{Binding LastBidTimeDisplay}" Width="70"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<!-- Footer Button -->
|
||||
<Button Grid.Row="2"
|
||||
x:Name="ClearBiddersButton"
|
||||
Content="Pulisci"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Margin="5"
|
||||
Click="ClearBiddersButton_Click"/>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
|
||||
<!-- Tab 2: Storia Puntate -->
|
||||
<TabItem Header="Storia Puntate">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="10,8">
|
||||
<TextBlock x:Name="BidHistoryCount"
|
||||
Text="Ultime puntate: 0"
|
||||
Foreground="#00D800"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"/>
|
||||
</Border>
|
||||
|
||||
<!-- Storia Puntate Grid -->
|
||||
<DataGrid Grid.Row="1"
|
||||
x:Name="BidHistoryGrid"
|
||||
ItemsSource="{Binding ElementName=MultiAuctionsGrid, Path=SelectedItem.BidHistoryEntries}"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
CanUserAddRows="False"
|
||||
CanUserDeleteRows="False"
|
||||
CanUserResizeRows="False"
|
||||
HeadersVisibility="Column"
|
||||
GridLinesVisibility="Horizontal"
|
||||
HorizontalGridLinesBrush="#3E3E42"
|
||||
Background="#1E1E1E"
|
||||
Foreground="#CCCCCC"
|
||||
BorderThickness="0"
|
||||
RowHeight="28">
|
||||
|
||||
<DataGrid.Columns>
|
||||
<!-- Colonna Prezzo -->
|
||||
<DataGridTextColumn Header="PREZZO"
|
||||
Binding="{Binding PriceFormatted}"
|
||||
Width="70">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#00D800"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="11"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<!-- Colonna Modalita' -->
|
||||
<DataGridTextColumn Header="TIPO"
|
||||
Binding="{Binding BidType}"
|
||||
Width="65">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding BidType}" Value="Auto">
|
||||
<Setter Property="Foreground" Value="#FFC107"/>
|
||||
</DataTrigger>
|
||||
<DataTrigger Binding="{Binding BidType}" Value="Manuale">
|
||||
<Setter Property="Foreground" Value="#03A9F4"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<!-- Colonna Orario -->
|
||||
<DataGridTextColumn Header="ORARIO"
|
||||
Binding="{Binding TimeFormatted}"
|
||||
Width="70">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#9E9E9E"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Center"/>
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
|
||||
<!-- Colonna Utente -->
|
||||
<DataGridTextColumn Header="UTENTE"
|
||||
Binding="{Binding Username}"
|
||||
Width="*">
|
||||
<DataGridTextColumn.ElementStyle>
|
||||
<Style TargetType="TextBlock">
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="Margin" Value="8,0,0,0"/>
|
||||
<Setter Property="FontSize" Value="11"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding IsMyBid}" Value="True">
|
||||
<Setter Property="Foreground" Value="#00D800"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGridTextColumn.ElementStyle>
|
||||
</DataGridTextColumn>
|
||||
</DataGrid.Columns>
|
||||
|
||||
<!-- Stili righe -->
|
||||
<DataGrid.RowStyle>
|
||||
<Style TargetType="DataGridRow">
|
||||
<Setter Property="Background" Value="#1E1E1E"/>
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="#3E3E42"/>
|
||||
</Trigger>
|
||||
<DataTrigger Binding="{Binding IsMyBid}" Value="True">
|
||||
<Setter Property="Background" Value="#1A4D1A"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</DataGrid.RowStyle>
|
||||
|
||||
<!-- Stile header -->
|
||||
<DataGrid.ColumnHeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="Background" Value="#252526"/>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="FontSize" Value="10"/>
|
||||
<Setter Property="Padding" Value="8,6"/>
|
||||
<Setter Property="BorderThickness" Value="0,0,1,1"/>
|
||||
<Setter Property="BorderBrush" Value="#3E3E42"/>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Center"/>
|
||||
</Style>
|
||||
</DataGrid.ColumnHeaderStyle>
|
||||
</DataGrid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Border>
|
||||
|
||||
<!-- Vertical Splitter 2 -->
|
||||
<GridSplitter Grid.Column="3"
|
||||
Width="5"
|
||||
HorizontalAlignment="Stretch"
|
||||
Background="#3E3E42"
|
||||
ResizeBehavior="PreviousAndNext"/>
|
||||
|
||||
<!-- BOTTOM RIGHT: Auction Log -->
|
||||
<Border Grid.Column="4" Style="{StaticResource CardBorder}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="10,8" CornerRadius="4,4,0,0">
|
||||
<Grid>
|
||||
<TextBlock Text="Log Asta"
|
||||
Foreground="#00D800"
|
||||
FontSize="13"
|
||||
FontWeight="Bold"
|
||||
VerticalAlignment="Center"/>
|
||||
<Button x:Name="ClearLogButton"
|
||||
Content="Pulisci"
|
||||
HorizontalAlignment="Right"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource SmallRoundedButton}"
|
||||
Padding="8,4"
|
||||
FontSize="10"
|
||||
Click="ClearLogButton_Click"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- Auction Log Box -->
|
||||
<RichTextBox Grid.Row="1"
|
||||
x:Name="SelectedAuctionLog"
|
||||
IsReadOnly="True"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
Background="#1E1E1E"
|
||||
Foreground="#CCCCCC"
|
||||
BorderThickness="0"
|
||||
FontFamily="Consolas"
|
||||
FontSize="10"
|
||||
Padding="8"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<!-- Hidden user info panel for compatibility -->
|
||||
<Border x:Name="UserInfoPanel"
|
||||
Visibility="Collapsed">
|
||||
<StackPanel>
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBlock x:Name="UsernameText" Text=""/>
|
||||
<TextBlock x:Name="UserIdText" Text=""/>
|
||||
</StackPanel>
|
||||
<TextBlock x:Name="UserEmailText" Text=""/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
461
Mimante/Controls/AuctionMonitorControl.xaml.cs
Normal file
@@ -0,0 +1,461 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace AutoBidder.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for AuctionMonitorControl.xaml
|
||||
/// </summary>
|
||||
public partial class AuctionMonitorControl : UserControl
|
||||
{
|
||||
public AuctionMonitorControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
// Dependency Properties per Commands (da bindare al MainWindow)
|
||||
public static readonly DependencyProperty GridStartCommandProperty =
|
||||
DependencyProperty.Register(nameof(GridStartCommand), typeof(ICommand), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly DependencyProperty GridPauseCommandProperty =
|
||||
DependencyProperty.Register(nameof(GridPauseCommand), typeof(ICommand), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly DependencyProperty GridStopCommandProperty =
|
||||
DependencyProperty.Register(nameof(GridStopCommand), typeof(ICommand), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly DependencyProperty GridBidCommandProperty =
|
||||
DependencyProperty.Register(nameof(GridBidCommand), typeof(ICommand), typeof(AuctionMonitorControl));
|
||||
|
||||
public ICommand? GridStartCommand
|
||||
{
|
||||
get => (ICommand?)GetValue(GridStartCommandProperty);
|
||||
set => SetValue(GridStartCommandProperty, value);
|
||||
}
|
||||
|
||||
public ICommand? GridPauseCommand
|
||||
{
|
||||
get => (ICommand?)GetValue(GridPauseCommandProperty);
|
||||
set => SetValue(GridPauseCommandProperty, value);
|
||||
}
|
||||
|
||||
public ICommand? GridStopCommand
|
||||
{
|
||||
get => (ICommand?)GetValue(GridStopCommandProperty);
|
||||
set => SetValue(GridStopCommandProperty, value);
|
||||
}
|
||||
|
||||
public ICommand? GridBidCommand
|
||||
{
|
||||
get => (ICommand?)GetValue(GridBidCommandProperty);
|
||||
set => SetValue(GridBidCommandProperty, value);
|
||||
}
|
||||
|
||||
// Event handlers - these will bubble up to MainWindow
|
||||
private void StartButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(StartClickedEvent, this));
|
||||
}
|
||||
|
||||
private void PauseAllButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(PauseAllClickedEvent, this));
|
||||
}
|
||||
|
||||
private void StopButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(StopClickedEvent, this));
|
||||
}
|
||||
|
||||
private void AddUrlButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(AddUrlClickedEvent, this));
|
||||
}
|
||||
|
||||
private void RemoveUrlButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(RemoveUrlClickedEvent, this));
|
||||
}
|
||||
|
||||
private void RemoveAllButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(RemoveAllClickedEvent, this));
|
||||
}
|
||||
|
||||
private void ExportButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(ExportClickedEvent, this));
|
||||
}
|
||||
|
||||
private void MultiAuctionsGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
// Forza il focus sul DataGrid quando viene selezionata una riga
|
||||
// Questo assicura che il tasto Canc venga catturato
|
||||
if (sender is DataGrid grid && grid.SelectedItem != null)
|
||||
{
|
||||
// Attende che il rendering sia completo prima di dare il focus
|
||||
grid.Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
if (!grid.IsFocused)
|
||||
{
|
||||
grid.Focus();
|
||||
System.Diagnostics.Debug.WriteLine("[FOCUS] DataGrid ora ha il focus keyboard");
|
||||
}
|
||||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
RaiseEvent(new RoutedEventArgs(AuctionSelectionChangedEvent, this));
|
||||
}
|
||||
|
||||
// Usato PreviewKeyDown invece di KeyDown per catturare l'evento prima che venga consumato
|
||||
private void MultiAuctionsGrid_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Delete && MultiAuctionsGrid.SelectedItem != null)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine("[DELETE KEY] Tasto Canc premuto su asta selezionata");
|
||||
|
||||
// Lancia direttamente l'evento senza chiedere conferma
|
||||
// La conferma verrà mostrata dal gestore RemoveUrlButton_Click
|
||||
System.Diagnostics.Debug.WriteLine("[DELETE KEY] Lancio evento RemoveUrlClicked");
|
||||
RaiseEvent(new RoutedEventArgs(RemoveUrlClickedEvent, this));
|
||||
|
||||
// Previeni che l'evento venga gestito da altri controlli
|
||||
e.Handled = true;
|
||||
}
|
||||
// NUOVO: Gestione esplicita frecce Su/Giù per navigazione
|
||||
else if (e.Key == Key.Up && MultiAuctionsGrid.Items.Count > 0)
|
||||
{
|
||||
int currentIndex = MultiAuctionsGrid.SelectedIndex;
|
||||
if (currentIndex > 0)
|
||||
{
|
||||
MultiAuctionsGrid.SelectedIndex = currentIndex - 1;
|
||||
MultiAuctionsGrid.ScrollIntoView(MultiAuctionsGrid.SelectedItem);
|
||||
e.Handled = true; // Previeni ridimensionamento pannelli
|
||||
}
|
||||
}
|
||||
else if (e.Key == Key.Down && MultiAuctionsGrid.Items.Count > 0)
|
||||
{
|
||||
int currentIndex = MultiAuctionsGrid.SelectedIndex;
|
||||
if (currentIndex < MultiAuctionsGrid.Items.Count - 1)
|
||||
{
|
||||
MultiAuctionsGrid.SelectedIndex = currentIndex + 1;
|
||||
MultiAuctionsGrid.ScrollIntoView(MultiAuctionsGrid.SelectedItem);
|
||||
e.Handled = true; // Previeni ridimensionamento pannelli
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MoveUpButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(MoveUpClickedEvent, this));
|
||||
}
|
||||
|
||||
private void MoveDownButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(MoveDownClickedEvent, this));
|
||||
}
|
||||
|
||||
private void CopyAuctionUrlButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(CopyUrlClickedEvent, this));
|
||||
}
|
||||
|
||||
private void ResetSettingsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(ResetSettingsClickedEvent, this));
|
||||
}
|
||||
|
||||
private void ClearBiddersButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(ClearBiddersClickedEvent, this));
|
||||
}
|
||||
|
||||
private void ClearLogButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(ClearLogClickedEvent, this));
|
||||
}
|
||||
|
||||
private void ClearGlobalLogButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(ClearGlobalLogClickedEvent, this));
|
||||
}
|
||||
|
||||
private void OpenAuctionInternalButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(OpenAuctionInternalClickedEvent, this));
|
||||
}
|
||||
|
||||
private void OpenAuctionExternalButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(OpenAuctionExternalClickedEvent, this));
|
||||
}
|
||||
|
||||
private void ExportAuctionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(ExportAuctionClickedEvent, this));
|
||||
}
|
||||
|
||||
private void RefreshProductInfoButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(RefreshProductInfoClickedEvent, this));
|
||||
}
|
||||
|
||||
private void ConnectionStatusButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(ConnectionStatusClickedEvent, this));
|
||||
}
|
||||
|
||||
private void SelectedBidBeforeDeadlineMs_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(BidBeforeDeadlineMsChangedEvent, this));
|
||||
}
|
||||
|
||||
private void SelectedCheckAuctionOpen_Changed(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(CheckAuctionOpenChangedEvent, this));
|
||||
}
|
||||
|
||||
private void SelectedMinPrice_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(MinPriceChangedEvent, this));
|
||||
}
|
||||
|
||||
private void SelectedMaxPrice_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(MaxPriceChangedEvent, this));
|
||||
}
|
||||
|
||||
private void SelectedMaxClicks_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(MaxClicksChangedEvent, this));
|
||||
}
|
||||
|
||||
// Routed Events
|
||||
public static readonly RoutedEvent StartClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"StartClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent PauseAllClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"PauseAllClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent StopClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"StopClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent AddUrlClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"AddUrlClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent RemoveUrlClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"RemoveUrlClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent RemoveAllClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"RemoveAllClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent ExportClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"ExportClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent AuctionSelectionChangedEvent = EventManager.RegisterRoutedEvent(
|
||||
"AuctionSelectionChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent CopyUrlClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"CopyUrlClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent ResetSettingsClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"ResetSettingsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent ClearBiddersClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"ClearBiddersClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent ClearLogClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"ClearLogClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent ClearGlobalLogClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"ClearGlobalLogClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent BidBeforeDeadlineMsChangedEvent = EventManager.RegisterRoutedEvent(
|
||||
"BidBeforeDeadlineMsChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent CheckAuctionOpenChangedEvent = EventManager.RegisterRoutedEvent(
|
||||
"CheckAuctionOpenChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent MinPriceChangedEvent = EventManager.RegisterRoutedEvent(
|
||||
"MinPriceChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent MaxPriceChangedEvent = EventManager.RegisterRoutedEvent(
|
||||
"MaxPriceChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent MaxClicksChangedEvent = EventManager.RegisterRoutedEvent(
|
||||
"MaxClicksChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent OpenAuctionInternalClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"OpenAuctionInternalClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent OpenAuctionExternalClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"OpenAuctionExternalClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent ExportAuctionClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"ExportAuctionClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent RefreshProductInfoClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"RefreshProductInfoClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent ConnectionStatusClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"ConnectionStatusClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
// NUOVO: Eventi per riordinamento aste
|
||||
public static readonly RoutedEvent MoveUpClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"MoveUpClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public static readonly RoutedEvent MoveDownClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"MoveDownClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(AuctionMonitorControl));
|
||||
|
||||
public event RoutedEventHandler StartClicked
|
||||
{
|
||||
add { AddHandler(StartClickedEvent, value); }
|
||||
remove { RemoveHandler(StartClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler PauseAllClicked
|
||||
{
|
||||
add { AddHandler(PauseAllClickedEvent, value); }
|
||||
remove { RemoveHandler(PauseAllClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler StopClicked
|
||||
{
|
||||
add { AddHandler(StopClickedEvent, value); }
|
||||
remove { RemoveHandler(StopClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler AddUrlClicked
|
||||
{
|
||||
add { AddHandler(AddUrlClickedEvent, value); }
|
||||
remove { RemoveHandler(AddUrlClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler RemoveUrlClicked
|
||||
{
|
||||
add { AddHandler(RemoveUrlClickedEvent, value); }
|
||||
remove { RemoveHandler(RemoveUrlClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler RemoveAllClicked
|
||||
{
|
||||
add { AddHandler(RemoveAllClickedEvent, value); }
|
||||
remove { RemoveHandler(RemoveAllClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler ExportClicked
|
||||
{
|
||||
add { AddHandler(ExportClickedEvent, value); }
|
||||
remove { RemoveHandler(ExportClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler AuctionSelectionChanged
|
||||
{
|
||||
add { AddHandler(AuctionSelectionChangedEvent, value); }
|
||||
remove { RemoveHandler(AuctionSelectionChangedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler CopyUrlClicked
|
||||
{
|
||||
add { AddHandler(CopyUrlClickedEvent, value); }
|
||||
remove { RemoveHandler(CopyUrlClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler ResetSettingsClicked
|
||||
{
|
||||
add { AddHandler(ResetSettingsClickedEvent, value); }
|
||||
remove { RemoveHandler(ResetSettingsClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler ClearBiddersClicked
|
||||
{
|
||||
add { AddHandler(ClearBiddersClickedEvent, value); }
|
||||
remove { RemoveHandler(ClearBiddersClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler ClearLogClicked
|
||||
{
|
||||
add { AddHandler(ClearLogClickedEvent, value); }
|
||||
remove { RemoveHandler(ClearLogClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler ClearGlobalLogClicked
|
||||
{
|
||||
add { AddHandler(ClearGlobalLogClickedEvent, value); }
|
||||
remove { RemoveHandler(ClearGlobalLogClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler BidBeforeDeadlineMsChanged
|
||||
{
|
||||
add { AddHandler(BidBeforeDeadlineMsChangedEvent, value); }
|
||||
remove { RemoveHandler(BidBeforeDeadlineMsChangedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler CheckAuctionOpenChanged
|
||||
{
|
||||
add { AddHandler(CheckAuctionOpenChangedEvent, value); }
|
||||
remove { RemoveHandler(CheckAuctionOpenChangedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler MinPriceChanged
|
||||
{
|
||||
add { AddHandler(MinPriceChangedEvent, value); }
|
||||
remove { RemoveHandler(MinPriceChangedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler MaxPriceChanged
|
||||
{
|
||||
add { AddHandler(MaxPriceChangedEvent, value); }
|
||||
remove { RemoveHandler(MaxPriceChangedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler MaxClicksChanged
|
||||
{
|
||||
add { AddHandler(MaxClicksChangedEvent, value); }
|
||||
remove { RemoveHandler(MaxClicksChangedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler OpenAuctionInternalClicked
|
||||
{
|
||||
add { AddHandler(OpenAuctionInternalClickedEvent, value); }
|
||||
remove { RemoveHandler(OpenAuctionInternalClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler OpenAuctionExternalClicked
|
||||
{
|
||||
add { AddHandler(OpenAuctionExternalClickedEvent, value); }
|
||||
remove { RemoveHandler(OpenAuctionExternalClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler ExportAuctionClicked
|
||||
{
|
||||
add { AddHandler(ExportAuctionClickedEvent, value); }
|
||||
remove { RemoveHandler(ExportAuctionClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler RefreshProductInfoClicked
|
||||
{
|
||||
add { AddHandler(RefreshProductInfoClickedEvent, value); }
|
||||
remove { RemoveHandler(RefreshProductInfoClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler ConnectionStatusClicked
|
||||
{
|
||||
add { AddHandler(ConnectionStatusClickedEvent, value); }
|
||||
remove { RemoveHandler(ConnectionStatusClickedEvent, value); }
|
||||
}
|
||||
|
||||
// NUOVO: Handler per eventi riordinamento
|
||||
public event RoutedEventHandler MoveUpClicked
|
||||
{
|
||||
add { AddHandler(MoveUpClickedEvent, value); }
|
||||
remove { RemoveHandler(MoveUpClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler MoveDownClicked
|
||||
{
|
||||
add { AddHandler(MoveDownClickedEvent, value); }
|
||||
remove { RemoveHandler(MoveDownClickedEvent, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
128
Mimante/Controls/BrowserControl.xaml
Normal file
@@ -0,0 +1,128 @@
|
||||
<UserControl x:Class="AutoBidder.Controls.BrowserControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="800" d:DesignWidth="1200"
|
||||
Background="#1E1E1E">
|
||||
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="RoundedButton" TargetType="Button">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
CornerRadius="4"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
</Style>
|
||||
|
||||
<!-- Nav Button Style (text only) -->
|
||||
<Style x:Key="NavButton" TargetType="Button" BasedOn="{StaticResource RoundedButton}">
|
||||
<Setter Property="MinWidth" Value="50"/>
|
||||
<Setter Property="Height" Value="30"/>
|
||||
<Setter Property="FontSize" Value="11"/>
|
||||
<Setter Property="Padding" Value="8,0"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Browser Toolbar -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="10" BorderBrush="#3E3E42" BorderThickness="0,0,0,1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Navigation Buttons (TEXT ONLY - NO SYMBOLS) -->
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal">
|
||||
<Button x:Name="BrowserBackButton"
|
||||
Content="Indietro"
|
||||
Margin="0,0,5,0"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource NavButton}"
|
||||
Click="BrowserBackButton_Click"
|
||||
ToolTip="Torna alla pagina precedente"/>
|
||||
|
||||
<Button x:Name="BrowserForwardButton"
|
||||
Content="Avanti"
|
||||
Margin="0,0,5,0"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource NavButton}"
|
||||
Click="BrowserForwardButton_Click"
|
||||
ToolTip="Vai alla pagina successiva"/>
|
||||
|
||||
<Button x:Name="BrowserRefreshButton"
|
||||
Content="Ricarica"
|
||||
Margin="0,0,5,0"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource NavButton}"
|
||||
Click="BrowserRefreshButton_Click"
|
||||
ToolTip="Ricarica la pagina corrente"/>
|
||||
|
||||
<Button x:Name="BrowserHomeButton"
|
||||
Content="Home"
|
||||
Margin="0,0,10,0"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource NavButton}"
|
||||
Click="BrowserHomeButton_Click"
|
||||
ToolTip="Vai alla homepage Bidoo"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Address Bar -->
|
||||
<Border Grid.Column="1"
|
||||
Background="#1E1E1E"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Margin="10,0">
|
||||
<TextBox x:Name="BrowserAddress"
|
||||
VerticalAlignment="Center"
|
||||
BorderThickness="0"
|
||||
Background="Transparent"
|
||||
Foreground="#CCCCCC"
|
||||
Padding="10,0"
|
||||
FontSize="13"
|
||||
IsReadOnly="True"
|
||||
Cursor="Arrow"
|
||||
ToolTip="Indirizzo della pagina corrente (non editabile)"/>
|
||||
</Border>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Margin="10,0,0,0">
|
||||
<Button x:Name="BrowserAddAuctionButton"
|
||||
Content="Aggiungi Asta"
|
||||
Padding="20,7"
|
||||
FontSize="13"
|
||||
Background="#00D800"
|
||||
Style="{StaticResource RoundedButton}"
|
||||
Click="BrowserAddAuctionButton_Click"
|
||||
ToolTip="Aggiungi l'asta corrente al monitoraggio"/>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- WebView2 -->
|
||||
<Border Grid.Row="1" Background="#1E1E1E">
|
||||
<wv2:WebView2 x:Name="EmbeddedWebView"
|
||||
PreviewMouseRightButtonUp="EmbeddedWebView_PreviewMouseRightButtonUp"/>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
157
Mimante/Controls/BrowserControl.xaml.cs
Normal file
@@ -0,0 +1,157 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
|
||||
namespace AutoBidder.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for BrowserControl.xaml
|
||||
/// REFACTORED: Gestione semplificata e diretta degli eventi WebView2
|
||||
/// </summary>
|
||||
public partial class BrowserControl : UserControl
|
||||
{
|
||||
public BrowserControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// ? NUOVO: Collega eventi NavigationStarting e NavigationCompleted direttamente qui
|
||||
EmbeddedWebView.NavigationStarting += WebView_NavigationStarting;
|
||||
EmbeddedWebView.NavigationCompleted += WebView_NavigationCompleted;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ? NUOVO: Aggiorna address bar quando inizia la navigazione
|
||||
/// </summary>
|
||||
private void WebView_NavigationStarting(object? sender, CoreWebView2NavigationStartingEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Aggiorna immediatamente l'address bar con l'URL di destinazione
|
||||
if (!string.IsNullOrEmpty(e.Uri))
|
||||
{
|
||||
BrowserAddress.Text = e.Uri;
|
||||
}
|
||||
|
||||
// Propaga l'evento al MainWindow
|
||||
var args = new BrowserNavigationEventArgs(BrowserNavigationStartingEvent, this)
|
||||
{
|
||||
Uri = e.Uri
|
||||
};
|
||||
RaiseEvent(args);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ? NUOVO: Aggiorna address bar quando la navigazione è completata
|
||||
/// </summary>
|
||||
private void WebView_NavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Aggiorna l'address bar con l'URL finale (dopo eventuali redirect)
|
||||
var finalUrl = EmbeddedWebView?.Source?.ToString();
|
||||
if (!string.IsNullOrEmpty(finalUrl))
|
||||
{
|
||||
BrowserAddress.Text = finalUrl;
|
||||
}
|
||||
|
||||
// Propaga l'evento al MainWindow
|
||||
RaiseEvent(new RoutedEventArgs(BrowserNavigationCompletedEvent, this));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void BrowserBackButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(BrowserBackClickedEvent, this));
|
||||
}
|
||||
|
||||
private void BrowserForwardButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(BrowserForwardClickedEvent, this));
|
||||
}
|
||||
|
||||
private void BrowserRefreshButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(BrowserRefreshClickedEvent, this));
|
||||
}
|
||||
|
||||
private void BrowserHomeButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(BrowserHomeClickedEvent, this));
|
||||
}
|
||||
|
||||
private void BrowserAddAuctionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(BrowserAddAuctionClickedEvent, this));
|
||||
}
|
||||
|
||||
private void EmbeddedWebView_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
// Routed Events
|
||||
public static readonly RoutedEvent BrowserBackClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"BrowserBackClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BrowserControl));
|
||||
|
||||
public static readonly RoutedEvent BrowserForwardClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"BrowserForwardClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BrowserControl));
|
||||
|
||||
public static readonly RoutedEvent BrowserRefreshClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"BrowserRefreshClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BrowserControl));
|
||||
|
||||
public static readonly RoutedEvent BrowserHomeClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"BrowserHomeClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BrowserControl));
|
||||
|
||||
public static readonly RoutedEvent BrowserAddAuctionClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"BrowserAddAuctionClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BrowserControl));
|
||||
|
||||
public static readonly RoutedEvent BrowserNavigationStartingEvent = EventManager.RegisterRoutedEvent(
|
||||
"BrowserNavigationStarting", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BrowserControl));
|
||||
|
||||
public static readonly RoutedEvent BrowserNavigationCompletedEvent = EventManager.RegisterRoutedEvent(
|
||||
"BrowserNavigationCompleted", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(BrowserControl));
|
||||
|
||||
public event RoutedEventHandler BrowserBackClicked
|
||||
{
|
||||
add { AddHandler(BrowserBackClickedEvent, value); }
|
||||
remove { RemoveHandler(BrowserBackClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler BrowserForwardClicked
|
||||
{
|
||||
add { AddHandler(BrowserForwardClickedEvent, value); }
|
||||
remove { RemoveHandler(BrowserForwardClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler BrowserRefreshClicked
|
||||
{
|
||||
add { AddHandler(BrowserRefreshClickedEvent, value); }
|
||||
remove { RemoveHandler(BrowserRefreshClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler BrowserHomeClicked
|
||||
{
|
||||
add { AddHandler(BrowserHomeClickedEvent, value); }
|
||||
remove { RemoveHandler(BrowserHomeClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler BrowserAddAuctionClicked
|
||||
{
|
||||
add { AddHandler(BrowserAddAuctionClickedEvent, value); }
|
||||
remove { RemoveHandler(BrowserAddAuctionClickedEvent, value); }
|
||||
}
|
||||
}
|
||||
|
||||
public class BrowserNavigationEventArgs : RoutedEventArgs
|
||||
{
|
||||
public string? Uri { get; set; }
|
||||
|
||||
public BrowserNavigationEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
520
Mimante/Controls/SettingsControl.xaml
Normal file
@@ -0,0 +1,520 @@
|
||||
<UserControl x:Class="AutoBidder.Controls.SettingsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="800" d:DesignWidth="1200"
|
||||
Background="#1E1E1E">
|
||||
|
||||
<UserControl.Resources>
|
||||
<!-- Modern Button Style -->
|
||||
<Style x:Key="ModernButton" TargetType="Button">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
CornerRadius="4"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontWeight" Value="SemiBold"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Setter Property="Padding" Value="20,10"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
</Style>
|
||||
|
||||
<!-- Section Header Style -->
|
||||
<Style x:Key="SectionHeader" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="16"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="Margin" Value="0,0,0,15"/>
|
||||
</Style>
|
||||
|
||||
<!-- Label Style -->
|
||||
<Style x:Key="FieldLabel" TargetType="TextBlock">
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="Margin" Value="0,0,0,5"/>
|
||||
</Style>
|
||||
|
||||
<!-- TextBox Style -->
|
||||
<Style TargetType="TextBox">
|
||||
<Setter Property="Background" Value="#252526"/>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="BorderBrush" Value="#3E3E42"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="Padding" Value="10"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
</Style>
|
||||
|
||||
<!-- CheckBox Style -->
|
||||
<Style TargetType="CheckBox">
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="Margin" Value="0,6"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
</Style>
|
||||
|
||||
<!-- RadioButton Style -->
|
||||
<Style TargetType="RadioButton">
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="Margin" Value="0,0,20,0"/>
|
||||
<Setter Property="FontSize" Value="13"/>
|
||||
</Style>
|
||||
|
||||
<!-- Info Box Style -->
|
||||
<Style x:Key="InfoBox" TargetType="Border">
|
||||
<Setter Property="Background" Value="#2D2D30"/>
|
||||
<Setter Property="BorderBrush" Value="#3E3E42"/>
|
||||
<Setter Property="BorderThickness" Value="1"/>
|
||||
<Setter Property="CornerRadius" Value="4"/>
|
||||
<Setter Property="Padding" Value="15"/>
|
||||
<Setter Property="Margin" Value="0,10,0,0"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Scrollable Content -->
|
||||
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel Margin="30,20">
|
||||
|
||||
<!-- SEZIONE 1: Impostazioni Predefinite Aste -->
|
||||
<Border Background="#252526"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Padding="20"
|
||||
Margin="0,0,0,20">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Impostazioni Predefinite Aste"
|
||||
Style="{StaticResource SectionHeader}"/>
|
||||
|
||||
<TextBlock Text="Queste impostazioni verranno applicate automaticamente alle nuove aste."
|
||||
Foreground="#999999"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,20"/>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="250"/>
|
||||
<ColumnDefinition Width="150"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="Anticipo Puntata (millisecondi)" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center" ToolTip="Millisecondi prima della scadenza per puntare"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1" x:Name="DefaultBidBeforeDeadlineMsTextBox" Text="200" Margin="10,10"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="Verifica Stato Prima Di Puntare" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center" ToolTip="Controlla che l'asta sia ancora aperta prima di puntare"/>
|
||||
<CheckBox Grid.Row="1" Grid.Column="1" x:Name="DefaultCheckAuctionOpenCheckBox" Margin="10,10" VerticalAlignment="Center"/>
|
||||
|
||||
<TextBlock Grid.Row="2" Grid.Column="0" Text="Prezzo Minimo (€)" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="2" Grid.Column="1" x:Name="DefaultMinPriceTextBox" Text="0" Margin="10,10"/>
|
||||
|
||||
<TextBlock Grid.Row="3" Grid.Column="0" Text="Prezzo Massimo (€)" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="3" Grid.Column="1" x:Name="DefaultMaxPriceTextBox" Text="0" Margin="10,10"/>
|
||||
|
||||
<TextBlock Grid.Row="4" Grid.Column="0" Text="Max Click" Foreground="#CCCCCC" Margin="0,10" VerticalAlignment="Center"/>
|
||||
<TextBox Grid.Row="4" Grid.Column="1" x:Name="DefaultMaxClicksTextBox" Text="0" Margin="10,10"/>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- SEZIONE 2: Stato Iniziale Aste -->
|
||||
<Border Background="#252526"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Padding="20"
|
||||
Margin="0,0,0,20">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Stato Iniziale Aste"
|
||||
Style="{StaticResource SectionHeader}"/>
|
||||
|
||||
<TextBlock Text="Configura come devono comportarsi le aste quando vengono caricate o aggiunte."
|
||||
Foreground="#999999"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,20"/>
|
||||
|
||||
<!-- Stato all'apertura applicazione -->
|
||||
<TextBlock Text="Stato aste al caricamento dell'applicazione"
|
||||
Style="{StaticResource FieldLabel}"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
|
||||
<RadioButton x:Name="LoadAuctionsStopped"
|
||||
Content="Fermate"
|
||||
GroupName="LoadState"
|
||||
IsChecked="True"
|
||||
ToolTip="Le aste salvate verranno caricate in stato fermo"/>
|
||||
<RadioButton x:Name="LoadAuctionsPaused"
|
||||
Content="In Pausa"
|
||||
GroupName="LoadState"
|
||||
ToolTip="Le aste salvate verranno caricate in pausa (pronte ad essere avviate)"/>
|
||||
<RadioButton x:Name="LoadAuctionsActive"
|
||||
Content="Attive"
|
||||
GroupName="LoadState"
|
||||
ToolTip="Le aste salvate verranno avviate automaticamente all'apertura"/>
|
||||
<RadioButton x:Name="LoadAuctionsRemember"
|
||||
Content="Ricorda Stato"
|
||||
GroupName="LoadState"
|
||||
ToolTip="Ogni asta ripristina lo stato che aveva alla chiusura (attiva/pausa/ferma)"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Stato nuove aste -->
|
||||
<TextBlock Text="Stato iniziale di una nuova asta aggiunta"
|
||||
Style="{StaticResource FieldLabel}"/>
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,0,0,0">
|
||||
<RadioButton x:Name="NewAuctionStopped"
|
||||
Content="Fermata"
|
||||
GroupName="NewAuctionState"
|
||||
IsChecked="True"
|
||||
ToolTip="Le nuove aste verranno aggiunte in stato fermo"/>
|
||||
<RadioButton x:Name="NewAuctionPaused"
|
||||
Content="In Pausa"
|
||||
GroupName="NewAuctionState"
|
||||
ToolTip="Le nuove aste verranno aggiunte in pausa"/>
|
||||
<RadioButton x:Name="NewAuctionActive"
|
||||
Content="Attiva"
|
||||
GroupName="NewAuctionState"
|
||||
ToolTip="Le nuove aste verranno avviate automaticamente"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Info Box -->
|
||||
<Border Style="{StaticResource InfoBox}" Margin="0,15,0,0">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Informazioni"
|
||||
FontWeight="Bold"
|
||||
Foreground="#007ACC"
|
||||
Margin="0,0,0,10"/>
|
||||
<TextBlock TextWrapping="Wrap"
|
||||
Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
LineHeight="18">
|
||||
• <Bold>Fermata:</Bold> L'asta non viene monitorata fino all'avvio manuale.<LineBreak/>
|
||||
• <Bold>In Pausa:</Bold> L'asta è pronta ma non punta automaticamente (utile per preparare le aste).<LineBreak/>
|
||||
• <Bold>Attiva:</Bold> L'asta viene monitorata e punta automaticamente quando necessario.<LineBreak/>
|
||||
• <Bold>Ricorda Stato:</Bold> Ogni asta ripristina lo stato esatto che aveva alla chiusura (SOVRASCRIVE le altre opzioni).<LineBreak/>
|
||||
<LineBreak/>
|
||||
<Bold>Consiglio:</Bold> Usa "Fermata" per caricare le aste senza avviarle, poi avvia manualmente quelle desiderate.<LineBreak/>
|
||||
Usa "Ricorda Stato" per riprendere esattamente da dove avevi lasciato.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- SEZIONE 3: Protezione Account -->
|
||||
<Border Background="#252526"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Padding="20"
|
||||
Margin="0,0,0,20">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Protezione Account"
|
||||
Style="{StaticResource SectionHeader}"/>
|
||||
|
||||
<TextBlock Text="Impostazioni di sicurezza per proteggere il tuo account dalle puntate eccessive."
|
||||
Foreground="#999999"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,20"/>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="250"/>
|
||||
<ColumnDefinition Width="150"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Puntate Minime da Mantenere -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="Puntate Minime da Mantenere"
|
||||
Foreground="#CCCCCC"
|
||||
Margin="0,10"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="Numero minimo di puntate residue da mantenere sull'account. Se > 0, non punterà se scende sotto questa soglia (0 = nessun limite)"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
x:Name="MinimumRemainingBidsTextBox"
|
||||
Text="0"
|
||||
Margin="10,10"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Info Box -->
|
||||
<Border Style="{StaticResource InfoBox}" Margin="0,15,0,0">
|
||||
<StackPanel>
|
||||
<TextBlock Text="🛡️ Protezione Puntate"
|
||||
FontWeight="Bold"
|
||||
Foreground="#00D800"
|
||||
Margin="0,0,0,10"/>
|
||||
<TextBlock TextWrapping="Wrap"
|
||||
Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
LineHeight="18">
|
||||
• Se impostato > 0, il sistema non punterà se le puntate residue scenderebbero sotto questa soglia.<LineBreak/>
|
||||
• Utile per mantenere sempre un "cuscinetto" di sicurezza sull'account.<LineBreak/>
|
||||
• Nel banner principale apparirà un indicatore colorato: <LineBreak/>
|
||||
- <Bold>Verde:</Bold> Puntate abbondanti (oltre +10 dal limite)<LineBreak/>
|
||||
- <Bold>Giallo:</Bold> Vicino al limite (entro 10 puntate)<LineBreak/>
|
||||
- <Bold>Rosso:</Bold> Al limite o sotto (puntate bloccate)<LineBreak/>
|
||||
• Valore 0 = nessun limite (comportamento default).
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- SEZIONE 4: Limiti Log -->
|
||||
<Border Background="#252526"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Padding="20">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Limiti Log"
|
||||
Style="{StaticResource SectionHeader}"/>
|
||||
|
||||
<TextBlock Text="Configura il numero massimo di righe di log da mantenere in memoria per ottimizzare le performance."
|
||||
Foreground="#999999"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,20"/>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="250"/>
|
||||
<ColumnDefinition Width="150"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||
Text="Max Righe Log per Asta"
|
||||
Foreground="#CCCCCC"
|
||||
Margin="0,10"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="Numero massimo di righe di log da mantenere per ogni singola asta (raccomandato: 500-1000)"/>
|
||||
<TextBox Grid.Row="0" Grid.Column="1"
|
||||
x:Name="MaxLogLinesPerAuctionTextBox"
|
||||
Text="500"
|
||||
Margin="10,10"/>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||
Text="Max Righe Log Globale"
|
||||
Foreground="#CCCCCC"
|
||||
Margin="0,10"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="Numero massimo di righe di log da mantenere nel log globale dell'applicazione (raccomandato: 1000-2000)"/>
|
||||
<TextBox Grid.Row="1" Grid.Column="1"
|
||||
x:Name="MaxGlobalLogLinesTextBox"
|
||||
Text="1000"
|
||||
Margin="10,10"/>
|
||||
|
||||
<!-- 📊 NUOVO: Max Storia Puntate -->
|
||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||
Text="Max Puntate da Visualizzare"
|
||||
Foreground="#CCCCCC"
|
||||
Margin="0,10"
|
||||
VerticalAlignment="Center"
|
||||
ToolTip="Numero massimo di puntate da mostrare nella scheda Storia Puntate (raccomandato: 20-50, 0 = tutte)"/>
|
||||
<TextBox Grid.Row="2" Grid.Column="1"
|
||||
x:Name="MaxBidHistoryEntriesTextBox"
|
||||
Text="20"
|
||||
Margin="10,10"/>
|
||||
</Grid>
|
||||
|
||||
<!-- Info Box -->
|
||||
<Border Style="{StaticResource InfoBox}" Margin="0,15,0,0">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Informazioni"
|
||||
FontWeight="Bold"
|
||||
Foreground="#007ACC"
|
||||
Margin="0,0,0,10"/>
|
||||
<TextBlock TextWrapping="Wrap"
|
||||
Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
LineHeight="18">
|
||||
• I log più vecchi verranno automaticamente rimossi quando si raggiunge il limite.<LineBreak/>
|
||||
• Valori più bassi = meno memoria utilizzata, ma meno storico disponibile.<LineBreak/>
|
||||
• Valori più alti = più storico disponibile, ma maggiore uso di memoria.<LineBreak/>
|
||||
• Valori consigliati: 500-1000 per asta, 1000-2000 per log globale.
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
<!-- SEZIONE 5: Livello di Dettaglio Log -->
|
||||
<Border Background="#252526"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="1"
|
||||
CornerRadius="4"
|
||||
Padding="20"
|
||||
Margin="0,20,0,0">
|
||||
<StackPanel>
|
||||
<TextBlock Text="Livello di Dettaglio Log"
|
||||
Style="{StaticResource SectionHeader}"/>
|
||||
|
||||
<TextBlock Text="Configura il livello minimo dei messaggi da visualizzare nel log. Livelli più bassi mostrano solo messaggi critici, livelli più alti mostrano tutti i dettagli (utile per debug)."
|
||||
Foreground="#999999"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,20"/>
|
||||
|
||||
<!-- Radio Buttons per livello log -->
|
||||
<StackPanel>
|
||||
<RadioButton x:Name="LogLevelErrorOnly"
|
||||
Content="Solo Errori"
|
||||
GroupName="LogLevel"
|
||||
Margin="0,5"
|
||||
ToolTip="Mostra solo errori critici (uso minimo per produzione)"/>
|
||||
|
||||
<RadioButton x:Name="LogLevelNormal"
|
||||
Content="Normale (Errori + Avvisi)"
|
||||
GroupName="LogLevel"
|
||||
IsChecked="True"
|
||||
Margin="0,5"
|
||||
ToolTip="Mostra errori e avvisi (uso giornaliero raccomandato)"/>
|
||||
|
||||
<RadioButton x:Name="LogLevelInformational"
|
||||
Content="Informativo (Include operazioni completate)"
|
||||
GroupName="LogLevel"
|
||||
Margin="0,5"
|
||||
ToolTip="Mostra anche messaggi informativi e conferme (uso dettagliato)"/>
|
||||
|
||||
<RadioButton x:Name="LogLevelDebug"
|
||||
Content="Debug (Include dettagli tecnici)"
|
||||
GroupName="LogLevel"
|
||||
Margin="0,5"
|
||||
ToolTip="Mostra anche messaggi di debug per sviluppo"/>
|
||||
|
||||
<RadioButton x:Name="LogLevelTrace"
|
||||
Content="Trace (Tutto - molto verboso)"
|
||||
GroupName="LogLevel"
|
||||
Margin="0,5"
|
||||
ToolTip="Mostra ogni singola operazione (debug avanzato)"/>
|
||||
</StackPanel>
|
||||
|
||||
<!-- Info Box -->
|
||||
<Border Style="{StaticResource InfoBox}" Margin="0,15,0,0">
|
||||
<StackPanel>
|
||||
<TextBlock Text="🔍 Guida alla Scelta"
|
||||
FontWeight="Bold"
|
||||
Foreground="#FFB700"
|
||||
Margin="0,0,0,10"/>
|
||||
<TextBlock Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,5">
|
||||
<Run>Solo Errori: Usa in produzione per vedere solo problemi critici.</Run>
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,5">
|
||||
<Run>Normale: Raccomandato per uso giornaliero. Mostra errori e avvisi importanti.</Run>
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,5">
|
||||
<Run>Informativo: Utile per seguire le operazioni principali (aggiunte aste, puntate).</Run>
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,5">
|
||||
<Run>Debug: Per sviluppo. Mostra parametri chiamate API e valori interni.</Run>
|
||||
</TextBlock>
|
||||
<TextBlock Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
TextWrapping="Wrap"
|
||||
Margin="0,0,0,10">
|
||||
<Run>Trace: Debug avanzato. Mostra ogni singola chiamata (molto verboso).</Run>
|
||||
</TextBlock>
|
||||
|
||||
<TextBlock Foreground="#CCCCCC"
|
||||
FontSize="12"
|
||||
FontWeight="Bold"
|
||||
Margin="0,5,0,5">Legenda colori log:</TextBlock>
|
||||
|
||||
<StackPanel>
|
||||
<TextBlock FontSize="11" Margin="0,2">
|
||||
<Run Foreground="#E81123">■ ROSSO</Run>
|
||||
<Run Foreground="#CCCCCC"> = Errori critici</Run>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="11" Margin="0,2">
|
||||
<Run Foreground="#FFB700">■ ARANCIONE</Run>
|
||||
<Run Foreground="#CCCCCC"> = Avvisi</Run>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="11" Margin="0,2">
|
||||
<Run Foreground="#64B4FF">■ BLU</Run>
|
||||
<Run Foreground="#CCCCCC"> = Informazioni</Run>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="11" Margin="0,2">
|
||||
<Run Foreground="#00D800">■ VERDE</Run>
|
||||
<Run Foreground="#CCCCCC"> = Operazioni riuscite</Run>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="11" Margin="0,2">
|
||||
<Run Foreground="#FF8CFF">■ MAGENTA</Run>
|
||||
<Run Foreground="#CCCCCC"> = Debug</Run>
|
||||
</TextBlock>
|
||||
<TextBlock FontSize="11" Margin="0,2">
|
||||
<Run Foreground="#A0A0A0">■ GRIGIO</Run>
|
||||
<Run Foreground="#CCCCCC"> = Trace</Run>
|
||||
</TextBlock>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
|
||||
<!-- Fixed Bottom Bar with Save/Cancel -->
|
||||
<Border Grid.Row="1"
|
||||
Background="#2D2D30"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="0,1,0,0"
|
||||
Padding="30,15">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Content="Salva"
|
||||
Background="#00D800"
|
||||
Style="{StaticResource ModernButton}"
|
||||
Margin="0,0,10,0"
|
||||
Padding="40,10"
|
||||
Click="SaveAllSettings_Click"/>
|
||||
|
||||
<Button Content="Annulla"
|
||||
Background="#3E3E42"
|
||||
Style="{StaticResource ModernButton}"
|
||||
Padding="40,10"
|
||||
Click="CancelAllSettings_Click"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
90
Mimante/Controls/SettingsControl.xaml.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace AutoBidder.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for SettingsControl.xaml
|
||||
/// </summary>
|
||||
public partial class SettingsControl : UserControl
|
||||
{
|
||||
public SettingsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
// Non servono proprietà wrapper - MainWindow.xaml.cs accede direttamente ai controlli tramite:
|
||||
// Settings.DefaultBidBeforeDeadlineMsTextBox (definito nel XAML con x:Name)
|
||||
// Settings.MaxLogLinesPerAuctionTextBox (definito nel XAML con x:Name)
|
||||
// etc.
|
||||
|
||||
// Proprietà per limiti log
|
||||
public TextBox MaxLogLinesPerAuction => MaxLogLinesPerAuctionTextBox;
|
||||
public TextBox MaxGlobalLogLines => MaxGlobalLogLinesTextBox;
|
||||
|
||||
// ?? NUOVO: Proprietà per limite storia puntate
|
||||
public TextBox MaxBidHistoryEntries => MaxBidHistoryEntriesTextBox;
|
||||
|
||||
private void SaveDefaultsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(SaveDefaultsClickedEvent, this));
|
||||
}
|
||||
|
||||
private void CancelDefaultsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(CancelDefaultsClickedEvent, this));
|
||||
}
|
||||
|
||||
// Nuovo evento unificato - SALVA TUTTE LE IMPOSTAZIONI
|
||||
private void SaveAllSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Salva impostazioni predefinite aste (export rimosso)
|
||||
RaiseEvent(new RoutedEventArgs(SaveDefaultsClickedEvent, this));
|
||||
|
||||
// UNICO MessageBox di conferma
|
||||
MessageBox.Show(
|
||||
"Tutte le impostazioni sono state salvate con successo.\n\nLe nuove impostazioni verranno applicate alle aste future.",
|
||||
"Impostazioni Salvate",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information
|
||||
);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"Errore durante il salvataggio: " + ex.Message,
|
||||
"Errore",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Error
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelAllSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Annulla tutte le modifiche
|
||||
RaiseEvent(new RoutedEventArgs(CancelDefaultsClickedEvent, this));
|
||||
}
|
||||
|
||||
// Routed Events
|
||||
public static readonly RoutedEvent SaveDefaultsClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"SaveDefaultsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
||||
|
||||
public static readonly RoutedEvent CancelDefaultsClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"CancelDefaultsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(SettingsControl));
|
||||
|
||||
public event RoutedEventHandler SaveDefaultsClicked
|
||||
{
|
||||
add { AddHandler(SaveDefaultsClickedEvent, value); }
|
||||
remove { RemoveHandler(SaveDefaultsClickedEvent, value); }
|
||||
}
|
||||
|
||||
public event RoutedEventHandler CancelDefaultsClicked
|
||||
{
|
||||
add { AddHandler(CancelDefaultsClickedEvent, value); }
|
||||
remove { RemoveHandler(CancelDefaultsClickedEvent, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Mimante/Controls/SimpleToolbar.xaml
Normal file
@@ -0,0 +1,16 @@
|
||||
<UserControl x:Class="AutoBidder.Controls.SimpleToolbar"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="48" d:DesignWidth="800">
|
||||
<Grid Background="Transparent">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ContentPresenter Content="{Binding LeftContent, RelativeSource={RelativeSource AncestorType=UserControl}}" VerticalAlignment="Center" />
|
||||
<ContentPresenter Grid.Column="1" Content="{Binding RightContent, RelativeSource={RelativeSource AncestorType=UserControl}}" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</UserControl>
|
||||
28
Mimante/Controls/SimpleToolbar.xaml.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace AutoBidder.Controls
|
||||
{
|
||||
public partial class SimpleToolbar : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty LeftContentProperty = DependencyProperty.Register("LeftContent", typeof(object), typeof(SimpleToolbar));
|
||||
public static readonly DependencyProperty RightContentProperty = DependencyProperty.Register("RightContent", typeof(object), typeof(SimpleToolbar));
|
||||
|
||||
public object? LeftContent
|
||||
{
|
||||
get => GetValue(LeftContentProperty);
|
||||
set => SetValue(LeftContentProperty, value);
|
||||
}
|
||||
|
||||
public object? RightContent
|
||||
{
|
||||
get => GetValue(RightContentProperty);
|
||||
set => SetValue(RightContentProperty, value);
|
||||
}
|
||||
|
||||
public SimpleToolbar()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
135
Mimante/Controls/StatisticsControl.xaml
Normal file
@@ -0,0 +1,135 @@
|
||||
<UserControl x:Class="AutoBidder.Controls.StatisticsControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="800" d:DesignWidth="1200"
|
||||
Background="#1E1E1E">
|
||||
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="RoundedButton" TargetType="Button">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Button">
|
||||
<Border Background="{TemplateBinding Background}"
|
||||
CornerRadius="8"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
<Setter Property="Foreground" Value="White"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Setter Property="Padding" Value="15,10"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Header -->
|
||||
<Border Grid.Row="0" Background="#2D2D30" Padding="15" BorderBrush="#3E3E42" BorderThickness="0,0,0,1">
|
||||
<Grid>
|
||||
<TextBlock Text="📊 Dati Statistici - Analisi Aste Chiuse"
|
||||
Foreground="#00D800"
|
||||
FontSize="16"
|
||||
FontWeight="Bold"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<Button x:Name="LoadClosedAuctionsButton"
|
||||
Content="🔄 Carica Statistiche"
|
||||
HorizontalAlignment="Right"
|
||||
Background="#007ACC"
|
||||
Style="{StaticResource RoundedButton}"
|
||||
Click="LoadClosedAuctionsButton_Click"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- DataGrid Statistiche -->
|
||||
<DataGrid Grid.Row="1"
|
||||
x:Name="StatsDataGrid"
|
||||
AutoGenerateColumns="False"
|
||||
IsReadOnly="True"
|
||||
Background="#1E1E1E"
|
||||
Foreground="#CCCCCC"
|
||||
RowBackground="#1E1E1E"
|
||||
AlternatingRowBackground="#252526"
|
||||
GridLinesVisibility="Horizontal"
|
||||
HeadersVisibility="Column"
|
||||
BorderThickness="0"
|
||||
Margin="15">
|
||||
<DataGrid.ColumnHeaderStyle>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="Background" Value="#2D2D30"/>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
<Setter Property="FontWeight" Value="Bold"/>
|
||||
<Setter Property="Padding" Value="10,8"/>
|
||||
<Setter Property="BorderThickness" Value="0,0,1,1"/>
|
||||
<Setter Property="BorderBrush" Value="#3E3E42"/>
|
||||
</Style>
|
||||
</DataGrid.ColumnHeaderStyle>
|
||||
<DataGrid.CellStyle>
|
||||
<Style TargetType="DataGridCell">
|
||||
<Setter Property="BorderThickness" Value="0"/>
|
||||
<Setter Property="Padding" Value="10,5"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Foreground" Value="#CCCCCC"/>
|
||||
</Style>
|
||||
</DataGrid.CellStyle>
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Prodotto" Binding="{Binding ProductName}" Width="3*"/>
|
||||
<DataGridTextColumn Header="Prezzo Medio" Binding="{Binding AverageFinalPrice, StringFormat=€{0:F2}}" Width="120"/>
|
||||
<DataGridTextColumn Header="Click Medi" Binding="{Binding AverageBidsUsed, StringFormat={}{0:F0}}" Width="100"/>
|
||||
<DataGridTextColumn Header="Vincitore Frequente" Binding="{Binding Winner}" Width="150"/>
|
||||
<DataGridTextColumn Header="# Aste" Binding="{Binding Count}" Width="80"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<!-- Footer: Status -->
|
||||
<Border Grid.Row="2"
|
||||
Background="#252526"
|
||||
Padding="15"
|
||||
BorderBrush="#3E3E42"
|
||||
BorderThickness="0,1,0,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<StackPanel Grid.Column="0">
|
||||
<TextBlock x:Name="StatsStatusText"
|
||||
Text="Pronto per caricare statistiche"
|
||||
FontSize="13"
|
||||
Foreground="#CCCCCC"
|
||||
VerticalAlignment="Center"/>
|
||||
|
||||
<TextBlock x:Name="ExportProgressText"
|
||||
Text=""
|
||||
FontSize="11"
|
||||
Foreground="#999999"
|
||||
Margin="0,5,0,0"
|
||||
Visibility="Collapsed"/>
|
||||
</StackPanel>
|
||||
|
||||
<ProgressBar Grid.Column="1"
|
||||
x:Name="ExportProgressBar"
|
||||
Width="200"
|
||||
Height="20"
|
||||
IsIndeterminate="True"
|
||||
Foreground="#007ACC"
|
||||
Background="#1E1E1E"
|
||||
BorderBrush="#3E3E42"
|
||||
Visibility="Collapsed"/>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
31
Mimante/Controls/StatisticsControl.xaml.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace AutoBidder.Controls
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for StatisticsControl.xaml
|
||||
/// </summary>
|
||||
public partial class StatisticsControl : UserControl
|
||||
{
|
||||
public StatisticsControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void LoadClosedAuctionsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RaiseEvent(new RoutedEventArgs(LoadClosedAuctionsClickedEvent, this));
|
||||
}
|
||||
|
||||
// Routed Events
|
||||
public static readonly RoutedEvent LoadClosedAuctionsClickedEvent = EventManager.RegisterRoutedEvent(
|
||||
"LoadClosedAuctionsClicked", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(StatisticsControl));
|
||||
|
||||
public event RoutedEventHandler LoadClosedAuctionsClicked
|
||||
{
|
||||
add { AddHandler(LoadClosedAuctionsClickedEvent, value); }
|
||||
remove { RemoveHandler(LoadClosedAuctionsClickedEvent, value); }
|
||||
}
|
||||
}
|
||||
}
|
||||
163
Mimante/Core/EventHandlers/MainWindow.EventHandlers.Browser.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Browser event handlers and navigation
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private void BrowserBackButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (EmbeddedWebView?.CoreWebView2 != null && EmbeddedWebView.CoreWebView2.CanGoBack)
|
||||
EmbeddedWebView.CoreWebView2.GoBack();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void BrowserForwardButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (EmbeddedWebView?.CoreWebView2 != null && EmbeddedWebView.CoreWebView2.CanGoForward)
|
||||
EmbeddedWebView.CoreWebView2.GoForward();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void BrowserRefreshButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
EmbeddedWebView?.Reload();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void BrowserHomeButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
EmbeddedWebView?.CoreWebView2?.Navigate("https://it.bidoo.com/");
|
||||
BrowserAddress.Text = "https://it.bidoo.com/";
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void BrowserAddAuctionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = BrowserAddress.Text?.Trim() ?? EmbeddedWebView?.Source?.ToString();
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
_ = AddAuctionFromUrl(url);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void EmbeddedWebView_NavigationStarting(object sender, CoreWebView2NavigationStartingEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
BrowserAddress.Text = e.Uri ?? string.Empty;
|
||||
var btn = this.FindName("BrowserAddAuctionButton") as Button;
|
||||
if (btn != null)
|
||||
btn.IsEnabled = IsValidAuctionUrl(e.Uri ?? string.Empty);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void EmbeddedWebView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var uri = EmbeddedWebView?.Source?.ToString() ?? BrowserAddress.Text;
|
||||
BrowserAddress.Text = uri;
|
||||
var btn = this.FindName("BrowserAddAuctionButton") as Button;
|
||||
if (btn != null)
|
||||
btn.IsEnabled = IsValidAuctionUrl(uri);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void EmbeddedWebView_PreviewMouseRightButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
e.Handled = true;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void CoreWebView2_ContextMenuRequested(object? sender, CoreWebView2ContextMenuRequestedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Prevent default native menu
|
||||
e.Handled = true;
|
||||
|
||||
var target = e.ContextMenuTarget;
|
||||
string? link = null;
|
||||
try
|
||||
{
|
||||
link = target?.LinkUri;
|
||||
if (string.IsNullOrEmpty(link)) link = target?.PageUri;
|
||||
}
|
||||
catch { }
|
||||
|
||||
// Show WPF ContextMenu on UI thread
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var menu = new ContextMenu();
|
||||
|
||||
var canAdd = !string.IsNullOrEmpty(link) || IsValidAuctionUrl(EmbeddedWebView?.Source?.ToString() ?? BrowserAddress.Text);
|
||||
|
||||
var addItem = new MenuItem { Header = "Aggiungi Asta", IsEnabled = canAdd };
|
||||
addItem.Click += async (s, args) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
string? urlToAdd = link;
|
||||
if (string.IsNullOrEmpty(urlToAdd))
|
||||
urlToAdd = EmbeddedWebView?.Source?.ToString() ?? BrowserAddress.Text;
|
||||
|
||||
if (!string.IsNullOrEmpty(urlToAdd))
|
||||
{
|
||||
await AddAuctionFromUrl(urlToAdd);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Aggiungi Asta dal menu: {ex.Message}");
|
||||
}
|
||||
};
|
||||
|
||||
menu.Items.Add(addItem);
|
||||
|
||||
var copyLink = new MenuItem { Header = "Copia link", IsEnabled = !string.IsNullOrEmpty(link) };
|
||||
copyLink.Click += (s, args) =>
|
||||
{
|
||||
try { if (!string.IsNullOrEmpty(link)) Clipboard.SetText(link); }
|
||||
catch { }
|
||||
};
|
||||
menu.Items.Add(copyLink);
|
||||
|
||||
menu.Placement = System.Windows.Controls.Primitives.PlacementMode.MousePoint;
|
||||
menu.IsOpen = true;
|
||||
}
|
||||
catch { }
|
||||
}));
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
321
Mimante/Core/EventHandlers/MainWindow.EventHandlers.Settings.cs
Normal file
@@ -0,0 +1,321 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using AutoBidder.Utilities;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Settings and configuration event handlers - REFACTORED
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Carica TUTTE le impostazioni salvate nei controlli UI
|
||||
/// </summary>
|
||||
private void LoadDefaultSettings()
|
||||
{
|
||||
try
|
||||
{
|
||||
var settings = Utilities.SettingsManager.Load();
|
||||
|
||||
// Carica impostazioni predefinite aste
|
||||
DefaultBidBeforeDeadlineMs.Text = settings.DefaultBidBeforeDeadlineMs.ToString();
|
||||
DefaultCheckAuctionOpen.IsChecked = settings.DefaultCheckAuctionOpenBeforeBid;
|
||||
DefaultMinPrice.Text = settings.DefaultMinPrice.ToString("F2", System.Globalization.CultureInfo.InvariantCulture);
|
||||
DefaultMaxPrice.Text = settings.DefaultMaxPrice.ToString("F2", System.Globalization.CultureInfo.InvariantCulture);
|
||||
DefaultMaxClicks.Text = settings.DefaultMaxClicks.ToString();
|
||||
|
||||
// Carica limiti log
|
||||
Settings.MaxLogLinesPerAuctionTextBox.Text = settings.MaxLogLinesPerAuction.ToString();
|
||||
Settings.MaxGlobalLogLinesTextBox.Text = settings.MaxGlobalLogLines.ToString();
|
||||
|
||||
// ?? NUOVO: Carica limite storia puntate
|
||||
Settings.MaxBidHistoryEntriesTextBox.Text = settings.MaxBidHistoryEntries.ToString();
|
||||
|
||||
// ?? NUOVO: Carica limite minimo puntate
|
||||
MinimumRemainingBidsTextBox.Text = settings.MinimumRemainingBids.ToString();
|
||||
|
||||
// ?? NUOVO: Carica livello log
|
||||
var logLevelErrorOnly = Settings.FindName("LogLevelErrorOnly") as System.Windows.Controls.RadioButton;
|
||||
var logLevelNormal = Settings.FindName("LogLevelNormal") as System.Windows.Controls.RadioButton;
|
||||
var logLevelInformational = Settings.FindName("LogLevelInformational") as System.Windows.Controls.RadioButton;
|
||||
var logLevelDebug = Settings.FindName("LogLevelDebug") as System.Windows.Controls.RadioButton;
|
||||
var logLevelTrace = Settings.FindName("LogLevelTrace") as System.Windows.Controls.RadioButton;
|
||||
|
||||
switch (settings.MinLogLevel)
|
||||
{
|
||||
case "ErrorOnly":
|
||||
if (logLevelErrorOnly != null) logLevelErrorOnly.IsChecked = true;
|
||||
break;
|
||||
case "Informational":
|
||||
if (logLevelInformational != null) logLevelInformational.IsChecked = true;
|
||||
break;
|
||||
case "Debug":
|
||||
if (logLevelDebug != null) logLevelDebug.IsChecked = true;
|
||||
break;
|
||||
case "Trace":
|
||||
if (logLevelTrace != null) logLevelTrace.IsChecked = true;
|
||||
break;
|
||||
case "Normal":
|
||||
default:
|
||||
if (logLevelNormal != null) logLevelNormal.IsChecked = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Aggiorna indicatore visivo
|
||||
UpdateMinBidsIndicator(settings.MinimumRemainingBids);
|
||||
|
||||
// Carica stato iniziale aste
|
||||
// ? NUOVO: Se RememberAuctionStates è attivo, seleziona "Ricorda Stato"
|
||||
if (settings.RememberAuctionStates)
|
||||
{
|
||||
Settings.LoadAuctionsRemember.IsChecked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Altrimenti usa DefaultStartAuctionsOnLoad
|
||||
switch (settings.DefaultStartAuctionsOnLoad)
|
||||
{
|
||||
case "Active":
|
||||
Settings.LoadAuctionsActive.IsChecked = true;
|
||||
break;
|
||||
case "Paused":
|
||||
Settings.LoadAuctionsPaused.IsChecked = true;
|
||||
break;
|
||||
case "Stopped":
|
||||
default:
|
||||
Settings.LoadAuctionsStopped.IsChecked = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (settings.DefaultNewAuctionState)
|
||||
{
|
||||
case "Active":
|
||||
Settings.NewAuctionActive.IsChecked = true;
|
||||
break;
|
||||
case "Paused":
|
||||
Settings.NewAuctionPaused.IsChecked = true;
|
||||
break;
|
||||
case "Stopped":
|
||||
default:
|
||||
Settings.NewAuctionStopped.IsChecked = true;
|
||||
break;
|
||||
}
|
||||
|
||||
Log($"[OK] Impostazioni caricate: Anticipo={settings.DefaultBidBeforeDeadlineMs}ms, LogAsta={settings.MaxLogLinesPerAuction}, LogGlobale={settings.MaxGlobalLogLines}, MinBids={settings.MinimumRemainingBids}", Utilities.LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Caricamento impostazioni predefinite: {ex.Message}", Utilities.LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveDefaultsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// ? Carica le impostazioni esistenti per non perdere gli altri valori
|
||||
var settings = Utilities.SettingsManager.Load() ?? new Utilities.AppSettings();
|
||||
|
||||
// === SEZIONE DEFAULTS: Validazione e Salvataggio ===
|
||||
if (int.TryParse(DefaultBidBeforeDeadlineMs.Text, out var bidMs) && bidMs >= 0 && bidMs <= 5000)
|
||||
{
|
||||
settings.DefaultBidBeforeDeadlineMs = bidMs;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[ERRORE] Valore anticipo puntata non valido (deve essere 0-5000ms)", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
settings.DefaultCheckAuctionOpenBeforeBid = DefaultCheckAuctionOpen.IsChecked ?? false;
|
||||
|
||||
if (double.TryParse(DefaultMinPrice.Text.Replace(',', '.'), System.Globalization.NumberStyles.Any,
|
||||
System.Globalization.CultureInfo.InvariantCulture, out var minPrice))
|
||||
{
|
||||
settings.DefaultMinPrice = minPrice;
|
||||
}
|
||||
|
||||
if (double.TryParse(DefaultMaxPrice.Text.Replace(',', '.'), System.Globalization.NumberStyles.Any,
|
||||
System.Globalization.CultureInfo.InvariantCulture, out var maxPrice))
|
||||
{
|
||||
settings.DefaultMaxPrice = maxPrice;
|
||||
}
|
||||
|
||||
if (int.TryParse(DefaultMaxClicks.Text, out var maxClicks))
|
||||
{
|
||||
settings.DefaultMaxClicks = maxClicks;
|
||||
}
|
||||
|
||||
// === SEZIONE DEFAULTS: Limiti Log ===
|
||||
if (int.TryParse(Settings.MaxLogLinesPerAuctionTextBox.Text, out var maxLogPerAuction) && maxLogPerAuction > 0)
|
||||
{
|
||||
settings.MaxLogLinesPerAuction = maxLogPerAuction;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[ERRORE] Valore max log per asta non valido (deve essere > 0)", LogLevel.Error);
|
||||
}
|
||||
|
||||
if (int.TryParse(Settings.MaxGlobalLogLinesTextBox.Text, out var maxGlobalLog) && maxGlobalLog > 0)
|
||||
{
|
||||
settings.MaxGlobalLogLines = maxGlobalLog;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[ERRORE] Valore max log globale non valido (deve essere > 0)", LogLevel.Error);
|
||||
}
|
||||
|
||||
// ?? NUOVO: Salva limite storia puntate
|
||||
if (int.TryParse(Settings.MaxBidHistoryEntriesTextBox.Text, out var maxBidHistory) && maxBidHistory >= 0)
|
||||
{
|
||||
settings.MaxBidHistoryEntries = maxBidHistory;
|
||||
|
||||
if (maxBidHistory > 0)
|
||||
{
|
||||
Log($"[HISTORY] Impostato limite storia puntate: {maxBidHistory}", LogLevel.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[HISTORY] Limite storia puntate disabilitato (mostra tutte)", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[ERRORE] Valore limite storia puntate non valido (deve essere >= 0)", LogLevel.Error);
|
||||
}
|
||||
|
||||
// ?? NUOVO: Salva limite minimo puntate
|
||||
if (int.TryParse(MinimumRemainingBidsTextBox.Text, out var minBids) && minBids >= 0)
|
||||
{
|
||||
settings.MinimumRemainingBids = minBids;
|
||||
|
||||
// Aggiorna indicatore visivo
|
||||
UpdateMinBidsIndicator(minBids);
|
||||
|
||||
if (minBids > 0)
|
||||
{
|
||||
Log($"[LIMIT] Impostato limite minimo puntate: {minBids}", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[ERRORE] Valore limite minimo puntate non valido (deve essere >= 0)", LogLevel.Error);
|
||||
}
|
||||
|
||||
// ?? NUOVO: Salva livello log
|
||||
var logLevelErrorOnly = Settings.FindName("LogLevelErrorOnly") as System.Windows.Controls.RadioButton;
|
||||
var logLevelNormal = Settings.FindName("LogLevelNormal") as System.Windows.Controls.RadioButton;
|
||||
var logLevelInformational = Settings.FindName("LogLevelInformational") as System.Windows.Controls.RadioButton;
|
||||
var logLevelDebug = Settings.FindName("LogLevelDebug") as System.Windows.Controls.RadioButton;
|
||||
var logLevelTrace = Settings.FindName("LogLevelTrace") as System.Windows.Controls.RadioButton;
|
||||
|
||||
string selectedLogLevel = "Normal"; // Default
|
||||
if (logLevelErrorOnly?.IsChecked == true)
|
||||
selectedLogLevel = "ErrorOnly";
|
||||
else if (logLevelInformational?.IsChecked == true)
|
||||
selectedLogLevel = "Informational";
|
||||
else if (logLevelDebug?.IsChecked == true)
|
||||
selectedLogLevel = "Debug";
|
||||
else if (logLevelTrace?.IsChecked == true)
|
||||
selectedLogLevel = "Trace";
|
||||
else if (logLevelNormal?.IsChecked == true)
|
||||
selectedLogLevel = "Normal";
|
||||
|
||||
settings.MinLogLevel = selectedLogLevel;
|
||||
|
||||
Log($"[LOG] Livello log impostato: {selectedLogLevel}", LogLevel.Info);
|
||||
|
||||
// === SEZIONE DEFAULTS: Stati Iniziali Aste ===
|
||||
var loadAuctionsRemember = Settings.FindName("LoadAuctionsRemember") as System.Windows.Controls.RadioButton;
|
||||
var loadAuctionsActive = Settings.FindName("LoadAuctionsActive") as System.Windows.Controls.RadioButton;
|
||||
var loadAuctionsPaused = Settings.FindName("LoadAuctionsPaused") as System.Windows.Controls.RadioButton;
|
||||
|
||||
// ? NUOVO: Gestione "Ricorda Stato"
|
||||
if (loadAuctionsRemember?.IsChecked == true)
|
||||
{
|
||||
// Attiva RememberAuctionStates
|
||||
settings.RememberAuctionStates = true;
|
||||
// DefaultStartAuctionsOnLoad diventa irrilevante, ma lo lasciamo a "Stopped" per compatibilità
|
||||
settings.DefaultStartAuctionsOnLoad = "Stopped";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disattiva RememberAuctionStates e usa DefaultStartAuctionsOnLoad
|
||||
settings.RememberAuctionStates = false;
|
||||
settings.DefaultStartAuctionsOnLoad = loadAuctionsActive?.IsChecked == true ? "Active" :
|
||||
loadAuctionsPaused?.IsChecked == true ? "Paused" :
|
||||
"Stopped";
|
||||
}
|
||||
|
||||
var newAuctionActive = Settings.FindName("NewAuctionActive") as System.Windows.Controls.RadioButton;
|
||||
var newAuctionPaused = Settings.FindName("NewAuctionPaused") as System.Windows.Controls.RadioButton;
|
||||
|
||||
settings.DefaultNewAuctionState = newAuctionActive?.IsChecked == true ? "Active" :
|
||||
newAuctionPaused?.IsChecked == true ? "Paused" :
|
||||
"Stopped";
|
||||
|
||||
Utilities.SettingsManager.Save(settings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Salvataggio impostazioni: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelDefaultsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Ricarica defaults salvati
|
||||
LoadDefaultSettings();
|
||||
MessageBox.Show(this, "Impostazioni predefinite ripristinate.", "Annulla", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Ripristino impostazioni: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show(this, "Errore durante ripristino: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
// === HANDLER PER PULSANTI UNIFICATI ===
|
||||
|
||||
private void SaveAllSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Salva tutte le impostazioni (ora solo defaults, export rimosso)
|
||||
SaveDefaultsButton_Click(sender, e);
|
||||
|
||||
MessageBox.Show(
|
||||
"Tutte le impostazioni sono state salvate con successo.\n\nLe nuove impostazioni verranno applicate alle aste future.",
|
||||
"Impostazioni Salvate",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information
|
||||
);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Salvataggio impostazioni: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show(this, "Errore durante salvataggio: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelAllSettings_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Annulla tutte le modifiche
|
||||
LoadDefaultSettings();
|
||||
MessageBox.Show(this, "Impostazioni ripristinate alle ultime salvate.", "Annulla", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Ripristino impostazioni: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show(this, "Errore durante ripristino: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
271
Mimante/Core/EventHandlers/MainWindow.EventHandlers.Stats.cs
Normal file
@@ -0,0 +1,271 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Xml.Linq;
|
||||
using AutoBidder.Models;
|
||||
using AutoBidder.Utilities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Statistics and closed auctions event handlers
|
||||
/// NOTA: Funzionalità statistiche temporaneamente disabilitate - in sviluppo
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private void ExportStatsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBox.Show(this, "Funzionalità statistiche in sviluppo", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
private async void LoadClosedAuctionsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBox.Show(this, "Funzionalità statistiche in sviluppo", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
|
||||
/* CODICE TEMPORANEAMENTE DISABILITATO - Statistiche in sviluppo
|
||||
try
|
||||
{
|
||||
StatsStatusText.Text = "Avvio caricamento statistiche...";
|
||||
var settings = Utilities.SettingsManager.Load();
|
||||
if (settings == null || string.IsNullOrWhiteSpace(settings.ExportPath) || !Directory.Exists(settings.ExportPath))
|
||||
{
|
||||
MessageBox.Show(this, "Percorso export non configurato o non valido. Configuralo nelle impostazioni.", "Carica Statistiche", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
StatsStatusText.Text = "Percorso export non valido";
|
||||
return;
|
||||
}
|
||||
|
||||
ExportProgressBar.Visibility = Visibility.Visible;
|
||||
ExportProgressText.Visibility = Visibility.Visible;
|
||||
ExportProgressText.Text = "Caricamento statistiche...";
|
||||
|
||||
var folder = settings.ExportPath!;
|
||||
var files = Directory.GetFiles(folder, "auction_*.*");
|
||||
if (files.Length == 0)
|
||||
{
|
||||
MessageBox.Show(this, "Nessun file di aste trovato nella cartella di export.", "Carica Statistiche", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
StatsStatusText.Text = "Nessun file trovato";
|
||||
ExportProgressBar.Visibility = Visibility.Collapsed;
|
||||
ExportProgressText.Visibility = Visibility.Collapsed;
|
||||
return;
|
||||
}
|
||||
|
||||
var aggregated = new Dictionary<string, List<ClosedAuctionRecord>>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
await Task.Run(() =>
|
||||
{
|
||||
foreach (var f in files)
|
||||
{
|
||||
try
|
||||
{
|
||||
var ext = Path.GetExtension(f).ToLowerInvariant();
|
||||
if (ext == ".json")
|
||||
{
|
||||
var txt = File.ReadAllText(f, Encoding.UTF8);
|
||||
try
|
||||
{
|
||||
var rec = System.Text.Json.JsonSerializer.Deserialize<ClosedAuctionRecord>(txt);
|
||||
if (rec != null)
|
||||
{
|
||||
var key = (rec.ProductName ?? ExtractProductFromFilename(f) ?? "<unknown>").Trim();
|
||||
if (!aggregated.ContainsKey(key)) aggregated[key] = new List<ClosedAuctionRecord>();
|
||||
aggregated[key].Add(rec);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
try
|
||||
{
|
||||
var arr = System.Text.Json.JsonSerializer.Deserialize<List<ClosedAuctionRecord>>(txt);
|
||||
if (arr != null)
|
||||
{
|
||||
foreach (var r in arr)
|
||||
{
|
||||
var key = (r.ProductName ?? ExtractProductFromFilename(f) ?? "<unknown>").Trim();
|
||||
if (!aggregated.ContainsKey(key)) aggregated[key] = new List<ClosedAuctionRecord>();
|
||||
aggregated[key].Add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else if (ext == ".xml")
|
||||
{
|
||||
try
|
||||
{
|
||||
var doc = XDocument.Load(f);
|
||||
var auctionElems = doc.Descendants("Auction");
|
||||
if (!auctionElems.Any()) auctionElems = doc.Descendants("AuctionExport");
|
||||
foreach (var n in auctionElems)
|
||||
{
|
||||
var name = n.Descendants("Name").FirstOrDefault()?.Value ?? n.Descendants("ProductName").FirstOrDefault()?.Value;
|
||||
double d = 0; double.TryParse(n.Descendants("FinalPrice").FirstOrDefault()?.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out d);
|
||||
int bids = 0; int.TryParse(n.Descendants("TotalBids").FirstOrDefault()?.Value, out bids);
|
||||
var winner = n.Descendants("Winner").FirstOrDefault()?.Value ?? string.Empty;
|
||||
var url = n.Descendants("OriginalUrl").FirstOrDefault()?.Value ?? string.Empty;
|
||||
var rec = new ClosedAuctionRecord { ProductName = name, FinalPrice = d == 0 ? null : (double?)d, Winner = winner, BidsUsed = bids, AuctionUrl = url };
|
||||
var key = (rec.ProductName ?? ExtractProductFromFilename(f) ?? "<unknown>").Trim();
|
||||
if (!aggregated.ContainsKey(key)) aggregated[key] = new List<ClosedAuctionRecord>();
|
||||
aggregated[key].Add(rec);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
else // CSV or text
|
||||
{
|
||||
try
|
||||
{
|
||||
var lines = File.ReadAllLines(f, Encoding.UTF8);
|
||||
string product = ExtractProductFromFilename(f) ?? "<unknown>";
|
||||
double? price = null; int? bids = null; string winner = string.Empty; string url = string.Empty;
|
||||
foreach (var l in lines)
|
||||
{
|
||||
var line = l.Trim();
|
||||
if (line.StartsWith("Name,") || line.StartsWith("ProductName,"))
|
||||
{
|
||||
var parts = line.Split(',', 2);
|
||||
if (parts.Length == 2) product = parts[1].Trim('"');
|
||||
}
|
||||
else if (line.StartsWith("FinalPrice", StringComparison.OrdinalIgnoreCase) || line.StartsWith("Price,"))
|
||||
{
|
||||
var parts = line.Split(',', 2);
|
||||
if (parts.Length == 2 && double.TryParse(parts[1].Trim('"').Replace('€', ' ').Trim(), NumberStyles.Any, CultureInfo.InvariantCulture, out var p)) price = p;
|
||||
}
|
||||
else if (line.StartsWith("TotalBids", StringComparison.OrdinalIgnoreCase) || line.StartsWith("BidsUsed", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var parts = line.Split(',', 2);
|
||||
if (parts.Length == 2 && int.TryParse(parts[1].Trim('"'), out var b)) bids = b;
|
||||
}
|
||||
else if (line.StartsWith("Winner", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var parts = line.Split(',', 2);
|
||||
if (parts.Length == 2) winner = parts[1].Trim('"');
|
||||
}
|
||||
else if (line.StartsWith("OriginalUrl", StringComparison.OrdinalIgnoreCase) || line.StartsWith("AuctionUrl", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var parts = line.Split(',', 2);
|
||||
if (parts.Length == 2) url = parts[1].Trim('"');
|
||||
}
|
||||
}
|
||||
var rec = new ClosedAuctionRecord { ProductName = product, FinalPrice = price, BidsUsed = bids, Winner = winner, AuctionUrl = url };
|
||||
var key = (rec.ProductName ?? ExtractProductFromFilename(f) ?? "<unknown>").Trim();
|
||||
if (!aggregated.ContainsKey(key)) aggregated[key] = new List<ClosedAuctionRecord>();
|
||||
aggregated[key].Add(rec);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
});
|
||||
|
||||
var stats = new List<object>();
|
||||
foreach (var kv in aggregated)
|
||||
{
|
||||
var list = kv.Value.Where(x => x.FinalPrice.HasValue || x.BidsUsed.HasValue).ToList();
|
||||
if (list.Count == 0) continue;
|
||||
var avgPrice = list.Where(x => x.FinalPrice.HasValue).Select(x => x.FinalPrice!.Value).DefaultIfEmpty(0).Average();
|
||||
var avgBids = list.Where(x => x.BidsUsed.HasValue).Select(x => x.BidsUsed!.Value).DefaultIfEmpty(0).Average();
|
||||
var winner = list.Where(x => !string.IsNullOrEmpty(x.Winner)).GroupBy(x => x.Winner).OrderByDescending(g => g.Count()).Select(g => g.Key).FirstOrDefault() ?? string.Empty;
|
||||
var example = list.FirstOrDefault(x => !string.IsNullOrEmpty(x.AuctionUrl))?.AuctionUrl ?? string.Empty;
|
||||
|
||||
stats.Add(new
|
||||
{
|
||||
ProductName = kv.Key,
|
||||
FinalPrice = avgPrice,
|
||||
Winner = winner,
|
||||
BidsUsed = (int)Math.Round(avgBids),
|
||||
AuctionUrl = example,
|
||||
Count = list.Count,
|
||||
AverageFinalPrice = avgPrice,
|
||||
AverageBidsUsed = avgBids
|
||||
});
|
||||
}
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
StatsDataGrid.ItemsSource = stats.OrderByDescending(s => (int)s.GetType().GetProperty("Count")!.GetValue(s)).ToList();
|
||||
StatsStatusText.Text = $"Caricati {stats.Count} prodotti ({files.Length} file analizzati)";
|
||||
ExportProgressBar.Visibility = Visibility.Collapsed;
|
||||
ExportProgressText.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatsStatusText.Text = "Errore caricamento statistiche";
|
||||
Log($"[ERRORE] Carica statistiche: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show(this, "Errore durante caricamento statistiche: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
ExportProgressBar.Visibility = Visibility.Collapsed;
|
||||
ExportProgressText.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private static string? ExtractProductFromFilename(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
var name = Path.GetFileNameWithoutExtension(path);
|
||||
var m = Regex.Match(name, @"auction_(.+)");
|
||||
if (m.Success)
|
||||
{
|
||||
var v = m.Groups[1].Value;
|
||||
if (Regex.IsMatch(v, "^\\d+$")) return null;
|
||||
return v.Replace('_', ' ');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
catch { return null; }
|
||||
}
|
||||
|
||||
private async void ApplyInsightsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBox.Show(this, "Funzionalità statistiche in sviluppo", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
|
||||
/* CODICE TEMPORANEAMENTE DISABILITATO
|
||||
try
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show(this, "Seleziona un'asta prima di applicare le raccomandazioni.", "Applica Raccomandazioni", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var optionsBuilder = new Microsoft.EntityFrameworkCore.DbContextOptionsBuilder<Data.StatisticsContext>();
|
||||
var dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "stats.db");
|
||||
optionsBuilder.UseSqlite($"Data Source={dbPath}");
|
||||
using var ctx = new Data.StatisticsContext(optionsBuilder.Options);
|
||||
var svc = new Services.StatsService(ctx);
|
||||
|
||||
var (recBids, recPrice) = await svc.GetRecommendationAsync(_selectedAuction.AuctionInfo.Name, _selectedAuction.AuctionInfo.OriginalUrl);
|
||||
_selectedAuction.MaxClicks = Math.Max(_selectedAuction.MaxClicks, recBids);
|
||||
_selectedAuction.MaxPrice = Math.Max(_selectedAuction.MaxPrice, recPrice);
|
||||
Log($"[OK] Raccomandazioni: MaxClicks={recBids}, MaxPrice={recPrice:F2} applicate a {_selectedAuction.Name}", LogLevel.Success);
|
||||
UpdateSelectedAuctionDetails(_selectedAuction);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] ApplyInsights: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show(this, "Errore applicazione raccomandazioni: " + ex.Message, "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private void FreeBidsStart_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBox.Show(this, "Funzionalità non ancora implementata", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
|
||||
private void FreeBidsStop_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MessageBox.Show(this, "Funzionalità non ancora implementata", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
Mimante/Core/EventHandlers/MainWindow.EventHandlers.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Stub event handlers for XAML binding - actual implementations are in dedicated partial files
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
// These methods exist only to satisfy XAML event bindings
|
||||
// The actual implementations are in the appropriate partial class files:
|
||||
// - MainWindow.ButtonHandlers.cs for button clicks
|
||||
// - MainWindow.EventHandlers.Browser.cs for browser events
|
||||
// - MainWindow.EventHandlers.Export.cs for export events
|
||||
// - MainWindow.EventHandlers.Settings.cs for settings events
|
||||
// - MainWindow.EventHandlers.Stats.cs for statistics events
|
||||
|
||||
private void MultiAuctionsGrid_PreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
// Optional: Add keyboard shortcuts for grid navigation
|
||||
}
|
||||
}
|
||||
}
|
||||
657
Mimante/Core/MainWindow.AuctionManagement.cs
Normal file
@@ -0,0 +1,657 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using AutoBidder.Models;
|
||||
using AutoBidder.ViewModels;
|
||||
using AutoBidder.Utilities;
|
||||
using AutoBidder.Services; // ? AGGIUNTO per RequestPriority e HtmlResponse
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Auction management: Add, Remove, Update
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private async Task AddAuctionById(string input)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(input))
|
||||
{
|
||||
MessageBox.Show("Input non valido!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
string auctionId;
|
||||
string? productName = null;
|
||||
string originalUrl;
|
||||
|
||||
// Verifica se è un URL o solo un ID
|
||||
if (input.Contains("bidoo.com") || input.Contains("http"))
|
||||
{
|
||||
// È un URL - estrai ID e nome prodotto dall'URL stesso
|
||||
originalUrl = input.Trim();
|
||||
auctionId = ExtractAuctionId(originalUrl);
|
||||
if (string.IsNullOrEmpty(auctionId))
|
||||
{
|
||||
MessageBox.Show("Impossibile estrarre ID dall'URL!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
productName = ExtractProductName(originalUrl);
|
||||
}
|
||||
else
|
||||
{
|
||||
// È solo un ID numerico - costruisci URL generico
|
||||
auctionId = input.Trim();
|
||||
originalUrl = $"https://it.bidoo.com/auction.php?a=asta_{auctionId}";
|
||||
}
|
||||
|
||||
// Verifica duplicati
|
||||
if (_auctionViewModels.Any(a => a.AuctionId == auctionId))
|
||||
{
|
||||
MessageBox.Show("Asta già monitorata!", "Duplicato", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
// ? MODIFICATO: Nome senza ID (già nella colonna separata)
|
||||
var displayName = string.IsNullOrEmpty(productName)
|
||||
? $"Asta {auctionId}"
|
||||
: DecodeAllHtmlEntities(productName);
|
||||
|
||||
// CARICA IMPOSTAZIONI PREDEFINITE SALVATE
|
||||
var settings = Utilities.SettingsManager.Load();
|
||||
|
||||
// ? Determina stato iniziale dalla configurazione
|
||||
bool isActive = false;
|
||||
bool isPaused = false;
|
||||
|
||||
switch (settings.DefaultNewAuctionState)
|
||||
{
|
||||
case "Active":
|
||||
isActive = true;
|
||||
isPaused = false;
|
||||
break;
|
||||
case "Paused":
|
||||
isActive = true;
|
||||
isPaused = true;
|
||||
break;
|
||||
case "Stopped":
|
||||
default:
|
||||
isActive = false;
|
||||
isPaused = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Crea model con valori dalle impostazioni salvate e stato configurato
|
||||
var auction = new AuctionInfo
|
||||
{
|
||||
AuctionId = auctionId,
|
||||
Name = DecodeAllHtmlEntities(displayName),
|
||||
OriginalUrl = originalUrl,
|
||||
BidBeforeDeadlineMs = settings.DefaultBidBeforeDeadlineMs,
|
||||
CheckAuctionOpenBeforeBid = settings.DefaultCheckAuctionOpenBeforeBid,
|
||||
IsActive = isActive,
|
||||
IsPaused = isPaused
|
||||
};
|
||||
|
||||
// Aggiungi al monitor
|
||||
_auctionMonitor.AddAuction(auction);
|
||||
|
||||
// Crea ViewModel con valori dalle impostazioni
|
||||
var vm = new AuctionViewModel(auction)
|
||||
{
|
||||
MinPrice = settings.DefaultMinPrice,
|
||||
MaxPrice = settings.DefaultMaxPrice,
|
||||
MaxClicks = settings.DefaultMaxClicks
|
||||
};
|
||||
_auctionViewModels.Add(vm);
|
||||
|
||||
// ? Auto-start del monitoraggio se l'asta è attiva e il monitoraggio è fermo
|
||||
if (isActive && !_isAutomationActive)
|
||||
{
|
||||
_auctionMonitor.Start();
|
||||
_isAutomationActive = true;
|
||||
Log($"[AUTO-START] Monitoraggio avviato automaticamente per nuova asta: {vm.Name}", LogLevel.Info);
|
||||
}
|
||||
|
||||
SaveAuctions();
|
||||
UpdateTotalCount();
|
||||
UpdateGlobalControlButtons();
|
||||
|
||||
var stateText = isActive ? (isPaused ? "Paused" : "Active") : "Stopped";
|
||||
Log($"[ADD] Asta aggiunta con stato={stateText}, Anticipo={settings.DefaultBidBeforeDeadlineMs}ms", Utilities.LogLevel.Info);
|
||||
|
||||
// ? NUOVO: Se il nome non è stato estratto, recuperalo in background DOPO l'aggiunta
|
||||
if (string.IsNullOrEmpty(productName))
|
||||
{
|
||||
_ = FetchAuctionNameInBackgroundAsync(auction, vm);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"Errore aggiunta asta: {ex.Message}");
|
||||
MessageBox.Show($"Errore: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Recupera il nome dell'asta in background e aggiorna l'UI quando completa
|
||||
/// </summary>
|
||||
private async Task FetchAuctionNameInBackgroundAsync(AuctionInfo auction, AuctionViewModel vm)
|
||||
{
|
||||
try
|
||||
{
|
||||
// ? USA IL SERVIZIO CENTRALIZZATO invece di HttpClient diretto
|
||||
var response = await _htmlCacheService.GetHtmlAsync(
|
||||
auction.OriginalUrl,
|
||||
RequestPriority.Normal,
|
||||
bypassCache: false // Usa cache se disponibile
|
||||
);
|
||||
|
||||
if (!response.Success)
|
||||
{
|
||||
Log($"[WARN] Impossibile recuperare nome per asta {auction.AuctionId}: {response.Error}", LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Estrai nome dal <title>
|
||||
var match = System.Text.RegularExpressions.Regex.Match(response.Html, @"<title>([^<]+)</title>");
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
var productName = match.Groups[1].Value.Trim().Replace(" - Bidoo", "");
|
||||
// ? Decodifica entity HTML (incluse quelle non standard)
|
||||
productName = DecodeAllHtmlEntities(productName);
|
||||
// ? MODIFICATO: Nome senza ID
|
||||
var newName = productName;
|
||||
|
||||
// Aggiorna il nome su thread UI
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
auction.Name = newName;
|
||||
// Forza refresh della griglia per mostrare il nuovo nome
|
||||
var tempSource = MultiAuctionsGrid.ItemsSource;
|
||||
MultiAuctionsGrid.ItemsSource = null;
|
||||
MultiAuctionsGrid.ItemsSource = tempSource;
|
||||
SaveAuctions(); // Salva il nome aggiornato
|
||||
Log($"[NAME] Nome recuperato per asta {auction.AuctionId}: {productName}{(response.FromCache ? " (cached)" : "")}", LogLevel.Info);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[WARN] Nome non trovato nell'HTML per asta {auction.AuctionId}", LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[WARN] Errore recupero nome per asta {auction.AuctionId}: {ex.Message}", LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodifica tutte le entity HTML, incluse quelle non standard come +
|
||||
/// </summary>
|
||||
private string DecodeAllHtmlEntities(string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return text;
|
||||
|
||||
// Prima decodifica entity standard
|
||||
var decoded = System.Net.WebUtility.HtmlDecode(text);
|
||||
|
||||
// ? Poi sostituisci entity non standard che WebUtility.HtmlDecode non gestisce
|
||||
decoded = decoded.Replace("+", "+");
|
||||
decoded = decoded.Replace("=", "=");
|
||||
decoded = decoded.Replace("−", "-");
|
||||
decoded = decoded.Replace("×", "×");
|
||||
decoded = decoded.Replace("÷", "÷");
|
||||
decoded = decoded.Replace("%", "%");
|
||||
decoded = decoded.Replace("$", "$");
|
||||
decoded = decoded.Replace("€", "€");
|
||||
decoded = decoded.Replace("£", "£");
|
||||
|
||||
return decoded;
|
||||
}
|
||||
|
||||
private async Task AddAuctionFromUrl(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!IsValidAuctionUrl(url))
|
||||
{
|
||||
MessageBox.Show("URL asta non valido!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var auctionId = ExtractAuctionId(url);
|
||||
if (string.IsNullOrEmpty(auctionId))
|
||||
{
|
||||
MessageBox.Show("Impossibile estrarre ID asta!", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Verifica duplicati
|
||||
if (_auctionViewModels.Any(a => a.AuctionId == auctionId))
|
||||
{
|
||||
MessageBox.Show("Asta già monitorata!", "Duplicato", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch nome (opzionale)
|
||||
var name = $"Asta {auctionId}";
|
||||
try
|
||||
{
|
||||
// ? USA IL SERVIZIO CENTRALIZZATO
|
||||
var response = await _htmlCacheService.GetHtmlAsync(url, RequestPriority.Normal);
|
||||
|
||||
if (response.Success)
|
||||
{
|
||||
var match2 = System.Text.RegularExpressions.Regex.Match(response.Html, @"<title>([^<]+)</title>");
|
||||
if (match2.Success)
|
||||
{
|
||||
name = DecodeAllHtmlEntities(match2.Groups[1].Value.Trim().Replace(" - Bidoo", ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
|
||||
// CARICA IMPOSTAZIONI PREDEFINITE SALVATE
|
||||
var settings = Utilities.SettingsManager.Load();
|
||||
|
||||
// ? Determina stato iniziale dalla configurazione
|
||||
bool isActive = false;
|
||||
bool isPaused = false;
|
||||
|
||||
switch (settings.DefaultNewAuctionState)
|
||||
{
|
||||
case "Active":
|
||||
isActive = true;
|
||||
isPaused = false;
|
||||
break;
|
||||
case "Paused":
|
||||
isActive = true;
|
||||
isPaused = true;
|
||||
break;
|
||||
case "Stopped":
|
||||
default:
|
||||
isActive = false;
|
||||
isPaused = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// Crea model con valori dalle impostazioni salvate e stato configurato
|
||||
var auction = new AuctionInfo
|
||||
{
|
||||
AuctionId = auctionId,
|
||||
Name = DecodeAllHtmlEntities(name),
|
||||
OriginalUrl = url,
|
||||
BidBeforeDeadlineMs = settings.DefaultBidBeforeDeadlineMs,
|
||||
CheckAuctionOpenBeforeBid = settings.DefaultCheckAuctionOpenBeforeBid,
|
||||
IsActive = isActive,
|
||||
IsPaused = isPaused
|
||||
};
|
||||
|
||||
// Aggiungi al monitor
|
||||
_auctionMonitor.AddAuction(auction);
|
||||
|
||||
// Crea ViewModel con valori dalle impostazioni
|
||||
var vm = new AuctionViewModel(auction)
|
||||
{
|
||||
MinPrice = settings.DefaultMinPrice,
|
||||
MaxPrice = settings.DefaultMaxPrice,
|
||||
MaxClicks = settings.DefaultMaxClicks
|
||||
};
|
||||
_auctionViewModels.Add(vm);
|
||||
|
||||
// ? Auto-start del monitoraggio se l'asta è attiva e il monitoraggio è fermo
|
||||
if (isActive && !_isAutomationActive)
|
||||
{
|
||||
_auctionMonitor.Start();
|
||||
_isAutomationActive = true;
|
||||
Log($"[AUTO-START] Monitoraggio avviato automaticamente per nuova asta: {vm.Name}", LogLevel.Info);
|
||||
}
|
||||
|
||||
SaveAuctions();
|
||||
UpdateTotalCount();
|
||||
UpdateGlobalControlButtons();
|
||||
|
||||
var stateText = isActive ? (isPaused ? "Paused" : "Active") : "Stopped";
|
||||
Log($"[ADD] Asta aggiunta con stato={stateText}, Anticipo={settings.DefaultBidBeforeDeadlineMs}ms", Utilities.LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Errore aggiunta asta: {ex.Message}");
|
||||
MessageBox.Show($"Errore: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiorna manualmente il nome di un'asta recuperandolo dall'HTML
|
||||
/// </summary>
|
||||
public async Task RefreshAuctionNameAsync(AuctionViewModel vm)
|
||||
{
|
||||
if (vm == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
Log($"[NAME REFRESH] Aggiornamento nome per: {vm.Name}", LogLevel.Info);
|
||||
await FetchAuctionNameInBackgroundAsync(vm.AuctionInfo, vm);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Refresh nome asta: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Controlla se ci sono aste con nomi generici e prova a recuperarli dopo un delay
|
||||
/// </summary>
|
||||
private async Task RetryFailedAuctionNamesAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Aspetta 30 secondi prima di ritentare (dà tempo alle altre richieste di completare)
|
||||
await System.Threading.Tasks.Task.Delay(TimeSpan.FromSeconds(30));
|
||||
|
||||
// Trova aste con nomi generici "Asta XXXX"
|
||||
var auctionsWithGenericNames = _auctionViewModels
|
||||
.Where(vm => vm.Name.StartsWith("Asta ") && !vm.Name.Contains("Shop") && !vm.Name.Contains("€"))
|
||||
.ToList();
|
||||
|
||||
if (auctionsWithGenericNames.Count > 0)
|
||||
{
|
||||
Log($"[NAME RETRY] Trovate {auctionsWithGenericNames.Count} aste con nomi generici. Ritento recupero...", LogLevel.Info);
|
||||
|
||||
// Ritenta il recupero per ognuna (con delay tra una e l'altra per non sovraccaricare)
|
||||
foreach (var vm in auctionsWithGenericNames)
|
||||
{
|
||||
await FetchAuctionNameInBackgroundAsync(vm.AuctionInfo, vm);
|
||||
await System.Threading.Tasks.Task.Delay(2000); // 2 secondi tra una richiesta e l'altra
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[WARN] Errore retry nomi aste: {ex.Message}", LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveAuctions()
|
||||
{
|
||||
try
|
||||
{
|
||||
var auctions = _auctionMonitor.GetAuctions();
|
||||
Utilities.PersistenceManager.SaveAuctions(auctions);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Errore salvataggio: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadSavedAuctions()
|
||||
{
|
||||
try
|
||||
{
|
||||
// ? Carica impostazioni
|
||||
var settings = Utilities.SettingsManager.Load();
|
||||
|
||||
// Ottieni username corrente dalla sessione per ripristinare IsMyBid
|
||||
var session = _auctionMonitor.GetSession();
|
||||
var currentUsername = session?.Username ?? string.Empty;
|
||||
|
||||
var auctions = Utilities.PersistenceManager.LoadAuctions();
|
||||
foreach (var auction in auctions)
|
||||
{
|
||||
// Protezione: rimuovi eventuali BidHistory null
|
||||
auction.BidHistory = auction.BidHistory?.Where(b => b != null).ToList() ?? new System.Collections.Generic.List<BidHistory>();
|
||||
|
||||
// ? Decode HTML entities (incluse quelle non standard)
|
||||
try { auction.Name = DecodeAllHtmlEntities(auction.Name ?? string.Empty); } catch { }
|
||||
|
||||
// ? Ripristina IsMyBid per tutte le puntate in RecentBids
|
||||
if (auction.RecentBids != null && auction.RecentBids.Count > 0 && !string.IsNullOrEmpty(currentUsername))
|
||||
{
|
||||
foreach (var bid in auction.RecentBids)
|
||||
{
|
||||
bid.IsMyBid = bid.Username.Equals(currentUsername, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ? NUOVO: Gestione stato in base a RememberAuctionStates
|
||||
if (settings.RememberAuctionStates)
|
||||
{
|
||||
// MODO 1: Ripristina lo stato salvato di ogni asta (IsActive e IsPaused vengono dal file salvato)
|
||||
// Non serve fare nulla, lo stato è già quello salvato nel file
|
||||
}
|
||||
else
|
||||
{
|
||||
// MODO 2: Applica DefaultStartAuctionsOnLoad a tutte le aste
|
||||
var loadState = settings.DefaultStartAuctionsOnLoad;
|
||||
switch (loadState)
|
||||
{
|
||||
case "Active":
|
||||
auction.IsActive = true;
|
||||
auction.IsPaused = false;
|
||||
break;
|
||||
case "Paused":
|
||||
auction.IsActive = true;
|
||||
auction.IsPaused = true;
|
||||
break;
|
||||
case "Stopped":
|
||||
default:
|
||||
auction.IsActive = false;
|
||||
auction.IsPaused = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_auctionMonitor.AddAuction(auction);
|
||||
var vm = new AuctionViewModel(auction);
|
||||
_auctionViewModels.Add(vm);
|
||||
}
|
||||
|
||||
// ? Avvia monitoraggio se ci sono aste in stato Active O Paused
|
||||
bool hasActiveOrPausedAuctions = auctions.Any(a => a.IsActive);
|
||||
|
||||
if (hasActiveOrPausedAuctions && auctions.Count > 0)
|
||||
{
|
||||
_auctionMonitor.Start();
|
||||
_isAutomationActive = true;
|
||||
|
||||
if (settings.RememberAuctionStates)
|
||||
{
|
||||
var activeCount = auctions.Count(a => a.IsActive && !a.IsPaused);
|
||||
var pausedCount = auctions.Count(a => a.IsActive && a.IsPaused);
|
||||
Log($"[AUTO-START] Monitoraggio avviato: {activeCount} attive, {pausedCount} in pausa (stati ripristinati)", LogLevel.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
var loadState = settings.DefaultStartAuctionsOnLoad;
|
||||
if (loadState == "Active")
|
||||
{
|
||||
Log($"[AUTO-START] Monitoraggio avviato automaticamente per {auctions.Count} aste caricate in stato attivo", LogLevel.Info);
|
||||
}
|
||||
else if (loadState == "Paused")
|
||||
{
|
||||
Log($"[AUTO-START] Monitoraggio avviato automaticamente per {auctions.Count} aste caricate in pausa", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UpdateTotalCount();
|
||||
UpdateGlobalControlButtons();
|
||||
|
||||
// Log sempre mostrato (anche con 0 aste)
|
||||
if (auctions.Count > 0)
|
||||
{
|
||||
if (settings.RememberAuctionStates)
|
||||
{
|
||||
Log($"[LOAD] {auctions.Count} aste caricate con stati individuali ripristinati", LogLevel.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[LOAD] {auctions.Count} aste caricate con stato iniziale: {settings.DefaultStartAuctionsOnLoad}", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[LOAD] Nessuna asta salvata", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Caricamento aste: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiorna i dettagli dell'asta selezionata nel pannello Info Prodotto
|
||||
/// </summary>
|
||||
private void UpdateSelectedAuctionDetails(AuctionViewModel? vm)
|
||||
{
|
||||
if (vm == null || vm.AuctionInfo == null)
|
||||
{
|
||||
// Resetta campi se nessuna asta selezionata
|
||||
AuctionMonitor.ProductBuyNowPriceText.Text = "-";
|
||||
AuctionMonitor.ProductShippingCostText.Text = "-";
|
||||
AuctionMonitor.ProductWinLimitText.Text = "-";
|
||||
return;
|
||||
}
|
||||
|
||||
var auction = vm.AuctionInfo;
|
||||
|
||||
// CARICA AUTOMATICAMENTE INFO PRODOTTO SE NON PRESENTI
|
||||
if (!auction.BuyNowPrice.HasValue && !auction.ShippingCost.HasValue)
|
||||
{
|
||||
// Carica in background senza bloccare l'UI
|
||||
_ = LoadProductInfoInBackgroundAsync(auction);
|
||||
}
|
||||
|
||||
// Aggiorna i campi delle impostazioni
|
||||
UpdateAuctionSettingsDisplay(vm);
|
||||
|
||||
// Aggiorna Valore (Compra Subito)
|
||||
if (auction.BuyNowPrice.HasValue)
|
||||
{
|
||||
AuctionMonitor.ProductBuyNowPriceText.Text = $"{auction.BuyNowPrice.Value:F2}€";
|
||||
}
|
||||
else
|
||||
{
|
||||
AuctionMonitor.ProductBuyNowPriceText.Text = "-";
|
||||
}
|
||||
|
||||
// Aggiorna Spese di Spedizione
|
||||
if (auction.ShippingCost.HasValue)
|
||||
{
|
||||
AuctionMonitor.ProductShippingCostText.Text = $"{auction.ShippingCost.Value:F2}€";
|
||||
}
|
||||
else
|
||||
{
|
||||
AuctionMonitor.ProductShippingCostText.Text = "-";
|
||||
}
|
||||
|
||||
// Aggiorna Limiti di Vincita
|
||||
if (auction.HasWinLimit && !string.IsNullOrWhiteSpace(auction.WinLimitDescription))
|
||||
{
|
||||
AuctionMonitor.ProductWinLimitText.Text = auction.WinLimitDescription;
|
||||
}
|
||||
else if (!auction.HasWinLimit)
|
||||
{
|
||||
AuctionMonitor.ProductWinLimitText.Text = "Nessun limite";
|
||||
}
|
||||
else
|
||||
{
|
||||
AuctionMonitor.ProductWinLimitText.Text = "-";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carica le informazioni del prodotto (e nome se generico) in background quando selezioni un'asta
|
||||
/// </summary>
|
||||
private async System.Threading.Tasks.Task LoadProductInfoInBackgroundAsync(AuctionInfo auction)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool hasGenericName = auction.Name.StartsWith("Asta ") &&
|
||||
!auction.Name.Contains("Shop") &&
|
||||
!auction.Name.Contains("€") &&
|
||||
!auction.Name.Contains("Buono") &&
|
||||
!auction.Name.Contains("Carburante");
|
||||
|
||||
Log($"[PRODUCT INFO] Caricamento automatico per: {auction.Name}{(hasGenericName ? " (+ nome generico)" : "")}", Utilities.LogLevel.Info);
|
||||
|
||||
// ? USA IL SERVIZIO CENTRALIZZATO
|
||||
var response = await _htmlCacheService.GetHtmlAsync(
|
||||
auction.OriginalUrl,
|
||||
RequestPriority.High, // Priorità alta per info prodotto
|
||||
bypassCache: false
|
||||
);
|
||||
|
||||
if (!response.Success)
|
||||
{
|
||||
Log($"[PRODUCT INFO] Errore caricamento: {response.Error}", Utilities.LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
bool updated = false;
|
||||
|
||||
// 1. ? Se nome generico, estrai nome reale dal <title>
|
||||
if (hasGenericName)
|
||||
{
|
||||
var matchTitle = System.Text.RegularExpressions.Regex.Match(response.Html, @"<title>([^<]+)</title>");
|
||||
if (matchTitle.Success)
|
||||
{
|
||||
var productName = matchTitle.Groups[1].Value.Trim().Replace(" - Bidoo", "");
|
||||
productName = DecodeAllHtmlEntities(productName);
|
||||
// ? MODIFICATO: Nome senza ID
|
||||
var newName = productName;
|
||||
|
||||
auction.Name = newName;
|
||||
updated = true;
|
||||
Log($"[NAME] Nome recuperato: {productName}{(response.FromCache ? " (cached)" : "")}", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. ? Estrai informazioni prodotto (prezzo, spedizione, limiti)
|
||||
var extracted = Utilities.ProductValueCalculator.ExtractProductInfo(response.Html, auction);
|
||||
if (extracted)
|
||||
{
|
||||
updated = true;
|
||||
Log($"[PRODUCT INFO] Valore={auction.BuyNowPrice:F2}€, Spedizione={auction.ShippingCost:F2}€{(response.FromCache ? " (cached)" : "")}", Utilities.LogLevel.Success);
|
||||
}
|
||||
|
||||
// 3. ? Salva e aggiorna UI solo se qualcosa è cambiato
|
||||
if (updated)
|
||||
{
|
||||
SaveAuctions();
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
// Refresh griglia per mostrare nome aggiornato
|
||||
if (hasGenericName)
|
||||
{
|
||||
var tempSource = MultiAuctionsGrid.ItemsSource;
|
||||
MultiAuctionsGrid.ItemsSource = null;
|
||||
MultiAuctionsGrid.ItemsSource = tempSource;
|
||||
}
|
||||
|
||||
// Refresh dettagli se ancora selezionata
|
||||
if (_selectedAuction != null && _selectedAuction.AuctionId == auction.AuctionId)
|
||||
{
|
||||
UpdateSelectedAuctionDetails(_selectedAuction);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[PRODUCT INFO] Errore caricamento: {ex.Message}", Utilities.LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
642
Mimante/Core/MainWindow.ButtonHandlers.cs
Normal file
@@ -0,0 +1,642 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using AutoBidder.Dialogs;
|
||||
using AutoBidder.Utilities;
|
||||
using AutoBidder.ViewModels;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Button click event handlers for auction operations
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private void StartButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_isAutomationActive)
|
||||
{
|
||||
// Avvia il monitoraggio globale
|
||||
_auctionMonitor.Start();
|
||||
_isAutomationActive = true;
|
||||
Log("[START] Monitoraggio avviato!", LogLevel.Success);
|
||||
}
|
||||
|
||||
// Attiva e riprendi tutte le aste
|
||||
foreach (var vm in _auctionViewModels)
|
||||
{
|
||||
if (!vm.IsActive)
|
||||
{
|
||||
vm.IsActive = true;
|
||||
}
|
||||
vm.IsPaused = false;
|
||||
}
|
||||
|
||||
if (sender != null) // Solo se chiamato dall'utente, non internamente
|
||||
{
|
||||
Log("[START ALL] Tutte le aste avviate/riprese", LogLevel.Info);
|
||||
}
|
||||
|
||||
// ? Salva gli stati aggiornati su disco
|
||||
SaveAuctions();
|
||||
UpdateGlobalControlButtons();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Avvio: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void StopButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Ferma tutte le aste
|
||||
foreach (var vm in _auctionViewModels)
|
||||
{
|
||||
vm.IsActive = false;
|
||||
}
|
||||
|
||||
// Ferma il monitoraggio globale
|
||||
if (_isAutomationActive)
|
||||
{
|
||||
_auctionMonitor.Stop();
|
||||
_isAutomationActive = false;
|
||||
}
|
||||
|
||||
// ? Salva gli stati aggiornati su disco
|
||||
SaveAuctions();
|
||||
UpdateGlobalControlButtons();
|
||||
|
||||
if (sender != null) // Solo se chiamato dall'utente
|
||||
{
|
||||
Log("[STOP ALL] Monitoraggio fermato e tutte le aste arrestate", LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE STOP] {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void PauseAllButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
foreach (var vm in _auctionViewModels.Where(a => a.IsActive))
|
||||
{
|
||||
vm.IsPaused = true;
|
||||
}
|
||||
|
||||
// ? Salva gli stati aggiornati su disco
|
||||
SaveAuctions();
|
||||
UpdateGlobalControlButtons();
|
||||
|
||||
if (sender != null) // Solo se chiamato dall'utente
|
||||
{
|
||||
Log("[PAUSE ALL] Tutte le aste in pausa", LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Pausa globale: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void AddUrlButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dialog = new AddAuctionSimpleDialog();
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
var raw = dialog.AuctionId ?? string.Empty;
|
||||
var parts = Regex.Split(raw, "[\r\n;]+|\\s+")
|
||||
.Select(p => p.Trim())
|
||||
.Where(p => !string.IsNullOrWhiteSpace(p))
|
||||
.ToList();
|
||||
|
||||
if (parts.Count == 0)
|
||||
{
|
||||
MessageBox.Show("Nessun URL/ID valido trovato.", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var added = 0;
|
||||
var skipped = new System.Collections.Generic.List<string>();
|
||||
|
||||
foreach (var part in parts)
|
||||
{
|
||||
try
|
||||
{
|
||||
var input = part;
|
||||
string? aid = null;
|
||||
if (input.Contains("bidoo.com") || input.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
aid = ExtractAuctionId(input);
|
||||
}
|
||||
else
|
||||
{
|
||||
aid = input;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(aid) && _auctionViewModels.Any(a => a.AuctionId == aid))
|
||||
{
|
||||
skipped.Add(part + " (duplicato)");
|
||||
continue;
|
||||
}
|
||||
|
||||
await AddAuctionById(input);
|
||||
added++;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
skipped.Add(part + " (errore: " + ex.Message + ")");
|
||||
}
|
||||
}
|
||||
|
||||
UpdateGlobalControlButtons();
|
||||
|
||||
var summary = $"Aggiunte: {added}. Skipped: {skipped.Count}.";
|
||||
if (skipped.Count > 0)
|
||||
summary += "\nDettagli: " + string.Join("; ", skipped.Take(10));
|
||||
|
||||
MessageBox.Show(summary, "Aggiunta aste", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
|
||||
// ? RIMOSSO: Retry automatico ora avviene alla selezione on-demand
|
||||
// Le aste con nome generico vengono aggiornate automaticamente quando l'utente le seleziona
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveUrlButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var auctionName = _selectedAuction.Name;
|
||||
var auctionId = _selectedAuction.AuctionId;
|
||||
|
||||
// Salva l'indice corrente prima di rimuovere
|
||||
var currentIndex = _auctionViewModels.IndexOf(_selectedAuction);
|
||||
|
||||
// Conferma rimozione
|
||||
var result = MessageBox.Show(
|
||||
$"Rimuovere l'asta dal monitoraggio?\n\n{auctionName}\n(ID: {auctionId})\n\nL'asta verrà eliminata dalla lista e non sarà più monitorata.",
|
||||
"Conferma Rimozione",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Question);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
{
|
||||
Log($"[REMOVE] Rimozione annullata: {auctionName}", LogLevel.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Rimuove dal monitor
|
||||
_auctionMonitor.RemoveAuction(auctionId);
|
||||
|
||||
// Rimuove dal ViewModel
|
||||
_auctionViewModels.Remove(_selectedAuction);
|
||||
|
||||
// Salva modifiche
|
||||
SaveAuctions();
|
||||
UpdateTotalCount();
|
||||
UpdateGlobalControlButtons();
|
||||
|
||||
Log($"[REMOVE] Asta rimossa: {auctionName} (ID: {auctionId})", LogLevel.Success);
|
||||
|
||||
// ? NUOVO: Sposta il focus sulla riga successiva
|
||||
if (_auctionViewModels.Count > 0)
|
||||
{
|
||||
// Se c'è ancora almeno un'asta nella lista
|
||||
int newIndex;
|
||||
|
||||
if (currentIndex >= _auctionViewModels.Count)
|
||||
{
|
||||
// L'asta rimossa era l'ultima, seleziona la nuova ultima
|
||||
newIndex = _auctionViewModels.Count - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Seleziona l'asta che ora si trova nella stessa posizione
|
||||
newIndex = currentIndex;
|
||||
}
|
||||
|
||||
// Seleziona l'asta
|
||||
MultiAuctionsGrid.SelectedIndex = newIndex;
|
||||
_selectedAuction = _auctionViewModels[newIndex];
|
||||
|
||||
// ? FIX: Salva il nome della NUOVA asta selezionata per il log
|
||||
var newAuctionName = _selectedAuction?.Name ?? "Sconosciuta";
|
||||
|
||||
// Forza il focus sulla griglia dopo un breve delay per permettere alla UI di aggiornarsi
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
MultiAuctionsGrid.Focus();
|
||||
|
||||
// Scroll fino alla riga selezionata per assicurarsi che sia visibile
|
||||
if (MultiAuctionsGrid.SelectedItem != null)
|
||||
{
|
||||
MultiAuctionsGrid.ScrollIntoView(MultiAuctionsGrid.SelectedItem);
|
||||
}
|
||||
|
||||
// ? FIX: Usa la variabile locale invece di _selectedAuction.Name
|
||||
Log($"[FOCUS] Focus spostato su: {newAuctionName}", LogLevel.Info);
|
||||
}), System.Windows.Threading.DispatcherPriority.Background);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nessuna asta rimasta, reset selezione
|
||||
_selectedAuction = null;
|
||||
Log($"[REMOVE] Nessuna asta rimasta nella lista", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERROR] Errore rimozione asta: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante la rimozione:\n{ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveAllButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_auctionViewModels.Count == 0)
|
||||
{
|
||||
MessageBox.Show("Non ci sono aste da rimuovere", "Lista Vuota", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var count = _auctionViewModels.Count;
|
||||
|
||||
// Conferma rimozione
|
||||
var result = MessageBox.Show(
|
||||
$"Rimuovere TUTTE le aste dal monitoraggio?\n\nSono presenti {count} aste monitorate.\n\nTutte le aste verranno eliminate dalla lista e non saranno più monitorate.",
|
||||
"Conferma Rimozione Totale",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Warning);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
{
|
||||
Log($"[REMOVE ALL] Rimozione annullata", LogLevel.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Ferma il monitoraggio se attivo
|
||||
if (_isAutomationActive)
|
||||
{
|
||||
_auctionMonitor.Stop();
|
||||
_isAutomationActive = false;
|
||||
Log("[STOP] Monitoraggio fermato prima della rimozione totale", LogLevel.Info);
|
||||
}
|
||||
|
||||
// Rimuove tutte le aste dal monitor e dal ViewModel
|
||||
var auctionsToRemove = _auctionViewModels.ToList(); // Copia per evitare modifiche durante iterazione
|
||||
|
||||
foreach (var auction in auctionsToRemove)
|
||||
{
|
||||
_auctionMonitor.RemoveAuction(auction.AuctionId);
|
||||
}
|
||||
|
||||
// Pulisci la lista ViewModel
|
||||
_auctionViewModels.Clear();
|
||||
|
||||
// Resetta selezione
|
||||
_selectedAuction = null;
|
||||
|
||||
// Salva modifiche
|
||||
SaveAuctions();
|
||||
UpdateTotalCount();
|
||||
UpdateGlobalControlButtons();
|
||||
|
||||
Log($"[REMOVE ALL] Tutte le aste rimosse: {count} aste eliminate", LogLevel.Success);
|
||||
|
||||
MessageBox.Show($"Tutte le {count} aste sono state rimosse dal monitoraggio.", "Rimozione Completata", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERROR] Errore rimozione totale: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante la rimozione delle aste: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void CopyAuctionUrlButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"Seleziona un'asta dalla griglia prima di copiare l'URL.",
|
||||
"Nessuna Asta Selezionata",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information);
|
||||
Log("[INFO] Tentativo di copia URL senza asta selezionata", LogLevel.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
var url = _selectedAuction.AuctionInfo.OriginalUrl;
|
||||
if (string.IsNullOrEmpty(url))
|
||||
url = $"https://it.bidoo.com/auction.php?a=asta_{_selectedAuction.AuctionId}";
|
||||
|
||||
// Tenta di copiare con retry mechanism
|
||||
const int maxAttempts = 3;
|
||||
const int delayMs = 50;
|
||||
|
||||
for (int attempt = 1; attempt <= maxAttempts; attempt++)
|
||||
{
|
||||
try
|
||||
{
|
||||
Clipboard.SetText(url);
|
||||
Log("URL copiato negli appunti", LogLevel.Success);
|
||||
return; // Successo, esci
|
||||
}
|
||||
catch (System.Runtime.InteropServices.COMException ex) when (ex.ErrorCode == unchecked((int)0x800401D0)) // CLIPBRD_E_CANT_OPEN
|
||||
{
|
||||
if (attempt < maxAttempts)
|
||||
{
|
||||
// Clipboard occupato, riprova dopo un breve delay
|
||||
System.Threading.Thread.Sleep(delayMs);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ultimo tentativo fallito
|
||||
Log($"[WARN] Clipboard temporaneamente occupato. Il testo potrebbe essere stato copiato.", LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Altri errori
|
||||
Log($"[ERRORE] Impossibile copiare URL: {ex.Message}", LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenAuctionInternalButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var url = _selectedAuction.AuctionInfo.OriginalUrl;
|
||||
if (string.IsNullOrEmpty(url))
|
||||
url = $"https://it.bidoo.com/auction.php?a=asta_{_selectedAuction.AuctionId}";
|
||||
|
||||
// Naviga alla scheda Browser
|
||||
TabBrowser.IsChecked = true;
|
||||
|
||||
// Naviga all'URL
|
||||
if (EmbeddedWebView?.CoreWebView2 != null)
|
||||
{
|
||||
EmbeddedWebView.CoreWebView2.Navigate(url);
|
||||
Log($"[BROWSER] Apertura asta nel browser interno: {_selectedAuction.Name}", LogLevel.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[WARN] Browser interno non ancora inizializzato", LogLevel.Warning);
|
||||
MessageBox.Show("Il browser interno non è ancora pronto.\nRiprova tra qualche secondo.", "Browser", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Apertura nel browser interno: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante l'apertura: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenAuctionExternalButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var url = _selectedAuction.AuctionInfo.OriginalUrl;
|
||||
if (string.IsNullOrEmpty(url))
|
||||
url = $"https://it.bidoo.com/auction.php?a=asta_{_selectedAuction.AuctionId}";
|
||||
|
||||
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = url,
|
||||
UseShellExecute = true
|
||||
});
|
||||
|
||||
Log($"[BROWSER] Apertura asta nel browser esterno: {_selectedAuction.Name}", LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Apertura nel browser esterno: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante l'apertura: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportAuctionButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
MessageBox.Show(
|
||||
$"Esportazione singola asta:\n\n{_selectedAuction.Name}\n(ID: {_selectedAuction.AuctionId})\n\nFunzionalità in sviluppo.\nUsa 'Esporta' dalla toolbar per esportare tutte le aste.",
|
||||
"Export Asta",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information);
|
||||
|
||||
Log($"[INFO] Richiesto export singolo per asta: {_selectedAuction.Name} (funzionalità in sviluppo)", LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Export asta: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private async void RefreshProductInfoButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
var auction = _selectedAuction.AuctionInfo;
|
||||
|
||||
// Verifica che ci siano le info prodotto caricate
|
||||
if (!auction.BuyNowPrice.HasValue)
|
||||
{
|
||||
MessageBox.Show(
|
||||
"Informazioni prodotto non disponibili.\n\n" +
|
||||
"Il sistema le sta caricando automaticamente.\n" +
|
||||
"Riprova tra qualche secondo.",
|
||||
"Info Prodotto Mancanti",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
// Feedback visivo
|
||||
AuctionMonitor.RefreshProductInfoButton.IsEnabled = false;
|
||||
|
||||
// CALCOLA LIMITI SUGGERITI (CONSERVATIVI)
|
||||
double buyNowPrice = auction.BuyNowPrice.Value;
|
||||
double shippingCost = auction.ShippingCost ?? 0;
|
||||
double totalValue = buyNowPrice + shippingCost;
|
||||
|
||||
// Max EUR = 40% del valore TOTALE (più conservativo del 50%)
|
||||
double suggestedMaxPrice = totalValue * 0.40;
|
||||
suggestedMaxPrice = Math.Round(suggestedMaxPrice, 2);
|
||||
|
||||
// CALCOLA MAX CLICKS (numero massimo puntate conservativo)
|
||||
// Formula: (Valore Totale - Max EUR) / 0.20€ per puntata
|
||||
// Poi riduciamo del 20% per maggiore margine di sicurezza
|
||||
int maxClicksTheoretical = (int)Math.Floor((totalValue - suggestedMaxPrice) / 0.20);
|
||||
int suggestedMaxClicks = (int)Math.Floor(maxClicksTheoretical * 0.80); // 80% del teorico
|
||||
|
||||
// Minimo 10 puntate per dare comunque una chance
|
||||
if (suggestedMaxClicks < 10) suggestedMaxClicks = 10;
|
||||
|
||||
Log($"[LIMITI] Valore={buyNowPrice:F2}€ + Extra={shippingCost:F2}€ = Tot={totalValue:F2}€ ? MaxEUR={suggestedMaxPrice:F2}€ (40%), MaxClicks={suggestedMaxClicks}", LogLevel.Info);
|
||||
|
||||
// CHIEDI CONFERMA
|
||||
var result = MessageBox.Show(
|
||||
$"Limiti suggeriti (conservativi):\n\n" +
|
||||
$"Max EUR: {suggestedMaxPrice:F2}€\n" +
|
||||
$"Max Clicks: {suggestedMaxClicks}\n\n" +
|
||||
$"Applicare questi valori?",
|
||||
"Conferma Limiti",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Question);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
{
|
||||
Log($"[LIMITI] Annullato dall'utente", LogLevel.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
// APPLICA I LIMITI
|
||||
_selectedAuction.MaxPrice = suggestedMaxPrice;
|
||||
_selectedAuction.MaxClicks = suggestedMaxClicks;
|
||||
|
||||
// AGGIORNA UI
|
||||
UpdateAuctionSettingsDisplay(_selectedAuction);
|
||||
|
||||
// SALVA
|
||||
SaveAuctions();
|
||||
|
||||
Log($"[LIMITI] Applicati: MaxEUR={suggestedMaxPrice:F2}€, MaxClicks={suggestedMaxClicks}", LogLevel.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Calcolo limiti: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante il calcolo dei limiti:\n\n{ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
finally
|
||||
{
|
||||
AuctionMonitor.RefreshProductInfoButton.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sposta l'asta selezionata verso l'alto nell'elenco
|
||||
/// </summary>
|
||||
private void MoveUpButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var currentIndex = _auctionViewModels.IndexOf(_selectedAuction);
|
||||
|
||||
if (currentIndex <= 0)
|
||||
{
|
||||
// Già in cima o non trovata
|
||||
Log($"[MOVE] L'asta è già in cima alla lista", LogLevel.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sposta l'elemento verso l'alto
|
||||
_auctionViewModels.Move(currentIndex, currentIndex - 1);
|
||||
|
||||
// Mantieni la selezione
|
||||
MultiAuctionsGrid.SelectedItem = _selectedAuction;
|
||||
MultiAuctionsGrid.ScrollIntoView(_selectedAuction);
|
||||
|
||||
// Salva il nuovo ordine
|
||||
SaveAuctions();
|
||||
|
||||
Log($"[MOVE UP] Asta spostata verso l'alto: {_selectedAuction.Name}", LogLevel.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Spostamento asta verso l'alto: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante lo spostamento: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sposta l'asta selezionata verso il basso nell'elenco
|
||||
/// </summary>
|
||||
private void MoveDownButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var currentIndex = _auctionViewModels.IndexOf(_selectedAuction);
|
||||
|
||||
if (currentIndex < 0 || currentIndex >= _auctionViewModels.Count - 1)
|
||||
{
|
||||
// Già in fondo o non trovata
|
||||
Log($"[MOVE] L'asta è già in fondo alla lista", LogLevel.Info);
|
||||
return;
|
||||
}
|
||||
|
||||
// Sposta l'elemento verso il basso
|
||||
_auctionViewModels.Move(currentIndex, currentIndex + 1);
|
||||
|
||||
// Mantieni la selezione
|
||||
MultiAuctionsGrid.SelectedItem = _selectedAuction;
|
||||
MultiAuctionsGrid.ScrollIntoView(_selectedAuction);
|
||||
|
||||
// Salva il nuovo ordine
|
||||
SaveAuctions();
|
||||
|
||||
Log($"[MOVE DOWN] Asta spostata verso il basso: {_selectedAuction.Name}", LogLevel.Success);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Spostamento asta verso il basso: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante lo spostamento: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
139
Mimante/Core/MainWindow.Commands.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using AutoBidder.Utilities;
|
||||
using AutoBidder.ViewModels;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Command implementations for MainWindow
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private void InitializeCommands()
|
||||
{
|
||||
StartAllCommand = new RelayCommand(_ => ExecuteStartAll());
|
||||
StopAllCommand = new RelayCommand(_ => ExecuteStopAll());
|
||||
PauseAllCommand = new RelayCommand(_ => ExecutePauseAll());
|
||||
|
||||
GridStartCommand = new RelayCommand(param => ExecuteGridStart(param as AuctionViewModel));
|
||||
GridPauseCommand = new RelayCommand(param => ExecuteGridPause(param as AuctionViewModel));
|
||||
GridStopCommand = new RelayCommand(param => ExecuteGridStop(param as AuctionViewModel));
|
||||
GridBidCommand = new RelayCommand(async param => await ExecuteGridBidAsync(param as AuctionViewModel));
|
||||
}
|
||||
|
||||
private void ExecuteStartAll()
|
||||
{
|
||||
StartButton_Click(null, null);
|
||||
}
|
||||
|
||||
private void ExecuteStopAll()
|
||||
{
|
||||
StopButton_Click(null, null);
|
||||
}
|
||||
|
||||
private void ExecutePauseAll()
|
||||
{
|
||||
PauseAllButton_Click(null, null);
|
||||
}
|
||||
|
||||
private void ExecuteGridStart(AuctionViewModel? vm)
|
||||
{
|
||||
if (vm == null) return;
|
||||
|
||||
// Attiva l'asta
|
||||
vm.IsActive = true;
|
||||
vm.IsPaused = false;
|
||||
|
||||
// Se il monitoraggio globale non è attivo, avvialo automaticamente
|
||||
if (!_isAutomationActive)
|
||||
{
|
||||
_auctionMonitor.Start();
|
||||
_isAutomationActive = true;
|
||||
Log($"[AUTO-START] Monitoraggio avviato automaticamente per asta: {vm.Name}", LogLevel.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[START] Asta avviata: {vm.Name}", LogLevel.Info);
|
||||
}
|
||||
|
||||
// ? Salva gli stati aggiornati su disco
|
||||
SaveAuctions();
|
||||
UpdateGlobalControlButtons();
|
||||
}
|
||||
|
||||
private void ExecuteGridPause(AuctionViewModel? vm)
|
||||
{
|
||||
if (vm == null) return;
|
||||
vm.IsPaused = true;
|
||||
Log($"[PAUSA] Asta in pausa: {vm.Name}", LogLevel.Info);
|
||||
|
||||
// ? Salva gli stati aggiornati su disco
|
||||
SaveAuctions();
|
||||
UpdateGlobalControlButtons();
|
||||
}
|
||||
|
||||
private void ExecuteGridStop(AuctionViewModel? vm)
|
||||
{
|
||||
if (vm == null) return;
|
||||
vm.IsActive = false;
|
||||
|
||||
// Se tutte le aste sono fermate, ferma anche il monitoraggio globale
|
||||
bool hasActiveAuctions = _auctionViewModels.Any(a => a.IsActive);
|
||||
if (!hasActiveAuctions && _isAutomationActive)
|
||||
{
|
||||
_auctionMonitor.Stop();
|
||||
_isAutomationActive = false;
|
||||
Log($"[AUTO-STOP] Monitoraggio fermato: nessuna asta attiva", LogLevel.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[STOP] Asta fermata: {vm.Name}", LogLevel.Info);
|
||||
}
|
||||
|
||||
// ? Salva gli stati aggiornati su disco
|
||||
SaveAuctions();
|
||||
UpdateGlobalControlButtons();
|
||||
}
|
||||
|
||||
private async Task ExecuteGridBidAsync(AuctionViewModel? vm)
|
||||
{
|
||||
if (vm == null) return;
|
||||
try
|
||||
{
|
||||
Log($"[BID] Puntata manuale richiesta su: {vm.Name}", LogLevel.Info);
|
||||
var result = await _auctionMonitor.PlaceManualBidAsync(vm.AuctionInfo);
|
||||
|
||||
// Aggiorna dati puntate da risposta server per puntata manuale
|
||||
if (result.Success)
|
||||
{
|
||||
if (result.RemainingBids.HasValue)
|
||||
{
|
||||
vm.AuctionInfo.RemainingBids = result.RemainingBids.Value;
|
||||
|
||||
// Aggiorna immediatamente il banner in alto
|
||||
Dispatcher.Invoke(() => UpdateRemainingBidsDisplay());
|
||||
}
|
||||
if (result.BidsUsedOnThisAuction.HasValue)
|
||||
{
|
||||
vm.AuctionInfo.BidsUsedOnThisAuction = result.BidsUsedOnThisAuction.Value;
|
||||
}
|
||||
|
||||
// Notifica aggiornamento contatori per aggiornare la UI - SUL THREAD UI
|
||||
Dispatcher.Invoke(() => vm.RefreshCounters());
|
||||
|
||||
Log($"[OK] Puntata manuale su {vm.Name}: {result.LatencyMs}ms", LogLevel.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[FAIL] Puntata manuale su {vm.Name}: {result.Error}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Puntata manuale: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
112
Mimante/Core/MainWindow.ConnectionHandlers.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handlers per il nuovo sistema di connessione automatica
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Handler per il click sul nome utente nella sidebar
|
||||
/// </summary>
|
||||
private void SidebarUsername_Click(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
// Riusa la stessa logica del pulsante connessione (se fosse ancora presente)
|
||||
ConnectionStatusButton_Click(sender, new RoutedEventArgs());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handler per il pulsante stato connessione nel banner
|
||||
/// Se non connesso: apre tab Browser per login
|
||||
/// Se connesso: mostra opzioni (disconnetti, riconnetti)
|
||||
/// </summary>
|
||||
private void ConnectionStatusButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var session = _sessionService?.GetCurrentSession();
|
||||
|
||||
if (session != null && !string.IsNullOrEmpty(session.Username))
|
||||
{
|
||||
// Già connesso - Mostra opzioni
|
||||
var result = MessageBox.Show(
|
||||
this,
|
||||
$"Connesso come: {session.Username}\n" +
|
||||
$"Puntate residue: {session.RemainingBids}\n" +
|
||||
$"Credito Shop: EUR {session.ShopCredit:F2}\n\n" +
|
||||
"Vuoi disconnettere e accedere con un altro account?",
|
||||
"Gestione Connessione",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Question);
|
||||
|
||||
if (result == MessageBoxResult.Yes)
|
||||
{
|
||||
// Disconnetti
|
||||
DisconnectSession();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Non connesso - Apri browser per login
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Per accedere:\n\n" +
|
||||
"1. Fai login su Bidoo nella scheda Browser\n" +
|
||||
"2. La connessione sarà automatica\n\n" +
|
||||
"Apertura scheda Browser...",
|
||||
"Accedi a Bidoo",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information);
|
||||
|
||||
// Apri tab Browser
|
||||
TabBrowser.IsChecked = true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Gestione connessione: {ex.Message}", Utilities.LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnette la sessione corrente
|
||||
/// </summary>
|
||||
private void DisconnectSession()
|
||||
{
|
||||
try
|
||||
{
|
||||
Log("[SESSION] Disconnessione in corso...", Utilities.LogLevel.Info);
|
||||
|
||||
// Clear session tramite SessionService
|
||||
_sessionService?.ClearSession();
|
||||
|
||||
// Aggiorna UI
|
||||
SetUserBanner(string.Empty, 0);
|
||||
|
||||
// Ferma monitoraggio se attivo
|
||||
if (_isAutomationActive)
|
||||
{
|
||||
_auctionMonitor?.Stop();
|
||||
_isAutomationActive = false;
|
||||
UpdateGlobalControlButtons();
|
||||
}
|
||||
|
||||
Log("[SESSION] Disconnesso con successo", Utilities.LogLevel.Success);
|
||||
|
||||
MessageBox.Show(
|
||||
this,
|
||||
"Disconnesso con successo.\n\n" +
|
||||
"Per riconnetterti, fai login nella scheda Browser.",
|
||||
"Disconnesso",
|
||||
MessageBoxButton.OK,
|
||||
MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Disconnessione: {ex.Message}", Utilities.LogLevel.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
337
Mimante/Core/MainWindow.ControlEvents.cs
Normal file
@@ -0,0 +1,337 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Event handlers for UserControl events and tab navigation
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
// ===== TAB NAVIGATION =====
|
||||
|
||||
private void TabAsteAttive_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ShowPanel(AuctionMonitor);
|
||||
}
|
||||
|
||||
private void TabBrowser_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ShowPanel(Browser);
|
||||
}
|
||||
|
||||
private void TabPuntateGratis_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ShowPanel(PuntateGratisPanel);
|
||||
}
|
||||
|
||||
private void TabDatiStatistici_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ShowPanel(StatisticsPanel);
|
||||
}
|
||||
|
||||
private void TabImpostazioni_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Mostra il pannello Impostazioni
|
||||
ShowPanel(Settings);
|
||||
|
||||
// Carica impostazioni quando si apre la tab
|
||||
LoadDefaultSettings();
|
||||
|
||||
// NOTA: Caricamento cookie RIMOSSO - ora automatico tramite browser
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void ShowPanel(System.Windows.UIElement? panelToShow)
|
||||
{
|
||||
// Prevent NullReferenceException during initialization
|
||||
if (AuctionMonitor == null || Browser == null || StatisticsPanel == null || Settings == null || PuntateGratisPanel == null)
|
||||
return;
|
||||
|
||||
// Hide all panels
|
||||
AuctionMonitor.Visibility = Visibility.Collapsed;
|
||||
Browser.Visibility = Visibility.Collapsed;
|
||||
PuntateGratisPanel.Visibility = Visibility.Collapsed;
|
||||
StatisticsPanel.Visibility = Visibility.Collapsed;
|
||||
Settings.Visibility = Visibility.Collapsed;
|
||||
|
||||
// Show selected panel
|
||||
if (panelToShow != null)
|
||||
panelToShow.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
// ===== AUCTION MONITOR CONTROL EVENTS =====
|
||||
|
||||
private void AuctionMonitor_StartClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
StartButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_PauseAllClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
PauseAllButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_StopClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
StopButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_ExportClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Chiama il metodo di export esistente
|
||||
try
|
||||
{
|
||||
// Esporta tutte le aste monitorate
|
||||
var auctions = _auctionMonitor.GetAuctions();
|
||||
if (auctions.Count == 0)
|
||||
{
|
||||
System.Windows.MessageBox.Show("Nessuna asta da esportare", "Export", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Implementare dialog export con scelta formato
|
||||
System.Windows.MessageBox.Show($"Export di {auctions.Count} aste.\n\nFunzionalità in sviluppo.\nUsa le impostazioni nella scheda Impostazioni per configurare l'export.", "Export Aste", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
|
||||
Log($"[INFO] Richiesto export di {auctions.Count} aste (funzionalità in sviluppo)", Utilities.LogLevel.Info);
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Export: {ex.Message}", Utilities.LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void AuctionMonitor_AddUrlClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AddUrlButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_RemoveUrlClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RemoveUrlButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_RemoveAllClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RemoveAllButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_MoveUpClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MoveUpButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_MoveDownClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
MoveDownButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_AuctionSelectionChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AuctionMonitor.MultiAuctionsGrid.SelectedItem is ViewModels.AuctionViewModel selected)
|
||||
{
|
||||
_selectedAuction = selected;
|
||||
UpdateSelectedAuctionDetails(selected);
|
||||
|
||||
// ? NUOVO: Rileva nome generico O info prodotto mancanti e recupera automaticamente
|
||||
var auction = selected.AuctionInfo;
|
||||
bool hasGenericName = auction.Name.StartsWith("Asta ") &&
|
||||
!auction.Name.Contains("Shop") &&
|
||||
!auction.Name.Contains("€") &&
|
||||
!auction.Name.Contains("Buono") &&
|
||||
!auction.Name.Contains("Carburante");
|
||||
|
||||
bool needsProductInfo = !auction.BuyNowPrice.HasValue && !auction.ShippingCost.HasValue;
|
||||
|
||||
// Se ha nome generico O mancano info prodotto ? recupera in background
|
||||
if (hasGenericName || needsProductInfo)
|
||||
{
|
||||
Log($"[AUTO-FETCH] Recupero automatico per: {auction.Name} (nome generico={hasGenericName}, info mancanti={needsProductInfo})", Utilities.LogLevel.Info);
|
||||
|
||||
// Avvia fetch in background senza bloccare UI
|
||||
_ = LoadProductInfoInBackgroundAsync(auction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AuctionMonitor_CopyUrlClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CopyAuctionUrlButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_OpenAuctionInternalClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
OpenAuctionInternalButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_OpenAuctionExternalClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
OpenAuctionExternalButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_ExportAuctionClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ExportAuctionButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_ResetSettingsClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ResetSettingsButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_ClearBiddersClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ClearBiddersButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_ClearLogClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ClearLogButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_ClearGlobalLogClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ClearLogButton_Click(sender, e); // Clear Log invece di ClearGlobalLog
|
||||
}
|
||||
|
||||
// ===== AUCTION SETTINGS EVENTS =====
|
||||
|
||||
private void AuctionMonitor_RefreshProductInfoClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
RefreshProductInfoButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_ConnectionStatusClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ConnectionStatusButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void AuctionMonitor_BidBeforeDeadlineMsChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Gestito internamente dal binding WPF
|
||||
if (_selectedAuction != null && int.TryParse(AuctionMonitor.SelectedBidBeforeDeadlineMs.Text, out int ms))
|
||||
{
|
||||
_selectedAuction.AuctionInfo.BidBeforeDeadlineMs = ms;
|
||||
SaveAuctions();
|
||||
}
|
||||
}
|
||||
|
||||
private void AuctionMonitor_CheckAuctionOpenChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Gestito internamente dal binding WPF
|
||||
if (_selectedAuction != null)
|
||||
{
|
||||
_selectedAuction.AuctionInfo.CheckAuctionOpenBeforeBid = AuctionMonitor.SelectedCheckAuctionOpen.IsChecked ?? false;
|
||||
SaveAuctions();
|
||||
}
|
||||
}
|
||||
|
||||
private void AuctionMonitor_MinPriceChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Gestito internamente dal binding WPF
|
||||
if (_selectedAuction != null && double.TryParse(AuctionMonitor.SelectedMinPrice.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double price))
|
||||
{
|
||||
_selectedAuction.MinPrice = price;
|
||||
SaveAuctions();
|
||||
}
|
||||
}
|
||||
|
||||
private void AuctionMonitor_MaxPriceChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Gestito internamente dal binding WPF
|
||||
if (_selectedAuction != null && double.TryParse(AuctionMonitor.SelectedMaxPrice.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out double price))
|
||||
{
|
||||
_selectedAuction.MaxPrice = price;
|
||||
SaveAuctions();
|
||||
}
|
||||
}
|
||||
|
||||
private void AuctionMonitor_MaxClicksChanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// Gestito internamente dal binding WPF
|
||||
if (_selectedAuction != null && int.TryParse(AuctionMonitor.SelectedMaxClicks.Text, out int clicks))
|
||||
{
|
||||
_selectedAuction.MaxClicks = clicks;
|
||||
SaveAuctions();
|
||||
}
|
||||
}
|
||||
|
||||
// ===== BROWSER CONTROL EVENTS =====
|
||||
|
||||
private void Browser_BrowserBackClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Browser.EmbeddedWebView?.CoreWebView2 != null && Browser.EmbeddedWebView.CoreWebView2.CanGoBack)
|
||||
Browser.EmbeddedWebView.CoreWebView2.GoBack();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void Browser_BrowserForwardClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Browser.EmbeddedWebView?.CoreWebView2 != null && Browser.EmbeddedWebView.CoreWebView2.CanGoForward)
|
||||
Browser.EmbeddedWebView.CoreWebView2.GoForward();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void Browser_BrowserRefreshClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Browser.EmbeddedWebView?.Reload();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void Browser_BrowserHomeClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Browser.EmbeddedWebView?.CoreWebView2?.Navigate("https://it.bidoo.com/");
|
||||
Browser.BrowserAddress.Text = "https://it.bidoo.com/";
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void Browser_BrowserGoClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = Browser.BrowserAddress.Text?.Trim();
|
||||
if (string.IsNullOrEmpty(url)) return;
|
||||
if (!url.StartsWith("http", System.StringComparison.OrdinalIgnoreCase))
|
||||
url = "https://" + url;
|
||||
Browser.EmbeddedWebView?.CoreWebView2?.Navigate(url);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void Browser_BrowserAddAuctionClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = Browser.BrowserAddress.Text?.Trim() ?? Browser.EmbeddedWebView?.Source?.ToString();
|
||||
if (!string.IsNullOrEmpty(url))
|
||||
_ = AddAuctionFromUrl(url);
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
// ===== SETTINGS CONTROL EVENTS =====
|
||||
|
||||
private void Settings_SaveDefaultsClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
SaveDefaultsButton_Click(sender, e);
|
||||
}
|
||||
|
||||
private void Settings_CancelDefaultsClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
CancelDefaultsButton_Click(sender, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
99
Mimante/Core/MainWindow.Logging.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using AutoBidder.Utilities;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Logging functionality with color-coded severity levels and configurable minimum level filtering
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
/// <summary>
|
||||
/// Scrive un messaggio nel log globale con filtraggio basato sul livello minimo configurato
|
||||
/// </summary>
|
||||
/// <param name="message">Messaggio da loggare</param>
|
||||
/// <param name="level">Livello di severità del messaggio</param>
|
||||
private void Log(string message, LogLevel level = LogLevel.Info)
|
||||
{
|
||||
Dispatcher.BeginInvoke(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Carica impostazioni per ottenere livello minimo e limite righe
|
||||
var settings = SettingsManager.Load();
|
||||
|
||||
// Filtra messaggi in base al livello minimo configurato
|
||||
MinimumLogLevel minLevel = MinimumLogLevel.Normal; // Default
|
||||
if (Enum.TryParse<MinimumLogLevel>(settings.MinLogLevel, out var parsedLevel))
|
||||
{
|
||||
minLevel = parsedLevel;
|
||||
}
|
||||
|
||||
// Se il livello del messaggio è maggiore del minimo configurato, ignora
|
||||
if ((int)level > (int)minLevel)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
|
||||
// Prefisso in base al livello per chiarezza
|
||||
string prefix = level switch
|
||||
{
|
||||
LogLevel.Error => "[ERROR]",
|
||||
LogLevel.Warning => "[WARN]",
|
||||
LogLevel.Info => "[INFO]",
|
||||
LogLevel.Success => "[OK]",
|
||||
LogLevel.Debug => "[DEBUG]",
|
||||
LogLevel.Trace => "[TRACE]",
|
||||
_ => "[LOG]"
|
||||
};
|
||||
|
||||
var logEntry = $"[{timestamp}] {prefix} {message}";
|
||||
|
||||
// Color coding based on severity for dark theme
|
||||
var color = level switch
|
||||
{
|
||||
LogLevel.Error => new SolidColorBrush(Color.FromRgb(232, 17, 35)), // #E81123 (Red)
|
||||
LogLevel.Warning => new SolidColorBrush(Color.FromRgb(255, 191, 0)), // #FFBF00 (Yellow)
|
||||
LogLevel.Success => new SolidColorBrush(Color.FromRgb(0, 216, 0)), // #00D800 (Green)
|
||||
LogLevel.Info => new SolidColorBrush(Color.FromRgb(100, 180, 255)), // #64B4FF (Light Blue)
|
||||
LogLevel.Debug => new SolidColorBrush(Color.FromRgb(255, 140, 255)), // #FF8CFF (Magenta)
|
||||
LogLevel.Trace => new SolidColorBrush(Color.FromRgb(160, 160, 160)), // #A0A0A0 (Gray)
|
||||
_ => new SolidColorBrush(Color.FromRgb(204, 204, 204)) // #CCCCCC (Light Gray)
|
||||
};
|
||||
|
||||
var p = new System.Windows.Documents.Paragraph { Margin = new Thickness(0, 2, 0, 2) };
|
||||
var r = new System.Windows.Documents.Run(logEntry) { Foreground = color };
|
||||
p.Inlines.Add(r);
|
||||
LogBox.Document.Blocks.Add(p);
|
||||
|
||||
// Mantieni solo gli ultimi N paragrafi (configurabile dalle impostazioni)
|
||||
int maxLogLines = settings.MaxGlobalLogLines;
|
||||
|
||||
if (LogBox.Document.Blocks.Count > maxLogLines)
|
||||
{
|
||||
// Rimuovi i paragrafi più vecchi (primi inseriti)
|
||||
int excessCount = LogBox.Document.Blocks.Count - maxLogLines;
|
||||
for (int i = 0; i < excessCount; i++)
|
||||
{
|
||||
if (LogBox.Document.Blocks.FirstBlock != null)
|
||||
{
|
||||
LogBox.Document.Blocks.Remove(LogBox.Document.Blocks.FirstBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-scroll if near bottom
|
||||
if (LogBox.VerticalOffset >= LogBox.ExtentHeight - LogBox.ViewportHeight - 40)
|
||||
{
|
||||
LogBox.ScrollToEnd();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
321
Mimante/Core/MainWindow.UIUpdates.cs
Normal file
@@ -0,0 +1,321 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using AutoBidder.Utilities;
|
||||
using AutoBidder.ViewModels;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// UI update methods and selected auction details
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private void UpdateAuctionLog(AuctionViewModel auction)
|
||||
{
|
||||
try
|
||||
{
|
||||
var auctionInfo = auction.AuctionInfo;
|
||||
var logBox = SelectedAuctionLog;
|
||||
var doc = logBox.Document;
|
||||
doc.Blocks.Clear();
|
||||
|
||||
foreach (var entry in auctionInfo.AuctionLog)
|
||||
{
|
||||
var upper = entry.ToUpperInvariant();
|
||||
|
||||
// Color coding based on log content
|
||||
Brush color;
|
||||
if (upper.Contains("[ERRORE]") || upper.Contains("[FAIL]") || upper.Contains("EXCEPTION"))
|
||||
color = new SolidColorBrush(Color.FromRgb(232, 17, 35)); // Red
|
||||
else if (upper.Contains("[WARN]") || upper.Contains("ATTENZIONE"))
|
||||
color = new SolidColorBrush(Color.FromRgb(255, 183, 0)); // Yellow/Orange
|
||||
else if (upper.Contains("[OK]") || upper.Contains("SUCCESS"))
|
||||
color = new SolidColorBrush(Color.FromRgb(0, 216, 0)); // Green
|
||||
else
|
||||
color = new SolidColorBrush(Color.FromRgb(100, 180, 255)); // Light Blue - #64B4FF (più chiaro e leggibile)
|
||||
|
||||
var p = new System.Windows.Documents.Paragraph { Margin = new Thickness(0, 2, 0, 2) };
|
||||
var r = new System.Windows.Documents.Run(entry) { Foreground = color };
|
||||
p.Inlines.Add(r);
|
||||
doc.Blocks.Add(p);
|
||||
}
|
||||
|
||||
// Auto-scroll if near bottom
|
||||
var viewer = logBox;
|
||||
var vpos = viewer.VerticalOffset;
|
||||
var vmax = viewer.ExtentHeight - viewer.ViewportHeight;
|
||||
if (vmax - vpos < 40)
|
||||
{
|
||||
viewer.ScrollToEnd();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void RefreshBiddersGrid(AuctionViewModel auction)
|
||||
{
|
||||
try
|
||||
{
|
||||
var bidders = auction.AuctionInfo.BidderStats.Values
|
||||
.OrderByDescending(b => b.BidCount)
|
||||
.ToList();
|
||||
|
||||
SelectedAuctionBiddersGrid.ItemsSource = null;
|
||||
SelectedAuctionBiddersGrid.ItemsSource = bidders;
|
||||
SelectedAuctionBiddersCount.Text = $"Utenti: {bidders?.Count ?? 0}";
|
||||
|
||||
// ?? NUOVO: Aggiorna il contatore della storia puntate con limite configurato
|
||||
var settings = SettingsManager.Load();
|
||||
var maxEntries = settings?.MaxBidHistoryEntries ?? 20;
|
||||
var historyCount = auction.BidHistoryEntries?.Count ?? 0;
|
||||
|
||||
var bidHistoryCountTextBlock = AuctionMonitor.FindName("BidHistoryCount") as TextBlock;
|
||||
if (bidHistoryCountTextBlock != null)
|
||||
{
|
||||
// Mostra "Ultime 20 puntate" se il limite è attivo
|
||||
if (maxEntries > 0)
|
||||
{
|
||||
bidHistoryCountTextBlock.Text = $"Ultime {maxEntries} puntate";
|
||||
}
|
||||
else
|
||||
{
|
||||
bidHistoryCountTextBlock.Text = $"Ultime puntate: {historyCount}";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void UpdateAuctionSettingsDisplay(AuctionViewModel auction)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Blocca temporaneamente i TextChanged per evitare loop di aggiornamento
|
||||
_isUpdatingSelection = true;
|
||||
|
||||
SelectedAuctionName.Text = auction.Name;
|
||||
SelectedBidBeforeDeadlineMs.Text = auction.AuctionInfo.BidBeforeDeadlineMs.ToString();
|
||||
SelectedCheckAuctionOpen.IsChecked = auction.AuctionInfo.CheckAuctionOpenBeforeBid;
|
||||
SelectedMinPrice.Text = auction.MinPrice.ToString("F2", System.Globalization.CultureInfo.InvariantCulture);
|
||||
SelectedMaxPrice.Text = auction.MaxPrice.ToString("F2", System.Globalization.CultureInfo.InvariantCulture);
|
||||
SelectedMaxClicks.Text = auction.MaxClicks.ToString();
|
||||
|
||||
var url = auction.AuctionInfo.OriginalUrl;
|
||||
if (string.IsNullOrEmpty(url))
|
||||
url = $"https://it.bidoo.com/auction.php?a=asta_{auction.AuctionId}";
|
||||
SelectedAuctionUrl.Text = url;
|
||||
|
||||
ResetSettingsButton.IsEnabled = true;
|
||||
ClearBiddersButton.IsEnabled = true;
|
||||
ClearLogButton.IsEnabled = true;
|
||||
|
||||
UpdateAuctionLog(auction);
|
||||
RefreshBiddersGrid(auction);
|
||||
|
||||
_isUpdatingSelection = false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
_isUpdatingSelection = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTotalCount()
|
||||
{
|
||||
MonitorateTitle.Text = $"Aste monitorate: {_auctionViewModels.Count}";
|
||||
}
|
||||
|
||||
private void UpdateGlobalControlButtons()
|
||||
{
|
||||
try
|
||||
{
|
||||
var hasAuctions = _auctionViewModels.Count > 0;
|
||||
|
||||
if (!hasAuctions)
|
||||
{
|
||||
// Nessuna asta: tutti disabilitati
|
||||
StartButton.IsEnabled = false;
|
||||
StartButton.Opacity = 0.4;
|
||||
PauseAllButton.IsEnabled = false;
|
||||
PauseAllButton.Opacity = 0.4;
|
||||
StopButton.IsEnabled = false;
|
||||
StopButton.Opacity = 0.4;
|
||||
return;
|
||||
}
|
||||
|
||||
// Conta quante aste possono eseguire ogni azione
|
||||
int canStartCount = _auctionViewModels.Count(a => a.CanStart);
|
||||
int canPauseCount = _auctionViewModels.Count(a => a.CanPause);
|
||||
int canStopCount = _auctionViewModels.Count(a => a.CanStop);
|
||||
|
||||
// AVVIA TUTTI: abilitato se ALMENO UNA asta può essere avviata
|
||||
// Scuro se NESSUNA asta può essere avviata (tutte già avviate)
|
||||
StartButton.IsEnabled = canStartCount > 0;
|
||||
StartButton.Opacity = canStartCount > 0 ? 1.0 : 0.4;
|
||||
|
||||
// PAUSA TUTTI: abilitato se ALMENO UNA asta può essere messa in pausa
|
||||
// Scuro se NESSUNA asta può essere messa in pausa (tutte già in pausa o ferme)
|
||||
PauseAllButton.IsEnabled = canPauseCount > 0;
|
||||
PauseAllButton.Opacity = canPauseCount > 0 ? 1.0 : 0.4;
|
||||
|
||||
// FERMA TUTTI: abilitato se ALMENO UNA asta può essere fermata
|
||||
// Scuro se NESSUNA asta può essere fermata (tutte già ferme)
|
||||
StopButton.IsEnabled = canStopCount > 0;
|
||||
StopButton.Opacity = canStopCount > 0 ? 1.0 : 0.4;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private void MultiAuctionsGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (MultiAuctionsGrid.SelectedItem is AuctionViewModel selected)
|
||||
{
|
||||
_selectedAuction = selected;
|
||||
UpdateSelectedAuctionDetails(selected);
|
||||
}
|
||||
}
|
||||
|
||||
private void GridOpenAuction_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sender is FrameworkElement element && element.DataContext is AuctionViewModel vm)
|
||||
{
|
||||
var url = vm.AuctionInfo.OriginalUrl;
|
||||
if (string.IsNullOrEmpty(url))
|
||||
url = $"https://it.bidoo.com/auction.php?a=asta_{vm.AuctionId}";
|
||||
|
||||
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = url,
|
||||
UseShellExecute = true
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Apertura asta: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExportSelectedAuction_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sender is FrameworkElement element && element.DataContext is AuctionViewModel vm)
|
||||
{
|
||||
MessageBox.Show(this, $"Esportazione singola asta non ancora implementata.\nUsa 'Esporta Aste' dalla toolbar.", "Info", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Esportazione asta: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resetta le impostazioni dell'asta selezionata ai valori predefiniti
|
||||
/// </summary>
|
||||
private void ResetSettingsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var settings = SettingsManager.Load();
|
||||
|
||||
// Resetta ai valori predefiniti dalle impostazioni
|
||||
_selectedAuction.AuctionInfo.BidBeforeDeadlineMs = settings.DefaultBidBeforeDeadlineMs;
|
||||
_selectedAuction.AuctionInfo.CheckAuctionOpenBeforeBid = settings.DefaultCheckAuctionOpenBeforeBid;
|
||||
_selectedAuction.MinPrice = settings.DefaultMinPrice;
|
||||
_selectedAuction.MaxPrice = settings.DefaultMaxPrice;
|
||||
_selectedAuction.MaxClicks = settings.DefaultMaxClicks;
|
||||
|
||||
// Aggiorna UI
|
||||
UpdateAuctionSettingsDisplay(_selectedAuction);
|
||||
|
||||
// Salva
|
||||
SaveAuctions();
|
||||
|
||||
Log($"[RESET] Impostazioni ripristinate ai valori predefiniti per: {_selectedAuction.Name}", LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Reset impostazioni: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante il reset: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pulisce la lista degli utenti che hanno puntato sull'asta selezionata
|
||||
/// </summary>
|
||||
private void ClearBiddersButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var result = MessageBox.Show(
|
||||
$"Pulire la lista degli utenti per questa asta?\n\n{_selectedAuction.Name}\n\nLa lista degli utenti che hanno puntato verrà svuotata.",
|
||||
"Conferma Pulizia",
|
||||
MessageBoxButton.YesNo,
|
||||
MessageBoxImage.Question);
|
||||
|
||||
if (result != MessageBoxResult.Yes)
|
||||
return;
|
||||
|
||||
// Pulisci la lista bidders
|
||||
_selectedAuction.AuctionInfo.BidderStats.Clear();
|
||||
|
||||
// Aggiorna UI
|
||||
RefreshBiddersGrid(_selectedAuction);
|
||||
|
||||
Log($"[CLEAR] Lista utenti pulita per: {_selectedAuction.Name}", LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Pulizia lista utenti: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante la pulizia: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pulisce il log dell'asta selezionata
|
||||
/// </summary>
|
||||
private void ClearLogButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (_selectedAuction == null)
|
||||
{
|
||||
MessageBox.Show("Seleziona un'asta dalla griglia", "Nessuna Selezione", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
// Pulisci il log dell'asta
|
||||
_selectedAuction.AuctionInfo.AuctionLog.Clear();
|
||||
|
||||
// Aggiorna UI
|
||||
UpdateAuctionLog(_selectedAuction);
|
||||
|
||||
Log($"[CLEAR] Log pulito per: {_selectedAuction.Name}", LogLevel.Info);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Pulizia log asta: {ex.Message}", LogLevel.Error);
|
||||
MessageBox.Show($"Errore durante la pulizia: {ex.Message}", "Errore", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
118
Mimante/Core/MainWindow.UrlParsing.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// URL parsing and validation utilities
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private bool IsValidAuctionUrl(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
var host = uri.Host.ToLowerInvariant();
|
||||
|
||||
// Valida dominio Bidoo
|
||||
if (!host.Contains("bidoo.com") && !host.Contains("bidoo.it") &&
|
||||
!host.Contains("bidoo.fr") && !host.Contains("bidoo.es") &&
|
||||
!host.Contains("bidoo.de"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Valida path asta
|
||||
return uri.AbsolutePath.Contains("/asta/") || uri.Query.Contains("a=");
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private string? ExtractAuctionId(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
|
||||
// Formato nuovo: /asta/nome-prodotto-81204324
|
||||
var match = Regex.Match(uri.AbsolutePath, @"/asta/[^/]*-(\d{8,})");
|
||||
if (match.Success)
|
||||
{
|
||||
return match.Groups[1].Value;
|
||||
}
|
||||
|
||||
// Formato vecchio: /asta/81204324
|
||||
match = Regex.Match(uri.AbsolutePath, @"/asta/(\d{8,})");
|
||||
if (match.Success)
|
||||
{
|
||||
return match.Groups[1].Value;
|
||||
}
|
||||
|
||||
// Formato query: ?a=Galaxy_S25_Ultra_256GB_81204324
|
||||
match = Regex.Match(uri.Query, @"[?&]a=([^&]+)");
|
||||
if (match.Success)
|
||||
{
|
||||
var aValue = match.Groups[1].Value;
|
||||
|
||||
// Estrai ID numerico finale (8+ cifre)
|
||||
var idMatch = Regex.Match(aValue, @"(\d{8,})");
|
||||
if (idMatch.Success)
|
||||
{
|
||||
return idMatch.Groups[1].Value;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private string? ExtractProductName(string url)
|
||||
{
|
||||
try
|
||||
{
|
||||
var uri = new Uri(url);
|
||||
|
||||
// Formato query: ?a=Galaxy_S25_Ultra_256GB_81204324
|
||||
var match = Regex.Match(uri.Query, @"[?&]a=([^&]+)");
|
||||
if (match.Success)
|
||||
{
|
||||
var aValue = match.Groups[1].Value;
|
||||
|
||||
// Rimuovi l'ID finale e gli underscore
|
||||
var nameMatch = Regex.Match(aValue, @"^(.+?)_(\d{8,})$");
|
||||
if (nameMatch.Success)
|
||||
{
|
||||
var productName = nameMatch.Groups[1].Value;
|
||||
productName = productName.Replace('_', ' ');
|
||||
return productName;
|
||||
}
|
||||
}
|
||||
|
||||
// Formato path: /asta/galaxy-s25-ultra-256gb-81204324
|
||||
match = Regex.Match(uri.AbsolutePath, @"/asta/(.+?)-(\d{8,})");
|
||||
if (match.Success)
|
||||
{
|
||||
var productName = match.Groups[1].Value;
|
||||
productName = System.Globalization.CultureInfo.CurrentCulture.TextInfo.ToTitleCase(
|
||||
productName.Replace('-', ' ')
|
||||
);
|
||||
return productName;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
338
Mimante/Core/MainWindow.UserInfo.cs
Normal file
@@ -0,0 +1,338 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using AutoBidder.Services;
|
||||
using AutoBidder.Utilities;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// User info and banner management - REFACTORED con SessionService
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private System.Windows.Threading.DispatcherTimer _userBannerTimer;
|
||||
private System.Windows.Threading.DispatcherTimer _userHtmlTimer;
|
||||
private SessionService _sessionService; // NUOVO: Servizio centralizzato
|
||||
|
||||
private void InitializeUserInfoTimers()
|
||||
{
|
||||
// Timer per aggiornamento dati utente da HTML ogni 5 minuti (PRINCIPALE)
|
||||
_userHtmlTimer = new System.Windows.Threading.DispatcherTimer();
|
||||
_userHtmlTimer.Interval = TimeSpan.FromMinutes(5);
|
||||
_userHtmlTimer.Tick += UserHtmlTimer_Tick;
|
||||
_userHtmlTimer.Start();
|
||||
|
||||
// Timer per aggiornamento banner API ogni 10 minuti (SECONDARIO - fallback)
|
||||
_userBannerTimer = new System.Windows.Threading.DispatcherTimer();
|
||||
_userBannerTimer.Interval = TimeSpan.FromMinutes(10);
|
||||
_userBannerTimer.Tick += UserBannerTimer_Tick;
|
||||
_userBannerTimer.Start();
|
||||
}
|
||||
|
||||
private void InitializeSessionService()
|
||||
{
|
||||
// NUOVO: Inizializza SessionService
|
||||
_sessionService = new SessionService(_auctionMonitor.GetApiClient());
|
||||
|
||||
// Event handlers
|
||||
_sessionService.OnLog += (msg) => Log(msg, LogLevel.Info);
|
||||
_sessionService.OnSessionChanged += (session) =>
|
||||
{
|
||||
Dispatcher.Invoke(() => SetUserBanner(session.Username, session.RemainingBids));
|
||||
};
|
||||
}
|
||||
|
||||
private void SetUserBanner(string username, int? remainingBids)
|
||||
{
|
||||
try
|
||||
{
|
||||
var session = _sessionService?.GetCurrentSession();
|
||||
|
||||
if (!string.IsNullOrEmpty(username))
|
||||
{
|
||||
// === CONNESSO ===
|
||||
|
||||
// Header - Puntate + Credito
|
||||
RemainingBidsText.Text = remainingBids?.ToString() ?? "0";
|
||||
|
||||
if (session?.ShopCredit > 0)
|
||||
{
|
||||
AuctionMonitor.ShopCreditText.Text = $"EUR {session.ShopCredit:F2}";
|
||||
}
|
||||
else
|
||||
{
|
||||
AuctionMonitor.ShopCreditText.Text = "EUR 0.00";
|
||||
}
|
||||
|
||||
// Aste vinte
|
||||
BannerAsteDaRiscattare.Text = "0";
|
||||
|
||||
// Indicatore limite puntate
|
||||
var settings = Utilities.SettingsManager.Load();
|
||||
UpdateMinBidsIndicator(settings.MinimumRemainingBids);
|
||||
|
||||
// === SIDEBAR - Mostra dati utente ===
|
||||
SidebarUsernameText.Text = username;
|
||||
SidebarUsernameText.Foreground = new System.Windows.Media.SolidColorBrush(
|
||||
System.Windows.Media.Color.FromRgb(0, 216, 0)); // Verde
|
||||
SidebarUsernameText.FontWeight = System.Windows.FontWeights.Bold;
|
||||
SidebarUsernameText.ToolTip = $"Connesso come {username} - Click per disconnettere";
|
||||
|
||||
// Mostra dettagli (ID + Email)
|
||||
if (session?.UserId > 0)
|
||||
{
|
||||
SidebarUserIdText.Text = $"ID: {session.UserId}";
|
||||
SidebarUserIdText.Visibility = System.Windows.Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
SidebarUserIdText.Visibility = System.Windows.Visibility.Collapsed;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(session?.Email))
|
||||
{
|
||||
SidebarUserEmailText.Text = session.Email;
|
||||
SidebarUserEmailText.Visibility = System.Windows.Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
SidebarUserEmailText.Visibility = System.Windows.Visibility.Collapsed;
|
||||
}
|
||||
|
||||
SidebarUserDetailsPanel.Visibility = System.Windows.Visibility.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
// === NON CONNESSO ===
|
||||
|
||||
// Reset header
|
||||
RemainingBidsText.Text = "0";
|
||||
AuctionMonitor.ShopCreditText.Text = "EUR 0.00";
|
||||
BannerAsteDaRiscattare.Text = "0";
|
||||
|
||||
// Nascondi indicatore limite
|
||||
MinBidsLimitIndicator.Visibility = Visibility.Collapsed;
|
||||
|
||||
// === SIDEBAR - Mostra "Non connesso" ===
|
||||
SidebarUsernameText.Text = "Non connesso";
|
||||
SidebarUsernameText.Foreground = new System.Windows.Media.SolidColorBrush(
|
||||
System.Windows.Media.Color.FromRgb(255, 82, 82)); // Rosso chiaro (#FF5252)
|
||||
SidebarUsernameText.FontWeight = System.Windows.FontWeights.Bold;
|
||||
SidebarUsernameText.ToolTip = "Non connesso - Click per accedere tramite browser";
|
||||
|
||||
// Nascondi dettagli (ID + Email)
|
||||
SidebarUserDetailsPanel.Visibility = System.Windows.Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private async void UserBannerTimer_Tick(object? sender, EventArgs e)
|
||||
{
|
||||
// Usa SessionService per refresh
|
||||
if (_sessionService != null)
|
||||
{
|
||||
await _sessionService.RefreshUserInfoAsync();
|
||||
}
|
||||
}
|
||||
|
||||
private async void UserHtmlTimer_Tick(object? sender, EventArgs e)
|
||||
{
|
||||
// Usa SessionService per refresh
|
||||
if (_sessionService != null)
|
||||
{
|
||||
await _sessionService.RefreshUserInfoAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Carica sessione salvata
|
||||
/// </summary>
|
||||
private void LoadSavedSession()
|
||||
{
|
||||
try
|
||||
{
|
||||
var session = _sessionService?.GetCurrentSession();
|
||||
|
||||
if (session != null && session.IsValid)
|
||||
{
|
||||
StartButton.IsEnabled = true;
|
||||
|
||||
Log($"[SESSION] Ripristino sessione per: {session.Username}", LogLevel.Info);
|
||||
|
||||
// Aggiorna UI con stato connesso (ottimistico)
|
||||
SetUserBanner(session.Username, session.RemainingBids);
|
||||
|
||||
// Verifica validità cookie in background
|
||||
System.Threading.Tasks.Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
Log("[SESSION] Verifica validità sessione...", LogLevel.Info);
|
||||
var success = await _auctionMonitor.UpdateUserInfoAsync();
|
||||
var updatedSession = _auctionMonitor.GetSession();
|
||||
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (success && updatedSession != null && !string.IsNullOrEmpty(updatedSession.Username))
|
||||
{
|
||||
SetUserBanner(updatedSession.Username, updatedSession.RemainingBids);
|
||||
Log($"[SESSION] Sessione valida - {updatedSession.Username} ({updatedSession.RemainingBids} puntate)", LogLevel.Success);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetUserBanner(string.Empty, 0);
|
||||
Log("[SESSION] Sessione scaduta", LogLevel.Warning);
|
||||
CheckBrowserCookieAfterWebViewReady();
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
SetUserBanner(string.Empty, 0);
|
||||
Log($"[SESSION] Errore verifica sessione: {ex.Message}", LogLevel.Warning);
|
||||
CheckBrowserCookieAfterWebViewReady();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[SESSION] Nessuna sessione salvata", LogLevel.Info);
|
||||
CheckBrowserCookieAfterWebViewReady();
|
||||
SetUserBanner(string.Empty, 0);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Caricamento sessione: {ex.Message}", LogLevel.Error);
|
||||
CheckBrowserCookieAfterWebViewReady();
|
||||
SetUserBanner(string.Empty, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attende che WebView sia pronta, poi verifica presenza cookie
|
||||
/// </summary>
|
||||
private void CheckBrowserCookieAfterWebViewReady()
|
||||
{
|
||||
System.Threading.Tasks.Task.Run(async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Aspetta che WebView sia inizializzata (max 60 secondi)
|
||||
var webViewReady = await WaitForWebViewInitAsync(60);
|
||||
|
||||
if (!webViewReady)
|
||||
{
|
||||
await Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Log("[WARN] WebView non inizializzata dopo 60 secondi", LogLevel.Warning);
|
||||
Log("[INFO] Per accedere:", LogLevel.Info);
|
||||
Log("[INFO] 1. Click su 'Non connesso' nella sidebar", LogLevel.Info);
|
||||
Log("[INFO] 2. Si aprirà la scheda Browser", LogLevel.Info);
|
||||
Log("[INFO] 3. Fai login su Bidoo", LogLevel.Info);
|
||||
Log("[INFO] 4. La connessione sarà automatica", LogLevel.Info);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// WebView pronta - verifica cookie
|
||||
await Dispatcher.InvokeAsync(async () =>
|
||||
{
|
||||
var browserCookie = await GetCookieFromWebView();
|
||||
|
||||
if (string.IsNullOrEmpty(browserCookie))
|
||||
{
|
||||
Log("[INFO] Nessun cookie nel browser", LogLevel.Info);
|
||||
Log("[INFO] Per accedere:", LogLevel.Info);
|
||||
Log("[INFO] 1. Click su 'Non connesso' nella sidebar", LogLevel.Info);
|
||||
Log("[INFO] 2. Si aprirà la scheda Browser", LogLevel.Info);
|
||||
Log("[INFO] 3. Fai login su Bidoo", LogLevel.Info);
|
||||
Log("[INFO] 4. La connessione sarà automatica", LogLevel.Info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[INFO] Cookie rilevato nel browser - importazione in corso...", LogLevel.Info);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[WARN] Errore verifica cookie: {ex.Message}", LogLevel.Warning);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aggiorna immediatamente il banner delle puntate residue (chiamato dopo ogni puntata)
|
||||
/// </summary>
|
||||
public void UpdateRemainingBidsDisplay()
|
||||
{
|
||||
try
|
||||
{
|
||||
var session = _sessionService?.GetCurrentSession();
|
||||
if (session != null && session.RemainingBids > 0)
|
||||
{
|
||||
RemainingBidsText.Text = session.RemainingBids.ToString();
|
||||
Log($"[BANNER UPDATE] Puntate residue aggiornate: {session.RemainingBids}", LogLevel.Info);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERROR] Errore aggiornamento banner: {ex.Message}", LogLevel.Error);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ? Aggiorna l'indicatore del limite minimo puntate nel banner
|
||||
/// </summary>
|
||||
private void UpdateMinBidsIndicator(int minBidsLimit)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (minBidsLimit > 0)
|
||||
{
|
||||
// Mostra indicatore con solo il numero tra parentesi
|
||||
MinBidsLimitIndicator.Visibility = Visibility.Visible;
|
||||
MinBidsLimitIndicator.Text = $"({minBidsLimit})";
|
||||
MinBidsLimitIndicator.ToolTip = $"Limite minimo puntate attivo: non scendera sotto {minBidsLimit} puntate";
|
||||
|
||||
// Colore basato su puntate residue
|
||||
var session = _sessionService?.GetCurrentSession();
|
||||
if (session != null && session.RemainingBids > 0)
|
||||
{
|
||||
if (session.RemainingBids <= minBidsLimit)
|
||||
{
|
||||
// Al limite - Rosso chiaro (più visibile su sfondo scuro)
|
||||
MinBidsLimitIndicator.Foreground = new System.Windows.Media.SolidColorBrush(
|
||||
System.Windows.Media.Color.FromRgb(255, 82, 82)); // #FF5252 - Rosso chiaro
|
||||
}
|
||||
else if (session.RemainingBids <= minBidsLimit + 10)
|
||||
{
|
||||
// Vicino al limite - Giallo
|
||||
MinBidsLimitIndicator.Foreground = new System.Windows.Media.SolidColorBrush(
|
||||
System.Windows.Media.Color.FromRgb(255, 193, 7)); // #FFC107 - Giallo
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sopra il limite - Verde
|
||||
MinBidsLimitIndicator.Foreground = new System.Windows.Media.SolidColorBrush(
|
||||
System.Windows.Media.Color.FromRgb(0, 216, 0)); // #00D800 - Verde
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nascondi indicatore
|
||||
MinBidsLimitIndicator.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
344
Mimante/Core/MainWindow.WebView.cs
Normal file
@@ -0,0 +1,344 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using AutoBidder.Utilities;
|
||||
|
||||
namespace AutoBidder
|
||||
{
|
||||
/// <summary>
|
||||
/// Gestione WebView2: pre-caricamento e estrazione cookie
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private bool _isWebViewInitialized = false;
|
||||
private TaskCompletionSource<bool>? _webViewInitCompletionSource;
|
||||
|
||||
/// <summary>
|
||||
/// Inizializza WebView2 in background all'avvio per pre-caricare il browser
|
||||
/// </summary>
|
||||
private async void InitializeWebView2()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (EmbeddedWebView == null)
|
||||
{
|
||||
Log("[WARN] WebView2 non disponibile", LogLevel.Warning);
|
||||
_webViewInitCompletionSource?.TrySetResult(false);
|
||||
return;
|
||||
}
|
||||
|
||||
Log("[BROWSER] Inizializzazione WebView2 in background...", LogLevel.Info);
|
||||
|
||||
// Aspetta un attimo che l'UI sia completamente caricata
|
||||
await System.Threading.Tasks.Task.Delay(500);
|
||||
|
||||
// ? FIX: WebView2 si inizializza SOLO se visibile
|
||||
// Salva tab corrente e switcha temporaneamente a Browser
|
||||
var wasVisible = Browser.Visibility == Visibility.Visible;
|
||||
var currentTab = TabAsteAttive.IsChecked == true ? "AsteAttive" :
|
||||
TabBrowser.IsChecked == true ? "Browser" :
|
||||
TabPuntateGratis.IsChecked == true ? "PuntateGratis" :
|
||||
TabDatiStatistici.IsChecked == true ? "DatiStatistici" :
|
||||
TabImpostazioni.IsChecked == true ? "Impostazioni" : "AsteAttive";
|
||||
|
||||
if (!wasVisible)
|
||||
{
|
||||
await Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Browser.Visibility = Visibility.Visible;
|
||||
});
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
// Specifica UserDataFolder esplicito
|
||||
var userDataFolder = System.IO.Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
|
||||
"AutoBidder",
|
||||
"WebView2"
|
||||
);
|
||||
|
||||
// Crea directory se non esiste
|
||||
System.IO.Directory.CreateDirectory(userDataFolder);
|
||||
|
||||
// Crea environment con UserDataFolder esplicito
|
||||
var env = await Microsoft.Web.WebView2.Core.CoreWebView2Environment.CreateAsync(
|
||||
browserExecutableFolder: null,
|
||||
userDataFolder: userDataFolder
|
||||
);
|
||||
|
||||
// Inizializza WebView con environment
|
||||
await EmbeddedWebView.EnsureCoreWebView2Async(env);
|
||||
|
||||
// Ripristina tab originale se necessario
|
||||
if (!wasVisible)
|
||||
{
|
||||
await Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Browser.Visibility = Visibility.Collapsed;
|
||||
|
||||
// Ripristina tab originale
|
||||
switch (currentTab)
|
||||
{
|
||||
case "AsteAttive":
|
||||
TabAsteAttive.IsChecked = true;
|
||||
AuctionMonitor.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case "PuntateGratis":
|
||||
TabPuntateGratis.IsChecked = true;
|
||||
PuntateGratisPanel.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case "DatiStatistici":
|
||||
TabDatiStatistici.IsChecked = true;
|
||||
StatisticsPanel.Visibility = Visibility.Visible;
|
||||
break;
|
||||
case "Impostazioni":
|
||||
TabImpostazioni.IsChecked = true;
|
||||
Settings.Visibility = Visibility.Visible;
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (EmbeddedWebView.CoreWebView2 != null)
|
||||
{
|
||||
_isWebViewInitialized = true;
|
||||
|
||||
// Pre-carica la pagina di Bidoo in background
|
||||
EmbeddedWebView.CoreWebView2.Navigate("https://it.bidoo.com");
|
||||
|
||||
Log("[BROWSER] WebView2 inizializzato e pre-caricato", LogLevel.Success);
|
||||
|
||||
// Registra evento per rilevare login automatico
|
||||
EmbeddedWebView.CoreWebView2.NavigationCompleted += OnWebViewNavigationCompleted;
|
||||
|
||||
// Notifica che WebView è pronta
|
||||
_webViewInitCompletionSource?.TrySetResult(true);
|
||||
|
||||
// Verifica immediata se c'è già un cookie
|
||||
await CheckAndImportCookieIfAvailable();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log("[ERROR] CoreWebView2 è null dopo init", LogLevel.Error);
|
||||
_webViewInitCompletionSource?.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERROR] Inizializzazione WebView2 fallita: {ex.Message}", LogLevel.Error);
|
||||
_webViewInitCompletionSource?.TrySetResult(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica e importa cookie se disponibile
|
||||
/// </summary>
|
||||
private async Task CheckAndImportCookieIfAvailable()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Aspetta che la pagina sia completamente caricata
|
||||
await Task.Delay(1000);
|
||||
|
||||
var cookie = await GetCookieFromWebView();
|
||||
|
||||
if (!string.IsNullOrEmpty(cookie))
|
||||
{
|
||||
var currentSession = _sessionService?.GetCurrentSession();
|
||||
|
||||
// Importa solo se diverso da quello salvato
|
||||
if (currentSession == null ||
|
||||
string.IsNullOrEmpty(currentSession.CookieString) ||
|
||||
!currentSession.CookieString.Contains(cookie))
|
||||
{
|
||||
Log("[BROWSER] Cookie rilevato nel browser - importazione automatica...", LogLevel.Info);
|
||||
await AutoImportCookieFromWebView(cookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[WARN] Verifica cookie fallita: {ex.Message}", LogLevel.Warning);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Aspetta che WebView sia inizializzata (con timeout)
|
||||
/// </summary>
|
||||
private async Task<bool> WaitForWebViewInitAsync(int timeoutSeconds = 60)
|
||||
{
|
||||
if (_isWebViewInitialized)
|
||||
return true;
|
||||
|
||||
_webViewInitCompletionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
// Timeout
|
||||
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(timeoutSeconds));
|
||||
var completedTask = await Task.WhenAny(_webViewInitCompletionSource.Task, timeoutTask);
|
||||
|
||||
if (completedTask == timeoutTask)
|
||||
{
|
||||
Log("[WARN] Timeout attesa inizializzazione WebView2", LogLevel.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
return await _webViewInitCompletionSource.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evento chiamato quando la navigazione nella WebView è completata
|
||||
/// Rileva automaticamente se l'utente ha effettuato il login
|
||||
/// </summary>
|
||||
private async void OnWebViewNavigationCompleted(object? sender, CoreWebView2NavigationCompletedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!e.IsSuccess || EmbeddedWebView?.CoreWebView2 == null)
|
||||
return;
|
||||
|
||||
var url = EmbeddedWebView.CoreWebView2.Source;
|
||||
|
||||
// Se l'utente è sulla homepage di Bidoo (dopo login), verifica cookie
|
||||
if (url.Contains("bidoo.com") && !url.Contains("login"))
|
||||
{
|
||||
// ? REFACTORED: Delega a CheckAndImportCookieIfAvailable
|
||||
await CheckAndImportCookieIfAvailable();
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Importa automaticamente il cookie dalla WebView senza conferma utente
|
||||
/// </summary>
|
||||
private async Task<bool> AutoImportCookieFromWebView(string cookieString)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Valida e attiva il cookie usando SessionService
|
||||
var result = await _sessionService.ValidateAndActivateSessionAsync(cookieString);
|
||||
|
||||
if (result.Success && result.Session != null)
|
||||
{
|
||||
// Salva automaticamente la sessione
|
||||
_sessionService.SaveSession(result.Session);
|
||||
|
||||
// Aggiorna il banner
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
SetUserBanner(result.Session.Username, result.Session.RemainingBids);
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Estrae il cookie __stattrb dalla WebView2
|
||||
/// </summary>
|
||||
/// <returns>Cookie completo o null se non trovato</returns>
|
||||
private async Task<string?> GetCookieFromWebView()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (EmbeddedWebView?.CoreWebView2 == null)
|
||||
return null;
|
||||
|
||||
// Ottieni tutti i cookie di bidoo.com
|
||||
var cookies = await EmbeddedWebView.CoreWebView2.CookieManager.GetCookiesAsync("https://it.bidoo.com");
|
||||
|
||||
if (cookies == null || cookies.Count == 0)
|
||||
return null;
|
||||
|
||||
// Cerca il cookie __stattrb (cookie di sessione principale)
|
||||
var stattrb = cookies.FirstOrDefault(c => c.Name == "__stattrb");
|
||||
|
||||
if (stattrb == null)
|
||||
return null;
|
||||
|
||||
// Costruisci la stringa cookie completa con tutti i cookie necessari
|
||||
var cookieStrings = cookies
|
||||
.Where(c => !string.IsNullOrEmpty(c.Value))
|
||||
.Select(c => $"{c.Name}={c.Value}")
|
||||
.ToList();
|
||||
|
||||
return string.Join("; ", cookieStrings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[WARN] Impossibile estrarre cookie da WebView: {ex.Message}", LogLevel.Warning);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Importa il cookie dalla WebView e lo salva per l'uso nelle API
|
||||
/// </summary>
|
||||
public async Task<bool> ImportCookieFromWebView()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_isWebViewInitialized || EmbeddedWebView?.CoreWebView2 == null)
|
||||
{
|
||||
Log("[WARN] Browser non inizializzato - attendi qualche secondo e riprova", LogLevel.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
Log("[BROWSER] Estrazione cookie dal browser...", LogLevel.Info);
|
||||
|
||||
var cookieString = await GetCookieFromWebView();
|
||||
|
||||
if (string.IsNullOrEmpty(cookieString))
|
||||
{
|
||||
Log("[WARN] Nessun cookie trovato nel browser - assicurati di aver effettuato il login su bidoo.com", LogLevel.Warning);
|
||||
return false;
|
||||
}
|
||||
|
||||
// ? NOTA: Non aggiorna più TextBox (rimossa) - direttamente alla validazione
|
||||
|
||||
// Valida e attiva il cookie usando SessionService
|
||||
var result = await _sessionService.ValidateAndActivateSessionAsync(cookieString);
|
||||
|
||||
if (result.Success && result.Session != null)
|
||||
{
|
||||
// Salva automaticamente la sessione
|
||||
_sessionService.SaveSession(result.Session);
|
||||
|
||||
// Aggiorna il banner
|
||||
SetUserBanner(result.Session.Username, result.Session.RemainingBids);
|
||||
|
||||
Log($"[OK] Cookie importato e validato - Utente: {result.Session.Username}, Puntate: {result.Session.RemainingBids}", LogLevel.Success);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log($"[ERRORE] Cookie importato ma non valido: {result.ErrorMessage}", LogLevel.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Importazione cookie: {ex.Message}", LogLevel.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica se WebView2 è pronta per l'uso
|
||||
/// </summary>
|
||||
public bool IsWebViewReady()
|
||||
{
|
||||
return _isWebViewInitialized && EmbeddedWebView?.CoreWebView2 != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
Mimante/Data/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
# This file ensures the data directory is tracked by git
|
||||
27
Mimante/Data/ApplicationDbContext.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.Data;
|
||||
|
||||
/// <summary>
|
||||
/// DbContext per autenticazione Identity
|
||||
/// </summary>
|
||||
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
|
||||
{
|
||||
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
base.OnModelCreating(builder);
|
||||
|
||||
// Personalizza nomi tabelle Identity (opzionale)
|
||||
builder.Entity<ApplicationUser>(entity =>
|
||||
{
|
||||
entity.ToTable("Users");
|
||||
});
|
||||
}
|
||||
}
|
||||
211
Mimante/Data/PostgresStatsContext.cs
Normal file
@@ -0,0 +1,211 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.Data
|
||||
{
|
||||
/// <summary>
|
||||
/// Context Entity Framework per PostgreSQL - Database Statistiche Aste
|
||||
/// Gestisce aste concluse, metriche strategiche e analisi performance
|
||||
/// </summary>
|
||||
public class PostgresStatsContext : DbContext
|
||||
{
|
||||
public PostgresStatsContext(DbContextOptions<PostgresStatsContext> options)
|
||||
: base(options)
|
||||
{
|
||||
}
|
||||
|
||||
// Tabelle principali
|
||||
public DbSet<CompletedAuction> CompletedAuctions { get; set; }
|
||||
public DbSet<BidderPerformance> BidderPerformances { get; set; }
|
||||
public DbSet<ProductStatistic> ProductStatistics { get; set; }
|
||||
public DbSet<DailyMetric> DailyMetrics { get; set; }
|
||||
public DbSet<StrategicInsight> StrategicInsights { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// Configurazione CompletedAuction
|
||||
modelBuilder.Entity<CompletedAuction>(entity =>
|
||||
{
|
||||
entity.ToTable("completed_auctions");
|
||||
entity.HasKey(e => e.Id);
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.AuctionId).HasColumnName("auction_id").IsRequired().HasMaxLength(100);
|
||||
entity.Property(e => e.ProductName).HasColumnName("product_name").IsRequired().HasMaxLength(500);
|
||||
entity.Property(e => e.FinalPrice).HasColumnName("final_price").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.BuyNowPrice).HasColumnName("buy_now_price").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.ShippingCost).HasColumnName("shipping_cost").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.TotalBids).HasColumnName("total_bids");
|
||||
entity.Property(e => e.MyBidsCount).HasColumnName("my_bids_count");
|
||||
entity.Property(e => e.ResetCount).HasColumnName("reset_count");
|
||||
entity.Property(e => e.Won).HasColumnName("won");
|
||||
entity.Property(e => e.WinnerUsername).HasColumnName("winner_username").HasMaxLength(100);
|
||||
entity.Property(e => e.CompletedAt).HasColumnName("completed_at");
|
||||
entity.Property(e => e.DurationSeconds).HasColumnName("duration_seconds");
|
||||
entity.Property(e => e.AverageLatency).HasColumnName("average_latency").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.Savings).HasColumnName("savings").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.TotalCost).HasColumnName("total_cost").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.CreatedAt).HasColumnName("created_at").HasDefaultValueSql("CURRENT_TIMESTAMP");
|
||||
|
||||
entity.HasIndex(e => e.AuctionId).HasDatabaseName("idx_auction_id");
|
||||
entity.HasIndex(e => e.ProductName).HasDatabaseName("idx_product_name");
|
||||
entity.HasIndex(e => e.CompletedAt).HasDatabaseName("idx_completed_at");
|
||||
entity.HasIndex(e => e.Won).HasDatabaseName("idx_won");
|
||||
});
|
||||
|
||||
// Configurazione BidderPerformance
|
||||
modelBuilder.Entity<BidderPerformance>(entity =>
|
||||
{
|
||||
entity.ToTable("bidder_performances");
|
||||
entity.HasKey(e => e.Id);
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.Username).HasColumnName("username").IsRequired().HasMaxLength(100);
|
||||
entity.Property(e => e.TotalAuctions).HasColumnName("total_auctions");
|
||||
entity.Property(e => e.AuctionsWon).HasColumnName("auctions_won");
|
||||
entity.Property(e => e.AuctionsLost).HasColumnName("auctions_lost");
|
||||
entity.Property(e => e.TotalBidsPlaced).HasColumnName("total_bids_placed");
|
||||
entity.Property(e => e.WinRate).HasColumnName("win_rate").HasColumnType("decimal(5,2)");
|
||||
entity.Property(e => e.AverageBidsPerAuction).HasColumnName("average_bids_per_auction").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.AverageCompetition).HasColumnName("average_competition").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.IsAggressive).HasColumnName("is_aggressive");
|
||||
entity.Property(e => e.LastSeenAt).HasColumnName("last_seen_at");
|
||||
entity.Property(e => e.UpdatedAt).HasColumnName("updated_at").HasDefaultValueSql("CURRENT_TIMESTAMP");
|
||||
|
||||
entity.HasIndex(e => e.Username).IsUnique().HasDatabaseName("idx_username");
|
||||
entity.HasIndex(e => e.WinRate).HasDatabaseName("idx_win_rate");
|
||||
});
|
||||
|
||||
// Configurazione ProductStatistic
|
||||
modelBuilder.Entity<ProductStatistic>(entity =>
|
||||
{
|
||||
entity.ToTable("product_statistics");
|
||||
entity.HasKey(e => e.Id);
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.ProductKey).HasColumnName("product_key").IsRequired().HasMaxLength(200);
|
||||
entity.Property(e => e.ProductName).HasColumnName("product_name").IsRequired().HasMaxLength(500);
|
||||
entity.Property(e => e.TotalAuctions).HasColumnName("total_auctions");
|
||||
entity.Property(e => e.AverageWinningBids).HasColumnName("average_winning_bids").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.AverageFinalPrice).HasColumnName("average_final_price").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.AverageResets).HasColumnName("average_resets").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.MinBidsSeen).HasColumnName("min_bids_seen");
|
||||
entity.Property(e => e.MaxBidsSeen).HasColumnName("max_bids_seen");
|
||||
entity.Property(e => e.RecommendedMaxBids).HasColumnName("recommended_max_bids");
|
||||
entity.Property(e => e.RecommendedMaxPrice).HasColumnName("recommended_max_price").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.CompetitionLevel).HasColumnName("competition_level").HasMaxLength(20);
|
||||
entity.Property(e => e.LastUpdated).HasColumnName("last_updated").HasDefaultValueSql("CURRENT_TIMESTAMP");
|
||||
|
||||
entity.HasIndex(e => e.ProductKey).IsUnique().HasDatabaseName("idx_product_key");
|
||||
entity.HasIndex(e => e.ProductName).HasDatabaseName("idx_product_name_stats");
|
||||
});
|
||||
|
||||
// Configurazione DailyMetric
|
||||
modelBuilder.Entity<DailyMetric>(entity =>
|
||||
{
|
||||
entity.ToTable("daily_metrics");
|
||||
entity.HasKey(e => e.Id);
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.Date).HasColumnName("date").HasColumnType("date");
|
||||
entity.Property(e => e.TotalBidsUsed).HasColumnName("total_bids_used");
|
||||
entity.Property(e => e.MoneySpent).HasColumnName("money_spent").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.AuctionsWon).HasColumnName("auctions_won");
|
||||
entity.Property(e => e.AuctionsLost).HasColumnName("auctions_lost");
|
||||
entity.Property(e => e.TotalSavings).HasColumnName("total_savings").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.AverageLatency).HasColumnName("average_latency").HasColumnType("decimal(10,2)");
|
||||
entity.Property(e => e.WinRate).HasColumnName("win_rate").HasColumnType("decimal(5,2)");
|
||||
entity.Property(e => e.ROI).HasColumnName("roi").HasColumnType("decimal(10,2)");
|
||||
|
||||
entity.HasIndex(e => e.Date).IsUnique().HasDatabaseName("idx_date");
|
||||
});
|
||||
|
||||
// Configurazione StrategicInsight
|
||||
modelBuilder.Entity<StrategicInsight>(entity =>
|
||||
{
|
||||
entity.ToTable("strategic_insights");
|
||||
entity.HasKey(e => e.Id);
|
||||
|
||||
entity.Property(e => e.Id).HasColumnName("id");
|
||||
entity.Property(e => e.InsightType).HasColumnName("insight_type").IsRequired().HasMaxLength(50);
|
||||
entity.Property(e => e.ProductKey).HasColumnName("product_key").HasMaxLength(200);
|
||||
entity.Property(e => e.RecommendedAction).HasColumnName("recommended_action").IsRequired();
|
||||
entity.Property(e => e.ConfidenceLevel).HasColumnName("confidence_level").HasColumnType("decimal(5,2)");
|
||||
entity.Property(e => e.DataPoints).HasColumnName("data_points");
|
||||
entity.Property(e => e.Reasoning).HasColumnName("reasoning");
|
||||
entity.Property(e => e.CreatedAt).HasColumnName("created_at").HasDefaultValueSql("CURRENT_TIMESTAMP");
|
||||
entity.Property(e => e.IsActive).HasColumnName("is_active").HasDefaultValue(true);
|
||||
|
||||
entity.HasIndex(e => e.InsightType).HasDatabaseName("idx_insight_type");
|
||||
entity.HasIndex(e => e.ProductKey).HasDatabaseName("idx_product_key_insight");
|
||||
entity.HasIndex(e => e.CreatedAt).HasDatabaseName("idx_created_at");
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica e crea lo schema del database
|
||||
/// </summary>
|
||||
public async Task<bool> EnsureSchemaAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Verifica connessione
|
||||
if (!await Database.CanConnectAsync())
|
||||
{
|
||||
Console.WriteLine("[PostgreSQL] Cannot connect to database");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Crea schema se non esistono le tabelle (senza migrations)
|
||||
var created = await Database.EnsureCreatedAsync();
|
||||
|
||||
if (created)
|
||||
{
|
||||
Console.WriteLine("[PostgreSQL] Schema created successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("[PostgreSQL] Schema already exists");
|
||||
}
|
||||
|
||||
// Verifica che tutte le tabelle esistano
|
||||
var hasCompletedAuctions = await CompletedAuctions.AnyAsync();
|
||||
Console.WriteLine($"[PostgreSQL] Database verified - {(hasCompletedAuctions ? "has data" : "empty")}");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[PostgreSQL ERROR] Schema creation failed: {ex.Message}");
|
||||
Console.WriteLine($"[PostgreSQL ERROR] Stack trace: {ex.StackTrace}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifica che tutte le tabelle richieste esistano
|
||||
/// </summary>
|
||||
public async Task<bool> ValidateSchemaAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Prova a contare le righe di ogni tabella (forza check esistenza)
|
||||
await CompletedAuctions.CountAsync();
|
||||
await BidderPerformances.CountAsync();
|
||||
await ProductStatistics.CountAsync();
|
||||
await DailyMetrics.CountAsync();
|
||||
await StrategicInsights.CountAsync();
|
||||
|
||||
Console.WriteLine("[PostgreSQL] All tables validated successfully");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[PostgreSQL ERROR] Schema validation failed: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Mimante/Data/StatisticsContext.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using AutoBidder.Models;
|
||||
|
||||
namespace AutoBidder.Data
|
||||
{
|
||||
public class StatisticsContext : DbContext
|
||||
{
|
||||
public DbSet<ProductStat> ProductStats { get; set; }
|
||||
|
||||
public StatisticsContext(DbContextOptions<StatisticsContext> options) : base(options)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<ProductStat>()
|
||||
.HasIndex(p => p.ProductKey)
|
||||
.IsUnique(false);
|
||||
|
||||
base.OnModelCreating(modelBuilder);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
Mimante/Dialogs/AddAuctionSimpleDialog.xaml
Normal file
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Window x:Class="AutoBidder.Dialogs.AddAuctionSimpleDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:AutoBidder.Controls"
|
||||
Title="Aggiungi Asta" Height="320" Width="700"
|
||||
Background="#0a0a0a" Foreground="#FFFFFF"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Icon="pack://application:,,,/Icon/favicon.ico"
|
||||
ResizeMode="NoResize">
|
||||
<Border Background="#1a1a1a" CornerRadius="8" Padding="16" Margin="8">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Text="Inserire URL dell'asta (uno o più)" Foreground="#CCCCCC" FontSize="14" Margin="0,0,0,6" />
|
||||
<TextBlock Grid.Row="1" Text="Puoi aggiungere più link separandoli con 'a capo', 'spazio' o ';'" Foreground="#999999" FontSize="12" Margin="0,0,0,10" />
|
||||
|
||||
<TextBox x:Name="AuctionUrlBox" Grid.Row="2" MinWidth="560" Margin="0,0,0,8"
|
||||
Background="#181818" Foreground="#00CCFF" BorderBrush="#444" BorderThickness="1"
|
||||
Padding="8" FontSize="13" ToolTip="Inserisci uno o più URL/ID dell'asta. Separali con a capo, spazio o ';'"
|
||||
AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" Height="160" />
|
||||
|
||||
<controls:SimpleToolbar Grid.Row="3" Margin="0,8,0,0">
|
||||
<controls:SimpleToolbar.RightContent>
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
||||
<Button Content="OK" Width="110" Margin="6" Padding="10,8"
|
||||
Style="{StaticResource SmallButtonStyle}" Background="#00CC66" Foreground="White" Click="OkButton_Click" />
|
||||
<Button Content="Annulla" Width="110" Margin="6" Padding="10,8"
|
||||
Style="{StaticResource SmallButtonStyle}" Background="#666" Foreground="White" Click="CancelButton_Click" />
|
||||
</StackPanel>
|
||||
</controls:SimpleToolbar.RightContent>
|
||||
</controls:SimpleToolbar>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
35
Mimante/Dialogs/AddAuctionSimpleDialog.xaml.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace AutoBidder.Dialogs
|
||||
{
|
||||
public partial class AddAuctionSimpleDialog : Window
|
||||
{
|
||||
public string AuctionId { get; private set; } = string.Empty;
|
||||
|
||||
public AddAuctionSimpleDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var text = AuctionUrlBox.Text ?? string.Empty;
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
MessageBox.Show("Inserisci almeno un URL o ID dell'asta.", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Return the raw text (may contain multiple entries); caller will parse it
|
||||
AuctionId = text.Trim();
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DialogResult = false;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
89
Mimante/Dialogs/ClosedAuctionsWindow.xaml
Normal file
@@ -0,0 +1,89 @@
|
||||
<Window x:Class="AutoBidder.Dialogs.ClosedAuctionsWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Aste Chiuse - Estrazione" Height="600" Width="1000"
|
||||
Background="#0a0a0a" Foreground="#FFFFFF" WindowStartupLocation="CenterOwner">
|
||||
<Grid Margin="10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="8" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Border Background="#1a1a1a" Padding="10" CornerRadius="6" Grid.Row="0" BorderBrush="#333333" BorderThickness="1">
|
||||
<DockPanel>
|
||||
<TextBlock Text="Estrazione Aste Chiuse" FontSize="16" FontWeight="Bold" Foreground="#00CC66" VerticalAlignment="Center" DockPanel.Dock="Left" />
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" DockPanel.Dock="Right">
|
||||
<Button x:Name="StartExtractButton" Content="Avvia Estrazione" Click="StartExtractButton_Click" Width="140" Height="36" Margin="8,0,0,0" Background="#00CC66" Style="{StaticResource SmallButtonStyle}"/>
|
||||
<Button x:Name="ExportStatsButton" Content="Esporta Statistiche" Click="ExportStatsButton_Click" Width="160" Height="36" Margin="8,0,0,0" Background="#8B5CF6" Style="{StaticResource SmallButtonStyle}"/>
|
||||
<Button x:Name="CloseButton" Content="Chiudi" Click="CloseButton_Click" Width="80" Height="36" Margin="8,0,0,0" Background="#666" Style="{StaticResource SmallButtonStyle}"/>
|
||||
</StackPanel>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
|
||||
<Border Grid.Row="2" Background="#1a1a1a" Padding="8" CornerRadius="6" BorderBrush="#333333" BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="8" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<!-- Products grid: styled like MainWindow -->
|
||||
<DataGrid x:Name="ProductsGrid" AutoGenerateColumns="False" Grid.Column="0" Background="#1a1a1a" Foreground="#FFFFFF" BorderBrush="#333333" BorderThickness="1"
|
||||
RowBackground="#1a1a1a" AlternatingRowBackground="#222222" GridLinesVisibility="Horizontal" HorizontalGridLinesBrush="#333333"
|
||||
IsReadOnly="True" SelectionUnit="CellOrRowHeader" SelectionMode="Extended" ClipboardCopyMode="IncludeHeader" CanUserAddRows="False" CanUserDeleteRows="False">
|
||||
<DataGrid.Resources>
|
||||
<Style TargetType="DataGridColumnHeader">
|
||||
<Setter Property="Background" Value="#2a2a2a" />
|
||||
<Setter Property="Foreground" Value="#FFFFFF" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="Padding" Value="10,8" />
|
||||
<Setter Property="BorderThickness" Value="0,0,0,2" />
|
||||
<Setter Property="BorderBrush" Value="#00CC66" />
|
||||
</Style>
|
||||
<Style TargetType="DataGridRow">
|
||||
<Setter Property="Height" Value="36" />
|
||||
<Style.Triggers>
|
||||
<Trigger Property="IsSelected" Value="True">
|
||||
<Setter Property="Background" Value="#0099FF" />
|
||||
<Setter Property="Foreground" Value="White" />
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
<Style TargetType="DataGridCell">
|
||||
<Setter Property="BorderThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="10,6" />
|
||||
</Style>
|
||||
</DataGrid.Resources>
|
||||
|
||||
<DataGrid.ContextMenu>
|
||||
<ContextMenu>
|
||||
<MenuItem Command="ApplicationCommands.Copy" Header="Copia" />
|
||||
</ContextMenu>
|
||||
</DataGrid.ContextMenu>
|
||||
|
||||
<DataGrid.Columns>
|
||||
<DataGridTextColumn Header="Asta URL" Binding="{Binding AuctionUrl}" Width="2*" />
|
||||
<DataGridTextColumn Header="Nome" Binding="{Binding ProductName}" Width="3*"/>
|
||||
<DataGridTextColumn Header="Prezzo" Binding="{Binding FinalPrice}" Width="80"/>
|
||||
<DataGridTextColumn Header="Vincitore" Binding="{Binding Winner}" Width="120"/>
|
||||
<DataGridTextColumn Header="Puntate Usate" Binding="{Binding BidsUsed}" Width="100"/>
|
||||
<DataGridTextColumn Header="Scraped At" Binding="{Binding ScrapedAt}" Width="140"/>
|
||||
</DataGrid.Columns>
|
||||
</DataGrid>
|
||||
|
||||
<GridSplitter Grid.Column="1" Width="8" />
|
||||
|
||||
<!-- Log area styled like main window log -->
|
||||
<Border Grid.Column="2" Background="#0f0f0f" Padding="8" CornerRadius="6" BorderBrush="#333333" BorderThickness="1">
|
||||
<DockPanel>
|
||||
<TextBlock Text="Log Operazioni" FontWeight="Bold" Foreground="#00CC66" DockPanel.Dock="Top" Margin="0,0,0,8" />
|
||||
<RichTextBox x:Name="ExtractLogBox" IsReadOnly="True" VerticalScrollBarVisibility="Auto" FontFamily="Consolas" FontSize="11" Background="#0f0f0f" Foreground="#CCC" BorderBrush="#333333" BorderThickness="1" />
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
140
Mimante/Dialogs/ClosedAuctionsWindow.xaml.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using Microsoft.Win32;
|
||||
using AutoBidder.Models;
|
||||
using AutoBidder.Services;
|
||||
using AutoBidder.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace AutoBidder.Dialogs
|
||||
{
|
||||
public partial class ClosedAuctionsWindow : Window
|
||||
{
|
||||
private ObservableCollection<ClosedAuctionRecord> _products = new();
|
||||
|
||||
private bool _isRunning = false;
|
||||
|
||||
// StatsService using local DB. Create context with default sqlite file in app folder
|
||||
private readonly StatsService _statsService;
|
||||
|
||||
public ClosedAuctionsWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
ProductsGrid.ItemsSource = _products;
|
||||
|
||||
var optionsBuilder = new DbContextOptionsBuilder<StatisticsContext>();
|
||||
var dbPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "stats.db");
|
||||
optionsBuilder.UseSqlite($"Data Source={dbPath}");
|
||||
var ctx = new StatisticsContext(optionsBuilder.Options);
|
||||
_statsService = new StatsService(ctx);
|
||||
|
||||
Log("Finestra pronta");
|
||||
}
|
||||
|
||||
private void Log(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
var para = new Paragraph(new Run($"{DateTime.Now:HH:mm} - {message}"));
|
||||
ExtractLogBox.Document.Blocks.Add(para);
|
||||
// keep size manageable
|
||||
while (ExtractLogBox.Document.Blocks.Count > 500)
|
||||
ExtractLogBox.Document.Blocks.Remove(ExtractLogBox.Document.Blocks.FirstBlock);
|
||||
ExtractLogBox.ScrollToEnd();
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
private async void StartExtractButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (_isRunning)
|
||||
{
|
||||
Log("Estrazione già in corso");
|
||||
return;
|
||||
}
|
||||
|
||||
_isRunning = true;
|
||||
StartExtractButton.IsEnabled = false;
|
||||
Log("Avvio procedura di estrazione da closed_auctions.php...");
|
||||
|
||||
try
|
||||
{
|
||||
var scraper = new ClosedAuctionsScraper(null, _statsService, Log);
|
||||
var closedUrl = "https://it.bidoo.com/closed_auctions.php";
|
||||
|
||||
Log($"Scarico: {closedUrl}");
|
||||
|
||||
int count = 0;
|
||||
await foreach (var rec in scraper.ScrapeYieldAsync(closedUrl))
|
||||
{
|
||||
// Filter out records without bids info (user requested)
|
||||
if (!rec.BidsUsed.HasValue)
|
||||
{
|
||||
Log($"Scartata asta (mancano puntate): {rec.AuctionUrl} - '{rec.ProductName ?? "?"}'");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add and log incrementally so user sees progress
|
||||
_products.Add(rec);
|
||||
count++;
|
||||
Log($"[{count}] {rec.ProductName} | Prezzo: {(rec.FinalPrice.HasValue?rec.FinalPrice.Value.ToString("F2")+"€":"--")} | Vincitore: {rec.Winner ?? "--"} | Puntate: {rec.BidsUsed.Value} | URL: {rec.AuctionUrl}");
|
||||
}
|
||||
|
||||
Log($"Estrazione completata: {count} record aggiunti.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Estrattore: {ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isRunning = false;
|
||||
StartExtractButton.IsEnabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.Close();
|
||||
}
|
||||
|
||||
private async void ExportStatsButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
Log("Preparazione esportazione statistiche...");
|
||||
var stats = await _statsService.GetAllStatsAsync();
|
||||
if (stats == null || stats.Count == 0)
|
||||
{
|
||||
Log("Nessuna statistica disponibile da esportare.");
|
||||
MessageBox.Show(this, "Nessuna statistica disponibile.", "Esporta Statistiche", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
return;
|
||||
}
|
||||
|
||||
var dlg = new SaveFileDialog() { Filter = "CSV files|*.csv|All files|*.*", FileName = "auction_stats.csv" };
|
||||
if (dlg.ShowDialog(this) != true) return;
|
||||
|
||||
using var sw = new StreamWriter(dlg.FileName, false, System.Text.Encoding.UTF8);
|
||||
sw.WriteLine("ProductKey,ProductName,TotalAuctions,AverageBidsUsed,AverageFinalPrice,LastSeen");
|
||||
foreach (var s in stats)
|
||||
{
|
||||
var line = $"\"{s.ProductKey}\",\"{s.ProductName}\",{s.TotalAuctions},{s.AverageBidsUsed:F2},{s.AverageFinalPrice:F2},{s.LastSeen:O}";
|
||||
sw.WriteLine(line);
|
||||
}
|
||||
|
||||
Log($"Statistiche esportate su: {dlg.FileName}");
|
||||
MessageBox.Show(this, "Statistiche esportate con successo.", "Esporta Statistiche", MessageBoxButton.OK, MessageBoxImage.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log($"[ERRORE] Esporta: {ex.Message}");
|
||||
MessageBox.Show(this, "Errore durante esportazione: " + ex.Message, "Esporta Statistiche", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
Mimante/Dialogs/SessionDialog.xaml
Normal file
@@ -0,0 +1,41 @@
|
||||
<Window x:Class="AutoBidder.Dialogs.SessionDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
Title="Configura Sessione" Height="440" Width="700"
|
||||
Background="#0a0a0a" Foreground="#FFFFFF"
|
||||
WindowStartupLocation="CenterOwner"
|
||||
Icon="pack://application:,,,/Icon/favicon.ico"
|
||||
ResizeMode="NoResize">
|
||||
<Border Background="#1a1a1a" CornerRadius="8" Padding="16" Margin="8">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="Inserisci Cookie di sessione" FontSize="16" FontWeight="SemiBold" Foreground="#00CC66" Margin="0,0,0,12" />
|
||||
<TextBlock Grid.Row="1" Text="Cookie di sessione (copia dal menu delle Impostazioni/Applicazioni di Chrome)" Foreground="#CCCCCC" FontSize="13" />
|
||||
<TextBlock Grid.Row="2" Foreground="#888" FontSize="12" TextWrapping="Wrap" Margin="0,4,0,10">
|
||||
<Run Text="Come trovare i cookie di sessione in Chrome:" />
|
||||
<LineBreak/>
|
||||
<Run Text="1. Apri Chrome e premi F12 (Windows) o Cmd+Option+I (Mac) per aprire gli Strumenti per sviluppatori." />
|
||||
<LineBreak/>
|
||||
<Run Text="2. Vai alla scheda 'Application'." />
|
||||
<LineBreak/>
|
||||
<Run Text="3. Nel pannello a sinistra, espandi 'Storage' e seleziona 'Cookies'." />
|
||||
<LineBreak/>
|
||||
<Run Text="4. Scegli il sito desiderato e copia il valore del cookie di sessione." />
|
||||
</TextBlock>
|
||||
<TextBox x:Name="CookieBox" Grid.Row="3" MinWidth="320" MinHeight="120" MaxHeight="220" VerticalScrollBarVisibility="Auto"
|
||||
Background="#181818" Foreground="#00CCFF" BorderBrush="#444" BorderThickness="1" Padding="8" FontSize="14" AcceptsReturn="True" TextWrapping="Wrap" />
|
||||
<StackPanel Grid.Row="4" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
|
||||
<Button x:Name="OkButton" Content="OK" Width="110" Margin="6" Padding="10,8"
|
||||
Style="{StaticResource SmallButtonStyle}" Background="#00CC66" Foreground="White" Click="OkButton_Click" />
|
||||
<Button x:Name="CancelButton" Content="Annulla" Width="110" Margin="6" Padding="10,8"
|
||||
Style="{StaticResource SmallButtonStyle}" Background="#666" Foreground="White" Click="CancelButton_Click" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
||||
33
Mimante/Dialogs/SessionDialog.xaml.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace AutoBidder.Dialogs
|
||||
{
|
||||
public partial class SessionDialog : Window
|
||||
{
|
||||
public string AuthToken { get; private set; } = string.Empty;
|
||||
|
||||
public SessionDialog(string existingToken = "", string existingUsername = "")
|
||||
{
|
||||
InitializeComponent();
|
||||
CookieBox.Text = existingToken ?? string.Empty;
|
||||
}
|
||||
|
||||
private void OkButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AuthToken = CookieBox.Text?.Trim() ?? string.Empty;
|
||||
if (string.IsNullOrEmpty(AuthToken))
|
||||
{
|
||||
MessageBox.Show("Cookie obbligatorio", "Errore", MessageBoxButton.OK, MessageBoxImage.Warning);
|
||||
return;
|
||||
}
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DialogResult = false;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
81
Mimante/Dockerfile
Normal file
@@ -0,0 +1,81 @@
|
||||
# ============================================
|
||||
# STAGE 1: Build
|
||||
# ============================================
|
||||
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
WORKDIR /src
|
||||
|
||||
# Copy csproj and restore dependencies (cache layer)
|
||||
COPY ["AutoBidder.csproj", "."]
|
||||
RUN dotnet restore "./AutoBidder.csproj"
|
||||
|
||||
# Copy all source files
|
||||
COPY . .
|
||||
|
||||
# Build application
|
||||
WORKDIR "/src/."
|
||||
RUN dotnet build "./AutoBidder.csproj" -c $BUILD_CONFIGURATION -o /app/build --no-restore
|
||||
|
||||
# ============================================
|
||||
# STAGE 2: Publish
|
||||
# ============================================
|
||||
FROM build AS publish
|
||||
ARG BUILD_CONFIGURATION=Release
|
||||
# RIMOSSO --no-build per evitare errore path
|
||||
RUN dotnet publish "./AutoBidder.csproj" \
|
||||
-c $BUILD_CONFIGURATION \
|
||||
-o /app/publish \
|
||||
/p:UseAppHost=false
|
||||
|
||||
# ============================================
|
||||
# STAGE 3: Final Runtime
|
||||
# ============================================
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS final
|
||||
WORKDIR /app
|
||||
|
||||
# Install curl for healthcheck and sqlite3
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
ca-certificates \
|
||||
sqlite3 && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Create data directories for persistence
|
||||
RUN mkdir -p /app/Data /app/Data/backups /app/logs && \
|
||||
chmod 777 /app/Data /app/logs
|
||||
|
||||
# Copy published application
|
||||
COPY --from=publish /app/publish .
|
||||
|
||||
# Expose port (single HTTP for simplicity)
|
||||
EXPOSE 8080
|
||||
|
||||
# Environment variables (overridable via docker-compose/unraid)
|
||||
ENV ASPNETCORE_URLS=http://+:8080
|
||||
ENV ASPNETCORE_ENVIRONMENT=Production
|
||||
ENV Kestrel__EnableHttps=false
|
||||
|
||||
# Database path - tutti i database SQLite e dati persistenti
|
||||
# Può essere sovrascritto nel docker-compose per mappare un volume persistente
|
||||
ENV DATA_PATH=/app/Data
|
||||
|
||||
# Autenticazione applicazione (OBBLIGATORIO)
|
||||
ENV ADMIN_USERNAME=admin
|
||||
ENV ADMIN_PASSWORD=
|
||||
|
||||
# Health check
|
||||
# Aumentato timeout e start-period per Blazor Server
|
||||
HEALTHCHECK --interval=30s --timeout=30s --start-period=90s --retries=5 \
|
||||
CMD curl -f http://localhost:8080/ || exit 1
|
||||
|
||||
# Labels for metadata
|
||||
LABEL org.opencontainers.image.title="AutoBidder" \
|
||||
org.opencontainers.image.description="Sistema automatizzato gestione aste Bidoo - Blazor .NET 8" \
|
||||
org.opencontainers.image.version="1.2.0" \
|
||||
org.opencontainers.image.vendor="Alby96" \
|
||||
org.opencontainers.image.source="https://gitea.encke-hake.ts.net/Alby96/Mimante"
|
||||
|
||||
# Entry point
|
||||
ENTRYPOINT ["dotnet", "AutoBidder.dll"]
|
||||
|
||||
26
Mimante/Documentation/Modifiche.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
______________________________________________________________________________________________________________
|
||||
FUNZIONALITA
|
||||
|
||||
Cambiare la pagina delle statistiche in modo da aggiungere una sezione in più, oltre alle statistiche memorizzate in un automatico, in cui posso associare un range di prezzo e di puntate per ogni articolo, identificato tramite il suo nome
|
||||
|
||||
Aggiungere una scansione periodica e automatica delle aste terminate in modo da aggiornare automaticamente il mio elenco degli articoli delle aste terminate per aggiornare prezzo e numero di puntate usate in automatico. Molto importante: salvare anche l'ora di chiusura dell'asta
|
||||
|
||||
Aggiungere una funzionalità di aggiunta automatica delle aste al monitor appena compaiono nell'elenco delle aste disponibile cercando tramite sezione e nome articolo
|
||||
|
||||
Aggiungi una indicazione visiva nella colonna dello stato che indica quando un'asta pur essendo nello stato attiva il bot non punta perché fuori range oppure per altri motivi
|
||||
|
||||
Fare una tasto nelle statistiche che applichi massivamente i limiti a tutti gli articoli attualmente monitorati che hanno delle informazioni salvate nel database delle aste terminate
|
||||
|
||||
_______________________________________________________________________________________________________________
|
||||
REWORK
|
||||
|
||||
Esegui un rework generico del sistema di log della singola asta e del log globale. Ci sono troppe righe inutili come tante righe simili duplicate nel log della singola asta e informazioni inutili nel log globale come per esempio l'indicazione del focus che si sposta su una certa riga. Valuta i cambiamenti e le ottimizzazioni da fare e applica le modifiche.
|
||||
|
||||
Esegui un rework della grafica in modo da eliminare le animazioni popup che danno fastidio all'usabilità del programma. In particolare intendo che quando il mouse passa su un pulsante o una griglia questa aumenta leggermente di dimensione per evidenziarsi ma questo non mi piace. Elimina questa cosa e sostituiscila piuttosto con una illuminazione o colorazione più chiara o scura per evidenziare il fatto che sto per selezionare quel particolare pulsante
|
||||
|
||||
_______________________________________________________________________________________________________________
|
||||
CORREZIONI
|
||||
|
||||
Aggiungi più stati per indicare la strategia o il fatto che non sta puntando e per quale motivo.
|
||||
In particolare oltre agli stati già presenti indicare anche il motivo per cui non sta puntando come per esempio "fuori range di prezzo", "fuori range di puntate", "asta terminata", "strategia non permette puntata", ecc
|
||||
|
||||
4992
Mimante/Examples/10€ Idea Shopping +10P - Bidoo.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="17px" height="18px" viewBox="0 0 17 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<!-- Generator: sketchtool 57.1 (101010) - https://sketch.com -->
|
||||
<title>E3DC3394-397D-4994-B12B-47234FB13863</title>
|
||||
<desc>Created with sketchtool.</desc>
|
||||
<g id="Product-Pages" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Home---Portrait-Version-A-Copy-6" transform="translate(-77.000000, -637.000000)">
|
||||
<g id="Group-20" transform="translate(63.000000, 553.000000)">
|
||||
<g id="Group-17-Copy" transform="translate(14.000000, 84.000000)">
|
||||
<g id="001-settings" transform="translate(0.000000, 0.500000)">
|
||||
<path d="M15.6392002,7.48800011 C14.1532002,7.20200011 13.4720002,5.46640008 14.3672002,4.24600006 L14.9952002,3.38800005 L13.6376002,2.03040003 L12.7936002,2.60200004 C11.5408002,3.45200005 9.83120015,2.70520004 9.60160014,1.21000002 L9.44080014,0.160000002 L7.52040011,0.160000002 L7.27200011,1.45360002 C6.9920001,2.90520004 5.31720008,3.59920005 4.09200006,2.76920004 L3.00320004,2.03040003 L1.64520002,3.38800005 L2.27360003,4.24600006 C3.16880005,5.46640008 2.48600004,7.20200011 1.00160001,7.48800011 L0,7.68040011 L0,9.60080014 L1.05000002,9.76160015 C2.54520004,9.99120015 3.29200005,11.7008002 2.44200004,12.9536002 L1.87040003,13.7976002 L3.22800005,15.1552002 L4.08600006,14.5272002 C5.30640008,13.6320002 7.0420001,14.3132002 7.32800011,15.7992002 L7.52040011,16.8008003 L9.44080014,16.8008003 L9.55320014,16.0616002 C9.78920015,14.5336002 11.5608002,13.7992002 12.8080002,14.7132002 L13.4108002,15.1552002 L14.7688002,13.7976002 L14.1968002,12.9536002 C13.3484002,11.7008002 14.0936002,9.99120015 15.5892002,9.76160015 L16.6408002,9.60080014 L16.6408002,7.68040011 L15.6392002,7.48800011 Z M8.47960013,10.0804002 C7.68440011,10.0804002 7.0408001,9.43520014 7.0408001,8.63960013 C7.0408001,7.84440012 7.68440011,7.20080011 8.47960013,7.20080011 C9.27520014,7.20080011 9.92040015,7.84440012 9.92040015,8.63960013 C9.92040015,9.43520014 9.27520014,10.0804002 8.47960013,10.0804002 Z" id="Fill-1" fill="#C7CAC7"/>
|
||||
<path d="M8.47960013,5.60080008 C6.8016001,5.60080008 5.44080008,6.9616001 5.44080008,8.63960013 C5.44080008,10.3192002 6.8016001,11.6804002 8.47960013,11.6804002 C10.1592002,11.6804002 11.5204002,10.3192002 11.5204002,8.63960013 C11.5204002,6.9616001 10.1592002,5.60080008 8.47960013,5.60080008 Z M8.47960013,10.0804002 C7.68440011,10.0804002 7.0408001,9.43520014 7.0408001,8.63960013 C7.0408001,7.84440012 7.68440011,7.20080011 8.47960013,7.20080011 C9.27520014,7.20080011 9.92040015,7.84440012 9.92040015,8.63960013 C9.92040015,9.43520014 9.27520014,10.0804002 8.47960013,10.0804002 Z" id="Fill-2" fill="#556080"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18.96 32.35"><defs><style>.cls-1{fill:#38454f;}.cls-2{fill:#1caee4;}.cls-3{fill:#1081e0;}.cls-4{fill:#cbd4d8;}.cls-5{fill:#546a79;}</style></defs><title>Asset 10002-app</title><g id="Layer_2" data-name="Layer 2"><g id="Livello_1" data-name="Livello 1"><path class="cls-1" d="M15.76,32.35H3.2A3.21,3.21,0,0,1,0,29.14V3.2A3.2,3.2,0,0,1,3.2,0H15.76A3.2,3.2,0,0,1,19,3.2V29.14A3.21,3.21,0,0,1,15.76,32.35Z"/><rect class="cls-2" x="1.67" y="3.35" width="15.61" height="23.98"/><path class="cls-3" d="M3.35,7.81a.56.56,0,0,0,.39-.17L6,5.41a.56.56,0,0,0,0-.79.57.57,0,0,0-.79,0L3,6.86a.54.54,0,0,0,0,.78A.56.56,0,0,0,3.35,7.81Z"/><path class="cls-3" d="M3.35,10.6a.56.56,0,0,0,.39-.17L4.86,9.32a.57.57,0,0,0,0-.79.56.56,0,0,0-.79,0L3,9.64a.57.57,0,0,0,.4,1Z"/><path class="cls-3" d="M5.18,7.41a.59.59,0,0,0-.16.4.57.57,0,0,0,.16.39.6.6,0,0,0,.4.17A.58.58,0,0,0,6,8.2a.57.57,0,0,0,.16-.39.56.56,0,0,0-1-.4Z"/><path class="cls-3" d="M6.3,7.09a.54.54,0,0,0,.39.16.57.57,0,0,0,.4-.16L8.76,5.41a.56.56,0,0,0,0-.79.57.57,0,0,0-.79,0L6.3,6.3A.56.56,0,0,0,6.3,7.09Z"/><path class="cls-3" d="M8,7.41l-5,5a.56.56,0,0,0,.4,1,.54.54,0,0,0,.39-.16l5-5a.56.56,0,0,0,0-.79A.57.57,0,0,0,8,7.41Z"/><path class="cls-3" d="M9.08,6.3a.57.57,0,0,0-.16.39.59.59,0,0,0,.16.4.61.61,0,0,0,.4.16A.55.55,0,0,0,10,6.69a.57.57,0,0,0-.16-.39A.59.59,0,0,0,9.08,6.3Z"/><path class="cls-3" d="M11.55,4.62a.57.57,0,0,0-.79,0l-.56.56a.56.56,0,0,0,.4,1A.54.54,0,0,0,11,6l.56-.56A.56.56,0,0,0,11.55,4.62Z"/><path class="cls-4" d="M11.15,2.23H7.81a.56.56,0,0,1-.56-.56.55.55,0,0,1,.56-.55h3.34a.55.55,0,0,1,.56.55A.56.56,0,0,1,11.15,2.23Z"/><path class="cls-5" d="M16.17,2.23h-.56a.56.56,0,0,1-.55-.56.55.55,0,0,1,.55-.55h.56a.55.55,0,0,1,.56.55A.56.56,0,0,1,16.17,2.23Z"/><path class="cls-5" d="M13.94,2.23h-.56a.56.56,0,0,1-.55-.56.55.55,0,0,1,.55-.55h.56a.55.55,0,0,1,.56.55A.56.56,0,0,1,13.94,2.23Z"/><path class="cls-4" d="M10.87,30.67H8.09a.84.84,0,0,1-.84-.83h0A.85.85,0,0,1,8.09,29h2.78a.85.85,0,0,1,.84.84h0A.84.84,0,0,1,10.87,30.67Z"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 31.83 32.52"><defs><style>.cls-1{fill:#ffd039;}.cls-2{fill:#f4b70c;}.cls-3{fill:#ffbb64;}.cls-4{fill:#ffae47;}.cls-5{fill:#ffdf65;}.cls-6{fill:#ffcd2c;}.cls-7{fill:#ffa035;}.cls-8{fill:#f78819;}</style></defs><title>Asset 9002-cup</title><g id="Layer_2" data-name="Layer 2"><g id="Livello_1" data-name="Livello 1"><path class="cls-1" d="M31.05,5.85h0a3.61,3.61,0,0,0-2.83-1.36H24.84a.47.47,0,0,0-.47.48V7.05a.47.47,0,0,0,.47.48h3.38a.56.56,0,0,1,.45.22.58.58,0,0,1,.11.46,9,9,0,0,1-1.93,4,5.79,5.79,0,0,1-2.37,1.58.46.46,0,0,0-.31.34,8.32,8.32,0,0,1-.84,2.26.46.46,0,0,0,0,.5.46.46,0,0,0,.39.2h.08a9,9,0,0,0,5.27-2.83,11.8,11.8,0,0,0,2.64-5.33A3.61,3.61,0,0,0,31.05,5.85Z"/><path class="cls-2" d="M27,12.28V12l-.15.16a5.79,5.79,0,0,1-2.37,1.58.46.46,0,0,0-.31.34,8.32,8.32,0,0,1-.84,2.26.46.46,0,0,0,0,.5.46.46,0,0,0,.39.2h.08a10,10,0,0,0,2.22-.65A9.45,9.45,0,0,0,27,12.28Z"/><path class="cls-2" d="M24.37,5V7.05a.47.47,0,0,0,.47.48H27v-3H24.84A.47.47,0,0,0,24.37,5Z"/><path class="cls-3" d="M19.5,28.05c-.14-.11-1.42-1.18-1.58-7a.49.49,0,0,0-.17-.36.54.54,0,0,0-.39-.1,8.66,8.66,0,0,1-1.44.13h0a8.69,8.69,0,0,1-1.45-.13.54.54,0,0,0-.39.1.49.49,0,0,0-.17.36c-.16,5.8-1.44,6.87-1.58,7a.44.44,0,0,0-.32.5.51.51,0,0,0,.5.42h6.81a.51.51,0,0,0,.5-.42A.44.44,0,0,0,19.5,28.05Z"/><path class="cls-4" d="M19.5,28.05c-.14-.11-1.42-1.18-1.58-7a.49.49,0,0,0-.17-.36.54.54,0,0,0-.39-.1,8.66,8.66,0,0,1-1.44.13h0l-.46,0a.48.48,0,0,1,.16.35c.16,5.8,1.43,6.87,1.58,7a.44.44,0,0,1,.32.5A.51.51,0,0,1,17,29h2.31a.51.51,0,0,0,.5-.42A.44.44,0,0,0,19.5,28.05Z"/><path class="cls-1" d="M.79,5.85h0A3.58,3.58,0,0,1,3.61,4.49H7A.47.47,0,0,1,7.46,5V7.05A.47.47,0,0,1,7,7.53H3.61a.56.56,0,0,0-.45.22.58.58,0,0,0-.11.46,9,9,0,0,0,1.93,4,5.79,5.79,0,0,0,2.37,1.58.46.46,0,0,1,.31.34,8.32,8.32,0,0,0,.84,2.26.46.46,0,0,1,0,.5.46.46,0,0,1-.39.2H8a9,9,0,0,1-5.27-2.83A11.8,11.8,0,0,1,.09,8.89,3.58,3.58,0,0,1,.79,5.85Z"/><path class="cls-2" d="M4.83,12.28V12l.15.16a5.79,5.79,0,0,0,2.37,1.58.46.46,0,0,1,.31.34,8.32,8.32,0,0,0,.84,2.26.46.46,0,0,1,0,.5.46.46,0,0,1-.39.2H8a10.16,10.16,0,0,1-2.22-.65A9.45,9.45,0,0,1,4.83,12.28Z"/><path class="cls-2" d="M7.46,5V7.05A.47.47,0,0,1,7,7.53H4.83v-3H7A.47.47,0,0,1,7.46,5Z"/><path class="cls-5" d="M24.84,2.76H7a.47.47,0,0,0-.48.48v9a9.41,9.41,0,1,0,18.81,0v-9A.47.47,0,0,0,24.84,2.76Z"/><path class="cls-6" d="M24.84,2.76H22.62a.47.47,0,0,1,.47.48v9a9.41,9.41,0,0,1-8.29,9.34,8.32,8.32,0,0,0,1.12.07,9.42,9.42,0,0,0,9.4-9.41v-9A.47.47,0,0,0,24.84,2.76Z"/><path class="cls-7" d="M20.06,11.17a1.05,1.05,0,0,0,.27-1.08,1,1,0,0,0-.85-.71l-1.76-.26a.08.08,0,0,1-.07,0l-.79-1.6a1,1,0,0,0-.94-.58h0a1,1,0,0,0-.95.58l-.79,1.6a.08.08,0,0,1-.07,0l-1.76.26a1,1,0,0,0-.85.71,1.05,1.05,0,0,0,.27,1.08L13,12.41a.1.1,0,0,1,0,.09l-.3,1.75a1.05,1.05,0,0,0,1.53,1.11l1.57-.83H16l1.57.83a1.11,1.11,0,0,0,.49.12,1.07,1.07,0,0,0,.62-.2,1,1,0,0,0,.42-1l-.3-1.75a.14.14,0,0,1,0-.09Z"/><path class="cls-8" d="M19.48,9.38,19,9.31,16.74,11.5a.57.57,0,0,0-.17.51l.52,3.11.44.24a1.11,1.11,0,0,0,.49.12,1.07,1.07,0,0,0,.62-.2,1,1,0,0,0,.42-1l-.3-1.75a.14.14,0,0,1,0-.09l1.27-1.24a1.05,1.05,0,0,0,.27-1.08A1,1,0,0,0,19.48,9.38Z"/><path class="cls-5" d="M25.12,31.89A5.14,5.14,0,0,0,20.43,28h-9a5.14,5.14,0,0,0-4.69,3.88.47.47,0,0,0,.07.43.49.49,0,0,0,.39.2h17.5a.48.48,0,0,0,.38-.2A.47.47,0,0,0,25.12,31.89Z"/><path class="cls-6" d="M25.12,31.89A5.14,5.14,0,0,0,20.43,28H16.77a5.14,5.14,0,0,1,4.69,3.88.5.5,0,0,1-.07.43.49.49,0,0,1-.39.2h3.67a.48.48,0,0,0,.38-.2A.47.47,0,0,0,25.12,31.89Z"/><path class="cls-1" d="M25.62,0H6.21a1.86,1.86,0,0,0,0,3.71H25.62a1.86,1.86,0,0,0,0-3.71Z"/><path class="cls-2" d="M25.62,0H23.46a1.86,1.86,0,1,1,0,3.71h2.16a1.86,1.86,0,0,0,0-3.71Z"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 73 KiB |
@@ -0,0 +1 @@
|
||||
var configuration_map = {"notificationRuleList":[],"config":{"enableNotification":true},"passKey":"{}"};
|
||||
@@ -0,0 +1,2 @@
|
||||
!function(){"use strict";"undefined"!=typeof PushSubscriptionOptions&&PushSubscriptionOptions.prototype.hasOwnProperty("applicationServerKey")||void 0!==window.safari&&void 0!==window.safari.pushNotification?function(){const n=document.createElement("script");n.src="https://cdn.onesignal.com/sdks/web/v16/OneSignalSDK.page.es6.js?v=160510",n.defer=!0,document.head.appendChild(n)}():function(){let n="Incompatible browser.";"Apple Computer, Inc."===navigator.vendor&&navigator.maxTouchPoints>0&&(n+=" Try these steps: https://tinyurl.com/bdh2j9f7"),console.info(n)}()}();
|
||||
//# sourceMappingURL=OneSignalSDK.page.js.map
|
||||
@@ -0,0 +1 @@
|
||||
window.google_ad_status = 1;
|
||||
@@ -0,0 +1,220 @@
|
||||
|
||||
var mult_send = 0;
|
||||
|
||||
function Contest_Send(){
|
||||
|
||||
mult_send = mult_send + 1;
|
||||
PreparaContestSend('senduscontestform',false);
|
||||
|
||||
if (mult_send == 1)
|
||||
{
|
||||
AJAXReqContestSend("POST","send_us_contest.php",true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function PreparaContestSend(nome,ele){
|
||||
stringa = "";
|
||||
var form = document.forms[nome];
|
||||
|
||||
var numeroElementi = form.elements.length;
|
||||
|
||||
for(var i = 0; i < numeroElementi; i++){
|
||||
|
||||
nmfrm = form.elements[i].name;
|
||||
|
||||
if(i < numeroElementi-1)
|
||||
{
|
||||
stringa += form.elements[i].name+"="+encodeURIComponent(form.elements[i].value)+"&";
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
stringa += form.elements[i].name+"="+encodeURIComponent(form.elements[i].value);
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function AJAXReqContestSend(method,url,bool){
|
||||
if(window.XMLHttpRequest){
|
||||
myReq = new XMLHttpRequest();
|
||||
} else
|
||||
|
||||
if(window.ActiveXObject){
|
||||
myReq = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
|
||||
if(!myReq){
|
||||
myReq = new ActiveXObject("Msxml2.XMLHTTP");
|
||||
}
|
||||
}
|
||||
|
||||
if(myReq){
|
||||
|
||||
myReq.onreadystatechange = state_ContestSend;
|
||||
|
||||
myReq.open(method,url,bool);
|
||||
|
||||
|
||||
myReq.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
|
||||
myReq.send(stringa);
|
||||
|
||||
}else{
|
||||
alert("Impossibilitati ad usare AJAX");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function state_ContestSend(bReload){
|
||||
|
||||
if (myReq.readyState==4){
|
||||
|
||||
mult_send = 0;
|
||||
|
||||
if (myReq.status==200){
|
||||
|
||||
ResponseContestSend(myReq.responseText);
|
||||
}
|
||||
else {
|
||||
if (bDebug) {alert("Problem retrieving XML data");}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function ResponseContestSend(sResponse){
|
||||
|
||||
|
||||
var vetResp = sResponse.split('|');
|
||||
|
||||
if (vetResp[0].toUpperCase() == 'OK')
|
||||
{
|
||||
if (MM_findObj("contest_name_msg"))
|
||||
{
|
||||
DisplayHTMLData(MM_findObj('contest_name_msg'), ' ');
|
||||
}
|
||||
if (MM_findObj("contest_video_msg"))
|
||||
{
|
||||
DisplayHTMLData(MM_findObj('contest_video_msg'), ' ');
|
||||
}
|
||||
if (MM_findObj("send_box_contest"))
|
||||
{
|
||||
MM_findObj("send_box_contest").style.display='none';
|
||||
}
|
||||
if (MM_findObj("send_box_contest_response"))
|
||||
{
|
||||
MM_findObj("send_box_contest_response").style.display='block';
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
if (MM_findObj("contest_name_msg"))
|
||||
{
|
||||
DisplayHTMLData(MM_findObj('contest_name_msg'), ' ');
|
||||
}
|
||||
if (MM_findObj("contest_video_msg"))
|
||||
{
|
||||
DisplayHTMLData(MM_findObj('contest_video_msg'), ' ');
|
||||
}
|
||||
for (b=1; b<vetResp.length; b++)
|
||||
{
|
||||
var f = vetResp[b].split(';');
|
||||
var fldcont = f[0];
|
||||
var msgcont = f[1];
|
||||
|
||||
if (fldcont == 'contest_name')
|
||||
{
|
||||
DisplayHTMLData(MM_findObj(fldcont + '_msg'), msgcont);
|
||||
}
|
||||
|
||||
if (fldcont == 'contest_video')
|
||||
{
|
||||
DisplayHTMLData(MM_findObj(fldcont + '_msg'), msgcont);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
var HTTP_FIRSTAUCT_URL = new String ('first_auct.php');
|
||||
var xmlhttpFirstAuct = null;
|
||||
|
||||
function FirstAuct() {
|
||||
|
||||
var sUrlFirstAuct = HTTP_FIRSTAUCT_URL + "?chk=" + new Date().valueOf();
|
||||
|
||||
if (xmlhttpFirstAuct) {
|
||||
|
||||
if ((xmlhttpFirstAuct.readyState != 4) && (xmlhttpFirstAuct.readyState != 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (window.XMLHttpRequest){
|
||||
|
||||
xmlhttpFirstAuct = new XMLHttpRequest();
|
||||
} else if (window.ActiveXObject){
|
||||
|
||||
xmlhttpFirstAuct = new ActiveXObject("Microsoft.XMLHTTP");
|
||||
}
|
||||
if (xmlhttpFirstAuct != null){
|
||||
xmlhttpFirstAuct.onreadystatechange = state_FirstAuct;
|
||||
xmlhttpFirstAuct.open("GET",sUrlFirstAuct,true);
|
||||
xmlhttpFirstAuct.send(null);
|
||||
return true;
|
||||
} else {
|
||||
if (bDebug)
|
||||
{
|
||||
alert("Your browser does not support XMLHTTP.");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
xmlhttpFirstAuct = null;
|
||||
if (bDebug) alert('Errore in loadXMLDocElenco');
|
||||
}
|
||||
finally {}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function state_FirstAuct(){
|
||||
|
||||
if (xmlhttpFirstAuct.readyState==4){
|
||||
|
||||
if (xmlhttpFirstAuct.status!=200){
|
||||
|
||||
if (bDebug) {
|
||||
alert("Problem retrieving XML data");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
btn-promo {
|
||||
border-radius: 3px;
|
||||
background: linear-gradient(rgb(82, 157, 253), rgb(46, 114, 202));
|
||||
background: -moz-linear-gradient(rgb(82, 157, 253), rgb(46, 114, 202));
|
||||
background: -webkit-linear-gradient(rgb(82, 157, 253), rgb(46, 114, 202));
|
||||
background: -o-linear-gradient(rgb(82, 157, 253), rgb(46, 114, 202));
|
||||
background: -ms-linear-gradient(rgb(82, 157, 253), rgb(46, 114, 202));
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn.btn-promo:hover {
|
||||
background: linear-gradient(rgb(117, 175, 250), rgb(53, 124, 216));
|
||||
background: -moz-linear-gradient(rgb(117, 175, 250), rgb(53, 124, 216));
|
||||
background: -webkit-linear-gradient(rgb(117, 175, 250), rgb(53, 124, 216));
|
||||
background: -o-linear-gradient(rgb(117, 175, 250), rgb(53, 124, 216));
|
||||
background: -ms-linear-gradient(rgb(117, 175, 250), rgb(53, 124, 216));
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.mCSB_inside > .mCSB_container {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.mCSB_scrollTools .mCSB_draggerRail {
|
||||
width: 6px;
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
.mCSB_scrollTools .mCSB_draggerContainer {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar {
|
||||
background-color: #20cb9a !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.loader {
|
||||
margin: 10px auto;
|
||||
border: 5px solid #f3f3f3;
|
||||
/* Light grey */
|
||||
border-top: 5px solid #20cb9a;
|
||||
/* Blue */
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
-webkit-animation: spin 2s linear infinite;
|
||||
animation: spin 2s linear infinite;
|
||||
}
|
||||
|
||||
.stopScroll{
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 384px) {
|
||||
#prod_win_cont_modal h3 {
|
||||
padding-left: 30px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 320px) {
|
||||
.prod_won__2 {
|
||||
margin-left: 1px !important;
|
||||
margin-right: 1px !important;
|
||||
}
|
||||
#prod_win_cont_modal .col-xs-6{
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
#modal iframe {
|
||||
width: 99%;
|
||||
}
|
||||
|
||||
#myModal3 .modal-dialog, #myModal2 .modal-dialog {
|
||||
margin: 30px auto;
|
||||
}
|
||||
|
||||
.settingBox form div {
|
||||
border-bottom: 1px solid #efefef;
|
||||
padding: 15px;
|
||||
font-weight: 500;
|
||||
font-size: 12px;
|
||||
color: #818181;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 991px) {
|
||||
#menuModal .show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
#menuModal .modal-header {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
#menuModal .height {
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
.parentOverflowY {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
#notifBoxContainer .mCSB_container {
|
||||
top: 0px;
|
||||
}
|
||||
1264
Mimante/Examples/10€ Idea Shopping +10P - Bidoo_files/auction.css
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1,206 @@
|
||||
const AuctionsBidManage = (function() {
|
||||
|
||||
const _defaultPart = "divAsta";
|
||||
let _nAstePerBonus = 10;
|
||||
let _limiteAsteVinte = 10;
|
||||
let _nAstePuntataVinte = 0;
|
||||
let _percentualeBonus = 0;
|
||||
let _nPuntateVinteOggi = 0;
|
||||
let _nAsteConfermate = 0;
|
||||
let _nPuntateRiscattate = 0;
|
||||
let _nPuntateDaRiscattare = 0;
|
||||
let _initialized = false;
|
||||
let _defaultValidUntil = null;
|
||||
let _viewSlot = false;
|
||||
|
||||
function _defaultObj() {
|
||||
return {
|
||||
auctions: {},
|
||||
nAsteConfermate: 0,
|
||||
percentualeBonus: 0,
|
||||
limiteAsteVinte: 10,
|
||||
nAstePerBonus: 10,
|
||||
validUntil: getDefaultValidUntil()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggiunge una nuova asta all'oggetto delle aste di puntata vinte in un giorno
|
||||
* @param idAuction {int}
|
||||
*/
|
||||
function add(idAuction){
|
||||
|
||||
let result = get();
|
||||
let retrievedObject = JSON.parse(result);
|
||||
let auctionBidWin = retrievedObject === null ? _defaultObj() : retrievedObject ;
|
||||
let auctionElement = document.getElementById(_defaultPart + idAuction);
|
||||
let creditValue = parseInt(auctionElement.getAttribute('data-credit-value')) > 0 ? parseInt(auctionElement.getAttribute('data-credit-value')) : 0;
|
||||
|
||||
|
||||
|
||||
if(creditValue > 0 && Object.keys(auctionBidWin.auctions).length <= auctionBidWin.limiteAsteVinte){
|
||||
|
||||
// let obj =
|
||||
// {
|
||||
// idAuction: idAuction,
|
||||
// value: creditValue
|
||||
// }
|
||||
// ;
|
||||
//
|
||||
// if(!auctionBidWin.auctions.hasOwnProperty(idAuction)){
|
||||
// auctionBidWin.auctions[idAuction] = obj;
|
||||
// }
|
||||
// let newObj = JSON.stringify(auctionBidWin);
|
||||
//
|
||||
// localStorage.setItem("auctionBidWin", newObj);
|
||||
getRemoteData();
|
||||
}
|
||||
return;
|
||||
}
|
||||
function getDefaultValidUntil(){
|
||||
|
||||
return _defaultValidUntil;
|
||||
|
||||
}
|
||||
|
||||
function setDefaultValidUntil(untilTimestamp){
|
||||
_defaultValidUntil = untilTimestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ritornano le informazioni salvate nel localStorage
|
||||
* @returns {string}
|
||||
*/
|
||||
function get(){
|
||||
return localStorage.getItem('auctionBidWin');
|
||||
}
|
||||
|
||||
/**
|
||||
* Rimuove dal localStorage
|
||||
*/
|
||||
function remove(){
|
||||
localStorage.removeItem('auctionBidWin');
|
||||
}
|
||||
|
||||
|
||||
function getRemoteData(callback = null){
|
||||
|
||||
fetch('./ajax/get_auction_bids_info_banner.php',{
|
||||
method: "GET"
|
||||
})
|
||||
// gestisci il successo
|
||||
.then(response => response.json()) // converti a json
|
||||
.then(function (data) {
|
||||
let obj = {
|
||||
auctions: data.auctions,
|
||||
nAsteConfermate: data.nAsteConfermate,
|
||||
nAsteVinte: data.nAsteVinte,
|
||||
nPuntateRiscattate: data.nPuntateRiscattate,
|
||||
nPuntateDaRiscattare: data.nPuntateDaRiscattare,
|
||||
limiteAsteVinte: data.limiteAsteVinte,
|
||||
nAstePerBonus: data.nAstePerBonus,
|
||||
percentualeBonus: data.percentualeBonus,
|
||||
validUntil: data.validUntil,
|
||||
viewSlot: data.viewSlot,
|
||||
extraSlots: data.extraSlots, //un elenco degli slots non scaduti e non aperti
|
||||
nPuntateBonus: data.nPuntateBonus
|
||||
};
|
||||
let newObj = JSON.stringify(obj);
|
||||
|
||||
localStorage.setItem("auctionBidWin", newObj);
|
||||
if(callback !== null){
|
||||
callback();
|
||||
}
|
||||
|
||||
})
|
||||
.catch(err => console.log('Request Failed', err)); // gestisci gli errori
|
||||
}
|
||||
|
||||
function retriveInfoComponent(){
|
||||
let result = JSON.parse(get());
|
||||
|
||||
if(result) {
|
||||
|
||||
_nAstePuntataVinte = result.nAsteVinte;
|
||||
_limiteAsteVinte = result.limiteAsteVinte;
|
||||
_nAsteConfermate = result.nAsteConfermate;
|
||||
_nPuntateDaRiscattare = result.nPuntateDaRiscattare;
|
||||
_nPuntateRiscattate = result.nPuntateRiscattate;
|
||||
_nAstePerBonus = result.nAstePerBonus;
|
||||
_percentualeBonus = result.percentualeBonus;
|
||||
_viewSlot = result.viewSlot;
|
||||
_nPuntateVinteOggi = result.nPuntateDaRiscattare + result.nPuntateRiscattate;
|
||||
|
||||
|
||||
|
||||
/*if (_percentualeBonus > 0) {
|
||||
let valorePercentualeBonus = ((_nPuntateVinteOggi * _percentualeBonus) / 100);
|
||||
_nPuntateVinteOggi = _nPuntateVinteOggi + valorePercentualeBonus;
|
||||
}*/
|
||||
|
||||
|
||||
let asteRimanentiPerBonus = _nAstePerBonus - _nAstePuntataVinte;
|
||||
|
||||
return {
|
||||
auctions: result.auctions,
|
||||
asteRimanentiPerBonus: asteRimanentiPerBonus,
|
||||
nAstePerBonus: _nAstePerBonus,
|
||||
nAstePuntataVinte: _nAstePuntataVinte,
|
||||
percentualeBonus: _percentualeBonus,
|
||||
nPuntateVinteOggi: parseInt(_nPuntateVinteOggi),
|
||||
limiteAsteVinte: _limiteAsteVinte,
|
||||
nAsteConfermate: _nAsteConfermate,
|
||||
nPuntateDaRiscattare: _nPuntateDaRiscattare,
|
||||
nPuntateRiscattate: _nPuntateRiscattate,
|
||||
|
||||
viewSlot: _viewSlot,
|
||||
extraSlots: result.extraSlots,
|
||||
nPuntateBonus: result.nPuntateBonus
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param auctionId
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function searchByAuctionId(auctionId){
|
||||
let data = retriveInfoComponent();
|
||||
let controllo = false;
|
||||
if(data == undefined || data == null ){ return; }
|
||||
|
||||
let keys = Object.keys(data.auctions);
|
||||
|
||||
for(let i= 0; i <= keys.length; i++){
|
||||
if(keys[i] === auctionId){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function initRemoteData(){
|
||||
if(!_initialized){
|
||||
getRemoteData();
|
||||
setInterval(function (){
|
||||
getRemoteData();
|
||||
}, 1000 * 60);
|
||||
}
|
||||
_initialized = true;
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
add,
|
||||
get,
|
||||
remove,
|
||||
getRemoteData,
|
||||
retriveInfoComponent,
|
||||
initRemoteData,
|
||||
setDefaultValidUntil,
|
||||
searchByAuctionId
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
@@ -0,0 +1,927 @@
|
||||
#wrapBonusSection{
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
margin-bottom: 20px;
|
||||
-webkit-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.2);
|
||||
-moz-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.2);
|
||||
box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.2);
|
||||
border-top: 1px solid #d0d0d0;
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
#wrapBonusSection.visible{
|
||||
display: block;
|
||||
}
|
||||
#BonusSection{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
width: 65%;
|
||||
min-height: 40px;
|
||||
margin: 0 auto;
|
||||
align-items: center;
|
||||
margin-bottom: -25px;
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
#BonusSection{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#BonusSection .wrap-msg-bonus, #BonusSection .pt-2 .wrap-progress, #BonusSection .pt-1 .wrap-progress, #BonusSection .pt-3 .wrap-progress, #BonusSection .pt-3 .wrap-bids, #auctionBidsModal .wrap-msg-bonus, #auctionBidsModal .wrap-msg-bonus .wrap-progress, #bidsBonusSection #section2 .wrap-progress, #bidsBonusSection #section3 .wrap-progress{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
#bidsBonusSection #section2 .wrap-progress{
|
||||
font-size: 14px;
|
||||
}
|
||||
#auctionBidsModal #countdownAddSlot{
|
||||
font-weight: bold;
|
||||
color: #55bc62;
|
||||
}
|
||||
#auctionBidsModal .wrap-msg-bonus{
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
#BonusSection .pt-2 .item, #BonusSection .pt-3 .item{
|
||||
margin: 2px;
|
||||
}
|
||||
#BonusSection .pt-2, #BonusSection .pt-1, #BonusSection .pt-3, #auctionBidsModal .wrap-pt2{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
#auctionBidsModal .wrap-pt2 .bonus-obtained{
|
||||
font-size: 12px;
|
||||
color: #6F6F6F;
|
||||
font-weight: bold;
|
||||
margin-top: 3px;
|
||||
display: none;
|
||||
}
|
||||
#auctionBidsModal .wrap-pt2{
|
||||
justify-content: space-around;
|
||||
align-items: flex-start;
|
||||
margin-top: 20px;
|
||||
border-top: 1px solid #DBDBDB;
|
||||
padding-top: 20px;
|
||||
font-size: 13px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@media (max-width: 340px) {
|
||||
#auctionBidsModal .wrap-pt2{
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
#auctionToBonusModal{
|
||||
font-size: 15px;
|
||||
color: #333;
|
||||
}
|
||||
#BonusSection .text{
|
||||
color: #6D6D6D;
|
||||
font-size: 15px;
|
||||
margin: auto 4px;
|
||||
}
|
||||
#BonusSection .pt-2 img{
|
||||
height: 29px;
|
||||
}
|
||||
#BonusSection .pt-2 .img-emoji img, #auctionBidsModal .img-emoji img {
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
margin-left: -10px;
|
||||
margin-top: -3px;
|
||||
}
|
||||
#auctionBidsModal .img-emoji img{
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
#auctionBidsModal .img-emoji{
|
||||
z-index: 9;
|
||||
margin-left: -3px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
#BonusSection .pt-dx img, #auctionBidsModal .pt-dx img, #auctionBidsModal .pt-center img{
|
||||
width: 16px;
|
||||
}
|
||||
#BonusSection .pt-2 .wrap-progress .progress{
|
||||
margin-left: 5px;
|
||||
background-color: #D1D1D1;
|
||||
}
|
||||
#auctionBidsModal .progress{
|
||||
width: 56px;
|
||||
height: 24px;
|
||||
margin: 0 6px;
|
||||
position: relative;
|
||||
background-color: #D1D1D1;
|
||||
border-radius: 20px;
|
||||
}
|
||||
#auctionBidsModal .progress{
|
||||
width: 110px;
|
||||
height: 22px;
|
||||
}
|
||||
#auctionBidsModal .pt-1 .progress{
|
||||
height: 11px;
|
||||
}
|
||||
#BonusSection .progress, #auctionBidsModal .progress{
|
||||
width: 60px;
|
||||
height: 13px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
#auctionBidsModal .progress{
|
||||
width: 90px;
|
||||
}
|
||||
#BonusSection #countdown-bonus{
|
||||
width: 60px;
|
||||
color: #fff;
|
||||
background-color: #FF0658;
|
||||
font-weight: bold;
|
||||
font-size: 11px;
|
||||
padding: 0px 4px;
|
||||
height: 16px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
#BonusSection #bonus-earned, #BonusSection #bonus-active-all{
|
||||
display: none;
|
||||
font-weight: bold;
|
||||
margin-right: 15px;
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
#BonusSection #bonus-earned, #BonusSection #bonus-active-all{
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
#BonusSection #bonus-active-all{
|
||||
color: #55bc62;
|
||||
}
|
||||
|
||||
|
||||
#BonusSection .progress .progress-bar, #auctionBidsModal .pt-1 .progress .progress-bar, #auctionBidsModal #bidsBonusSection #section2 .progress .progress-bar, #auctionBidsModal .progress .progress-bar{
|
||||
background: rgb(4,170,176);
|
||||
background: linear-gradient(90deg, rgba(4,170,176,1) 0%, rgba(7,206,173,1) 100%);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
#BonusSection .progress .progressbar-text{
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
height: 22px;
|
||||
color: #000;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
}
|
||||
#auctionBidsModal .progress .progressbar-text{
|
||||
font-size: 15px;
|
||||
top: 0;
|
||||
}
|
||||
#todayBids, #auctionBidsModal{
|
||||
font-size: 16px;
|
||||
color: #333;
|
||||
}
|
||||
#auctionBidsModal{
|
||||
font-weight: normal;
|
||||
}
|
||||
#auctionToBonus.active{
|
||||
font-weight: bold;
|
||||
color: #000;
|
||||
}
|
||||
#confirmedAuctionWithBonus{
|
||||
display: none;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#confirmedAuctionWithBonus .value{
|
||||
font-weight: bold;
|
||||
}
|
||||
.wrap-bonus-mobile{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.wrap-bonus-mobile .wrap-bonus-value{
|
||||
font-size: 14px;
|
||||
color: #504E4E;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#auctionBidsModal .wrap-bonus-value{
|
||||
margin-right: 2px;
|
||||
}
|
||||
#BonusSection .pt-3 img{
|
||||
width: 15px;
|
||||
}
|
||||
#BonusSection .wrap-title-bonus{
|
||||
display: flex;
|
||||
}
|
||||
#BonusSection .wrap-title-bonus .icon-check{
|
||||
width: 15px;
|
||||
display: none;
|
||||
margin-right: 4px;
|
||||
}
|
||||
#BonusSection .pt-2 #countdown-bonus{
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 1040px) {
|
||||
#BonusSection{
|
||||
width: 100%;
|
||||
justify-content: space-around;
|
||||
min-height: 50px;
|
||||
}
|
||||
#BonusSection .pt-1, #BonusSection .pt-2, #BonusSection .pt-3{
|
||||
flex-direction: column;
|
||||
}
|
||||
#BonusSection .pt-3 .wrap-bids{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
#BonusSection .text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#BonusSection .pt-2 img{
|
||||
margin-right: 5px;
|
||||
height: 18px;
|
||||
width: 10px;
|
||||
}
|
||||
#BonusSection .pt-1 .progress {
|
||||
width: 90px;
|
||||
height: 10px;
|
||||
}
|
||||
#todayBids{
|
||||
font-size: 14px;
|
||||
}
|
||||
#BonusSection .pt-3 .item{
|
||||
margin: 0;
|
||||
}
|
||||
#BonusSection .pt-3 img{
|
||||
width: 13px;
|
||||
margin-top: -1px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
#BonusSection .wrap-msg-bonus{
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.wrap-bonus-mobile{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
#BonusSection {
|
||||
min-height: 45px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 360px) {
|
||||
#BonusSection .text {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#auctionBidsModal .pt-left .wrap-progress, #auctionBidsModal .pt-dx .wrap-bids, #auctionBidsModal .pt-center .wrap-bids{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
#auctionBidsModal .pt-center .item, #auctionBidsModal .pt-dx .item{
|
||||
margin-left: 1px;
|
||||
margin-right: 1px;
|
||||
}
|
||||
#auctionBidsModal .pt-center .item img, #auctionBidsModal .pt-dx .item img{
|
||||
margin-left: 2px;
|
||||
margin-right: 2px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
#auctionToGoModal{
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
@media (max-width: 340px) {
|
||||
#auctionBidsModal .wrap-pt2{
|
||||
font-size: 12px;
|
||||
}
|
||||
#auctionToGoModal, #todayBidsModal, #todayBidsPayedModal{
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
#todayBidsModal, #todayBidsPayedModal{
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
#loaderAuctionBids{
|
||||
min-height: 40px;
|
||||
text-align: center;
|
||||
padding: 5px;
|
||||
font-size: 20px;
|
||||
}
|
||||
#auctionToGo{
|
||||
color: #000;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.loader-data{
|
||||
display: block;
|
||||
position: relative;
|
||||
margin-right: 0px !important;
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
.loader-data::before{
|
||||
content: "";
|
||||
background-color: #eaeaea;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 22px;
|
||||
position: absolute;
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
.loader-data{
|
||||
margin-top: 2px !important;
|
||||
margin-bottom: 2px !important;
|
||||
}
|
||||
.loader-data::before{
|
||||
height: 16px;
|
||||
min-width: 20px;
|
||||
}
|
||||
}
|
||||
#BonusSection .pt-1, #BonusSection .pt-2, #BonusSection .pt-3{
|
||||
position: relative;
|
||||
}
|
||||
.loader-data img{
|
||||
display: none !important;
|
||||
}
|
||||
.wrap-countdown-auctionBidsModal{
|
||||
color: #55BC62;
|
||||
font-weight: bold;
|
||||
}
|
||||
#auctionBidsModal .wrapTitle{
|
||||
margin: 20px auto 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
#auctionBidsModal .modal-body{
|
||||
padding: 0;
|
||||
}
|
||||
#auctionBidsModal .contentModal #bidsBonusSection .content, #auctionBidsModal .contentModal #rankingBonusSection{
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
margin-top: 15px;
|
||||
padding: 15px;
|
||||
}
|
||||
#auctionBidsModal .contentModal #bidsBonusSection .content{
|
||||
margin-top: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#auctionBidsModal .contentModal #bidsBonusSection .content.parent-content-div {
|
||||
padding: 0 0 5px 0;
|
||||
}
|
||||
|
||||
#tabsSection{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@media (max-width: 576px) {
|
||||
#tabsSection{
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
#tabsSection .pt-1{
|
||||
width: 55%;
|
||||
}
|
||||
#tabsSection .pt-2{
|
||||
width: 40%;
|
||||
}
|
||||
#tabsSection .pt-1, #tabsSection .pt-2{
|
||||
|
||||
padding: 8px 18px;
|
||||
border-bottom: 1px solid #BCBCBC;
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
#tabsSection .pt-1 .fa, #tabsSection .pt-2 .fa{
|
||||
margin-right: 5px;
|
||||
}
|
||||
#tabsSection .pt-3{
|
||||
width: 10%;
|
||||
padding: 5px 10px;
|
||||
border-bottom: 1px solid #BCBCBC;
|
||||
}
|
||||
button[aria-label='Close'] span{
|
||||
font-size: 26px;
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
#tabsSection .pt-3{
|
||||
padding: 4px 10px;
|
||||
}
|
||||
#tabsSection .pt-1, #tabsSection .pt-2{
|
||||
font-size: 12px;
|
||||
padding: 8px 10px;
|
||||
}
|
||||
button[aria-label='Close'] span{
|
||||
font-size: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
#tabsSection .pt-1.active, #tabsSection .pt-2.active, #tabsSection .pt-3.active{
|
||||
border-color: #2F80ED;
|
||||
}
|
||||
#tabsSection .pt-1.active a, #tabsSection .pt-2.active a, #tabsSection .pt-3.active a, #tabsSection .pt-1.active a:hover, #tabsSection .pt-2.active a:hover{
|
||||
color: #2F80ED;
|
||||
font-weight: bold;
|
||||
text-decoration: none;
|
||||
}
|
||||
#tabsSection .pt-1 a, #tabsSection .pt-2 a{
|
||||
color: #7d7d7d;
|
||||
}
|
||||
|
||||
|
||||
#tabsSection .pt-1 a:hover, #tabsSection .pt-2 a:hover{
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
color: #2F80ED;
|
||||
}
|
||||
#rankingBonusSection{
|
||||
display: none;
|
||||
}
|
||||
#bidsBonusSection #section2 .box-congrats,
|
||||
#bidsBonusSection #section3 .box-congrats{
|
||||
margin-top: 12px;
|
||||
}
|
||||
#bidsBonusSection #section2, #bidsBonusSection #section3{
|
||||
display: none;
|
||||
}
|
||||
#bidsBonusSection #section2 .titleModal{
|
||||
font-size: 20px;
|
||||
}
|
||||
#auctionBidsModal .wrap-credit-bonus{
|
||||
display: inline-block;
|
||||
}
|
||||
#auctionBidsModal #bidsBonusSection .wrap-content{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
#bidsBonusSection #section2 .summary-body #countdown-bonus{
|
||||
font-size: 14px;
|
||||
}
|
||||
#bidsBonusSection #section2 .summary-body .countdown{
|
||||
color: #FF0658;
|
||||
}
|
||||
#bidsBonusSection #section2 .summary-body #countdownForBonus{
|
||||
font-weight: bold;
|
||||
}
|
||||
#bidsBonusSection #section2 .summary{
|
||||
margin-top: 30px;
|
||||
}
|
||||
#bidsBonusSection #section2 .summary-body{
|
||||
width: 250px;
|
||||
margin: -18px auto 25px;
|
||||
border: 1px solid #000;
|
||||
border-radius: 5px;
|
||||
padding: 20px 15px;
|
||||
box-shadow: 2px 2px 3px 1px rgba(208, 209, 213, 0.2), 0 2px 2px 1px rgba(220, 221, 224, 0.2);
|
||||
-webkit-box-shadow: 2px 2px 3px 1px rgba(208, 209, 213, 0.2), 0 2px 2px 1px rgba(220, 221, 224, 0.2);
|
||||
-moz-box-shadow: 2px 2px 3px 1px rgba(208, 209, 213, 0.2), 0 2px 2px 1px rgba(220, 221, 224, 0.2);
|
||||
}
|
||||
#bidsBonusSection #section3 .summaryTitle{
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-top: 40px;
|
||||
|
||||
}
|
||||
#bidsBonusSection #section3 .summaryList img{
|
||||
width: 18px;
|
||||
}
|
||||
#bidsBonusSection #section3 .summaryList ul{
|
||||
text-align: left;
|
||||
width: 300px;
|
||||
margin: 5px auto 20px;
|
||||
line-height: 30px;
|
||||
}
|
||||
.bottom-area{
|
||||
font-size: 16px;
|
||||
}
|
||||
.bottom-area.highlight{
|
||||
color: #FF0658;
|
||||
font-weight: bold;
|
||||
margin-top: 15px;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
#auctionBidsModal #bidsBonusSection #bonusSection img{
|
||||
width: 20px;
|
||||
margin-top: -2px;
|
||||
}
|
||||
#auctionBidsModal #bidsBonusSection #bonusSection .bottomSection img{
|
||||
width: 16px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
#auctionBidsModal #bidsBonusSection #bonusSection .bottomSection{
|
||||
font-size: 16px;
|
||||
margin-bottom: 15px;
|
||||
color: #5F5F5F;
|
||||
}
|
||||
|
||||
#bonusSection .btnConfirm{
|
||||
font-size: 18px;
|
||||
display: inline-block;
|
||||
color: #333;
|
||||
background-color: #fcc62d;
|
||||
padding: 5px;
|
||||
line-height: 25px;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 10px;
|
||||
width: 95%;
|
||||
text-decoration: none;
|
||||
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
#auctionBidsModal #bidsBonusSection #bonusSection .bottomSection {
|
||||
font-size: 15px;
|
||||
}
|
||||
#bonusSection .btnConfirm{
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
#rankingBonusSection .title{
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#rankingBonusSection .subtitle{
|
||||
font-size: 14px;
|
||||
}
|
||||
#rankingBonusSection #ranking{
|
||||
padding: 0 10px;
|
||||
}
|
||||
#rankingBonusSection #ranking table{
|
||||
margin-top:30px;
|
||||
width: 100%;
|
||||
}
|
||||
#rankingBonusSection #ranking table td{
|
||||
text-align: left;
|
||||
}
|
||||
#rankingBonusSection #ranking table .td1{
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
#rankingBonusSection #ranking table .td1 img{
|
||||
width: 38px;
|
||||
}
|
||||
#rankingBonusSection #ranking table td.td2{
|
||||
font-size: 16px;
|
||||
width: 70%;
|
||||
padding: 8px 10px;
|
||||
text-transform: capitalize;
|
||||
}
|
||||
#rankingBonusSection #ranking table td.td3{
|
||||
width: 25%;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
}
|
||||
#rankingBonusSection #ranking table td.td3 img{
|
||||
width: 17px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
#auctionBidsModal #section1, #auctionBidsModal #section4{
|
||||
display: none;
|
||||
}
|
||||
#auctionBidsModal #section1{
|
||||
padding: 0px 20px;
|
||||
}
|
||||
#auctionBidsModal #section4 .sad{
|
||||
width: 25px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
#BonusSection .img-lock, #BonusSection .img-lock-open{
|
||||
display: none;
|
||||
}
|
||||
#BonusSection .img-lock img, #BonusSection .img-lock-open img{
|
||||
width: 12px;
|
||||
margin-left: 5px;
|
||||
margin-top: -1px;
|
||||
}
|
||||
#BonusSection .pay-bids-counter{
|
||||
margin-left: 5px;
|
||||
color: #fff;
|
||||
background-color: #FF0658;
|
||||
border-radius: 40px;
|
||||
width: 19px;
|
||||
height: 19px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
font-size: 11px;
|
||||
padding: 2px;
|
||||
display: none;
|
||||
}
|
||||
#auctionBidsModal .wrap-new-daily-challenge.wrap2{
|
||||
margin-top: 5px;
|
||||
}
|
||||
#auctionBidsModal .wrap-new-daily-challenge{
|
||||
color: #2F80ED;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin: 20px 60px 0px;
|
||||
display: none;
|
||||
}
|
||||
@media (max-width: 576px) {
|
||||
#auctionBidsModal .wrap-new-daily-challenge {
|
||||
margin: 20px 40px 0;
|
||||
}
|
||||
}
|
||||
#BonusSection .img-plus-not-active, #BonusSection .img-plus-active{
|
||||
display: none;
|
||||
}
|
||||
#auctionBidsModal .extraSlots .slot-title .open-lock{
|
||||
margin-top: -5px;
|
||||
width: 15px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
#auctionBidsModal .extraSlots .slot-title span .fa{
|
||||
font-size: 20px;
|
||||
position: absolute;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#auctionBidsModal .extraSlots .wrap-content-slot{
|
||||
padding: 10px 0 15px;
|
||||
}
|
||||
#auctionBidsModal .bonus-obtained{
|
||||
display: none;
|
||||
}
|
||||
#auctionBidsModal .extraSlots{
|
||||
border: none;
|
||||
margin: -5px auto 0;
|
||||
padding: 10px 15px;
|
||||
text-align: center;
|
||||
background-color: #f3f6f9;
|
||||
border-radius: 0;
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom-right-radius: 5px;
|
||||
}
|
||||
#auctionBidsModal .extraSlots.avaible{
|
||||
border-color: #55BC62;
|
||||
}
|
||||
#extraSlotTemplate{
|
||||
display: none;
|
||||
}
|
||||
#wrapSlots{
|
||||
display: flex;
|
||||
justify-content: space-evenly;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
#wrapSlots .box-extra-slot{
|
||||
border: 1px solid #6F6F6F;
|
||||
background-color: #f3f6f9;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
width: 100px;
|
||||
margin-top: 15px;
|
||||
display: none;
|
||||
}
|
||||
.wrap-num-other-slot{
|
||||
position: relative;
|
||||
display: none;
|
||||
font-weight: bold;
|
||||
margin-top: 10px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.wrap-num-other-slot .reduce{
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 20px;
|
||||
color: #333;
|
||||
text-decoration: underline;
|
||||
}
|
||||
.wrap-num-other-slot .open{
|
||||
color: #55BC62;
|
||||
text-decoration: underline;
|
||||
display: none;
|
||||
}
|
||||
#wrapSlots .box-extra-slot .expire{
|
||||
font-size: 10px;
|
||||
font-weight: bold;
|
||||
color: #6A6B6C;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#wrapSlots .box-extra-slot .expire img{
|
||||
margin-left: 2px;
|
||||
}
|
||||
#wrapSlots .box-extra-slot .content{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
#wrapSlots .box-extra-slot .content .slot-value{
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #333;
|
||||
}
|
||||
#wrapSlots .box-extra-slot .wrap-cta .cta{
|
||||
background-color: #B4B4B4;
|
||||
color: #fff;
|
||||
padding: 0px 10px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
width: 100%;
|
||||
max-height: 23px;
|
||||
|
||||
}
|
||||
#wrapSlots .box-extra-slot .wrap-cta .cta img{
|
||||
margin-top: -2px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.extraSlots .wrap-content-slot{
|
||||
display: none;
|
||||
}
|
||||
.extraSlots .slot-title a{
|
||||
width: 100%;
|
||||
display: block;
|
||||
color: #333;
|
||||
text-decoration: none;
|
||||
}
|
||||
.extraSlots .slot-title{
|
||||
color: #000;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.extraSlots .slot-content{
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.extraSlots .slot-content .beforeConfirmed, .extraSlots .slot-content .afterConfirmed{
|
||||
display: none;
|
||||
}
|
||||
.wrap-extra-slots .box-noSlot .titleNoSlot{
|
||||
color: #FE4E4E;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.wrap-extra-slots .box-noSlot .contentNoSlot{
|
||||
font-size: 12px;
|
||||
}
|
||||
.wrap-extra-slots .box-noSlot .contentNoSlot img{
|
||||
width: 17px;
|
||||
margin-top: -3px;
|
||||
margin-left: 3px;
|
||||
}
|
||||
.wrap-extra-slots .box-noSlot{
|
||||
margin-top: 10px;
|
||||
}
|
||||
.wrap-extra-slots .box-noSlot{
|
||||
display: none;
|
||||
}
|
||||
.wrap-extra-slots .box-noSlot .box-noextra-slot .no-extra-slot-content .slot-img img{
|
||||
width: 20px;
|
||||
opacity: 0.6;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.wrap-extra-slots .box-noSlot .box-noextra-slot .no-extra-slot-content{
|
||||
font-size: 10px;
|
||||
color: #333;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
}
|
||||
.wrap-extra-slots .box-noSlot .box-noextra-slot{
|
||||
width: 92px;
|
||||
margin: 20px auto;
|
||||
height: 81px;
|
||||
border: 1px solid #55BC62;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#wrapSlots.avaible .box-extra-slot{
|
||||
border-color: #55BC62;
|
||||
background-color: #EDF8EF;
|
||||
}
|
||||
#wrapSlots.avaible .box-extra-slot .wrap-cta .cta{
|
||||
background-color: #55BC62;
|
||||
}
|
||||
.wrap-extra-slots{
|
||||
display: none;
|
||||
}
|
||||
.wrap-extra-slots .title-extraSlot-blocked{
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
width: 100%;
|
||||
margin: 0 0 10px;
|
||||
display: none;
|
||||
text-align: center;
|
||||
}
|
||||
.wrap-extra-slots .title-extraSlot-blocked img{
|
||||
width: 18px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
#auctionBidsModal #bidsBonusSection .img-lock, #auctionBidsModal #bidsBonusSection .img-lock-open{
|
||||
display: none;
|
||||
|
||||
}
|
||||
#auctionBidsModal #bidsBonusSection .img-lock img, #auctionBidsModal #bidsBonusSection .img-lock-open img{
|
||||
margin-left: 5px;
|
||||
width: 14px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
#auctionBidsModal #differenzaAsteDaConfermare{
|
||||
color: #fff;
|
||||
background-color: #FF0658;
|
||||
border-radius: 40px;
|
||||
width: 23px;
|
||||
height: 23px;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
padding: 1px 2px;
|
||||
display: inline-block;
|
||||
font-size: 15px;
|
||||
}
|
||||
#auctionBidsModal #bonusEarned img{
|
||||
width: 15px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#auctionBidsModal .wrap-already-taken, #auctionBidsModal .bonus-yet-to-be-obtained{
|
||||
display: none;
|
||||
}
|
||||
#auctionBidsModal .wrap-already-taken .txt-already-taken{
|
||||
color: #797979;
|
||||
}
|
||||
#auctionBidsModal .bonus-yet-to-be-obtained{
|
||||
color: #FF0658;
|
||||
}
|
||||
#auctionBidsModal #bonusEarned .wrap-details-bonus{
|
||||
text-align: center;
|
||||
margin: 7px 0;
|
||||
}
|
||||
#auctionBidsModal #modalConfirmSlotStopGame{
|
||||
z-index: 11;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
height: 130px;
|
||||
background-color: #fff;
|
||||
width: 270px;
|
||||
margin: auto;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
text-align: center;
|
||||
display: none;
|
||||
}
|
||||
#auctionBidsModal #modalConfirmSlotStopGame .contentButton .btn{
|
||||
padding: 2px 13px;
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
margin: 3px;
|
||||
}
|
||||
#auctionBidsModal #modalConfirmSlotStopGame .contentButton .btn-confirm{
|
||||
background-color: #55BC62
|
||||
}
|
||||
#auctionBidsModal #modalConfirmSlotStopGame .contentButton .btn-cancel{
|
||||
background-color: #BFBFBF;
|
||||
}
|
||||
#auctionBidsModal #modalConfirmSlotStopGame .contentButton{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 10px;
|
||||
}
|
||||
#auctionBidsModal #modalConfirmSlotStopGame .content{
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
#auctionBidsModal #modalConfirmSlotStopGame .title{
|
||||
color: #FF0202;
|
||||
text-align: center;
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#auctionBidsModal .overlayModalConfirmSlotStopGame{
|
||||
background: rgba(0,0,0,0.2);
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
$(document).ready(function () {
|
||||
window.myAuctionsControlDetail = new Array(); // array di oggetti deputato a contenere l'asta dove si sta autopuntando
|
||||
window.myAuctionsControlDetail_lock = false; // flag to lock SetInterval execution
|
||||
|
||||
/*
|
||||
*
|
||||
* @returns {undefined}
|
||||
* questa funzione si occupa di controllare ogni 2 secondi se l'asta (dettaglio) su cui c'è un'autopuntata sia realmente attive o c'è stato un blocco lato UI
|
||||
*
|
||||
*/
|
||||
|
||||
setInterval(
|
||||
function () {
|
||||
|
||||
if (window.myAuctionsControlDetail_lock == false) {
|
||||
|
||||
window.myAuctionsControlDetail_lock = true; // lock setinterval execution
|
||||
|
||||
//console.log("--- Checking autobids..."); // FOR DEBUG
|
||||
let isAuctionStarted_element = $(".auction-action-timer.auction-header-item-size.closed-timer"); // element not present if auction started
|
||||
|
||||
let callingAjax = false;
|
||||
if (isAuctionStarted_element.length == 0) { // check element not present if auction started
|
||||
|
||||
let element_value = $('.auction-autobid-current-value'); // recupero il valore delle puntate rimanenti nell'asta
|
||||
|
||||
if (element_value.length > 0) {
|
||||
let value = $(element_value[0]).text(); // recupero il valore delle puntate rimanenti nell'asta
|
||||
//console.log("Puntate autobid = "+value); // FOR DEBUG
|
||||
|
||||
if (value > 0) {
|
||||
let idasta = $('input.js-switch.autobid-switch').data("id"); // recupero l'id dell'asta
|
||||
//console.log("Checking Asta: " + idasta); // FOR DEBUG
|
||||
let timestamp = Date.now();
|
||||
|
||||
let myAuctions = {
|
||||
idasta: idasta,
|
||||
value: value,
|
||||
timestamp: timestamp,
|
||||
element_value: element_value
|
||||
}
|
||||
|
||||
if (window.myAuctionsControlDetail.length == 0) { // controllo che questa asta non sia già nell'array
|
||||
//console.log("Adding Asta in array."); // FOR DEBUG
|
||||
window.myAuctionsControlDetail = myAuctions;
|
||||
} else {
|
||||
if (window.myAuctionsControlDetail.value != value) { // controllo che il valore sia cambiato per in modo da aggiornare le informazioni
|
||||
//console.log("Value changed."); // FOR DEBUG
|
||||
window.myAuctionsControlDetail = myAuctions;
|
||||
} else {
|
||||
//console.log("Checking time..."); // FOR DEBUG
|
||||
// in questa condizione il valore non è cambiato dunque controllerò da quanto tempo non cambia
|
||||
var diffMs = (Date.now() - window.myAuctionsControlDetail.timestamp);
|
||||
//console.log("diffMs = "+diffMs); // FOR DEBUG
|
||||
//var diffMins = Math.round(((diffMs % 86400000) % 3600000) / 60000); // minutes
|
||||
var diffSecs = Math.round(((diffMs % 86400000) % 3600000) / 1000); // minutes
|
||||
//console.log("diffSecs = "+diffSecs); // FOR DEBUG
|
||||
|
||||
// nel caso in cui la differenza è maggiore o uguale a 2 minuti invoco la funzione che si occuperà di spedire le informazioni lato backend
|
||||
if (diffSecs >= 70) { // default 70 secs
|
||||
callingAjax = true;
|
||||
sentToVerification(myAuctions);
|
||||
window.myAuctionsControlDetail = new Array(); // elimino l'asta dall'array
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
window.myAuctionsControlDetail = new Array(); // elimino l'asta dall'array
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (callingAjax === false) {
|
||||
window.myAuctionsControlDetail_lock = false; // unlock setinterval execution
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
2000);
|
||||
|
||||
|
||||
function sentToVerification(myAuctions) {
|
||||
|
||||
// funzione che serve ad inviare al backend l'asta attiva ma con valori di autopuntata fermi da 2 min
|
||||
//console.log(myAuctions); // FOR DEBUG
|
||||
|
||||
$.ajax({
|
||||
url: "check_autobid.php",
|
||||
//dataType: json,
|
||||
method: 'POST',
|
||||
timeout: 10000, // default 10000
|
||||
data : {
|
||||
idasta: myAuctions.idasta,
|
||||
value: myAuctions.value,
|
||||
timestamp: myAuctions.timestamp
|
||||
},
|
||||
}).done(function (response) {
|
||||
window.myAuctionsControlDetail_lock = false; // unlock setinterval execution
|
||||
//console.log("response = " + response); // FOR DEBUG
|
||||
$(myAuctions.element_value).text(response);
|
||||
}).fail(function(jqXHR, textStatus){
|
||||
if(textStatus === 'timeout') {
|
||||
//console.log("Ajax timeout. Recall ajax."); // FOR DEBUG
|
||||
sentToVerification(myAuctions);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,322 @@
|
||||
function getTexts() {
|
||||
"use strict"
|
||||
return {
|
||||
dialog_confirm: "Sei sicuro di voler rimuovere l\'AutoPuntata?",
|
||||
autobid_active: "Hai attivato la funzione utilizzando le puntate prenotate",
|
||||
autobid_not_active: "Attiva la funzione utilizzando le puntate prenotate",
|
||||
autobid_add: "AGGIUNGI",
|
||||
autobid_insert: "INSERISCI"
|
||||
};
|
||||
}
|
||||
|
||||
function enableAutobid() {
|
||||
"use strict";
|
||||
|
||||
$(".auction-action-autobid-trigger")
|
||||
.toggleClass("button-fucsia-flat", true)
|
||||
.toggleClass("button-gray-flat", false)
|
||||
.off('click')
|
||||
.on('click', setAutobid);
|
||||
|
||||
$(".auction-action-autobid-input")
|
||||
.attr('disabled', false)
|
||||
.off("keyup").keyup(function (e) {
|
||||
if (13 == e.which)
|
||||
$(".auction-action-autobid-trigger").click();
|
||||
$(".auction-action-autobid-mobile .auction-action-autobid-trigger").toggleClass("disable", $(this).val().length == 0);
|
||||
});
|
||||
}
|
||||
|
||||
function disableAutobid(reason) {
|
||||
"use strict";
|
||||
|
||||
$(".auction-action-autobid-trigger")
|
||||
.off('click')
|
||||
.on('click', function () {
|
||||
if (!reason)
|
||||
return;
|
||||
showErrorTooltip('.auction-action-autobid-trigger:eq(' + getAuctionSelector() + ')', {
|
||||
title: reason,
|
||||
html: true,
|
||||
container: "body",
|
||||
trigger: "manual",
|
||||
placement: "top",
|
||||
template: getTemplateTooltip("error")
|
||||
}, 3000);
|
||||
});
|
||||
}
|
||||
|
||||
function unsetAutobid(evt) {
|
||||
"use strict";
|
||||
if ('undefined' == typeof window['autobid_switchery']) {
|
||||
return;
|
||||
}
|
||||
if (!isSwitchEnabled()) {
|
||||
if (evt) {
|
||||
window._autoController.setAutobid('delete', null, cleanUpAutobidSwitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cleanUpAutobidSwitch() {
|
||||
"use strict"
|
||||
$(".auction-autobid-button")
|
||||
.toggleClass("active", false)
|
||||
.find(".bi-autobid")
|
||||
.toggleClass("bi-dark", true)
|
||||
.toggleClass("bi-green", false);
|
||||
$(".auction-action-bid-mobile .auction-autobid-current-value").empty();
|
||||
setTimeout(function () {
|
||||
if (!isSmartphoneDevice())
|
||||
$('.auction-action-autobid-trigger').text(getTexts().autobid_insert);
|
||||
}, 400);
|
||||
updateAutobid(0);
|
||||
$('.auction-action-autobid:not(.auction-seat-autobid) .autobid-switch-container, .auction-action-autobid-mobile .autobid-switch-container').hide();
|
||||
}
|
||||
|
||||
function isSwitchEnabled() {
|
||||
return 'undefined' != typeof window['autobid_switchery'] && window.autobid_switchery[isSmartphoneDevice() ? 1 : 0].isChecked();
|
||||
}
|
||||
|
||||
function hideAutobid() {
|
||||
"use strict";
|
||||
$(".auction-action-autobid:visible").hide();
|
||||
}
|
||||
|
||||
function showLoginAutobid() {
|
||||
"use strict";
|
||||
$(".auction-action-autobid-trigger")
|
||||
.off('click')
|
||||
.on('click', window.parent.showLogin);
|
||||
|
||||
$(".auction-action-autobid-input").attr('disabled', true);
|
||||
}
|
||||
|
||||
function bindAutobidTrigger() {
|
||||
"use strict";
|
||||
var sNickLoggato = $("#NickLoggato").length > 0 ? $("#NickLoggato").val() : "";
|
||||
|
||||
if (sNickLoggato.length <= 0) {
|
||||
return showLoginAutobid();
|
||||
}
|
||||
$('.auction-action-autobid-trigger').off('click').on('click', function (evt) {
|
||||
var triggerElement = $(this);
|
||||
rippleButton(triggerElement, evt);
|
||||
|
||||
var autobidInputElement = $(".auction-action-autobid-input").eq(isSmartphoneDevice() ? 1 : 0);
|
||||
|
||||
var inputAmount = parseInt(autobidInputElement.val(), 10);
|
||||
var dataInputAmount = parseInt(autobidInputElement.data("amount"), 10);
|
||||
var autobidAmount = !isNaN(dataInputAmount) ? dataInputAmount : inputAmount;
|
||||
autobidInputElement.removeData("amount");
|
||||
|
||||
var autobidLoader = $(".auction-autobid-loader-container");
|
||||
var switchContainer = $('.autobid-switch-container');
|
||||
|
||||
triggerElement.removeAttr("data-autobid-button");
|
||||
|
||||
var isNotValidAmount = isNaN(inputAmount) && isNaN(dataInputAmount);
|
||||
if (isNotValidAmount) {
|
||||
if (isSmartphoneDevice() && !$("[data-stage='2']").is(":visible"))
|
||||
return $(".auction-action-autobid-mobile .auction-action-autobid-input").trigger("focus");
|
||||
} else {
|
||||
autobidLoader.removeClass("hidden");
|
||||
switchContainer.hide();
|
||||
}
|
||||
|
||||
cleanAutobidRequest();
|
||||
window._autoController.setAutobid('create', autobidAmount, function () {
|
||||
switchContainer.show();
|
||||
if (true == isSwitchEnabled())
|
||||
return;
|
||||
$(".autobid-switch.js-switch:hidden")
|
||||
.eq(isSmartphoneDevice() ? 1 : 0)
|
||||
.data("autobid-enabled", "true")
|
||||
.trigger('click');
|
||||
$(".auction-autobid-button")
|
||||
.toggleClass("active", true)
|
||||
.find(".bi-autobid")
|
||||
.toggleClass("bi-dark", false)
|
||||
.toggleClass("bi-green", true);
|
||||
|
||||
var id_product = getUrlParam("a").split("_").reverse()[0];
|
||||
$("#DA"+id_product).find('.favorite').attr('title', "Non puoi rimuoverla dai preferiti se è attiva l\'autopuntata");
|
||||
$("#DA"+id_product).find('.favorite').attr('data-original-title', "Non puoi rimuoverla dai preferiti se è attiva l\'autopuntata");
|
||||
$("#DA"+id_product).find('.favorite').attr('disabled', 'disabled');
|
||||
$("#DA"+id_product).find('.favorite').addClass('active');
|
||||
if (isDeepModal()) {
|
||||
window.parent.BidooCnf.instances.auction.features.startAutobidAuctionUpdate();
|
||||
}
|
||||
|
||||
if (isSmartphoneDevice())
|
||||
return;
|
||||
|
||||
setTimeout(function () {
|
||||
$('.auction-action-autobid-trigger').text(getTexts().autobid_add);
|
||||
}, 400);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setAutobid() {
|
||||
"use strict";
|
||||
if ('undefined' == typeof window['autobid_switchery']) {
|
||||
return;
|
||||
}
|
||||
bindAutobidTrigger();
|
||||
$('.auction-action-autobid-trigger').not("[data-autobid-button]").trigger('click');
|
||||
}
|
||||
|
||||
function updateAutobid(value) {
|
||||
"use strict";
|
||||
var element = $(".auction-autobid-current-value");
|
||||
var oldValue = parseInt(element.eq(0).text(), 10);
|
||||
|
||||
if (value != oldValue) {
|
||||
element.toggle(value > 0);
|
||||
element.text(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function cleanAutobidRequest() {
|
||||
"use strict";
|
||||
$(".auction-action-autobid-input").val('');
|
||||
window._autoController.stopTicker();
|
||||
}
|
||||
|
||||
function updateAutobidStatus(status, value) {
|
||||
"use strict";
|
||||
switch (status) {
|
||||
case 'set':
|
||||
case 'create':
|
||||
{
|
||||
if (0 == value) {
|
||||
closeSwitch();
|
||||
} else {
|
||||
updateAutobid(value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'unset':
|
||||
{
|
||||
closeSwitch();
|
||||
unsetAutobid(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
function closeSwitch() {
|
||||
$('.js-switch.autobid-switch')
|
||||
.eq(isSmartphoneDevice() ? 1 : 0)
|
||||
.data("autobid-enabled", "false")
|
||||
.trigger("click");
|
||||
}
|
||||
function setAutobidUI(isAutobid) {
|
||||
"use strict"
|
||||
$(".auction-action-autobid-mobile .autobid-switch-container").toggle(isAutobid);
|
||||
$(".auction-action-bid-mobile .auction-autobid-button")
|
||||
.toggleClass("active", isAutobid)
|
||||
.find(".bi-autobid")
|
||||
.toggleClass("bi-dark", !isAutobid)
|
||||
.toggleClass("bi-green", isAutobid);
|
||||
$(".js-switch.autobid-switch")
|
||||
.data("autobid-enabled", "false")
|
||||
.trigger('click');
|
||||
}
|
||||
|
||||
function setCorrectPlaceholder(isFocused) {
|
||||
"use strict"
|
||||
this.attr("placeholder", isFocused ? "" : $(this).data("placeholder"));
|
||||
$(".auction-action-autobid-mobile .auction-action-autobid-trigger").toggleClass("disable", this.val().length == 0);
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
"use strict";
|
||||
window.autobid_switchery = [];
|
||||
window.autobid_seat_switchery = [];
|
||||
$(".js-switch.autobid-switch").each(function (k, item) {
|
||||
window.autobid_switchery.push(new Switchery(item, {size: 'small'}));
|
||||
});
|
||||
|
||||
$(".js-switch.autobid-seat-switch").each(function (k, item) {
|
||||
window.autobid_seat_switchery.push(new Switchery(item, {size: 'small'}));
|
||||
});
|
||||
|
||||
$('.js-switch.autobid-seat-switch').off('change').on('change', function () {
|
||||
var self = this;
|
||||
var isEnabled = $(this).is(':checked');
|
||||
if (isEnabled) {
|
||||
window.stage.getUpdate(function (update) {
|
||||
window._autoController.setAutobid('create', update.me.budget.total, function () {
|
||||
$(".autobid-seat-status").text(getTexts().autobid_active);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
window._autoController.setAutobid('delete', null, function () {
|
||||
updateAutobid(0);
|
||||
$(".autobid-seat-status").text(getTexts().autobid_not_active);
|
||||
});
|
||||
}
|
||||
if (isSmartphoneDevice())
|
||||
setAutobidUI(isEnabled);
|
||||
return true;
|
||||
});
|
||||
|
||||
function confirmAutobidUnset() {
|
||||
|
||||
if(confirm(getTexts().dialog_confirm)){
|
||||
|
||||
return true;
|
||||
}else{
|
||||
if (isSmartphoneDevice()){
|
||||
$('.switchery-small small').css('left', '30px');
|
||||
}else{
|
||||
$('#boxcontent .autobid-switch').click();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$('.js-switch.autobid-switch').off('change').on('change', function () {
|
||||
var switchAutobid = $(this);
|
||||
if (isSmartphoneDevice() && $("[data-stage='2']").is(":visible"))
|
||||
return true;
|
||||
var id_product = getUrlParam("a").split("_").reverse()[0];
|
||||
if (!switchAutobid.is(':checked') && ("false" == switchAutobid.data("autobid-enabled") || confirmAutobidUnset())) {
|
||||
unsetAutobid({});
|
||||
|
||||
|
||||
$("#DA"+id_product).find('.favorite').removeAttr('disabled');
|
||||
$("#DA"+id_product).find('.favorite').attr('title', "Rimuovi quest\'asta dalle tue preferite");
|
||||
if (isDeepModal()) {
|
||||
$("#DA"+id_product).find('.favorite').removeAttr('data-original-title');
|
||||
window.parent.BidooCnf.instances.auction.features.stopAutobidAuctionUpdate();
|
||||
setTimeout(function () {
|
||||
$("#divAsta"+id_product, parent.document).find('.favorite').removeAttr('data-original-title');
|
||||
$("#divAsta"+id_product, parent.document).find('.favorite').removeAttr('disabled');
|
||||
$("#divAsta"+id_product, parent.document).find('.favorite').attr('title', "Rimuovi quest\'asta dalle tue preferite");
|
||||
}, 500);
|
||||
} else {
|
||||
$("#DA"+id_product).find('.favorite').attr("data-original-title", "Rimuovi quest\'asta dalle tue preferite");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
$(".autobid-speed-dial > div > a").on('click', function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var self = $(this);
|
||||
var amount = parseInt(self.attr("data-amount"));
|
||||
$(".auction-action-autobid-input").data("amount", amount);
|
||||
$('.auction-action-autobid-trigger').attr("data-autobid-button", true).trigger('click');
|
||||
});
|
||||
|
||||
var scopeElement = $(".auction-action-autobid-input[data-placeholder]");
|
||||
scopeElement
|
||||
.focus(setCorrectPlaceholder.bind(scopeElement, true))
|
||||
.blur(setCorrectPlaceholder.bind(scopeElement, false));
|
||||
});
|
||||
|
After Width: | Height: | Size: 35 KiB |
13975
Mimante/Examples/10€ Idea Shopping +10P - Bidoo_files/base.js.download
Normal file
@@ -0,0 +1,255 @@
|
||||
.btn-promo, .btn-promo:hover {
|
||||
background: #2196f3 !important;
|
||||
}
|
||||
|
||||
.mCSB_inside > .mCSB_container {
|
||||
margin-right: 0px;
|
||||
}
|
||||
|
||||
.mCSB_scrollTools .mCSB_draggerRail {
|
||||
width: 6px;
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
.mCSB_scrollTools .mCSB_draggerContainer {
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.mCSB_scrollTools .mCSB_dragger .mCSB_dragger_bar {
|
||||
background-color: #20cb9a !important;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#toggleBar {
|
||||
margin-left: 0 !important;
|
||||
left: 20px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.barra {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.btn-promo {
|
||||
margin-top: -2px;
|
||||
line-height: 17.5px;
|
||||
}
|
||||
|
||||
.view_gray_link {
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.leader-btn {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.bid_chal img.img-lock{
|
||||
display: none;
|
||||
}
|
||||
.bid_chal img{
|
||||
margin-top: -3px;
|
||||
}
|
||||
.wrap-limit-unlock{
|
||||
color: #fff;
|
||||
background-color: #55bc62;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
padding: 0;
|
||||
text-transform: initial;
|
||||
width: 120px;
|
||||
margin: -4px auto 0;
|
||||
}
|
||||
|
||||
.wrap-button-get-bonus{
|
||||
color: #000;
|
||||
background-color: #FFC642;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
padding: 0;
|
||||
display: none;
|
||||
text-transform: initial;
|
||||
margin-top: -4px;
|
||||
}
|
||||
.wrap-button-get-bonus img{
|
||||
width: 14px;
|
||||
}
|
||||
.bid_chal {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-transform: none;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.next-level {
|
||||
background-color: #eaeaea;
|
||||
margin: 0;
|
||||
width: 124px;
|
||||
height: 8px;
|
||||
box-shadow: none;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#tickNotif {
|
||||
background: white;
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
transform: rotate(-45deg);
|
||||
border: 1px solid #e2e2e2;
|
||||
position: fixed;
|
||||
margin-top: -15px;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.notifIcon {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
#boxarea.dodici {
|
||||
width: 920px;
|
||||
}
|
||||
|
||||
#tickNotif {
|
||||
margin-left: 17px;
|
||||
}
|
||||
|
||||
.small_notif {
|
||||
margin-left: 119px !important;
|
||||
}
|
||||
|
||||
.bonus_dialog {
|
||||
left: 48.5%;
|
||||
}
|
||||
|
||||
.leader_btn {
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.tooltip.reach > .tooltip-inner .wrap{
|
||||
display: flex;
|
||||
}
|
||||
.tooltip.reach > .tooltip-inner .wrap img{
|
||||
width: 16px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.tooltip.reach > .tooltip-inner {
|
||||
background-color: #fff;
|
||||
border: 1px solid #333;
|
||||
color: #232323;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.tooltip.reach > .tooltip-inner > span {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tooltip.reach > .tooltip-inner > span:last-child {
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.tooltip.reach > .tooltip-inner strong {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.bid-challenge > strong {
|
||||
color: darkorange;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.tooltip.reach > .tooltip-inner {
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.leader-btn:hover, .leader-btn {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.paid-all {
|
||||
color: #565454;
|
||||
margin-top: -5px;
|
||||
text-transform: initial;
|
||||
}
|
||||
.active-all {
|
||||
color: #55bc62;
|
||||
margin-top: -5px;
|
||||
text-transform: initial;
|
||||
}
|
||||
.paid-all img, .active-all img{
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.bar-right-side .pull-right{
|
||||
margin-right: -30px;
|
||||
}
|
||||
|
||||
.bar-right-side .pull-right > *,
|
||||
.bar-left-side > *{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.bar-left-side{
|
||||
margin-top: 5px;
|
||||
}
|
||||
.auctions_won_bottom_bar { /*[GR]*/
|
||||
border: 2px solid #ffc518 !important;
|
||||
background-color:#fff;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
border-radius: 5px;
|
||||
padding: 5px 10px;
|
||||
color:#3d3a3a;
|
||||
outline: 0;
|
||||
font-weight:bold;
|
||||
height:29px;
|
||||
vertical-align: top;
|
||||
}
|
||||
.auctions_won_bottom_bar:hover{ /*[GR]*/
|
||||
background-color: #ffc518 !important;
|
||||
color: #fff;
|
||||
}
|
||||
.auctions_won_bottom_bar .badge { /*[GR]*/
|
||||
background-color: #ff2f4e;
|
||||
left: 20px;
|
||||
top: -12px;
|
||||
margin-left: -20px;
|
||||
}
|
||||
.barra[data-lang="es"] #ba #boxarea .notifIcon{
|
||||
margin-left: 10px;
|
||||
}
|
||||
.barra[data-lang="es"] #ba #boxarea #lim{
|
||||
margin-left: 5px;
|
||||
|
||||
}
|
||||
.barra[data-lang="es"] #ba #boxarea .auctions_won_bottom_bar{
|
||||
margin-left: 5px;
|
||||
margin-top: 1px;
|
||||
|
||||
}
|
||||
@media(max-width: 1200px){
|
||||
.barra[data-lang="es"] #ba #boxarea .auctions_won_bottom_bar, .barra[data-lang="es"] #ba #boxarea #lim{
|
||||
width: 110px;
|
||||
font-size: 11px;
|
||||
padding: 5px;
|
||||
}
|
||||
.barra[data-lang="es"] .notif{
|
||||
margin: -5px 6px !important;
|
||||
}
|
||||
}
|
||||
.bidooBell{
|
||||
color: #c3c0c1;
|
||||
font-size: 21px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.bidooBell:hover, .bidooBell:active, .bidooBell:focus, .bidooBell.active{
|
||||
color: #666666;
|
||||
transition: color 0.4s;
|
||||
}
|
||||
#auctionBidBottomBar{
|
||||
outline: none !important;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
function BottomBar(){
|
||||
"use strict"
|
||||
var self = this;
|
||||
self.footer = $(".footer");
|
||||
self.checkFooter();
|
||||
}
|
||||
|
||||
BottomBar.prototype.checkFooter = function() {
|
||||
"use strict"
|
||||
var self = this;
|
||||
if (!self.footer.length) return;
|
||||
$(window).scroll(function() {
|
||||
$(".goTop").find("i")
|
||||
.toggleClass("white_top_arrow", isElementInView(self.footer, false));
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
"use strict"
|
||||
new BottomBar();
|
||||
});
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
14
Mimante/Examples/10€ Idea Shopping +10P - Bidoo_files/bootstrap.min.css
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
var BUYNOW_COUNTDOWN = null;
|
||||
var BUYNOW_ERRORS = {
|
||||
already_used: 'Hai usato l’opzione Compralo in quest’asta',
|
||||
already_won: 'Hai vinto questa Asta.<br>Non puoi usare l’opzione Compralo'
|
||||
};
|
||||
window.serverTime = () => {
|
||||
//vado a prendere il valore dalla pagina, precedentemente messo in php
|
||||
if($('.buynow-countdown-container .product-buynow-countdown').hasClass('time-server')){
|
||||
return parseInt($('.time-server').attr('data-time-server')) != "NaN" ? parseInt($('.time-server').attr('data-time-server')) : null ;
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function startBuynowCountdown(time) {
|
||||
"use strict";
|
||||
|
||||
var element = $(".product-buynow-countdown[data-countdown]");
|
||||
|
||||
if('active' == element.attr("data-countdown-status")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if('undefined' != typeof time) {
|
||||
element.attr('data-countdown', time);
|
||||
}
|
||||
|
||||
var countdown = element.attr('data-countdown');
|
||||
|
||||
if(countdown && countdown.length > 0) {
|
||||
BUYNOW_COUNTDOWN = setInterval(function() {
|
||||
var countdown_value = SimpleCountdown(countdown);
|
||||
element.text(countdown_value);
|
||||
|
||||
/*
|
||||
Destroy interval
|
||||
Hide countdown
|
||||
*/
|
||||
var timeServer = typeof window.serverTime() != null ? window.serverTime() : (new Date()).getTime() / 1000;
|
||||
|
||||
var isExpired = countdown <= parseInt(timeServer);
|
||||
$(".buyitnow-status p > span.product-value").toggle(isExpired);
|
||||
$("span.product-buynow-countdown").toggle(!isExpired);
|
||||
if(isExpired) clearInterval(BUYNOW_COUNTDOWN);
|
||||
}, 1000);
|
||||
element.attr("data-countdown-status", "active");
|
||||
}
|
||||
}
|
||||
|
||||
function setStatusBuynowButton(status, error_type) {
|
||||
"use strict";
|
||||
|
||||
var selector = ".buyitnow-button";
|
||||
var element = $(selector);
|
||||
var defaults = "button-default button-full buyitnow-button ripple-button";
|
||||
var base = "buyitnow-button";
|
||||
var specific = 'button-blue-gradient';
|
||||
|
||||
switch(status) {
|
||||
default:
|
||||
case 'enabled': {
|
||||
bindBuynowTrigger(error_type);
|
||||
break;
|
||||
}
|
||||
case 'engaged': {
|
||||
$('body').find("[data-buynow-state='engaged']").fadeIn();
|
||||
bindBuynowTrigger(error_type);
|
||||
break;
|
||||
}
|
||||
case 'disabled': {
|
||||
specific = "button-gray-flat";
|
||||
element.off('click');
|
||||
element.find("[data-buynow-state='engaged']").fadeOut('fast');
|
||||
break;
|
||||
}
|
||||
case 'login': {
|
||||
element.off('click').on('click', window.parent.showLogin);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if("undefined"===typeof element[0]) return element;
|
||||
var oldClass = element[0].className;
|
||||
var newClass = [defaults, specific, [base, status].join('-')].join(' ');
|
||||
|
||||
if(oldClass != newClass) {
|
||||
$("main.buyitnow").find(selector).each(function(k, item) {
|
||||
$(item).removeClass();
|
||||
$(item).addClass(newClass);
|
||||
});
|
||||
$(".auction-action-bid-mobile .buyitnow-button")
|
||||
.toggleClass(specific,true);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
function bindBuynowTrigger(error_type) {
|
||||
"use strict";
|
||||
var selector = ".buyitnow-button";
|
||||
var element = $('body').find(selector);
|
||||
|
||||
element.each(function(k, elem) {
|
||||
$(elem).off('click').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
rippleButton($(elem), e);
|
||||
|
||||
if(!error_type) {
|
||||
var url = "buy_your_product.php"+parseURL(window.location.href).search;
|
||||
navigateDeepModalURL(url);
|
||||
return false;
|
||||
}
|
||||
|
||||
$(elem).popover({
|
||||
html: true,
|
||||
content: BUYNOW_ERRORS[error_type],
|
||||
placement: isSmartphoneDevice() ? "top" : "bottom",
|
||||
selector: selector,
|
||||
container: "body"
|
||||
}).on('shown.bs.popover', function() {
|
||||
setTimeout(function() {
|
||||
$(selector).popover('destroy');
|
||||
}, 3000);
|
||||
}).popover('show');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
"use strict";
|
||||
$("body").find(".expenditure-value").each(function(k, item) {
|
||||
var expenditure = $(item).text();
|
||||
if(expenditure.length && parseInt(expenditure, 10) > 0) {
|
||||
updateUserExpenditure(expenditure);
|
||||
$('[data-buynow-state="engaged"]').fadeIn();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,99 @@
|
||||
(function(){'use strict';var f,aa=function(a){var b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}},g=typeof Object.defineProperties=="function"?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a},ba=function(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");
|
||||
},ca=ba(this),da=function(a,b){if(b)a:{var c=ca;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&b!=null&&g(c,a,{configurable:!0,writable:!0,value:b})}};
|
||||
da("Symbol",function(a){if(a)return a;var b=function(h,k){this.g=h;g(this,"description",{configurable:!0,writable:!0,value:k})};b.prototype.toString=function(){return this.g};var c="jscomp_symbol_"+(Math.random()*1E9>>>0)+"_",d=0,e=function(h){if(this instanceof e)throw new TypeError("Symbol is not a constructor");return new b(c+(h||"")+"_"+d++,h)};return e});
|
||||
da("Symbol.iterator",function(a){if(a)return a;a=Symbol("Symbol.iterator");g(Array.prototype,a,{configurable:!0,writable:!0,value:function(){return ea(aa(this))}});return a});var ea=function(a){a={next:a};a[Symbol.iterator]=function(){return this};return a},fa=typeof Object.create=="function"?Object.create:function(a){var b=function(){};b.prototype=a;return new b},l;
|
||||
if(typeof Object.setPrototypeOf=="function")l=Object.setPrototypeOf;else{var n;a:{var ha={a:!0},ia={};try{ia.__proto__=ha;n=ia.a;break a}catch(a){}n=!1}l=n?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}
|
||||
var ja=l,q=function(a,b){a.prototype=fa(b.prototype);a.prototype.constructor=a;if(ja)ja(a,b);else for(var c in b)if(c!="prototype")if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.sc=b.prototype},ka=function(a){var b=typeof Symbol!="undefined"&&Symbol.iterator&&a[Symbol.iterator];if(b)return b.call(a);if(typeof a.length=="number")return{next:aa(a)};throw Error(String(a)+" is not an iterable or ArrayLike");};/*
|
||||
|
||||
Copyright The Closure Library Authors.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
var r=this||self,u=function(a){var b=typeof a;b=b!="object"?b:a?Array.isArray(a)?"array":b:"null";return b=="array"||b=="object"&&typeof a.length=="number"},v="closure_uid_"+(Math.random()*1E9>>>0),la=0,ma=function(a,b,c){return a.call.apply(a.bind,arguments)},na=function(a,b,c){if(!a)throw Error();if(arguments.length>2){var d=Array.prototype.slice.call(arguments,2);return function(){var e=Array.prototype.slice.call(arguments);Array.prototype.unshift.apply(e,d);return a.apply(b,e)}}return function(){return a.apply(b,
|
||||
arguments)}},w=function(a,b,c){w=Function.prototype.bind&&Function.prototype.bind.toString().indexOf("native code")!=-1?ma:na;return w.apply(null,arguments)},x=function(a,b){a=a.split(".");for(var c=r,d;a.length&&(d=a.shift());)a.length||b===void 0?c[d]&&c[d]!==Object.prototype[d]?c=c[d]:c=c[d]={}:c[d]=b};var chrome=chrome||window.chrome||{};chrome.cast=chrome.cast||{};chrome.cast.media=chrome.cast.media||{};chrome.cast.ReceiverActionListener={};chrome.cast.VERSION=[1,2];x("chrome.cast.VERSION",chrome.cast.VERSION);chrome.cast.rc=!0;x("chrome.cast.usingPresentationApi",chrome.cast.rc);chrome.cast.Na=function(a,b){this.credentials=a;this.credentialsType=b===void 0?"web":b};x("chrome.cast.CredentialsData",chrome.cast.Na);chrome.cast.Error=function(a,b,c){this.code=a;this.description=b||null;this.details=c||null};x("chrome.cast.Error",chrome.cast.Error);
|
||||
chrome.cast.nb=function(a){this.platform=a;this.packageId=this.url=null};x("chrome.cast.SenderApplication",chrome.cast.nb);chrome.cast.Image=function(a){this.url=a;this.width=this.height=null};x("chrome.cast.Image",chrome.cast.Image);chrome.cast.Volume=function(a,b){this.level=a===void 0?null:a;this.muted=b===void 0?null:b};x("chrome.cast.Volume",chrome.cast.Volume);chrome.cast.ha={CUSTOM_CONTROLLER_SCOPED:"custom_controller_scoped",TAB_AND_ORIGIN_SCOPED:"tab_and_origin_scoped",ORIGIN_SCOPED:"origin_scoped",PAGE_SCOPED:"page_scoped"};x("chrome.cast.AutoJoinPolicy",chrome.cast.ha);chrome.cast.ja={CREATE_SESSION:"create_session",CAST_THIS_TAB:"cast_this_tab"};x("chrome.cast.DefaultActionPolicy",chrome.cast.ja);chrome.cast.Ma={VIDEO_OUT:"video_out",AUDIO_OUT:"audio_out",VIDEO_IN:"video_in",AUDIO_IN:"audio_in",MULTIZONE_GROUP:"multizone_group"};
|
||||
x("chrome.cast.Capability",chrome.cast.Ma);chrome.cast.A={CANCEL:"cancel",TIMEOUT:"timeout",API_NOT_INITIALIZED:"api_not_initialized",INVALID_PARAMETER:"invalid_parameter",EXTENSION_NOT_COMPATIBLE:"extension_not_compatible",EXTENSION_MISSING:"extension_missing",RECEIVER_UNAVAILABLE:"receiver_unavailable",SESSION_ERROR:"session_error",CHANNEL_ERROR:"channel_error",LOAD_MEDIA_FAILED:"load_media_failed"};x("chrome.cast.ErrorCode",chrome.cast.A);chrome.cast.N={AVAILABLE:"available",UNAVAILABLE:"unavailable"};
|
||||
x("chrome.cast.ReceiverAvailability",chrome.cast.N);chrome.cast.ob={CHROME:"chrome",IOS:"ios",ANDROID:"android"};x("chrome.cast.SenderPlatform",chrome.cast.ob);chrome.cast.xa={CAST:"cast",DIAL:"dial",HANGOUT:"hangout",CUSTOM:"custom"};x("chrome.cast.ReceiverType",chrome.cast.xa);chrome.cast.Qa={RUNNING:"running",STOPPED:"stopped",ERROR:"error"};x("chrome.cast.DialAppState",chrome.cast.Qa);chrome.cast.jb={CAST:"cast",STOP:"stop"};x("chrome.cast.ReceiverAction",chrome.cast.jb);
|
||||
chrome.cast.K={CONNECTED:"connected",DISCONNECTED:"disconnected",STOPPED:"stopped"};x("chrome.cast.SessionStatus",chrome.cast.K);chrome.cast.Db={ATTENUATION:"attenuation",FIXED:"fixed",MASTER:"master"};x("chrome.cast.VolumeControlType",chrome.cast.Db);var oa=/&/g,pa=/</g,qa=/>/g,ra=/"/g,sa=/'/g,ta=/\x00/g,ua=/[\x00&<>"']/;/*
|
||||
|
||||
Copyright Google LLC
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
var va={};function wa(){if(va!==va)throw Error("Bad secret");};var xa=globalThis.trustedTypes,y;function ya(){var a=null;if(!xa)return a;try{var b=function(c){return c};a=xa.createPolicy("goog#html",{createHTML:b,createScript:b,createScriptURL:b})}catch(c){throw c;}return a};var z=function(a){wa();this.g=a};z.prototype.toString=function(){return this.g};new z("about:blank");new z("about:invalid#zClosurez");var za=[],Aa=function(a){console.warn("A URL with content '"+a+"' was sanitized away.")};za.indexOf(Aa)===-1&&za.push(Aa);var A=function(a){wa();this.g=a};A.prototype.toString=function(){return this.g+""};var Ba=Array.prototype.forEach?function(a,b){Array.prototype.forEach.call(a,b,void 0)}:function(a,b){for(var c=a.length,d=typeof a==="string"?a.split(""):a,e=0;e<c;e++)e in d&&b.call(void 0,d[e],e,a)};function Ca(a,b){for(var c=a.length,d=typeof a==="string"?a.split(""):a,e=0;e<c;e++)if(e in d&&b.call(void 0,d[e],e,a))return e;return-1};var Da=Object.freeze||function(a){return a};var Fa=function(a){var b={"&":"&","<":"<",">":">",""":'"'};var c=r.document.createElement("div");return a.replace(Ea,function(d,e){var h=b[d];if(h)return h;e.charAt(0)=="#"&&(e=Number("0"+e.slice(1)),isNaN(e)||(h=String.fromCharCode(e)));if(!h){h=d+" ";y===void 0&&(y=ya());h=(e=y)?e.createHTML(h):h;h=new A(h);if(c.nodeType===1&&(e=c.tagName,/^(script|style)$/i.test(e)))throw d=e.toLowerCase()==="script"?"Use setScriptTextContent with a SafeScript.":"Use setStyleTextContent with a SafeStyleSheet.",
|
||||
Error(d);if(h instanceof A)h=h.g;else throw Error("Unexpected type when unwrapping SafeHtml");c.innerHTML=h;h=c.firstChild.nodeValue.slice(0,-1)}return b[d]=h})},Ga=function(a){return a.replace(/&([^;]+);/g,function(b,c){switch(c){case "amp":return"&";case "lt":return"<";case "gt":return">";case "quot":return'"';default:return c.charAt(0)!="#"||(c=Number("0"+c.slice(1)),isNaN(c))?b:String.fromCharCode(c)}})},Ea=/&([^;\s<&]+);?/g;chrome.cast.Ia=function(a,b,c,d,e){this.sessionRequest=a;this.sessionListener=b;this.receiverListener=c;this.autoJoinPolicy=d||chrome.cast.ha.TAB_AND_ORIGIN_SCOPED;this.defaultActionPolicy=e||chrome.cast.ja.CREATE_SESSION;this.customDialLaunchCallback=null;this.invisibleSender=!1;this.additionalSessionRequests=[]};x("chrome.cast.ApiConfig",chrome.cast.Ia);chrome.cast.Ta=function(a,b){this.appName=a;this.launchParameter=b||null};x("chrome.cast.DialRequest",chrome.cast.Ta);
|
||||
chrome.cast.Ra=function(a,b,c){this.receiver=a;this.appState=b;this.extraData=c||null};x("chrome.cast.DialLaunchData",chrome.cast.Ra);chrome.cast.Sa=function(a,b){this.doLaunch=a;this.launchParameter=b||null};x("chrome.cast.DialLaunchResponse",chrome.cast.Sa);
|
||||
chrome.cast.pb=function(a,b,c,d,e){c=c===void 0?chrome.cast.timeout.requestSession:c;this.appId=a;this.capabilities=Array.isArray(b)?b:[];this.requestSessionTimeout=c;this.dialRequest=this.language=null;this.androidReceiverCompatible=d===void 0?!1:d;this.credentialsData=e===void 0?null:e};x("chrome.cast.SessionRequest",chrome.cast.pb);
|
||||
chrome.cast.ib=function(a,b,c,d){this.label=a;a=b;ua.test(a)&&(a.indexOf("&")!=-1&&(a=a.replace(oa,"&")),a.indexOf("<")!=-1&&(a=a.replace(pa,"<")),a.indexOf(">")!=-1&&(a=a.replace(qa,">")),a.indexOf('"')!=-1&&(a=a.replace(ra,""")),a.indexOf("'")!=-1&&(a=a.replace(sa,"'")),a.indexOf("\x00")!=-1&&(a=a.replace(ta,"�")));this.friendlyName=a;this.capabilities=c||[];this.volume=d||null;this.receiverType=chrome.cast.xa.CAST;this.displayStatus=this.isActiveInput=null};
|
||||
x("chrome.cast.Receiver",chrome.cast.ib);chrome.cast.kb=function(a,b){this.statusText=a;this.appImages=b;this.showStop=null};x("chrome.cast.ReceiverDisplayStatus",chrome.cast.kb);chrome.cast.Aa=function(){this.requestSession=6E4;this.getDialAppInfo=this.sendCustomMessage=this.setReceiverVolume=this.stopSession=this.leaveSession=3E3};x("chrome.cast.Timeout",chrome.cast.Aa);chrome.cast.timeout=new chrome.cast.Aa;x("chrome.cast.timeout",chrome.cast.timeout);chrome.cast.Ha="auto-join";
|
||||
chrome.cast.cb="cast-session_";chrome.cast.media.Va={SDR:"sdr",HDR:"hdr",DV:"dv"};x("chrome.cast.media.HdrType",chrome.cast.media.Va);chrome.cast.media.Wa={AAC:"aac",AC3:"ac3",MP3:"mp3",TS:"ts",TS_AAC:"ts_aac",E_AC3:"e_ac3",FMP4:"fmp4"};x("chrome.cast.media.HlsSegmentFormat",chrome.cast.media.Wa);chrome.cast.media.Xa={MPEG2_TS:"mpeg2_ts",FMP4:"fmp4"};x("chrome.cast.media.HlsVideoSegmentFormat",chrome.cast.media.Xa);chrome.cast.media.ab={PAUSE:"pause",SEEK:"seek",STREAM_VOLUME:"stream_volume",STREAM_MUTE:"stream_mute"};
|
||||
x("chrome.cast.media.MediaCommand",chrome.cast.media.ab);chrome.cast.media.gb={ALBUM:"ALBUM",PLAYLIST:"PLAYLIST",AUDIOBOOK:"AUDIOBOOK",RADIO_STATION:"RADIO_STATION",PODCAST_SERIES:"PODCAST_SERIES",TV_SERIES:"TV_SERIES",VIDEO_PLAYLIST:"VIDEO_PLAYLIST",LIVE_TV:"LIVE_TV",MOVIE:"MOVIE"};x("chrome.cast.media.QueueType",chrome.cast.media.gb);chrome.cast.media.U={GENERIC_CONTAINER:0,AUDIOBOOK_CONTAINER:1};x("chrome.cast.media.ContainerType",chrome.cast.media.U);
|
||||
chrome.cast.media.F={GENERIC:0,MOVIE:1,TV_SHOW:2,MUSIC_TRACK:3,PHOTO:4,AUDIOBOOK_CHAPTER:5};x("chrome.cast.media.MetadataType",chrome.cast.media.F);chrome.cast.media.B={IDLE:"IDLE",PLAYING:"PLAYING",PAUSED:"PAUSED",BUFFERING:"BUFFERING"};x("chrome.cast.media.PlayerState",chrome.cast.media.B);chrome.cast.media.V={OFF:"REPEAT_OFF",ALL:"REPEAT_ALL",SINGLE:"REPEAT_SINGLE",ALL_AND_SHUFFLE:"REPEAT_ALL_AND_SHUFFLE"};x("chrome.cast.media.RepeatMode",chrome.cast.media.V);
|
||||
chrome.cast.media.lb={PLAYBACK_START:"PLAYBACK_START",PLAYBACK_PAUSE:"PLAYBACK_PAUSE"};x("chrome.cast.media.ResumeState",chrome.cast.media.lb);chrome.cast.media.za={BUFFERED:"BUFFERED",LIVE:"LIVE",OTHER:"OTHER"};x("chrome.cast.media.StreamType",chrome.cast.media.za);chrome.cast.media.Ya={CANCELLED:"CANCELLED",INTERRUPTED:"INTERRUPTED",FINISHED:"FINISHED",ERROR:"ERROR"};x("chrome.cast.media.IdleReason",chrome.cast.media.Ya);chrome.cast.media.yb={TEXT:"TEXT",AUDIO:"AUDIO",VIDEO:"VIDEO"};
|
||||
x("chrome.cast.media.TrackType",chrome.cast.media.yb);chrome.cast.media.ub={SUBTITLES:"SUBTITLES",CAPTIONS:"CAPTIONS",DESCRIPTIONS:"DESCRIPTIONS",CHAPTERS:"CHAPTERS",METADATA:"METADATA"};x("chrome.cast.media.TextTrackType",chrome.cast.media.ub);chrome.cast.media.qb={NONE:"NONE",OUTLINE:"OUTLINE",DROP_SHADOW:"DROP_SHADOW",RAISED:"RAISED",DEPRESSED:"DEPRESSED"};x("chrome.cast.media.TextTrackEdgeType",chrome.cast.media.qb);chrome.cast.media.wb={NONE:"NONE",NORMAL:"NORMAL",ROUNDED_CORNERS:"ROUNDED_CORNERS"};
|
||||
x("chrome.cast.media.TextTrackWindowType",chrome.cast.media.wb);chrome.cast.media.rb={SANS_SERIF:"SANS_SERIF",MONOSPACED_SANS_SERIF:"MONOSPACED_SANS_SERIF",SERIF:"SERIF",MONOSPACED_SERIF:"MONOSPACED_SERIF",CASUAL:"CASUAL",CURSIVE:"CURSIVE",SMALL_CAPITALS:"SMALL_CAPITALS"};x("chrome.cast.media.TextTrackFontGenericFamily",chrome.cast.media.rb);chrome.cast.media.sb={NORMAL:"NORMAL",BOLD:"BOLD",BOLD_ITALIC:"BOLD_ITALIC",ITALIC:"ITALIC"};x("chrome.cast.media.TextTrackFontStyle",chrome.cast.media.sb);
|
||||
chrome.cast.media.zb={LIKE:"LIKE",DISLIKE:"DISLIKE",FOLLOW:"FOLLOW",UNFOLLOW:"UNFOLLOW"};x("chrome.cast.media.UserAction",chrome.cast.media.zb);chrome.cast.media.la=function(){this.customData=null};x("chrome.cast.media.GetStatusRequest",chrome.cast.media.la);chrome.cast.media.pa=function(){this.customData=null};x("chrome.cast.media.PauseRequest",chrome.cast.media.pa);chrome.cast.media.ra=function(){this.customData=null};x("chrome.cast.media.PlayRequest",chrome.cast.media.ra);chrome.cast.media.mb=function(){this.customData=this.resumeState=this.currentTime=null};x("chrome.cast.media.SeekRequest",chrome.cast.media.mb);
|
||||
chrome.cast.media.ya=function(){this.customData=null};x("chrome.cast.media.StopRequest",chrome.cast.media.ya);chrome.cast.media.Eb=function(a){this.volume=a;this.customData=null};x("chrome.cast.media.VolumeRequest",chrome.cast.media.Eb);
|
||||
chrome.cast.media.Za=function(a){this.type="LOAD";this.requestId=0;this.sessionId=null;this.media=a;this.activeTrackIds=null;this.autoplay=!0;this.atvCredentialsType=this.atvCredentials=this.credentialsType=this.credentials=void 0;this.customData=this.currentTime=null;this.queueData=this.playbackRate=void 0};x("chrome.cast.media.LoadRequest",chrome.cast.media.Za);chrome.cast.media.Ua=function(a,b){this.requestId=0;this.activeTrackIds=a||null;this.textTrackStyle=b||null};
|
||||
x("chrome.cast.media.EditTracksInfoRequest",chrome.cast.media.Ua);chrome.cast.media.T=function(a){this.containerType=a=a===void 0?chrome.cast.media.U.GENERIC_CONTAINER:a;this.containerDuration=this.containerImages=this.sections=this.title=void 0};x("chrome.cast.media.ContainerMetadata",chrome.cast.media.T);
|
||||
chrome.cast.media.MediaMetadata=function(a){this.metadataType=this.type=a;this.queueItemId=this.sectionStartTimeInContainer=this.sectionStartAbsoluteTime=this.sectionStartTimeInMedia=this.sectionDuration=void 0};x("chrome.cast.media.MediaMetadata",chrome.cast.media.MediaMetadata);chrome.cast.media.ka=function(){chrome.cast.media.MediaMetadata.call(this,chrome.cast.media.F.GENERIC);this.releaseDate=this.releaseYear=this.images=this.subtitle=this.title=void 0};q(chrome.cast.media.ka,chrome.cast.media.MediaMetadata);
|
||||
x("chrome.cast.media.GenericMediaMetadata",chrome.cast.media.ka);chrome.cast.media.na=function(){chrome.cast.media.MediaMetadata.call(this,chrome.cast.media.F.MOVIE);this.releaseDate=this.releaseYear=this.images=this.subtitle=this.studio=this.title=void 0};q(chrome.cast.media.na,chrome.cast.media.MediaMetadata);x("chrome.cast.media.MovieMediaMetadata",chrome.cast.media.na);
|
||||
chrome.cast.media.Ba=function(){chrome.cast.media.MediaMetadata.call(this,chrome.cast.media.F.TV_SHOW);this.originalAirdate=this.releaseYear=this.images=this.episode=this.episodeNumber=this.season=this.seasonNumber=this.episodeTitle=this.title=this.seriesTitle=void 0};q(chrome.cast.media.Ba,chrome.cast.media.MediaMetadata);x("chrome.cast.media.TvShowMediaMetadata",chrome.cast.media.Ba);
|
||||
chrome.cast.media.oa=function(){chrome.cast.media.MediaMetadata.call(this,chrome.cast.media.F.MUSIC_TRACK);this.releaseDate=this.releaseYear=this.images=this.discNumber=this.trackNumber=this.artistName=this.songName=this.composer=this.artist=this.albumArtist=this.title=this.albumName=void 0};q(chrome.cast.media.oa,chrome.cast.media.MediaMetadata);x("chrome.cast.media.MusicTrackMediaMetadata",chrome.cast.media.oa);
|
||||
chrome.cast.media.qa=function(){chrome.cast.media.MediaMetadata.call(this,chrome.cast.media.F.PHOTO);this.creationDateTime=this.height=this.width=this.longitude=this.latitude=this.images=this.location=this.artist=this.title=void 0};q(chrome.cast.media.qa,chrome.cast.media.MediaMetadata);x("chrome.cast.media.PhotoMediaMetadata",chrome.cast.media.qa);
|
||||
chrome.cast.media.ga=function(){chrome.cast.media.T.call(this,chrome.cast.media.U.AUDIOBOOK_CONTAINER);this.releaseDate=this.publisher=this.narrators=this.authors=void 0};q(chrome.cast.media.ga,chrome.cast.media.T);x("chrome.cast.media.AudiobookContainerMetadata",chrome.cast.media.ga);chrome.cast.media.fa=function(){chrome.cast.media.MediaMetadata.call(this,chrome.cast.media.F.AUDIOBOOK_CHAPTER);this.images=this.subtitle=this.bookTitle=this.chapterNumber=this.title=this.chapterTitle=void 0};
|
||||
q(chrome.cast.media.fa,chrome.cast.media.MediaMetadata);x("chrome.cast.media.AudiobookChapterMediaMetadata",chrome.cast.media.fa);
|
||||
chrome.cast.media.bb=function(a,b){this.contentId=a;this.contentUrl=void 0;this.streamType=chrome.cast.media.za.BUFFERED;this.contentType=b===void 0?"":b;this.metadata=null;this.atvEntity=this.entity=void 0;this.duration=null;this.startAbsoluteTime=void 0;this.customData=this.textTrackStyle=this.tracks=null;this.userActionStates=this.hlsVideoSegmentFormat=this.hlsSegmentFormat=this.vmapAdsRequest=this.breakClips=this.breaks=void 0};x("chrome.cast.media.MediaInfo",chrome.cast.media.bb);
|
||||
chrome.cast.media.ta=function(a){this.itemId=null;this.media=a;this.autoplay=!0;this.startTime=0;this.playbackDuration=null;this.preloadTime=0;this.customData=this.activeTrackIds=null};x("chrome.cast.media.QueueItem",chrome.cast.media.ta);chrome.cast.media.Pa="CC1AD845";x("chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID",chrome.cast.media.Pa);chrome.cast.media.timeout={};chrome.cast.media.timeout.load=0;x("chrome.cast.media.timeout.load",chrome.cast.media.timeout.load);
|
||||
chrome.cast.media.timeout.P=0;x("chrome.cast.media.timeout.getStatus",chrome.cast.media.timeout.P);chrome.cast.media.timeout.play=0;x("chrome.cast.media.timeout.play",chrome.cast.media.timeout.play);chrome.cast.media.timeout.pause=0;x("chrome.cast.media.timeout.pause",chrome.cast.media.timeout.pause);chrome.cast.media.timeout.seek=0;x("chrome.cast.media.timeout.seek",chrome.cast.media.timeout.seek);chrome.cast.media.timeout.stop=0;x("chrome.cast.media.timeout.stop",chrome.cast.media.timeout.stop);
|
||||
chrome.cast.media.timeout.R=0;x("chrome.cast.media.timeout.setVolume",chrome.cast.media.timeout.R);chrome.cast.media.timeout.O=0;x("chrome.cast.media.timeout.editTracksInfo",chrome.cast.media.timeout.O);chrome.cast.media.timeout.v=0;x("chrome.cast.media.timeout.queue",chrome.cast.media.timeout.v);chrome.cast.media.xb=function(a,b){this.trackId=a;this.trackContentType=this.trackContentId=null;this.type=b;this.customData=this.subtype=this.language=this.name=null};x("chrome.cast.media.Track",chrome.cast.media.xb);
|
||||
chrome.cast.media.tb=function(){this.customData=this.fontStyle=this.fontGenericFamily=this.fontFamily=this.fontScale=this.windowRoundedCornerRadius=this.windowColor=this.windowType=this.edgeColor=this.edgeType=this.backgroundColor=this.foregroundColor=null};x("chrome.cast.media.TextTrackStyle",chrome.cast.media.tb);chrome.cast.media.fb=function(a){this.type="QUEUE_LOAD";this.sessionId=this.requestId=null;this.items=a;this.startIndex=0;this.repeatMode=chrome.cast.media.V.OFF;this.customData=null};
|
||||
x("chrome.cast.media.QueueLoadRequest",chrome.cast.media.fb);chrome.cast.media.sa=function(a){this.type="QUEUE_INSERT";this.sessionId=this.requestId=null;this.items=a;this.customData=this.insertBefore=null};x("chrome.cast.media.QueueInsertItemsRequest",chrome.cast.media.sa);chrome.cast.media.hb=function(a){this.type="QUEUE_UPDATE";this.sessionId=this.requestId=null;this.items=a;this.customData=null};x("chrome.cast.media.QueueUpdateItemsRequest",chrome.cast.media.hb);
|
||||
chrome.cast.media.M=function(){this.type="QUEUE_UPDATE";this.customData=this.jump=this.currentItemId=this.sessionId=this.requestId=null};x("chrome.cast.media.QueueJumpRequest",chrome.cast.media.M);chrome.cast.media.wa=function(){this.type="QUEUE_UPDATE";this.customData=this.repeatMode=this.sessionId=this.requestId=null};x("chrome.cast.media.QueueSetPropertiesRequest",chrome.cast.media.wa);
|
||||
chrome.cast.media.ua=function(a){this.type="QUEUE_REMOVE";this.sessionId=this.requestId=null;this.itemIds=a;this.customData=null};x("chrome.cast.media.QueueRemoveItemsRequest",chrome.cast.media.ua);chrome.cast.media.va=function(a){this.type="QUEUE_REORDER";this.sessionId=this.requestId=null;this.itemIds=a;this.customData=this.insertBefore=null};x("chrome.cast.media.QueueReorderItemsRequest",chrome.cast.media.va);
|
||||
chrome.cast.media.Ja=function(a,b,c){this.id=a;this.breakClipIds=b;this.position=c;this.duration=void 0;this.isWatched=!1;this.isEmbedded=void 0};x("chrome.cast.media.Break",chrome.cast.media.Ja);chrome.cast.media.Ka=function(a){this.id=a;this.vastAdsRequest=this.customData=this.hlsSegmentFormat=this.clickThroughUrl=this.posterUrl=this.whenSkippable=this.duration=this.title=this.contentType=this.contentUrl=this.contentId=void 0};x("chrome.cast.media.BreakClip",chrome.cast.media.Ka);
|
||||
chrome.cast.media.Bb=function(){this.adsResponse=this.adTagUrl=void 0};x("chrome.cast.media.VastAdsRequest",chrome.cast.media.Bb);chrome.cast.media.La=function(){this.whenSkippable=this.breakClipId=this.breakId=this.currentBreakClipTime=this.currentBreakTime=void 0};x("chrome.cast.media.BreakStatus",chrome.cast.media.La);chrome.cast.media.ma=function(a,b,c,d){this.start=a;this.end=b;this.isMovingWindow=c;this.isLiveDone=d};x("chrome.cast.media.LiveSeekableRange",chrome.cast.media.ma);
|
||||
chrome.cast.media.eb=function(a,b,c,d,e,h,k){this.id=a;this.queueType=this.entity=void 0;this.name=b;this.description=c;this.repeatMode=d;this.shuffle=!1;this.items=e;this.startIndex=h;this.startTime=k;this.containerMetadata=void 0};x("chrome.cast.media.QueueData",chrome.cast.media.eb);chrome.cast.media.Ab=function(a){this.userAction=a;this.customData=void 0};x("chrome.cast.media.UserActionState",chrome.cast.media.Ab);chrome.cast.media.Cb=function(a,b,c){this.width=a;this.height=b;this.hdrType=c};
|
||||
x("chrome.cast.media.VideoInformation",chrome.cast.media.Cb);var B=null;chrome.cast.media.h=function(a,b){this.sessionId=a;this.mediaSessionId=b;this.media=null;this.videoInfo=this.queueData=void 0;this.playbackRate=1;this.playerState=chrome.cast.media.B.IDLE;this.currentTime=0;this.g=-1;this.supportedMediaCommands=[];this.volume=new chrome.cast.Volume;this.items=this.preloadedItemId=this.loadingItemId=this.currentItemId=this.customData=this.activeTrackIds=this.idleReason=null;this.repeatMode=chrome.cast.media.V.OFF;this.breakStatus=void 0;this.l=!1;this.i=[];this.liveSeekableRange=
|
||||
void 0};f=chrome.cast.media.h.prototype;f.P=function(a,b,c){a||(a=new chrome.cast.media.la);B.m(this,"MEDIA_GET_STATUS",a,b,c,chrome.cast.media.timeout.P)};f.play=function(a,b,c){var d=B;a||(a=new chrome.cast.media.ra);d.m(this,"PLAY",a,b,c,chrome.cast.media.timeout.play)};f.pause=function(a,b,c){var d=B;a||(a=new chrome.cast.media.pa);d.m(this,"PAUSE",a,b,c,chrome.cast.media.timeout.pause)};f.seek=function(a,b,c){B.m(this,"SEEK",a,b,c,chrome.cast.media.timeout.seek)};
|
||||
f.stop=function(a,b,c){a||(a=new chrome.cast.media.ya);B.m(this,"STOP_MEDIA",a,b,c,chrome.cast.media.timeout.stop)};f.R=function(a,b,c){B.m(this,"MEDIA_SET_VOLUME",a,b,c,chrome.cast.media.timeout.R)};f.O=function(a,b,c){B.m(this,"EDIT_TRACKS_INFO",a,b,c,chrome.cast.media.timeout.O)};f.Tb=function(a,b,c){B.m(this,"QUEUE_INSERT",a,b,c,chrome.cast.media.timeout.v)};f.Sb=function(a,b,c){B.m(this,"QUEUE_INSERT",new chrome.cast.media.sa([a]),b,c,chrome.cast.media.timeout.v)};
|
||||
f.dc=function(a,b,c){B.m(this,"QUEUE_UPDATE",a,b,c,chrome.cast.media.timeout.v)};f.Yb=function(a,b){var c=new chrome.cast.media.M;c.jump=-1;B.m(this,"QUEUE_UPDATE",c,a,b,chrome.cast.media.timeout.v)};f.Xb=function(a,b){var c=new chrome.cast.media.M;c.jump=1;B.m(this,"QUEUE_UPDATE",c,a,b,chrome.cast.media.timeout.v)};f.Ub=function(a,b,c){if(!(C(this,a)<0)){var d=new chrome.cast.media.M;d.currentItemId=a;B.m(this,"QUEUE_UPDATE",d,b,c,chrome.cast.media.timeout.v)}};
|
||||
f.cc=function(a,b,c){var d=new chrome.cast.media.wa;d.repeatMode=a;B.m(this,"QUEUE_UPDATE",d,b,c,chrome.cast.media.timeout.v)};f.ac=function(a,b,c){B.m(this,"QUEUE_REMOVE",a,b,c,chrome.cast.media.timeout.v)};f.Zb=function(a,b,c){C(this,a)<0||B.m(this,"QUEUE_REMOVE",new chrome.cast.media.ua([a]),b,c,chrome.cast.media.timeout.v)};f.bc=function(a,b,c){B.m(this,"QUEUE_REORDER",a,b,c,chrome.cast.media.timeout.v)};
|
||||
f.Wb=function(a,b,c,d){var e=C(this,a);if(!(e<0))if(b<0)d&&d(new chrome.cast.Error(chrome.cast.A.INVALID_PARAMETER));else if(e==b)c&&c();else{var h=null;b=b>e?b+1:b;b<this.items.length&&(h=this.items[b]);a=new chrome.cast.media.va([a]);a.insertBefore=h?h.itemId:null;B.m(this,"QUEUE_REORDER",a,c,d,chrome.cast.media.timeout.v)}};f.qc=function(a){return this.supportedMediaCommands.indexOf(a)>-1};
|
||||
f.Nb=function(){if(this.playerState==chrome.cast.media.B.PLAYING&&this.g>=0){var a=this.currentTime+(Date.now()-this.g)/1E3*this.playbackRate;this.media&&this.media.duration!=null&&a>this.media.duration&&this.media.duration!=-1&&(a=this.media.duration);a<0&&(a=0);return a}return this.currentTime};f.Lb=function(){if(this.breakStatus&&this.breakStatus.currentBreakTime!==void 0)return this.playerState==chrome.cast.media.B.PLAYING&&this.g>=0?this.breakStatus.currentBreakTime+(Date.now()-this.g)/1E3:this.breakStatus.currentBreakTime};
|
||||
f.Kb=function(){if(this.breakStatus&&this.breakStatus.currentBreakClipTime!==void 0)return this.playerState==chrome.cast.media.B.PLAYING&&this.g>=0?this.breakStatus.currentBreakClipTime+(Date.now()-this.g)/1E3:this.breakStatus.currentBreakClipTime};
|
||||
f.Mb=function(){if(this.liveSeekableRange&&this.liveSeekableRange.start!==void 0&&this.liveSeekableRange.end!==void 0){if(this.playerState==chrome.cast.media.B.PLAYING&&this.g>=0){var a=(Date.now()-this.g)/1E3,b=new chrome.cast.media.ma;b.isMovingWindow=this.liveSeekableRange.isMovingWindow;b.isLiveDone=this.liveSeekableRange.isLiveDone;b.start=b.isMovingWindow?this.liveSeekableRange.start+a:this.liveSeekableRange.start;b.end=b.isLiveDone?this.liveSeekableRange.end:this.liveSeekableRange.end+a;return b}return this.liveSeekableRange}};
|
||||
f.Y=function(a){B.Gb(this,a)};f.ba=function(a){B.fc(this,a)};var C=function(a,b){return Ca(a.items,function(c){return c.itemId==b})};x("chrome.cast.media.Media",chrome.cast.media.h);chrome.cast.media.h.prototype.removeUpdateListener=chrome.cast.media.h.prototype.ba;chrome.cast.media.h.prototype.addUpdateListener=chrome.cast.media.h.prototype.Y;chrome.cast.media.h.prototype.getEstimatedLiveSeekableRange=chrome.cast.media.h.prototype.Mb;chrome.cast.media.h.prototype.getEstimatedBreakClipTime=chrome.cast.media.h.prototype.Kb;
|
||||
chrome.cast.media.h.prototype.getEstimatedBreakTime=chrome.cast.media.h.prototype.Lb;chrome.cast.media.h.prototype.getEstimatedTime=chrome.cast.media.h.prototype.Nb;chrome.cast.media.h.prototype.supportsCommand=chrome.cast.media.h.prototype.qc;chrome.cast.media.h.prototype.queueMoveItemToNewIndex=chrome.cast.media.h.prototype.Wb;chrome.cast.media.h.prototype.queueReorderItems=chrome.cast.media.h.prototype.bc;chrome.cast.media.h.prototype.queueRemoveItem=chrome.cast.media.h.prototype.Zb;
|
||||
chrome.cast.media.h.prototype.queueRemoveItems=chrome.cast.media.h.prototype.ac;chrome.cast.media.h.prototype.queueSetRepeatMode=chrome.cast.media.h.prototype.cc;chrome.cast.media.h.prototype.queueJumpToItem=chrome.cast.media.h.prototype.Ub;chrome.cast.media.h.prototype.queueNext=chrome.cast.media.h.prototype.Xb;chrome.cast.media.h.prototype.queuePrev=chrome.cast.media.h.prototype.Yb;chrome.cast.media.h.prototype.queueUpdateItems=chrome.cast.media.h.prototype.dc;
|
||||
chrome.cast.media.h.prototype.queueAppendItem=chrome.cast.media.h.prototype.Sb;chrome.cast.media.h.prototype.queueInsertItems=chrome.cast.media.h.prototype.Tb;chrome.cast.media.h.prototype.editTracksInfo=chrome.cast.media.h.prototype.O;chrome.cast.media.h.prototype.setVolume=chrome.cast.media.h.prototype.R;chrome.cast.media.h.prototype.stop=chrome.cast.media.h.prototype.stop;chrome.cast.media.h.prototype.seek=chrome.cast.media.h.prototype.seek;chrome.cast.media.h.prototype.pause=chrome.cast.media.h.prototype.pause;
|
||||
chrome.cast.media.h.prototype.play=chrome.cast.media.h.prototype.play;chrome.cast.media.h.prototype.getStatus=chrome.cast.media.h.prototype.P;var Ha=function(a,b,c){this.sessionId=a;this.namespaceName=b;this.message=c};var Ia=function(a,b){this.type="SET_VOLUME";this.requestId=0;this.volume=a;this.expectedVolume=b||null};var Ja=function(a){this.type="STOP";this.requestId=0;this.sessionId=a||null};chrome.cast.j=function(a,b,c,d,e){this.sessionId=a;this.appId=b;this.displayName=c;this.statusText=null;this.appImages=d;this.receiver=e;this.senderApps=[];this.namespaces=[];this.media=[];this.status=chrome.cast.K.CONNECTED;this.transportId=""};f=chrome.cast.j.prototype;f.oc=function(a,b,c){var d=B;a=new Ia(new chrome.cast.Volume(a,null),this.receiver.volume);d.setReceiverVolume(this.sessionId,a,b,c)};
|
||||
f.nc=function(a,b,c){a=new Ia(new chrome.cast.Volume(null,a),this.receiver.volume);B.setReceiverVolume(this.sessionId,a,b,c)};f.getDialAppInfo=function(a,b){B.getDialAppInfo(a,b)};f.Ob=function(a,b){B.leaveSession(this.sessionId,a,b)};f.stop=function(a,b){B.Da(new Ja(this.sessionId),a,b,chrome.cast.timeout.stopSession)};f.sendMessage=function(a,b,c,d){B.kc(new Ha(this.sessionId,a,b),c,d)};f.Y=function(a){B.Ib(this.sessionId,a)};f.ba=function(a){B.jc(this.sessionId,a)};
|
||||
f.Hb=function(a,b){B.Fb(this.sessionId,a,b)};f.W=function(a){B.W(this.sessionId,a)};f.Z=function(a){B.Z(this.sessionId,a)};f.hc=function(a,b){B.ec(this.sessionId,a,b)};f.Pb=function(a,b,c){a.sessionId=this.sessionId;B.Ea(a,"LOAD",b,c)};f.Vb=function(a,b,c){a.sessionId=this.sessionId;B.Ea(a,"QUEUE_LOAD",b,c)};x("chrome.cast.Session",chrome.cast.j);chrome.cast.j.prototype.queueLoad=chrome.cast.j.prototype.Vb;chrome.cast.j.prototype.loadMedia=chrome.cast.j.prototype.Pb;
|
||||
chrome.cast.j.prototype.removeMessageListener=chrome.cast.j.prototype.hc;chrome.cast.j.prototype.removeMediaListener=chrome.cast.j.prototype.Z;chrome.cast.j.prototype.addMediaListener=chrome.cast.j.prototype.W;chrome.cast.j.prototype.addMessageListener=chrome.cast.j.prototype.Hb;chrome.cast.j.prototype.removeUpdateListener=chrome.cast.j.prototype.ba;chrome.cast.j.prototype.addUpdateListener=chrome.cast.j.prototype.Y;chrome.cast.j.prototype.sendMessage=chrome.cast.j.prototype.sendMessage;
|
||||
chrome.cast.j.prototype.stop=chrome.cast.j.prototype.stop;chrome.cast.j.prototype.leave=chrome.cast.j.prototype.Ob;chrome.cast.j.prototype.getDialAppInfo=chrome.cast.j.prototype.getDialAppInfo;chrome.cast.j.prototype.setReceiverMuted=chrome.cast.j.prototype.nc;chrome.cast.j.prototype.setReceiverVolumeLevel=chrome.cast.j.prototype.oc;var D=function(a,b){this.g=a[r.Symbol.iterator]();this.i=b};D.prototype[Symbol.iterator]=function(){return this};D.prototype.next=function(){var a=this.g.next();return{value:a.done?void 0:this.i.call(void 0,a.value),done:a.done}};var Ka=function(a,b){return new D(a,b)};var E=function(){};E.prototype.next=function(){return F};var F=Da({done:!0,value:void 0});E.prototype.o=function(){return this};var La=function(a){if(a instanceof E)return a;if(typeof a.o=="function")return a.o(!1);if(u(a)){var b=0,c=new E;c.next=function(){for(;;){if(b>=a.length)return F;if(b in a)return{value:a[b++],done:!1};b++}};return c}throw Error("Not implemented");},G=function(a,b){if(u(a))Ba(a,b);else for(a=La(a);;){var c=a.next();if(c.done)break;b.call(void 0,c.value,void 0,a)}};var Ma=function(a){if(a instanceof H||a instanceof I||a instanceof J)return a;if(typeof a.next=="function")return new H(function(){return a});if(typeof a[Symbol.iterator]=="function")return new H(function(){return a[Symbol.iterator]()});if(typeof a.o=="function")return new H(function(){return a.o()});throw Error("Not an iterator or iterable.");},H=function(a){this.g=a};H.prototype.o=function(){return new I(this.g())};H.prototype[Symbol.iterator]=function(){return new J(this.g())};H.prototype.i=function(){return new J(this.g())};
|
||||
var I=function(a){this.g=a};q(I,E);I.prototype.next=function(){return this.g.next()};I.prototype[Symbol.iterator]=function(){return new J(this.g)};I.prototype.i=function(){return new J(this.g)};var J=function(a){H.call(this,function(){return a});this.l=a};q(J,H);J.prototype.next=function(){return this.l.next()};var K=function(a,b){this.i={};this.g=[];this.l=this.size=0;var c=arguments.length;if(c>1){if(c%2)throw Error("Uneven number of arguments");for(var d=0;d<c;d+=2)this.set(arguments[d],arguments[d+1])}else if(a)if(a instanceof K)for(c=Na(a),d=0;d<c.length;d++)this.set(c[d],a.get(c[d]));else for(d in a)this.set(d,a[d])};K.prototype.L=function(){L(this);for(var a=[],b=0;b<this.g.length;b++)a.push(this.i[this.g[b]]);return a};var Na=function(a){L(a);return a.g.concat()};
|
||||
K.prototype.has=function(a){return M(this.i,a)};K.prototype.clear=function(){this.i={};this.l=this.size=this.g.length=0};K.prototype.remove=function(a){return this.delete(a)};K.prototype.delete=function(a){return M(this.i,a)?(delete this.i[a],--this.size,this.l++,this.g.length>2*this.size&&L(this),!0):!1};
|
||||
var L=function(a){if(a.size!=a.g.length){for(var b=0,c=0;b<a.g.length;){var d=a.g[b];M(a.i,d)&&(a.g[c++]=d);b++}a.g.length=c}if(a.size!=a.g.length){b={};for(d=c=0;c<a.g.length;){var e=a.g[c];M(b,e)||(a.g[d++]=e,b[e]=1);c++}a.g.length=d}};f=K.prototype;f.get=function(a,b){return M(this.i,a)?this.i[a]:b};f.set=function(a,b){M(this.i,a)||(this.size+=1,this.g.push(a),this.l++);this.i[a]=b};f.forEach=function(a,b){for(var c=Na(this),d=0;d<c.length;d++){var e=c[d],h=this.get(e);a.call(b,h,e,this)}};
|
||||
f.keys=function(){return Ma(this.o(!0)).i()};f.values=function(){return Ma(this.o(!1)).i()};f.entries=function(){var a=this;return Ka(this.keys(),function(b){return[b,a.get(b)]})};f.o=function(a){L(this);var b=0,c=this.l,d=this,e=new E;e.next=function(){if(c!=d.l)throw Error("The map has changed since the iterator was created");if(b>=d.g.length)return F;var h=d.g[b++];return{value:a?h:d.i[h],done:!1}};return e};var M=function(a,b){return Object.prototype.hasOwnProperty.call(a,b)};var N=function(a,b){this.requestId=a;this.u=b;this.Ga=null};N.prototype.i=function(){};var Oa=function(){this.g=new K},Pa=function(a,b){a.g.set(b.requestId,b);b.Ga=setTimeout(function(){a.g.delete(b.requestId);b.i()},b.u)},Qa=function(a,b){var c=a.g.get(b);if(!c)return null;clearTimeout(c.Ga);a.g.delete(b);return c};var O=function(a,b,c,d){N.call(this,a,d||6E5);this.l=b;this.g=c};q(O,N);O.prototype.i=function(){this.g(new chrome.cast.Error(chrome.cast.A.TIMEOUT))};var P=function(a,b,c,d){this.type=a;this.message=b;this.sequenceNumber=c!==void 0?c:-1;this.timeoutMillis=d||0;this.clientId=""};var Q=function(a){this.l=a;this.i=String(Date.now())+String(Math.floor(Math.random()*1E5));this.g=null},Ra=function(a,b){if(!a.g)return"No active session";b.clientId=a.i;b=JSON.stringify(b);if(b.length>32768)return"Message length over limit";a.g.send(b);return null};Q.prototype.connect=function(a){this.g=a;this.g.onmessage=w(this.u,this);Ra(this,new P("client_connect",this.i))};Q.prototype.disconnect=function(){this.g.close();this.g=null};
|
||||
Q.prototype.u=function(a){a=JSON.parse(a.data);if(a.clientId==this.i)this.l.onMessage(a)};var Sa=function(a,b,c){this.l=a;this.i=b;this.g=c},Ta=function(a){var b="cast-dial:"+a.l,c=new URLSearchParams;a.i&&c.set("dialPostData",a.i);a.g&&c.set("clientId",a.g);(a=c.toString())&&(b+="?"+a);return b};var Ua=function(a,b,c,d,e,h,k,m,p,t){this.I=a;this.g=b||null;this.l=c||null;this.C=d||null;this.D=e!==void 0?e:null;this.i=h||null;this.H=k||null;this.J=m||!1;this.G=p?["WEB","ANDROID_TV"]:["WEB"];this.u=t||null},Va=function(a){var b=a.I.map(function(c){var d="cast:"+c.appId,e=new URLSearchParams;c.capabilities&&c.capabilities.length>0&&e.set("capabilities",c.capabilities.join(","));a.g&&e.set("clientId",a.g);a.l&&e.set("autoJoinPolicy",a.l);a.C&&e.set("defaultActionPolicy",a.C);a.D!=null&&e.set("launchTimeout",
|
||||
String(a.D));a.J&&e.set("invisibleSender","true");e.set("supportedAppTypes",a.G.join(","));c=e.set;var h=JSON,k=h.stringify,m={launchCheckerParams:{}};a.u&&(m.launchCheckerParams.credentialsData=a.u);c.call(e,"appParams",k.call(h,m));return d+"?"+e.toString()});a.i&&b.push(Ta(new Sa(a.i,a.H,a.g)));return b};var Wa=function(){this.g={};this.i={}},Xa=function(a,b,c){var d=a.g[b];return d?(d.status=c,d.media.forEach(function(e){delete a.i[e.sessionId+"#"+e.mediaSessionId]}),delete a.g[b],!0):!1},Za=function(a,b){var c=a.g[b.sessionId];if(c)return c.statusText=b.statusText,c.namespaces=b.namespaces||[],c.receiver.volume=b.receiver.volume,c;c=new chrome.cast.j(b.sessionId,b.appId,b.displayName,b.appImages,b.receiver);for(var d in b)d=="media"?c.media=b.media.map(function(e){e=Ya(a,e);e.u=!1;e.l=!0;return e}):
|
||||
b.hasOwnProperty(d)&&(c[d]=b[d]);return a.g[b.sessionId]=c},Ya=function(a,b){var c=b.sessionId+"#"+b.mediaSessionId,d=a.i[c];d||(d=new chrome.cast.media.h(b.sessionId,b.mediaSessionId),a.i[c]=d,(a=a.g[b.sessionId])&&a.media.push(d));a=d;a.currentItemId=null;a.loadingItemId=null;a.preloadedItemId=null;for(var e in b)e!="items"&&b.hasOwnProperty(e)&&(e=="volume"?(a.volume.level=b.volume.level,a.volume.muted=b.volume.muted):a[e]=b[e]);e=ka(["idleReason","extendedStatus","breakStatus"]);for(c=e.next();!c.done;c=
|
||||
e.next())c=c.value,b.hasOwnProperty(c)||(a[c]=null);"currentTime"in b&&(a.g=Date.now());if(a.playerState==chrome.cast.media.B.IDLE&&a.loadingItemId==null)a.currentItemId=null,a.loadingItemId=null,a.preloadedItemId=null,a.items=null;else if(b.hasOwnProperty("items")&&b.items){e=[];var h=a.items;c={};if(h)for(var k=0;k<h.length;k++)c[h[k].itemId]=k;b=ka(b.items);for(h=b.next();!h.done;h=b.next()){h=h.value;if(!h.media){k=h.itemId;var m=a.items?a.items[c[k]]:null;m&&m.media?h.media=m.media:k==a.currentItemId&&
|
||||
a.media&&(h.media=a.media)}k=e;m=k.push;var p=void 0,t=new chrome.cast.media.ta(h.media);for(p in h)h.hasOwnProperty(p)&&(t[p]=h[p]);m.call(k,t)}a.items=e}return d},$a=function(a,b){delete a.i[b.sessionId+"#"+b.mediaSessionId];if(a=a.g[b.sessionId])b=a.media.indexOf(b),b!=-1&&a.media.splice(b,1)};function R(){var a=r.navigator;return a&&(a=a.userAgent)?a:""};var ab=R().toLowerCase().indexOf("webkit")!=-1&&R().indexOf("Edge")==-1;var bb={},S=null,cb=R().indexOf("Gecko")!=-1&&!(R().toLowerCase().indexOf("webkit")!=-1&&R().indexOf("Edge")==-1)&&!(R().indexOf("Trident")!=-1||R().indexOf("MSIE")!=-1)&&R().indexOf("Edge")==-1||ab||typeof r.btoa=="function",db=function(a){if(cb)var b=r.btoa(a);else{b=[];for(var c=0,d=0;d<a.length;d++){var e=a.charCodeAt(d);if(e>255)throw Error("go/unicode-to-byte-error");b[c++]=e}a=void 0;a===void 0&&(a=0);if(!S)for(S={},c="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".split(""),
|
||||
d=["+/=","+/","-_=","-_.","-_"],e=0;e<5;e++){var h=c.concat(d[e].split(""));bb[e]=h;for(var k=0;k<h.length;k++){var m=h[k];S[m]===void 0&&(S[m]=k)}}a=bb[a];c=Array(Math.floor(b.length/3));d=a[64]||"";for(e=h=0;h<b.length-2;h+=3){var p=b[h],t=b[h+1];m=b[h+2];k=a[p>>2];p=a[(p&3)<<4|t>>4];t=a[(t&15)<<2|m>>6];m=a[m&63];c[e++]=""+k+p+t+m}k=0;m=d;switch(b.length-h){case 2:k=b[h+1],m=a[(k&15)<<2]||d;case 1:b=b[h],c[e]=""+a[b>>2]+a[(b&3)<<4|k>>4]+m+d}b=c.join("")}return b};var eb=function(a){if(a.L&&typeof a.L=="function")return a.L();if(typeof Map!=="undefined"&&a instanceof Map||typeof Set!=="undefined"&&a instanceof Set)return Array.from(a.values());if(typeof a==="string")return a.split("");if(u(a)){for(var b=[],c=a.length,d=0;d<c;d++)b.push(a[d]);return b}b=[];c=0;for(d in a)b[c++]=a[d];return b};var T=function(){this.g=new K;this.size=0},U=function(a){var b=typeof a;return b=="object"&&a||b=="function"?"o"+(Object.prototype.hasOwnProperty.call(a,v)&&a[v]||(a[v]=++la)):b.slice(0,1)+a};f=T.prototype;f.add=function(a){this.g.set(U(a),a);this.size=this.g.size};f.removeAll=function(a){a=eb(a);for(var b=a.length,c=0;c<b;c++)this.remove(a[c]);this.size=this.g.size};f.delete=function(a){a=this.g.remove(U(a));this.size=this.g.size;return a};f.remove=function(a){return this.delete(a)};
|
||||
f.clear=function(){this.g.clear();this.size=0};f.has=function(a){var b=this.g;a=U(a);return b.has(a)};f.contains=function(a){var b=this.g;a=U(a);return b.has(a)};f.L=function(){return this.g.L()};f.values=function(){return this.g.values()};f.o=function(){return this.g.o(!1)};T.prototype[Symbol.iterator]=function(){return this.values()};var V=function(){this.C=new Q(this);this.g=null;this.G=new Wa;this.i=0;this.S=new Oa;this.D=new K;this.u=new K;this.I=new K;this.J=[];this.Oa=this.Jb.bind(this);this.ia=this.H=this.l=null},fb=function(a){var b=new chrome.cast.Error(chrome.cast.A.INVALID_PARAMETER,"Already requesting session");a&&a(b)},W=function(a,b,c,d){c&&Pa(a.S,c);d!==void 0?b.sequenceNumber=d:(b.sequenceNumber=a.i,a.i=(a.i+1)%9007199254740992);d=Ra(a.C,b);c&&d&&(a=Qa(a.S,b.sequenceNumber))&&(a=a.g,d=new chrome.cast.Error(chrome.cast.A.INVALID_PARAMETER,
|
||||
d),a&&a(d))};
|
||||
V.prototype.initialize=function(a,b){var c=this;B=this;this.g=a;a.invisibleSender||(a=new PresentationRequest(X(this)),a.getAvailability().then(function(d){d.onchange=function(){c.g.receiverListener(d.value?chrome.cast.N.AVAILABLE:chrome.cast.N.UNAVAILABLE)};d.onchange()},function(){c.g.receiverListener(chrome.cast.N.AVAILABLE)}),a.onconnectionavailable=function(d){Y(c,d.connection)},this.ia=(r.navigator||null).presentation.defaultRequest=a,a.reconnect(chrome.cast.Ha).then(function(d){Y(c,d)},function(){}));
|
||||
b&&b(void 0)};V.prototype.da=function(a){a.navigator.presentation.defaultRequest=this.ia};var Y=function(a,b,c){c=c===void 0?null:c;b.onclose=function(d){a.l=null;switch(d.reason){case "closed":gb(a,chrome.cast.K.DISCONNECTED);break;case "error":if(c){d=c;var e=new chrome.cast.Error(chrome.cast.A.SESSION_ERROR);d&&d(e)}}};b.onterminate=function(){gb(a,chrome.cast.K.STOPPED)};b.state=="connected"?a.C.connect(b):b.onconnect=function(){a.C.connect(b)}};
|
||||
V.prototype.requestSession=function(a,b,c){var d=this;this.l?fb(b):(c=X(this,c),this.l=a,(new PresentationRequest(c)).start().then(function(e){Y(d,e,b)}).catch(function(e){d.l=null;e=new chrome.cast.Error(e.name=="AbortError"||e.name=="NotAllowedError"?chrome.cast.A.CANCEL:chrome.cast.A.SESSION_ERROR);b&&b(e)}))};
|
||||
var X=function(a,b){var c=null,d=null;b=b||a.g.sessionRequest;var e=b.dialRequest;e&&(c=e.appName,(d=e.launchParameter)&&!d.match(hb)&&(d=db(d)));var h=[];h.push({appId:b.appId,capabilities:b.capabilities});b||Ba(a.g.additionalSessionRequests,function(k){h.push({appId:k.appId,capabilities:k.capabilities})});return Va(new Ua(h,a.C.i,a.g.autoJoinPolicy,a.g.defaultActionPolicy,b.requestSessionTimeout,c,d,a.g.invisibleSender,b.androidReceiverCompatible,b.credentialsData))};
|
||||
V.prototype.Ea=function(a,b,c,d){ib(this,null,b,a,function(e){e.l=!0;c&&c(e)},function(e){d(e)},chrome.cast.media.timeout.load)};V.prototype.m=function(a,b,c,d,e,h){var k=this;ib(this,a,b,c,function(m){k.Ca(m);d&&d(void 0)},e,h)};var ib=function(a,b,c,d,e,h,k){d.type=c;b!=null&&(d.mediaSessionId=b.mediaSessionId,d.sessionId=b.sessionId);a.Da(d,function(m){m.status&&m.status.length==1?e&&e(m.status[0]):(m=new chrome.cast.Error(chrome.cast.A.SESSION_ERROR),h&&h(m))},h,k)};f=V.prototype;
|
||||
f.setReceiverVolume=function(a,b,c,d){b.sessionId=a;W(this,new P("v2_message",b,void 0,chrome.cast.timeout.setReceiverVolume),new O(this.i,c,d,chrome.cast.timeout.sendCustomMessage))};f.getDialAppInfo=function(a,b){W(this,new P("dial_app_info",void 0,void 0,chrome.cast.timeout.getDialAppInfo),new O(this.i,a,b,chrome.cast.timeout.sendCustomMessage))};f.ca=function(a){var b=this;(new PresentationRequest(X(this))).reconnect(chrome.cast.cb+a).then(function(c){Y(b,c)},function(){})};
|
||||
f.leaveSession=function(a,b,c){W(this,new P("leave_session",a,void 0,chrome.cast.timeout.leaveSession),new O(this.i,b,c,chrome.cast.timeout.leaveSession))};f.kc=function(a,b,c){W(this,new P("app_message",a,void 0,chrome.cast.timeout.sendCustomMessage),new O(this.i,b,c,chrome.cast.timeout.sendCustomMessage))};f.Da=function(a,b,c,d){W(this,new P("v2_message",a,void 0,d),new O(this.i,b,c,d))};var jb=function(a,b,c){var d=a.get(b);d||(d=new T,a.set(b,d));d.add(c)};f=V.prototype;
|
||||
f.Ib=function(a,b){jb(this.D,a,b)};f.jc=function(a,b){(a=this.D.get(a))&&a.remove(b)};f.X=function(a){this.J.push(a)};f.aa=function(a){a=this.J.indexOf(a);a>=0&&this.J.splice(a,1)};f.Fb=function(a,b,c){var d=this.u.get(a);d||(d=new K,this.u.set(a,d));a=d.get(b);a||(a=new T,d.set(b,a));a.add(c)};f.ec=function(a,b,c){(a=this.u.get(a))&&(b=a.get(b))&&b.remove(c)};f.W=function(a,b){jb(this.I,a,b)};f.Z=function(a,b){(a=this.I.get(a))&&a.remove(b)};f.Gb=function(a,b){a.i.indexOf(b)==-1&&a.i.push(b)};
|
||||
f.fc=function(a,b){b=a.i.indexOf(b);b!=-1&&a.i.splice(b,1)};f.Ca=function(a){if(a.l){var b=a.playerState!=chrome.cast.media.B.IDLE||a.loadingItemId!=null;a.i.forEach(function(d){d(b)});b||$a(this.G,a)}else{a.l=!0;var c=this.I.get(a.sessionId);c&&G(c.o(),function(d){d(a)})}};f.Jb=function(a){return Ya(this.G,a)};var gb=function(a,b){if(a.H){var c=a.H;a.H=null;a.C.disconnect();var d=b!=chrome.cast.K.STOPPED;Xa(a.G,c,b)&&(a.u.delete(c),a.I.delete(c),b=a.D.get(c))&&(a.D.delete(c),G(b.o(),function(e){e(d)}))}};
|
||||
V.prototype.onMessage=function(a){switch(a.type){case "new_session":case "update_session":a.message=Za(this.G,a.message);break;case "v2_message":var b=a.message;b&&b.type=="MEDIA_STATUS"&&b.status&&(b.status=b.status.map(this.Oa))}if(b=Qa(this.S,a.sequenceNumber))a.type=="error"?(b=b.g)&&b(a.message):(b=b.l)&&b(a.message);if(b=a.message)switch(a.type){case "receiver_action":kb(this,b);break;case "new_session":this.H=b.sessionId;this.l?(this.l(b),this.l=null):this.g&&this.g.sessionListener(b);break;
|
||||
case "update_session":lb(this,b);break;case "app_message":mb(this,b);break;case "v2_message":b.type=="MEDIA_STATUS"&&b.status.forEach(this.Ca.bind(this));break;case "custom_dial_launch":nb(this,a.sequenceNumber,b)}};
|
||||
var lb=function(a,b){(a=a.D.get(b.sessionId))&&G(a.o(),function(c){c(!0)})},kb=function(a,b){a.J.forEach(function(c){c(b.receiver,b.action)})},mb=function(a,b){(a=a.u.get(b.sessionId))&&(a=a.get(b.namespaceName))&&G(a.o(),function(c){c(b.namespaceName,b.message)})},ob=function(a,b,c){W(a,new P("custom_dial_launch",c,void 0,chrome.cast.timeout.sendCustomMessage),null,b)},nb=function(a,b,c){a.g.customDialLaunchCallback?a.g.customDialLaunchCallback(c).then(function(d){ob(a,b,d)},function(){ob(a,b)}):
|
||||
ob(a,b)},hb=RegExp("^([0-9a-zA-Z+/]{4})*(([0-9a-zA-Z+/]{2}==)|([0-9a-zA-Z+/]{3}=))?$"),Z=new V;chrome.cast.initialize=function(a,b,c){Z.initialize(a,b,c)};x("chrome.cast.initialize",chrome.cast.initialize);chrome.cast.da=function(a){Z.da(a)};x("chrome.cast.setPageContext",chrome.cast.da);chrome.cast.requestSession=function(a,b,c){Z.requestSession(a,b,c)};x("chrome.cast.requestSession",chrome.cast.requestSession);chrome.cast.Rb=function(){};x("chrome.cast.precache",chrome.cast.Rb);chrome.cast.ca=function(a){Z.ca(a)};x("chrome.cast.requestSessionById",chrome.cast.ca);chrome.cast.X=function(a){Z.X(a)};
|
||||
x("chrome.cast.addReceiverActionListener",chrome.cast.X);chrome.cast.aa=function(a){Z.aa(a)};x("chrome.cast.removeReceiverActionListener",chrome.cast.aa);chrome.cast.Qb=function(){};x("chrome.cast.logMessage",chrome.cast.Qb);chrome.cast.lc=function(a,b){b()};x("chrome.cast.setCustomReceivers",chrome.cast.lc);chrome.cast.mc=function(a,b){b()};x("chrome.cast.setReceiverDisplayStatus",chrome.cast.mc);chrome.cast.unescape=function(a){return a.indexOf("&")!=-1?"document"in r?Fa(a):Ga(a):a};
|
||||
x("chrome.cast.unescape",chrome.cast.unescape);chrome.cast.isAvailable=!1;x("chrome.cast.isAvailable",chrome.cast.isAvailable);chrome.cast.Fa=!1;chrome.cast.ea=function(){if(!chrome.cast.Fa){chrome.cast.Fa=!0;chrome.cast.isAvailable=!0;var a=window.__onGCastApiAvailable;a&&typeof a=="function"&&a(!0)}};document.readyState=="complete"?chrome.cast.ea():(window.addEventListener("load",chrome.cast.ea,!1),window.addEventListener("DOMContentLoaded",chrome.cast.ea,!1));}).call(this);
|
||||
@@ -0,0 +1,12 @@
|
||||
(function(){/*
|
||||
|
||||
Copyright The Closure Library Authors.
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
'use strict';var l=function(){var a=h,b=0;return function(){return b<a.length?{done:!1,value:a[b++]}:{done:!0}}},m=this||self,n=/^[\w+/_-]+[=]{0,2}$/,p=null,q=function(a){return(a=a.querySelector&&a.querySelector("script[nonce]"))&&(a=a.nonce||a.getAttribute("nonce"))&&n.test(a)?a:""},r=function(a,b){function e(){}e.prototype=b.prototype;a.i=b.prototype;a.prototype=new e;a.prototype.constructor=a;a.h=function(c,g,k){for(var f=Array(arguments.length-2),d=2;d<arguments.length;d++)f[d-2]=arguments[d];
|
||||
return b.prototype[g].apply(c,f)}},t=function(a){return a};function u(a){if(Error.captureStackTrace)Error.captureStackTrace(this,u);else{var b=Error().stack;b&&(this.stack=b)}a&&(this.message=String(a))}r(u,Error);u.prototype.name="CustomError";var v=function(a,b){a=a.split("%s");for(var e="",c=a.length-1,g=0;g<c;g++)e+=a[g]+(g<b.length?b[g]:"%s");u.call(this,e+a[c])};r(v,u);v.prototype.name="AssertionError";var w=function(a,b){throw new v("Failure"+(a?": "+a:""),Array.prototype.slice.call(arguments,1));};var x;var A=function(a,b){this.g=b===z?a:""};A.prototype.toString=function(){return this.g+""};var z={};var B=function(){var a=window.navigator.userAgent.match(/Chrome\/([0-9]+)/);return a?parseInt(a[1],10):0},C=function(a){return!!document.currentScript&&(-1!=document.currentScript.src.indexOf("?"+a)||-1!=document.currentScript.src.indexOf("&"+a))},D=function(){return"function"==typeof window.__onGCastApiAvailable?window.__onGCastApiAvailable:null},F=function(a){a.length?E(a.shift(),function(){F(a)}):G()},H=function(a){return"chrome-extension://"+a+"/cast_sender.js"},E=function(a,b,e){var c=document.createElement("script");
|
||||
c.onerror=b;e&&(c.onload=e);if(void 0===x)if(b=null,(e=m.trustedTypes)&&e.createPolicy){try{b=e.createPolicy("goog#html",{createHTML:t,createScript:t,createScriptURL:t})}catch(y){m.console&&m.console.error(y.message)}x=b}else x=b;a=(b=x)?b.createScriptURL(a):a;a=new A(a,z);a:{try{var g=c&&c.ownerDocument,k=g&&(g.defaultView||g.parentWindow);k=k||m;if(k.Element&&k.Location){var f=k;break a}}catch(y){}f=null}if(f&&"undefined"!=typeof f.HTMLScriptElement&&(!c||!(c instanceof f.HTMLScriptElement)&&(c instanceof
|
||||
f.Location||c instanceof f.Element))){f=typeof c;if("object"==f&&null!=c||"function"==f)try{var d=c.constructor.displayName||c.constructor.name||Object.prototype.toString.call(c)}catch(y){d="<object could not be stringified>"}else d=void 0===c?"undefined":null===c?"null":typeof c;w("Argument is not a %s (or a non-Element, non-Location mock); got: %s","HTMLScriptElement",d)}a instanceof A&&a.constructor===A?d=a.g:(d=typeof a,w("expected object of type TrustedResourceUrl, got '"+a+"' of type "+("object"!=
|
||||
d?d:a?Array.isArray(a)?"array":d:"null")),d="type_error:TrustedResourceUrl");c.src=d;(d=c.ownerDocument&&c.ownerDocument.defaultView)&&d!=m?d=q(d.document):(null===p&&(p=q(m.document)),d=p);d&&c.setAttribute("nonce",d);(document.head||document.documentElement).appendChild(c)},I=function(){var a=B(),b=[];if(1<a){var e=a-1;b.push("//www.gstatic.com/eureka/clank/"+a+"/cast_sender.js");b.push("//www.gstatic.com/eureka/clank/"+e+"/cast_sender.js")}return b},G=function(){var a=D();a&&a(!1,"No cast extension found")},
|
||||
K=function(){if(J){var a=2,b=D(),e=function(){a--;0==a&&b&&b(!0)};window.__onGCastApiAvailable=e;E("//www.gstatic.com/cast/sdk/libs/sender/1.0/cast_framework.js",G,e)}},J=C("loadCastFramework")||C("loadCastApplicationFramework"),L=["pkedcjkdefgpdelpbcmbmeomcjbeemfm","enhhojjnijigcajfphajepfemndkmdlo"];if(0<=window.navigator.userAgent.indexOf("Android")&&0<=window.navigator.userAgent.indexOf("Chrome/")&&window.navigator.presentation){if(60<=B()){K();var M=I();M.push("//www.gstatic.com/eureka/clank/cast_sender.js");F(M)}}else if(!window.chrome||!window.navigator.presentation||0<=window.navigator.userAgent.indexOf("Edge"))G();else if(89<=B()){K();var N=I(),O=N.push,P=O.apply,h=L.map(H),Q;if(h instanceof Array)Q=h;else{var R,S="undefined"!=typeof Symbol&&Symbol.iterator&&h[Symbol.iterator];R=S?S.call(h):
|
||||
{next:l()};for(var T,U=[];!(T=R.next()).done;)U.push(T.value);Q=U}P.call(O,N,Q);N.push("//www.gstatic.com/eureka/clank/cast_sender.js");F(N)}else K(),F(L.map(H));}).call(this);
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="11" viewBox="0 0 14 11" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.40014 10.2952L0.854126 5.74924L1.99063 4.61273L5.40014 8.02224L12.7176 0.704758L13.8541 1.84126L5.40014 10.2952Z" fill="#55BC62"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 246 B |
@@ -0,0 +1,622 @@
|
||||
function UserNotifications() {
|
||||
"use strict"
|
||||
var self = this;
|
||||
self.totalScrollHeight = 0;
|
||||
self.topNotif = 0;
|
||||
self.offSss = false;
|
||||
self._tipTimeout = false;
|
||||
self.notifBoxHtml;
|
||||
self.audio = 1;
|
||||
self.undelivN = 0;
|
||||
self.HTTP_ENDPOINT = "/checkN.php";
|
||||
|
||||
self.startIntervals();
|
||||
}
|
||||
|
||||
UserNotifications.prototype.startIntervals = function () {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var intervals = BidooCnf.intervals.user.notifications;
|
||||
self.pingNotification();
|
||||
setInterval(self.bidping.bind(self, getBidsBonus()), intervals.bidping);
|
||||
setInterval(self.updateNotificationsDateTime.bind(self), intervals.updateNotificationsDateTime);
|
||||
setInterval(self.pingNotification.bind(self), intervals.pingNotification);
|
||||
setInterval(self.updateAuctionsWon.bind(self), intervals.auctionsWon); // [GR] for update badge number for auctions won to pay by user
|
||||
}
|
||||
|
||||
UserNotifications.prototype.updateNotificationsDateTime = function () {
|
||||
"use strict"
|
||||
var self = this;
|
||||
moment.locale('it');
|
||||
self.getCorrectNotifSelector().find("abbr").each(function () {
|
||||
var abbrTime = parseInt($(this).data("utime"), 10);
|
||||
var newTime = parseInt((new Date()).getTime() / 1000, 10);
|
||||
var moment_abbr_time = moment(abbrTime, "X");
|
||||
var shouldBeFromNow = (newTime - abbrTime) < 21600;
|
||||
$(this).data("alt", moment().format());
|
||||
$(this).text(shouldBeFromNow ? moment_abbr_time.fromNow() : moment_abbr_time.calendar());
|
||||
});
|
||||
};
|
||||
|
||||
UserNotifications.prototype.updateAuctionsWon = function () { // [GR] for update badge number for auctions won to pay by user
|
||||
"use strict"
|
||||
$.get("/check_auctions_won.php", function (data) {
|
||||
if (self.offSss) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
$(".navbar-fixed-bottom #bottomAuctionsWonToPay").html(data);
|
||||
$(".myBidooDesk #bottomAuctionsWonToPay").html(data);
|
||||
$(".myBidooMobile #bottomAuctionsWonToPay").html(data);
|
||||
$("#testataAuctionsWonToPay").html(data);
|
||||
if (parseInt(data) > 0) {
|
||||
$("#bottomAuctionsWonToPay").css("visibility", "visible");
|
||||
$("#testataAuctionsWonToPay").css("visibility", "visible");
|
||||
} else {
|
||||
$("#bottomAuctionsWonToPay").css("visibility", "hidden");
|
||||
$("#testataAuctionsWonToPay").css("visibility", "hidden");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
UserNotifications.prototype.bidping = function (bonus) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
$.get("/bidping.php", function (data) {
|
||||
if (self.offSss) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
var progressValue = data[0] + "/" + data[1];
|
||||
$("#seven_7").html(progressValue);
|
||||
$(".bid-challenge [data-spot=0]")
|
||||
.html(progressValue)
|
||||
.parent()
|
||||
.attr("data-progress", progressValue);
|
||||
$(".leader-btn .progress-bar-success").css("width", ((data[0] / data[1]) * 100.00).toFixed(2) + "%");
|
||||
if (data[0] >= data[1] && data[2] < data[1]) {
|
||||
$('.bid-challenge .img-lock-open').hide();
|
||||
$('.bid-challenge .img-lock').show();
|
||||
$('#auctionBidBottomBar .wrap-progress').hide();
|
||||
$('#auctionBidBottomBar .wrap-button-get-bonus').show();
|
||||
|
||||
}
|
||||
|
||||
if (data[0] >= data[1] && (typeof getCookie('won') == "undefined")) {
|
||||
var expireWonDate = new Date();
|
||||
expireWonDate.setTime(getTimeFrames());
|
||||
self.wonChallenge(data[0], bonus);
|
||||
setValueCookie("won", 1, expireWonDate);
|
||||
}
|
||||
}).fail(function (jqXHR, textStatus, error) {
|
||||
if (jqXHR.status == 403) {
|
||||
self.offSss = true;
|
||||
$(".btn.leader-btn[data-target=#leader]")
|
||||
.html(getSessionExpired(true))
|
||||
.attr('data-toggle', null)
|
||||
.attr('data-target', null)
|
||||
.off("click").on({
|
||||
click: showLogin
|
||||
});
|
||||
}
|
||||
});
|
||||
self.bidPingProduct();
|
||||
}
|
||||
|
||||
UserNotifications.prototype.bidPingProduct = function () {
|
||||
"use strict"
|
||||
$.get("/bidping_product.php", function (data) {
|
||||
if (self.offSss) {
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
$(".bid-challenge-product").html(data);
|
||||
});
|
||||
}
|
||||
|
||||
UserNotifications.prototype.getCallTipMsg = function (credits, bonus) {
|
||||
"use strict"
|
||||
var html = [
|
||||
"<div class='wrap'>",
|
||||
"<div>",
|
||||
"<img src='/images/razzo.svg'>",
|
||||
"</div>",
|
||||
"<div>",
|
||||
"<strong>Complimenti!</strong>",
|
||||
"<div>Hai Vinto " + credits + " Aste di Puntate</div>",
|
||||
"</div>",
|
||||
"</div>"
|
||||
];
|
||||
return html.join("");
|
||||
}
|
||||
|
||||
UserNotifications.prototype.callTip = function (credits, bonus, callback) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var tooltipReach = $(".tooltip.reach");
|
||||
$(".leader-btn")
|
||||
.tooltip('destroy').tooltip({
|
||||
html: true,
|
||||
placement: 'top',
|
||||
title: self.getCallTipMsg(credits, bonus),
|
||||
trigger: 'manual',
|
||||
animation: false,
|
||||
template: '<div class="tooltip reach" role="tooltip"><div class="tooltip-inner"></div></div>'
|
||||
})
|
||||
.tooltip("show");
|
||||
|
||||
tooltipReach.removeClass("bounceOutDown");
|
||||
if (self._tipTimeout)
|
||||
clearTimeout(self._tipTimeout);
|
||||
self._tipTimeout = setTimeout(function () {
|
||||
callback();
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
UserNotifications.prototype.wonChallenge = function (nAuctions, bonus) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var selector = $(".leader-btn > div.bid-challenge");
|
||||
if (!selector.hasClass("achieved")) {
|
||||
self.callTip(nAuctions, bonus);
|
||||
}
|
||||
}
|
||||
|
||||
UserNotifications.prototype.pingNotification = function () {
|
||||
"use strict"
|
||||
var self = this;
|
||||
$.get(self.HTTP_ENDPOINT, {_t: 1}, function (r) {
|
||||
if (r.count > 0) {
|
||||
$(".bubble_desktop, .bubble_mobile, .toggle_bar_mobile").html(r.count).show();
|
||||
if ($("#notifBox").is(":visible") || $("#notifBoxMobile").is(":visible")) {
|
||||
self.loadNotification(true);
|
||||
}
|
||||
if (typeof r.undeliv != "undefined" && (Object.keys(r.undeliv).length > 0 && self.undelivN != Object.keys(r.undeliv).length)) {
|
||||
var audioCookie = getCookie('audioN');
|
||||
if (self.audio && ("undefined" == typeof audioCookie || audioCookie < r.count)) {
|
||||
self
|
||||
.playSound(r.audio)
|
||||
.then(setCookieMinutes.bind(null, 'audioN', r.count, 5))
|
||||
.catch(function () {
|
||||
$(document)
|
||||
.off('touchstart click')
|
||||
.on('touchstart click', function () {
|
||||
self.playSound(r.audio);
|
||||
$(document).off('touchstart click');
|
||||
});
|
||||
});
|
||||
}
|
||||
self.undelivN = Object.keys(r.undeliv).length;
|
||||
}
|
||||
} else {
|
||||
delCookie('audioN');
|
||||
$(".bubble_desktop, .bubble_mobile").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
UserNotifications.prototype.playSound = function (audioSrc) {
|
||||
"use strict"
|
||||
var audio = $("#push");
|
||||
if (audio.length)
|
||||
audio.remove();
|
||||
var aSound = document.createElement('audio');
|
||||
aSound.id = 'push';
|
||||
aSound.setAttribute('src', audioSrc + "?chk=" + (new Date()).getTime());
|
||||
return aSound.play();
|
||||
}
|
||||
|
||||
UserNotifications.prototype.toggleAudio = function (audioSetting) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var isNotArgPassed = "undefined" == typeof audioSetting;
|
||||
var snd = self.getCorrectNotifSelector().find(".sAudio");
|
||||
var snData = !!(isNotArgPassed ? parseInt(snd.attr("data-audio")) : audioSetting);
|
||||
snd.attr("data-audio", (!snData | 0))
|
||||
.toggleClass("disabled glyphicon-volume-off", !snData)
|
||||
.toggleClass("enabled glyphicon-volume-up", snData);
|
||||
if (isNotArgPassed)
|
||||
$.get(self.HTTP_ENDPOINT, {_s: (snData | 0)});
|
||||
}
|
||||
|
||||
UserNotifications.prototype.loadSettings = function (shouldSetCheckOptions) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
$.get(self.HTTP_ENDPOINT, {_load: 0}, function (settings) {
|
||||
self.audio = settings.audio;
|
||||
self.toggleAudio(self.audio);
|
||||
if (shouldSetCheckOptions) {
|
||||
$("#ticketMail").prop("checked", !!+settings["1"]);
|
||||
$("#creditMail").prop("checked", !!+settings["2"]);
|
||||
$("#packageMail").prop("checked", !!+settings["3"]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
UserNotifications.prototype.cleanData = function (dirtyString) {
|
||||
"use strict"
|
||||
dirtyString = dirtyString.replace(/&/g, "&");
|
||||
dirtyString = dirtyString.replace(/>/g, ">");
|
||||
dirtyString = dirtyString.replace(/</g, "<");
|
||||
dirtyString = dirtyString.replace(/"/g, "\"");
|
||||
dirtyString = dirtyString.replace("</i>", "</i><p class='paragraph-notification'>");
|
||||
dirtyString = dirtyString.replace("</a>", "</p></a>");
|
||||
dirtyString = dirtyString.replace("data-href", "data-mobile-fullscreen='true' data-no-padding-modal-body='true' data-href");
|
||||
dirtyString = dirtyString.replace("//it.bidoo.com", "");
|
||||
return dirtyString;
|
||||
}
|
||||
|
||||
UserNotifications.prototype.getNotificationItem = function (data) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var flag = parseInt(data.readFlag, 10);
|
||||
var classNotif = 2 == flag ? "class='read wrap-notif'" : (1 == flag ? "class='deliv wrap-notif'" : "");
|
||||
var item = [
|
||||
"<li id='notification_" + data.id + "' data-type='" + data.type + "' " + classNotif + ">",
|
||||
"<div class='notif-sx'>"+self.cleanData(data.content)+"</div>",
|
||||
"<div class='notif-dx'><abbr data-utime='" + data.created_at + "'></abbr>",
|
||||
"<i class='fa fa-clock-o clock-notification' aria-hidden='true'></i></div>",
|
||||
"</li>"
|
||||
];
|
||||
return item.join("");
|
||||
}
|
||||
|
||||
UserNotifications.prototype.getEmptyNotifications = function () {
|
||||
"use strict"
|
||||
var notif = [
|
||||
'<li class="text-center empty-notification">',
|
||||
'<p>Non hai alcuna notifica.</p>',
|
||||
'</li>'
|
||||
];
|
||||
return notif.join("");
|
||||
}
|
||||
|
||||
UserNotifications.prototype._renderN = function (data, more) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var list = [];
|
||||
var selector = this.getCorrectNotifSelector().find("ul");
|
||||
if (data.length) {
|
||||
$.each(data, function (i, item) {
|
||||
if ("object" == typeof item) {
|
||||
selector.append(self.getNotificationItem(item));
|
||||
if (parseInt(item.readFlag, 10) < 2 && item.type != '1') {
|
||||
list.push(item.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
self.updateNotificationsDateTime();
|
||||
} else {
|
||||
if (more === undefined || more === false) {
|
||||
selector.append(self.getEmptyNotifications());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
UserNotifications.prototype._renderFoot = function (shouldLoadMore, paging) {
|
||||
"use strict"
|
||||
|
||||
var loader = [
|
||||
"<a href='javascript:void(0)' onclick='BidooCnf.instances.user.notifications.loadMore(" + paging + ");' class='load-more load-more-notif'>",
|
||||
"Vedi altre",
|
||||
"</a>"
|
||||
].join("");
|
||||
var footer = [
|
||||
"<div class='whatelse nFoot text-center' id='more'>",
|
||||
shouldLoadMore ? loader : "",
|
||||
"</div>"
|
||||
];
|
||||
return footer.join("");
|
||||
}
|
||||
|
||||
UserNotifications.prototype.loadMore = function (id) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
$.get(self.HTTP_ENDPOINT, {f: id, m: 5}, function (r) {
|
||||
var selector = self.getCorrectNotifSelector();
|
||||
var listNotif = selector.find("ul");
|
||||
selector.find(".whatelse").remove();
|
||||
if (Object.keys(r.elements).length > 0) {
|
||||
var list = self._renderN(r.elements, true);
|
||||
var welse = self._renderFoot(r.shexc, r.elements[Object.keys(r.elements).length - 1].id);
|
||||
listNotif.append(welse);
|
||||
if (listNotif.height() <= selector.find("#notifBoxContainer").height()) {
|
||||
//selector.find("#more").find("a").click();
|
||||
}
|
||||
}
|
||||
if (typeof list != "undefined" && list.length > 0) {
|
||||
self.sendReadReq(list);
|
||||
}
|
||||
self.loadCustomScrollbar();
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
}
|
||||
$("body").click(function (event) {
|
||||
window.elementSelected = event.target.classList[0];
|
||||
if ($('.bidooBell').hasClass('active')) {
|
||||
$('.bidooBell').removeClass('active');
|
||||
} else {
|
||||
$('.bidooBell').addClass('active');
|
||||
}
|
||||
});
|
||||
UserNotifications.prototype.loadNotification = function (forceFetchNotif) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var isMobile = $(window).width() <= 991;
|
||||
var selector = self.getCorrectNotifSelector();
|
||||
self.topNotif = 0;
|
||||
if (selector.is(":visible") && !forceFetchNotif) {
|
||||
stopBodyScroll(false);
|
||||
if (window.elementSelected == "bidooBell") {
|
||||
selector.hide();
|
||||
$("#tickNotif").hide();
|
||||
}
|
||||
if (isMobile) {
|
||||
$('#notifBoxMobile').hide();
|
||||
$('#menuModal #btn-1 span').addClass('fa-plus');
|
||||
$('#menuModal #btn-1 span').removeClass('fa-minus');
|
||||
$('#menuModal #submenu1').css('display', 'none');
|
||||
}
|
||||
self.totalScrollHeight = 0;
|
||||
} else {
|
||||
selector.empty().show();
|
||||
if (isMobile)
|
||||
self.hideModalHeaderNotifications(true);
|
||||
self.composeNotificationsUI(isMobile, function (jqXHR, textStatus, errorThrown) {
|
||||
var isError = jqXHR && textStatus && errorThrown;
|
||||
if (!isError) {
|
||||
self.loadCustomScrollbar();
|
||||
$("#notifBox").show(); // [GR] ADD
|
||||
if (isMobile) {
|
||||
var titleSelector = selector.find(".nTitle");
|
||||
var realHeightNotificationShade = (titleSelector.height() + parseInt(titleSelector.css("padding-top")));
|
||||
var heightNotifDialog = ($(window).height() - realHeightNotificationShade);
|
||||
selector.find("#notifBoxContainer").css("height", "auto");
|
||||
selector.find("#more").find("a").click();
|
||||
}
|
||||
}
|
||||
$("#tickNotif").show();
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
UserNotifications.prototype.getNotificationsStructure = function (mobile, isFirstLoadNotifications, isSettings) {
|
||||
"use strict"
|
||||
var arrow_left = [
|
||||
'<a href="javascript:void();" onclick="BidooCnf.instances.user.notifications.back();" id="arrow_left">',
|
||||
'<img src="images/arrow-left.png" width="12">',
|
||||
'</a>'
|
||||
].join("");
|
||||
var structure = [
|
||||
'<div class="nTitle">',
|
||||
mobile || isSettings ? arrow_left : "",
|
||||
'<p style="display: inline-block;">' + (isSettings ? "Impostazioni" : "Notifiche") + '</p>',
|
||||
'<span class="sAudio glyphicon glyphicon-volume-up" onclick="BidooCnf.instances.user.notifications.toggleAudio();"></span>',
|
||||
'<span class="sNotif glyphicon glyphicon-cog" onclick="BidooCnf.instances.user.notifications.toggleSettings();"></span>',
|
||||
'</div>',
|
||||
'<div id="notifBoxContainer">',
|
||||
isFirstLoadNotifications ? "<img src='/images/loader_card.gif' class='loader-notifications'>" : "",
|
||||
'<ul class="not"></ul>',
|
||||
'</div>'
|
||||
]
|
||||
return structure.join("");
|
||||
}
|
||||
|
||||
UserNotifications.prototype.composeNotificationsUI = function (mobile, callback) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var selector = self.getCorrectNotifSelector();
|
||||
selector.html(self.getNotificationsStructure(mobile, true));
|
||||
$.get(self.HTTP_ENDPOINT, function (r) {
|
||||
$(".bubble_desktop, .bubble_mobile, .toggle_bar_mobile").hide();
|
||||
self.delivReadReq();
|
||||
var mobile = $(window).width() <= 991;
|
||||
var selectorList = selector.find("ul");
|
||||
selector.find(".loader-notifications").remove();
|
||||
if (r !== null) {
|
||||
var list = self._renderN(r.elements);
|
||||
if (Object.keys(r.elements).length > 0) {
|
||||
var footer = self._renderFoot(r.shexc, r.elements[Object.keys(r.elements).length - 1].id);
|
||||
selectorList.append(footer);
|
||||
}
|
||||
if (typeof list != "undefined" && list.length > 0) {
|
||||
self.sendReadReq(list);
|
||||
}
|
||||
self.loadSettings();
|
||||
} else {
|
||||
selectorList.html(getSessionExpired());
|
||||
}
|
||||
callback();
|
||||
}).fail(callback);
|
||||
}
|
||||
|
||||
UserNotifications.prototype.sendReadReq = function (list) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
if (typeof list !== undefined && list.length > 0) {
|
||||
$.get(self.HTTP_ENDPOINT, {_r: 1, l: list.join(',')});
|
||||
}
|
||||
}
|
||||
|
||||
UserNotifications.prototype.delivReadReq = function () {
|
||||
"use strict"
|
||||
$.get(this.HTTP_ENDPOINT, {_d: 1});
|
||||
}
|
||||
|
||||
UserNotifications.prototype.getSettings = function () {
|
||||
"use strict"
|
||||
var html = [
|
||||
'<div class="settingBox">',
|
||||
'<form role="form" style="opacity: 1;">',
|
||||
'<div class="title-settings"><b>Notifiche Email</b></div>',
|
||||
'<div class="checkbox">',
|
||||
'<label for="ticketMail">',
|
||||
'<input type="checkbox" name="ticketMail" id="ticketMail">',
|
||||
'<span class="notif-settings-label">Ricevi email per nuovi Ticket</span>',
|
||||
'</label>',
|
||||
'</div>',
|
||||
'<div class="checkbox">',
|
||||
'<label for="packageMail">',
|
||||
'<input type="checkbox" name="packageMail" id="packageMail">',
|
||||
'<span class="notif-settings-label">Ricevi Email per aggiornamenti spedizione</span>',
|
||||
'</label>',
|
||||
'</div>',
|
||||
'<div class="checkbox">',
|
||||
'<label for="creditMail">',
|
||||
'<input type="checkbox" name="creditMail" id="creditMail">',
|
||||
'<span class="notif-settings-label">Ricevi Email per accrediti di Puntate Gratis</span>',
|
||||
'</label>',
|
||||
'</div>',
|
||||
'<a class="btn btn-block btn-primary" href="javascript:void(0);" onclick="BidooCnf.instances.user.notifications.saveSettings();"><b>Salva Impostazioni</b></a>',
|
||||
'</form>',
|
||||
'</div>'
|
||||
];
|
||||
return html.join("");
|
||||
}
|
||||
|
||||
UserNotifications.prototype.showSettingNotification = function () {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var selector = self.getCorrectNotifSelector();
|
||||
if (selector.length) {
|
||||
self.notifBoxHtml = selector.html();
|
||||
selector.html(self.getNotificationsStructure(true, false, true))
|
||||
.find("#notifBoxContainer")
|
||||
.append(self.getSettings());
|
||||
self.loadSettings(true);
|
||||
document.querySelector('#notifBoxMobile #notifBoxContainer .not').remove();
|
||||
}
|
||||
}
|
||||
|
||||
UserNotifications.prototype.back = function () {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var selector = self.getCorrectNotifSelector();
|
||||
if ($(window).width() <= 991 && !selector.find(".settingBox").length) {
|
||||
self.hideModalHeaderNotifications(false);
|
||||
backMobile();
|
||||
return;
|
||||
}
|
||||
selector.html(self.notifBoxHtml);
|
||||
self.loadCustomScrollbar(true);
|
||||
}
|
||||
|
||||
UserNotifications.prototype.toggleSettings = function () {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var selector = self.getCorrectNotifSelector();
|
||||
if (!selector.is(":visible")) {
|
||||
selector.show();
|
||||
self.loadNotification();
|
||||
} else {
|
||||
self.showSettingNotification();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
UserNotifications.prototype.saveSettings = function () {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var mail = +$("#ticketMail").is(":checked");
|
||||
var pack = +$("#packageMail").is(":checked");
|
||||
var accr = +$("#creditMail").is(":checked");
|
||||
var data = [
|
||||
'm', mail,
|
||||
'p', pack,
|
||||
'a', accr
|
||||
];
|
||||
$.get(self.HTTP_ENDPOINT, {_set: data.join("|")}, function () {
|
||||
self.back();
|
||||
});
|
||||
}
|
||||
|
||||
UserNotifications.prototype.loadCustomScrollbar = function (forceReload) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var notif_box_selector = self.getCorrectNotifSelector().find("#notifBoxContainer");
|
||||
|
||||
if ($(window).width() <= 991) {
|
||||
notif_box_selector.off("scroll").scroll(function () {
|
||||
if ($(this).scrollTop() + $(this).innerHeight() >= $(this)[0].scrollHeight) {
|
||||
self.topNotif = $(this).scrollTop();
|
||||
//notif_box_selector.find("#more").find("a").click();
|
||||
}
|
||||
});
|
||||
notif_box_selector.scrollTop(self.topNotif);
|
||||
} else if (forceReload || !notif_box_selector.hasClass("mCustomScrollbar")) {
|
||||
if (forceReload) {
|
||||
var list = notif_box_selector.find("ul").clone();
|
||||
notif_box_selector.empty().append(list);
|
||||
self.totalScrollHeight = 0;
|
||||
}
|
||||
notif_box_selector.mCustomScrollbar({
|
||||
documentTouchScroll: true,
|
||||
contentTouchScroll: 1,
|
||||
callbacks: {
|
||||
onTotalScroll: function () {
|
||||
var more_notif_selector = notif_box_selector.find("#more");
|
||||
if (more_notif_selector.is(":visible") && more_notif_selector.children().length) {
|
||||
// more_notif_selector.find("a").click();
|
||||
self.totalScrollHeight += 5 * 70;
|
||||
}
|
||||
},
|
||||
onInit: function () {
|
||||
if (self.totalScrollHeight != 0) {
|
||||
notif_box_selector.mCustomScrollbar("scrollTo", self.totalScrollHeight, {
|
||||
scrollInertia: 0
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
notif_box_selector
|
||||
.off("mouseover")
|
||||
.mouseover(true, stopBodyScroll)
|
||||
.off("mouseout")
|
||||
.mouseout(false, stopBodyScroll);
|
||||
bindModalCall("#notifBoxContainer", true);
|
||||
}
|
||||
|
||||
UserNotifications.prototype.getCorrectNotifSelector = function () {
|
||||
"use strict"
|
||||
var notifMobile = $("#notifBoxMobile");
|
||||
return $(window).width() <= 991 ? notifMobile : $("#notifBox");
|
||||
}
|
||||
|
||||
UserNotifications.prototype.hideModalHeaderNotifications = function (shouldHide) {
|
||||
"use strict"
|
||||
var self = this;
|
||||
self.getCorrectNotifSelector().parent()
|
||||
.parent()
|
||||
.find(".modal-header")
|
||||
.toggleClass("hidden", shouldHide);
|
||||
}
|
||||
|
||||
UserNotifications.prototype.closeAll = function () {
|
||||
"use strict"
|
||||
var self = this;
|
||||
var selector = self.getCorrectNotifSelector();
|
||||
if (!selector.is(":visible"))
|
||||
return;
|
||||
if (selector.find(".settingBox").is(":visible"))
|
||||
self.back();
|
||||
self.back();
|
||||
}
|
||||
|
||||
function bidping() {
|
||||
"use strict"
|
||||
if (BidooCnf.modules.exist(UserNotifications))
|
||||
BidooCnf.instances.user.notifications.bidping(getBidsBonus());
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
"use strict"
|
||||
BidooCnf.modules.notifications = UserNotifications;
|
||||
BidooCnf.instances.user.notifications = new UserNotifications();
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
#onesignal-slidedown-container #onesignal-slidedown-dialog .slidedown-body-message{
|
||||
font-size: 20px !important;
|
||||
}
|
||||
|
||||
#onesignal-slidedown-container #onesignal-slidedown-dialog .primary.slidedown-button+.secondary.slidedown-button, #slidedown-footer #onesignal-slidedown-cancel-button {
|
||||
color: #666666 !important;
|
||||
}
|
||||
#onesignal-slidedown-container #onesignal-slidedown-dialog .slidedown-button.primary, #slidedown-footer #onesignal-slidedown-allow-button {
|
||||
background: #00CC66 !important;
|
||||
}
|
||||
@media(max-width:576px){
|
||||
#onesignal-slidedown-container #onesignal-slidedown-dialog .primary.slidedown-button+.secondary.slidedown-button, #slidedown-footer #onesignal-slidedown-cancel-button {
|
||||
padding: 10px;
|
||||
}
|
||||
#onesignal-slidedown-container #onesignal-slidedown-dialog .slidedown-button.primary, #slidedown-footer #onesignal-slidedown-allow-button {
|
||||
padding: 10px;
|
||||
}
|
||||
#onesignal-slidedown-container #onesignal-slidedown-dialog .slidedown-body-message{
|
||||
font-size: 16px !important;
|
||||
}
|
||||
#onesignal-slidedown-container #onesignal-slidedown-dialog .slidedown-body-icon{
|
||||
width: 60px;
|
||||
height: 70px;
|
||||
}
|
||||
}
|
||||
#modalExplainForMac .modal-body{
|
||||
padding: 30px 50px 0px;
|
||||
}
|
||||
#modalExplainForMac .logo{
|
||||
width: 40px;
|
||||
margin-top: -7px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
#modalExplainForMac .intestazione{
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
}
|
||||
#modalExplainForMac p.sottotitolo{
|
||||
font-size: 16px;
|
||||
}
|
||||
#modalExplainForMac ol{
|
||||
padding-left: 15px;
|
||||
line-height: 23px;
|
||||
}
|
||||
#modalExplainForMac .modal-footer{
|
||||
border-top: none;
|
||||
padding-top: 5px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
#modalExplainForMac .modal-footer .btn-custom{
|
||||
background-color: #0c6;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
padding: 5px 30px;
|
||||
}
|
||||
|
After Width: | Height: | Size: 6.9 KiB |
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#2196F3;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M13.38,38.44c-2.22,0-4.05,1.83-4.05,4.05c0,2.22,1.83,4.05,4.05,4.05c2.28,0,4.05-1.83,4.05-4.05
|
||||
C17.44,40.27,15.6,38.44,13.38,38.44z"/>
|
||||
<path class="st0" d="M43.7,38.44c-2.22,0-4.05,1.83-4.05,4.05c0,2.22,1.83,4.05,4.05,4.05c2.28,0,4.05-1.83,4.05-4.05
|
||||
C47.76,40.27,45.92,38.44,43.7,38.44z"/>
|
||||
<path class="st0" d="M44.54,34.05c0-0.5-0.39-0.83-0.83-0.83H21.44c-0.17,0-0.33,0.06-0.5,0.17l-3.55,2.67
|
||||
c-0.39,0.22-0.44,0.78-0.17,1.11c0.17,0.22,0.44,0.33,0.67,0.33c0.17,0,0.33-0.06,0.5-0.11l3.33-2.5H43.7
|
||||
C44.2,34.88,44.54,34.55,44.54,34.05z"/>
|
||||
<path class="st0" d="M49.87,15.23c-0.11-0.17-0.33-0.28-0.56-0.33L9.88,8.95L9.61,7.79C9,4.73,6.44,3.45,0.83,3.45
|
||||
C0.33,3.45,0,3.84,0,4.29c0,0.5,0.39,0.83,0.83,0.83c4.05,0,6.66,0.5,7.22,3.05L8.44,9.9c0,0.06,0,0.06,0,0.06l3.11,14.49
|
||||
c0.39,2.44,2.5,4.28,4.94,4.28h26.32c2.44,0,4.5-1.72,4.89-4.28l2.28-8.55C50.03,15.67,49.98,15.39,49.87,15.23z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 80 50" style="enable-background:new 0 0 80 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#016FD0;}
|
||||
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
|
||||
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#016FD0;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M80,47.33c0,1.47-1.19,2.67-2.67,2.67H2.67C1.19,50,0,48.81,0,47.33V2.67C0,1.19,1.19,0,2.67,0h74.67
|
||||
C78.81,0,80,1.19,80,2.67V47.33z"/>
|
||||
<g>
|
||||
<path class="st1" d="M19.5,37.15V26.63h11.14l1.2,1.56l1.23-1.56h40.44v9.8c0,0-1.06,0.72-2.28,0.73H48.84l-1.35-1.66v1.66h-4.42
|
||||
v-2.83c0,0-0.6,0.4-1.91,0.4h-1.5v2.44h-6.69l-1.19-1.59l-1.21,1.59L19.5,37.15L19.5,37.15z"/>
|
||||
<path class="st1" d="M6.49,18.7L9,12.85h4.34l1.43,3.28v-3.28h5.4l0.85,2.37l0.82-2.37h24.24v1.19c0,0,1.27-1.19,3.37-1.19
|
||||
l7.87,0.03l1.4,3.24v-3.27h4.52l1.24,1.86v-1.86h4.56v10.52h-4.56L63.3,21.5v1.87h-6.64l-0.67-1.66h-1.79l-0.66,1.66h-4.5
|
||||
c-1.8,0-2.95-1.17-2.95-1.17v1.17H39.3l-1.35-1.66v1.66H12.7l-0.67-1.66h-1.78l-0.66,1.66h-3.1V18.7L6.49,18.7z"/>
|
||||
<path class="st2" d="M9.89,14.14L6.5,22.02h2.21l0.63-1.58h3.63l0.62,1.58h2.25l-3.39-7.88H9.89L9.89,14.14z M11.15,15.98
|
||||
l1.11,2.76h-2.22L11.15,15.98L11.15,15.98z"/>
|
||||
<polygon class="st2" points="16.08,22.02 16.08,14.14 19.21,14.15 21.04,19.23 22.82,14.14 25.93,14.14 25.93,22.02 23.96,22.02
|
||||
23.96,16.21 21.87,22.02 20.14,22.02 18.05,16.21 18.05,22.02 16.08,22.02 "/>
|
||||
<polygon class="st2" points="27.28,22.02 27.28,14.14 33.7,14.14 33.7,15.9 29.27,15.9 29.27,17.25 33.6,17.25 33.6,18.91
|
||||
29.27,18.91 29.27,20.31 33.7,20.31 33.7,22.02 27.28,22.02 "/>
|
||||
<path class="st2" d="M34.84,14.14v7.88h1.97v-2.8h0.83l2.36,2.8h2.41l-2.59-2.9c1.06-0.09,2.16-1,2.16-2.42
|
||||
c0-1.66-1.3-2.56-2.75-2.56H34.84L34.84,14.14z M36.81,15.9h2.25c0.54,0,0.93,0.42,0.93,0.83c0,0.52-0.51,0.83-0.9,0.83h-2.28
|
||||
L36.81,15.9L36.81,15.9L36.81,15.9z"/>
|
||||
<polygon class="st2" points="44.79,22.02 42.78,22.02 42.78,14.14 44.79,14.14 44.79,22.02 "/>
|
||||
<path class="st2" d="M49.56,22.02h-0.43c-2.1,0-3.38-1.65-3.38-3.91c0-2.31,1.26-3.97,3.91-3.97h2.18v1.87h-2.26
|
||||
c-1.08,0-1.84,0.84-1.84,2.13c0,1.53,0.87,2.17,2.13,2.17h0.52L49.56,22.02L49.56,22.02z"/>
|
||||
<path class="st2" d="M53.85,14.14l-3.39,7.88h2.21l0.63-1.58h3.63l0.62,1.58h2.25l-3.39-7.88H53.85L53.85,14.14z M55.1,15.98
|
||||
l1.11,2.76h-2.22L55.1,15.98L55.1,15.98z"/>
|
||||
<polygon class="st2" points="60.03,22.02 60.03,14.14 62.54,14.14 65.74,19.09 65.74,14.14 67.7,14.14 67.7,22.02 65.28,22.02
|
||||
62,16.94 62,22.02 60.03,22.02 "/>
|
||||
<polygon class="st2" points="20.85,35.81 20.85,27.93 27.28,27.93 27.28,29.69 22.84,29.69 22.84,31.04 27.17,31.04 27.17,32.7
|
||||
22.84,32.7 22.84,34.1 27.28,34.1 27.28,35.81 20.85,35.81 "/>
|
||||
<polygon class="st2" points="52.34,35.81 52.34,27.93 58.77,27.93 58.77,29.69 54.33,29.69 54.33,31.04 58.64,31.04 58.64,32.7
|
||||
54.33,32.7 54.33,34.1 58.77,34.1 58.77,35.81 52.34,35.81 "/>
|
||||
<polygon class="st2" points="27.52,35.81 30.65,31.92 27.45,27.93 29.93,27.93 31.84,30.39 33.75,27.93 36.14,27.93 32.98,31.87
|
||||
36.11,35.81 33.63,35.81 31.78,33.38 29.97,35.81 27.52,35.81 "/>
|
||||
<path class="st2" d="M36.35,27.93v7.88h2.02v-2.49h2.07c1.75,0,3.08-0.93,3.08-2.74c0-1.5-1.04-2.65-2.83-2.65H36.35L36.35,27.93z
|
||||
M38.37,29.71h2.18c0.57,0,0.97,0.35,0.97,0.91c0,0.53-0.4,0.91-0.98,0.91h-2.18V29.71L38.37,29.71L38.37,29.71z"/>
|
||||
<path class="st2" d="M44.38,27.93v7.88h1.97v-2.8h0.83l2.36,2.8h2.41l-2.59-2.9c1.06-0.09,2.16-1,2.16-2.42
|
||||
c0-1.66-1.3-2.56-2.75-2.56L44.38,27.93L44.38,27.93L44.38,27.93z M46.35,29.69h2.25c0.54,0,0.93,0.42,0.93,0.83
|
||||
c0,0.52-0.51,0.83-0.9,0.83h-2.28V29.69L46.35,29.69z"/>
|
||||
<path class="st2" d="M59.68,35.81V34.1h3.94c0.58,0,0.84-0.32,0.84-0.66c0-0.33-0.25-0.67-0.84-0.67h-1.78
|
||||
c-1.55,0-2.41-0.94-2.41-2.36c0-1.26,0.79-2.48,3.09-2.48h3.84l-0.83,1.77h-3.32c-0.63,0-0.83,0.33-0.83,0.65
|
||||
c0,0.33,0.24,0.69,0.73,0.69h1.87c1.73,0,2.47,0.98,2.47,2.26c0,1.38-0.83,2.51-2.57,2.51L59.68,35.81L59.68,35.81z"/>
|
||||
<path class="st2" d="M66.91,35.81V34.1h3.78c0.58,0,0.84-0.32,0.84-0.66c0-0.33-0.25-0.67-0.84-0.67h-1.61
|
||||
c-1.55,0-2.41-0.94-2.41-2.36c0-1.26,0.79-2.48,3.09-2.48h3.76l-0.83,1.77h-3.24c-0.63,0-0.83,0.33-0.83,0.65
|
||||
c0,0.33,0.24,0.69,0.73,0.69h1.7c1.73,0,2.48,0.98,2.48,2.26c0,1.38-0.83,2.51-2.57,2.51L66.91,35.81L66.91,35.81z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 80 50" style="enable-background:new 0 0 80 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F9F9F9;}
|
||||
.st1{fill:#6C6BBD;}
|
||||
.st2{fill:#D32011;}
|
||||
.st3{fill:#0099DF;}
|
||||
.st4{fill:#110F0D;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M76.56,50H3.44C1.55,50,0,48.45,0,46.56V3.44C0,1.55,1.55,0,3.44,0h73.12C78.45,0,80,1.55,80,3.44v43.12
|
||||
C80,48.45,78.45,50,76.56,50z"/>
|
||||
<g>
|
||||
<polygon class="st1" points="46.47,32.85 33.53,32.85 33.53,9.6 46.47,9.6 "/>
|
||||
<path class="st2" d="M34.35,21.22c0-4.72,2.21-8.92,5.65-11.63c-2.51-1.98-5.69-3.16-9.14-3.16c-8.17,0-14.79,6.62-14.79,14.79
|
||||
s6.62,14.79,14.79,14.79c3.45,0,6.62-1.18,9.14-3.16C36.56,30.14,34.35,25.94,34.35,21.22"/>
|
||||
<path class="st3" d="M63.92,21.22c0,8.17-6.62,14.79-14.79,14.79c-3.45,0-6.62-1.18-9.14-3.16c3.44-2.71,5.65-6.91,5.65-11.63
|
||||
S43.44,12.3,40,9.6c2.52-1.98,5.69-3.16,9.14-3.16C57.3,6.43,63.92,13.05,63.92,21.22"/>
|
||||
<path class="st4" d="M50.85,39.42c0.17,0,0.42,0.03,0.61,0.11l-0.26,0.8c-0.18-0.07-0.36-0.1-0.53-0.1
|
||||
c-0.56,0-0.84,0.36-0.84,1.01v2.2h-0.85v-3.93h0.85v0.48C50.03,39.65,50.35,39.42,50.85,39.42L50.85,39.42z M47.69,40.3h-1.4v1.77
|
||||
c0,0.39,0.14,0.66,0.57,0.66c0.22,0,0.5-0.07,0.75-0.22l0.25,0.73c-0.27,0.19-0.7,0.3-1.07,0.3c-1.01,0-1.36-0.54-1.36-1.45V40.3
|
||||
h-0.8v-0.78h0.8v-1.19h0.86v1.19h1.4V40.3L47.69,40.3z M36.76,41.13c0.09-0.57,0.44-0.95,1.04-0.95c0.55,0,0.9,0.35,0.99,0.95
|
||||
H36.76z M39.68,41.48c-0.01-1.22-0.76-2.06-1.87-2.06c-1.15,0-1.95,0.84-1.95,2.06c0,1.25,0.84,2.06,2.01,2.06
|
||||
c0.59,0,1.13-0.15,1.61-0.55l-0.42-0.63c-0.33,0.26-0.75,0.41-1.14,0.41c-0.55,0-1.05-0.25-1.17-0.96h2.92
|
||||
C39.67,41.7,39.68,41.59,39.68,41.48L39.68,41.48z M43.43,40.52c-0.24-0.15-0.72-0.34-1.22-0.34c-0.47,0-0.75,0.17-0.75,0.46
|
||||
c0,0.26,0.3,0.34,0.66,0.39l0.4,0.06c0.85,0.12,1.37,0.49,1.37,1.18c0,0.75-0.66,1.28-1.79,1.28c-0.64,0-1.23-0.16-1.7-0.51
|
||||
l0.4-0.67c0.29,0.22,0.72,0.41,1.31,0.41c0.58,0,0.89-0.17,0.89-0.48c0-0.22-0.22-0.35-0.69-0.41l-0.4-0.06
|
||||
c-0.88-0.12-1.36-0.52-1.36-1.16c0-0.78,0.64-1.26,1.63-1.26c0.62,0,1.19,0.14,1.6,0.41L43.43,40.52L43.43,40.52z M53.97,40.23
|
||||
c-0.18,0-0.34,0.03-0.49,0.09c-0.15,0.06-0.28,0.15-0.39,0.26c-0.11,0.11-0.2,0.24-0.26,0.4c-0.06,0.16-0.09,0.33-0.09,0.51
|
||||
c0,0.19,0.03,0.36,0.09,0.51c0.06,0.16,0.15,0.29,0.26,0.4c0.11,0.11,0.24,0.2,0.39,0.26c0.15,0.06,0.31,0.09,0.49,0.09
|
||||
c0.18,0,0.34-0.03,0.49-0.09c0.15-0.06,0.28-0.15,0.39-0.26c0.11-0.11,0.2-0.24,0.26-0.4c0.06-0.16,0.09-0.33,0.09-0.51
|
||||
c0-0.19-0.03-0.36-0.09-0.51c-0.06-0.16-0.15-0.29-0.26-0.4c-0.11-0.11-0.24-0.2-0.39-0.26C54.31,40.26,54.14,40.23,53.97,40.23
|
||||
L53.97,40.23z M53.97,39.42c0.3,0,0.59,0.05,0.85,0.16c0.26,0.11,0.48,0.25,0.67,0.44c0.19,0.19,0.34,0.4,0.44,0.66
|
||||
c0.11,0.25,0.16,0.53,0.16,0.82c0,0.3-0.05,0.57-0.16,0.82c-0.11,0.25-0.25,0.47-0.44,0.66c-0.19,0.19-0.41,0.33-0.67,0.44
|
||||
c-0.26,0.11-0.54,0.16-0.85,0.16s-0.59-0.05-0.85-0.16c-0.26-0.11-0.48-0.25-0.67-0.44c-0.19-0.19-0.34-0.41-0.44-0.66
|
||||
c-0.11-0.25-0.16-0.53-0.16-0.82c0-0.3,0.05-0.57,0.16-0.82c0.11-0.25,0.25-0.47,0.44-0.66c0.19-0.19,0.41-0.33,0.67-0.44
|
||||
C53.38,39.47,53.66,39.42,53.97,39.42L53.97,39.42z M31.77,41.48c0-0.69,0.45-1.26,1.19-1.26c0.71,0,1.18,0.54,1.18,1.26
|
||||
c0,0.71-0.48,1.26-1.18,1.26C32.22,42.73,31.77,42.17,31.77,41.48L31.77,41.48z M34.95,41.48v-1.96h-0.85v0.48
|
||||
c-0.27-0.35-0.68-0.58-1.24-0.58c-1.1,0-1.96,0.86-1.96,2.06c0,1.2,0.86,2.06,1.96,2.06c0.56,0,0.97-0.22,1.24-0.58v0.48h0.85
|
||||
V41.48z M30.13,43.44v-2.46c0-0.93-0.59-1.55-1.54-1.56c-0.5-0.01-1.02,0.15-1.38,0.7c-0.27-0.44-0.7-0.7-1.3-0.7
|
||||
c-0.42,0-0.83,0.12-1.15,0.58v-0.48h-0.85v3.93h0.86v-2.18c0-0.68,0.38-1.04,0.96-1.04c0.57,0,0.85,0.37,0.85,1.04v2.18h0.86
|
||||
v-2.18c0-0.68,0.39-1.04,0.96-1.04c0.58,0,0.86,0.37,0.86,1.04v2.18H30.13L30.13,43.44z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 80 50" style="enable-background:new 0 0 80 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#F9F9F9;}
|
||||
.st1{fill:#FF5F00;}
|
||||
.st2{fill:#EB001B;}
|
||||
.st3{fill:#F79E1B;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M76.56,50H3.44C1.55,50,0,48.45,0,46.56V3.44C0,1.55,1.55,0,3.44,0h73.12C78.45,0,80,1.55,80,3.44v43.12
|
||||
C80,48.45,78.45,50,76.56,50z"/>
|
||||
<g>
|
||||
<path d="M24.81,43.45v-2.46c0-0.94-0.57-1.56-1.56-1.56c-0.49,0-1.03,0.16-1.39,0.7c-0.29-0.45-0.7-0.7-1.31-0.7
|
||||
c-0.41,0-0.82,0.12-1.15,0.57v-0.49h-0.86v3.94h0.86v-2.17c0-0.7,0.37-1.03,0.94-1.03s0.86,0.37,0.86,1.03v2.17h0.86v-2.17
|
||||
c0-0.7,0.41-1.03,0.94-1.03c0.57,0,0.86,0.37,0.86,1.03v2.17H24.81L24.81,43.45z M37.56,39.52h-1.39v-1.19H35.3v1.19h-0.78v0.78
|
||||
h0.78v1.8c0,0.9,0.37,1.44,1.35,1.44c0.37,0,0.78-0.12,1.07-0.29l-0.25-0.74c-0.25,0.16-0.53,0.21-0.74,0.21
|
||||
c-0.41,0-0.57-0.25-0.57-0.66V40.3h1.39V39.52L37.56,39.52z M44.86,39.43c-0.49,0-0.82,0.25-1.03,0.57v-0.49h-0.86v3.94h0.86
|
||||
v-2.21c0-0.66,0.29-1.03,0.82-1.03c0.16,0,0.37,0.04,0.53,0.08l0.25-0.82C45.27,39.43,45.02,39.43,44.86,39.43L44.86,39.43
|
||||
L44.86,39.43z M33.83,39.84c-0.41-0.29-0.98-0.41-1.6-0.41c-0.98,0-1.64,0.49-1.64,1.27c0,0.66,0.49,1.03,1.35,1.15l0.41,0.04
|
||||
c0.45,0.08,0.7,0.21,0.7,0.41c0,0.29-0.33,0.49-0.9,0.49c-0.57,0-1.03-0.21-1.31-0.41l-0.41,0.66c0.45,0.33,1.07,0.49,1.68,0.49
|
||||
c1.15,0,1.8-0.53,1.8-1.27c0-0.7-0.53-1.07-1.35-1.19l-0.41-0.04c-0.37-0.04-0.66-0.12-0.66-0.37c0-0.29,0.29-0.45,0.74-0.45
|
||||
c0.49,0,0.98,0.21,1.23,0.33L33.83,39.84L33.83,39.84z M56.71,39.43c-0.49,0-0.82,0.25-1.03,0.57v-0.49h-0.86v3.94h0.86v-2.21
|
||||
c0-0.66,0.29-1.03,0.82-1.03c0.16,0,0.37,0.04,0.53,0.08l0.25-0.82C57.12,39.43,56.87,39.43,56.71,39.43L56.71,39.43L56.71,39.43z
|
||||
M45.72,41.49c0,1.19,0.82,2.05,2.09,2.05c0.57,0,0.98-0.12,1.39-0.45l-0.41-0.7c-0.33,0.25-0.66,0.37-1.03,0.37
|
||||
c-0.7,0-1.19-0.49-1.19-1.27c0-0.74,0.49-1.23,1.19-1.27c0.37,0,0.7,0.12,1.03,0.37l0.41-0.7c-0.41-0.33-0.82-0.45-1.39-0.45
|
||||
C46.54,39.43,45.72,40.3,45.72,41.49L45.72,41.49L45.72,41.49z M53.68,41.49v-1.97h-0.86v0.49c-0.29-0.37-0.7-0.57-1.23-0.57
|
||||
c-1.11,0-1.97,0.86-1.97,2.05c0,1.19,0.86,2.05,1.97,2.05c0.57,0,0.98-0.21,1.23-0.57v0.49h0.86V41.49z M50.52,41.49
|
||||
c0-0.7,0.45-1.27,1.19-1.27c0.7,0,1.19,0.53,1.19,1.27c0,0.7-0.49,1.27-1.19,1.27C50.97,42.72,50.52,42.18,50.52,41.49
|
||||
L50.52,41.49z M40.23,39.43c-1.15,0-1.97,0.82-1.97,2.05s0.82,2.05,2.01,2.05c0.57,0,1.15-0.16,1.6-0.53l-0.41-0.62
|
||||
c-0.33,0.25-0.74,0.41-1.15,0.41c-0.53,0-1.07-0.25-1.19-0.94h2.91v-0.33C42.07,40.26,41.33,39.43,40.23,39.43L40.23,39.43
|
||||
L40.23,39.43z M40.23,40.17c0.53,0,0.9,0.33,0.98,0.94h-2.05C39.24,40.58,39.61,40.17,40.23,40.17L40.23,40.17z M61.59,41.49
|
||||
v-3.53h-0.86v2.05c-0.29-0.37-0.7-0.57-1.23-0.57c-1.11,0-1.97,0.86-1.97,2.05c0,1.19,0.86,2.05,1.97,2.05
|
||||
c0.57,0,0.98-0.21,1.23-0.57v0.49h0.86V41.49z M58.43,41.49c0-0.7,0.45-1.27,1.19-1.27c0.7,0,1.19,0.53,1.19,1.27
|
||||
c0,0.7-0.49,1.27-1.19,1.27C58.88,42.72,58.43,42.18,58.43,41.49L58.43,41.49z M29.65,41.49v-1.97h-0.86v0.49
|
||||
c-0.29-0.37-0.7-0.57-1.23-0.57c-1.11,0-1.97,0.86-1.97,2.05c0,1.19,0.86,2.05,1.97,2.05c0.57,0,0.98-0.21,1.23-0.57v0.49h0.86
|
||||
V41.49z M26.45,41.49c0-0.7,0.45-1.27,1.19-1.27c0.7,0,1.19,0.53,1.19,1.27c0,0.7-0.49,1.27-1.19,1.27
|
||||
C26.9,42.72,26.45,42.18,26.45,41.49z"/>
|
||||
<rect x="33.54" y="9.62" class="st1" width="12.92" height="23.21"/>
|
||||
<path class="st2" d="M34.36,21.23c0-4.72,2.21-8.9,5.62-11.61c-2.5-1.97-5.66-3.16-9.1-3.16c-8.16,0-14.76,6.6-14.76,14.76
|
||||
s6.6,14.76,14.76,14.76c3.44,0,6.6-1.19,9.1-3.16C36.58,30.17,34.36,25.94,34.36,21.23z"/>
|
||||
<path class="st3" d="M63.89,21.23c0,8.16-6.6,14.76-14.76,14.76c-3.44,0-6.6-1.19-9.1-3.16c3.44-2.71,5.62-6.89,5.62-11.61
|
||||
s-2.21-8.9-5.62-11.61c2.5-1.97,5.66-3.16,9.1-3.16C57.28,6.46,63.89,13.11,63.89,21.23z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 80 50" style="enable-background:new 0 0 80 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
.st1{fill-rule:evenodd;clip-rule:evenodd;fill:#009EE3;}
|
||||
.st2{fill-rule:evenodd;clip-rule:evenodd;fill:#113984;}
|
||||
.st3{fill-rule:evenodd;clip-rule:evenodd;fill:#172C70;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M76.56,50H3.44C1.55,50,0,48.45,0,46.56V3.44C0,1.55,1.55,0,3.44,0h73.12C78.45,0,80,1.55,80,3.44v43.12
|
||||
C80,48.45,78.45,50,76.56,50z"/>
|
||||
<g>
|
||||
<path class="st1" d="M14.63,21.06h4.2c2.26,0,3.1,1.14,2.97,2.82c-0.22,2.77-1.89,4.3-4.11,4.3h-1.12c-0.3,0-0.51,0.2-0.59,0.75
|
||||
L15.5,32.1c-0.03,0.21-0.14,0.33-0.3,0.34h-2.64c-0.25,0-0.34-0.19-0.27-0.6l1.61-10.18C13.96,21.25,14.19,21.06,14.63,21.06z"/>
|
||||
<path class="st2" d="M32.87,20.87c1.42,0,2.72,0.77,2.55,2.68c-0.22,2.28-1.44,3.54-3.36,3.54h-1.68c-0.24,0-0.36,0.2-0.42,0.6
|
||||
l-0.33,2.07c-0.05,0.31-0.21,0.47-0.45,0.47h-1.56c-0.25,0-0.34-0.16-0.28-0.52l1.29-8.29c0.06-0.41,0.22-0.56,0.5-0.56H32.87
|
||||
L32.87,20.87z M30.32,25.31h1.27c0.8-0.03,1.33-0.58,1.38-1.58c0.03-0.61-0.38-1.05-1.04-1.05l-1.2,0.01L30.32,25.31L30.32,25.31z
|
||||
M39.67,29.6c0.14-0.13,0.29-0.2,0.27-0.04l-0.05,0.38c-0.03,0.2,0.05,0.31,0.24,0.31h1.39c0.23,0,0.35-0.09,0.41-0.46l0.86-5.38
|
||||
c0.04-0.27-0.02-0.4-0.23-0.4h-1.53c-0.14,0-0.2,0.08-0.24,0.29l-0.06,0.33c-0.03,0.17-0.11,0.2-0.18,0.03
|
||||
c-0.26-0.61-0.92-0.89-1.84-0.87c-2.14,0.04-3.59,1.67-3.74,3.76c-0.12,1.61,1.04,2.88,2.56,2.88
|
||||
C38.62,30.44,39.11,30.11,39.67,29.6L39.67,29.6L39.67,29.6z M38.5,28.77c-0.92,0-1.57-0.74-1.43-1.64s1-1.64,1.92-1.64
|
||||
s1.57,0.74,1.43,1.64S39.42,28.77,38.5,28.77L38.5,28.77z M45.49,24h-1.41c-0.29,0-0.41,0.22-0.32,0.48l1.75,5.12l-1.72,2.44
|
||||
c-0.14,0.2-0.03,0.39,0.17,0.39h1.58c0.19,0.02,0.37-0.07,0.47-0.23l5.38-7.72C51.57,24.25,51.5,24,51.22,24h-1.5
|
||||
c-0.26,0-0.36,0.1-0.51,0.32l-2.24,3.25l-1-3.26C45.91,24.11,45.77,24,45.49,24L45.49,24z"/>
|
||||
<path class="st1" d="M57.01,20.87c1.42,0,2.72,0.77,2.55,2.68c-0.22,2.28-1.44,3.54-3.36,3.54h-1.68c-0.24,0-0.36,0.2-0.42,0.6
|
||||
l-0.33,2.07c-0.05,0.31-0.21,0.47-0.45,0.47h-1.56c-0.25,0-0.34-0.16-0.28-0.52l1.29-8.29c0.06-0.41,0.22-0.56,0.5-0.56
|
||||
L57.01,20.87L57.01,20.87z M54.46,25.31h1.27c0.8-0.03,1.33-0.58,1.38-1.58c0.03-0.61-0.38-1.05-1.04-1.05l-1.2,0.01L54.46,25.31
|
||||
L54.46,25.31z M63.81,29.6c0.14-0.13,0.29-0.2,0.27-0.04l-0.05,0.38c-0.03,0.2,0.05,0.31,0.24,0.31h1.39
|
||||
c0.23,0,0.35-0.09,0.41-0.46l0.86-5.38c0.04-0.27-0.02-0.4-0.23-0.4h-1.53c-0.14,0-0.2,0.08-0.24,0.29l-0.06,0.33
|
||||
c-0.03,0.17-0.11,0.2-0.18,0.03c-0.26-0.61-0.92-0.89-1.84-0.87c-2.14,0.04-3.59,1.67-3.74,3.76c-0.12,1.61,1.04,2.88,2.56,2.88
|
||||
C62.76,30.44,63.26,30.11,63.81,29.6L63.81,29.6L63.81,29.6z M62.64,28.77c-0.92,0-1.57-0.74-1.43-1.64s1-1.64,1.92-1.64
|
||||
c0.92,0,1.57,0.74,1.43,1.64S63.57,28.77,62.64,28.77L62.64,28.77z M69.05,30.26h-1.6c-0.1,0-0.19-0.08-0.2-0.18
|
||||
c0-0.01,0-0.02,0-0.04l1.41-8.93c0.03-0.13,0.14-0.22,0.27-0.22h1.6c0.1,0,0.19,0.08,0.2,0.18c0,0.01,0,0.02,0,0.04l-1.41,8.93
|
||||
C69.29,30.17,69.18,30.26,69.05,30.26L69.05,30.26z"/>
|
||||
<path class="st2" d="M12,17.55h4.2c1.18,0,2.59,0.04,3.53,0.87c0.63,0.55,0.96,1.44,0.88,2.39c-0.26,3.21-2.18,5.01-4.75,5.01
|
||||
h-2.07c-0.35,0-0.59,0.23-0.69,0.87l-0.58,3.69c-0.04,0.24-0.14,0.38-0.33,0.4H9.61c-0.29,0-0.39-0.22-0.31-0.7l1.86-11.82
|
||||
C11.23,17.78,11.49,17.55,12,17.55z"/>
|
||||
<path class="st3" d="M13.17,26.31l0.73-4.65c0.06-0.41,0.29-0.6,0.73-0.6h4.2c0.69,0,1.26,0.11,1.7,0.31
|
||||
c-0.42,2.86-2.27,4.45-4.69,4.45h-2.07C13.49,25.81,13.29,25.95,13.17,26.31z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 80 50" style="enable-background:new 0 0 80 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FBE200;}
|
||||
.st1{fill:#004A99;}
|
||||
</style>
|
||||
<g>
|
||||
<g>
|
||||
<path class="st0" d="M80,47.33c0,1.47-1.19,2.67-2.67,2.67H2.67C1.19,50,0,48.81,0,47.33V2.67C0,1.19,1.19,0,2.67,0h74.67
|
||||
C78.81,0,80,1.19,80,2.67V47.33z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M14.1,20.45c-0.38,0-0.8,0.06-1.15,0.21c-0.09,0.03-0.21,0.06-0.3,0.12c-0.44,0.21-0.89,0.56-1.33,1
|
||||
l0.12-1.21h-1.42C10,20.92,9.97,21.25,9.94,21.6c-0.06,0.35-0.12,0.68-0.18,1.03l-2.04,8.95h1.57l0.95-4.11
|
||||
c0.3,0.41,0.65,0.74,1.03,0.95c0.41,0.21,0.86,0.33,1.42,0.33c0.09,0,0.18,0,0.27,0c0.59-0.06,1.12-0.21,1.6-0.5
|
||||
c0.59-0.33,1.06-0.8,1.42-1.42c0.32-0.5,0.56-1.09,0.71-1.77c0.18-0.68,0.24-1.33,0.18-1.92c-0.09-0.83-0.35-1.51-0.86-1.98
|
||||
C15.52,20.69,14.87,20.45,14.1,20.45z M15.14,24.73c-0.15,0.56-0.35,1.06-0.62,1.54c-0.27,0.47-0.59,0.83-0.97,1.06
|
||||
c-0.18,0.09-0.38,0.18-0.59,0.24c-0.21,0.06-0.44,0.09-0.68,0.09c-0.47,0-0.86-0.15-1.15-0.41c-0.3-0.3-0.47-0.65-0.5-1.12
|
||||
c-0.03-0.41,0-0.92,0.15-1.57c0.15-0.62,0.35-1.18,0.62-1.65c0.24-0.47,0.56-0.86,0.95-1.12c0.21-0.12,0.41-0.24,0.62-0.3
|
||||
c0.18-0.06,0.38-0.09,0.59-0.09c0.47,0,0.89,0.15,1.21,0.47c0.3,0.33,0.47,0.74,0.53,1.27C15.32,23.64,15.29,24.17,15.14,24.73z"
|
||||
/>
|
||||
<path class="st1" d="M53.78,21.04c-0.44-0.44-1.06-0.68-1.83-0.68c-0.5,0-0.97,0.09-1.39,0.3c-0.06,0.03-0.12,0.06-0.21,0.09
|
||||
c-0.35,0.21-0.68,0.47-1.03,0.8l0.06-0.97h-2.22c-0.06,0.53-0.21,1.36-0.44,2.45l-1.89,8.57h2.45l0.95-4.22
|
||||
c0.24,0.44,0.56,0.8,0.97,1c0.32,0.18,0.71,0.3,1.15,0.33c0.09,0,0.21,0.03,0.3,0.03c1.24,0,2.25-0.56,2.98-1.68
|
||||
c0.77-1.09,1.06-2.45,0.92-4.05C54.49,22.13,54.23,21.48,53.78,21.04z M52.04,24.53c-0.12,0.53-0.3,1.03-0.5,1.48
|
||||
c-0.21,0.41-0.41,0.71-0.68,0.92c-0.15,0.12-0.32,0.21-0.5,0.24c-0.12,0.03-0.24,0.06-0.35,0.06c-0.41,0-0.74-0.15-0.97-0.41
|
||||
c-0.27-0.27-0.38-0.65-0.44-1.15c-0.09-0.97,0.09-1.86,0.56-2.66c0.32-0.56,0.74-0.95,1.21-1.09c0.18-0.03,0.32-0.06,0.5-0.06
|
||||
c0.38,0,0.68,0.12,0.92,0.35c0.21,0.21,0.35,0.53,0.38,0.97C52.19,23.55,52.16,24,52.04,24.53z"/>
|
||||
<path class="st1" d="M61.91,20.95c-0.56-0.35-1.33-0.5-2.36-0.5c-0.33,0-0.65,0-0.95,0.06c-0.62,0.09-1.12,0.27-1.57,0.53
|
||||
c-0.59,0.41-0.95,0.97-1,1.71h2.33c0.06-0.24,0.12-0.44,0.24-0.59c0.03-0.09,0.09-0.12,0.15-0.18c0.18-0.15,0.44-0.24,0.8-0.24
|
||||
c0.3,0,0.53,0.06,0.68,0.18c0.18,0.12,0.27,0.3,0.3,0.53c0,0.12,0,0.24-0.03,0.38c0,0.18-0.06,0.38-0.12,0.68
|
||||
c-0.09,0-0.18,0-0.27,0s-0.24,0-0.41,0c-0.38,0-0.77,0-1.09,0.03c-1.15,0.09-2.04,0.35-2.69,0.77c-0.83,0.53-1.21,1.3-1.12,2.3
|
||||
c0.06,0.65,0.3,1.15,0.74,1.54c0.44,0.38,1,0.59,1.71,0.59c0.5,0,0.92-0.12,1.3-0.33l0.06-0.03c0.35-0.18,0.71-0.5,1-0.92
|
||||
c0,0.21-0.03,0.38-0.03,0.59c0,0.21,0,0.38,0,0.56h2.25c0-0.35,0-0.68,0.03-1.03c0.06-0.35,0.09-0.68,0.18-1l0.62-2.72
|
||||
c0.06-0.27,0.12-0.53,0.15-0.74c0.03-0.24,0.03-0.44,0-0.65C62.73,21.81,62.44,21.31,61.91,20.95z M59.31,26.6
|
||||
c-0.24,0.27-0.47,0.44-0.71,0.56c-0.18,0.09-0.38,0.12-0.59,0.12c-0.27,0-0.47-0.06-0.62-0.21c-0.18-0.15-0.27-0.35-0.27-0.62
|
||||
c-0.06-0.47,0.15-0.89,0.65-1.21c0.24-0.18,0.5-0.3,0.83-0.38c0.3-0.09,0.65-0.12,1.03-0.12c0.12,0,0.18,0,0.27,0
|
||||
c0.06,0,0.12,0,0.18,0.03C59.96,25.5,59.69,26.12,59.31,26.6z"/>
|
||||
<polygon class="st1" points="69.97,20.51 66.84,26.06 66.16,20.51 63.74,20.51 65.16,28.6 63.21,31.56 65.81,31.56 67.25,28.93
|
||||
72.28,20.51 "/>
|
||||
<path class="st1" d="M23.91,21.04c-0.56-0.44-1.3-0.68-2.25-0.68c-0.27,0-0.53,0-0.77,0.03c-0.47,0.06-0.95,0.18-1.33,0.33
|
||||
c-0.59,0.27-1.06,0.62-1.45,1.12c-0.41,0.56-0.71,1.21-0.92,1.98c-0.24,0.77-0.3,1.48-0.24,2.19c0.06,0.86,0.38,1.54,0.97,2.01
|
||||
c0.56,0.5,1.33,0.74,2.27,0.74c0.24,0,0.47-0.03,0.68-0.03c0.59-0.06,1.09-0.18,1.51-0.38c0.59-0.27,1.06-0.71,1.48-1.33
|
||||
c0.35-0.53,0.62-1.18,0.8-1.92c0.21-0.74,0.27-1.45,0.21-2.1C24.8,22.16,24.5,21.51,23.91,21.04z M23.12,24.76
|
||||
c-0.15,0.62-0.35,1.18-0.65,1.68c-0.27,0.44-0.56,0.77-0.92,0.97c-0.18,0.12-0.41,0.21-0.65,0.27c-0.18,0.03-0.35,0.06-0.56,0.06
|
||||
c-0.53,0-0.95-0.15-1.27-0.44c-0.3-0.3-0.5-0.68-0.53-1.21c-0.03-0.47,0-1.03,0.15-1.68s0.35-1.18,0.62-1.62
|
||||
c0.27-0.47,0.59-0.83,0.95-1.09c0.21-0.12,0.44-0.21,0.65-0.27s0.38-0.09,0.59-0.09c0.56,0,0.98,0.15,1.27,0.44
|
||||
c0.3,0.27,0.47,0.71,0.53,1.33C23.32,23.58,23.26,24.11,23.12,24.76z"/>
|
||||
<path class="st1" d="M31.06,20.78c-0.44-0.27-1.12-0.41-2.04-0.41c-1,0-1.8,0.24-2.39,0.68c-0.56,0.47-0.83,1.03-0.77,1.74
|
||||
c0.03,0.41,0.21,0.8,0.56,1.09c0.32,0.33,0.92,0.68,1.74,1.06c0.65,0.3,1.06,0.53,1.27,0.71c0.21,0.18,0.32,0.38,0.32,0.62
|
||||
c0.03,0.38-0.12,0.71-0.47,0.97c-0.35,0.24-0.83,0.35-1.45,0.35c-0.47,0-0.8-0.06-1.03-0.24c-0.24-0.15-0.35-0.38-0.38-0.71
|
||||
c-0.03-0.09-0.03-0.18,0-0.3c0-0.12,0.03-0.24,0.09-0.38h-1.6c-0.03,0.18-0.06,0.35-0.09,0.5c-0.03,0.18-0.03,0.32,0,0.44
|
||||
c0.06,0.59,0.32,1.03,0.83,1.36c0.53,0.3,1.21,0.47,2.1,0.47c1.12,0,2.04-0.27,2.72-0.77c0.71-0.5,1-1.15,0.95-1.89
|
||||
c-0.03-0.44-0.21-0.83-0.47-1.12c-0.27-0.3-0.92-0.68-1.86-1.12c-0.68-0.32-1.12-0.56-1.3-0.74c-0.21-0.15-0.3-0.35-0.32-0.56
|
||||
c-0.03-0.35,0.09-0.65,0.38-0.86c0.27-0.21,0.65-0.33,1.15-0.33c0.44,0,0.77,0.09,0.97,0.24c0.24,0.15,0.35,0.38,0.38,0.68
|
||||
c0,0.06,0,0.15,0,0.21s0,0.15,0,0.24h1.45c0.03-0.21,0.03-0.35,0.03-0.44c0-0.12,0-0.21,0-0.3
|
||||
C31.77,21.43,31.54,21.04,31.06,20.78z"/>
|
||||
<path class="st1" d="M35.55,27.6c-0.35,0-0.62-0.06-0.77-0.18c-0.15-0.09-0.24-0.24-0.24-0.47c-0.03-0.09,0-0.21,0.03-0.38
|
||||
c0-0.15,0.06-0.38,0.15-0.71l0.89-4.2h1.74l0.24-1.03h-1.74l0.47-2.22l-1.57,0.38l-0.41,1.83h-1.45l-0.27,1.03h1.48l-0.92,4.02
|
||||
c-0.06,0.38-0.15,0.74-0.18,1.09c-0.03,0.33-0.06,0.59-0.03,0.74c0.03,0.44,0.18,0.77,0.47,0.95c0.27,0.21,0.71,0.3,1.3,0.3
|
||||
c0.21,0,0.44-0.03,0.68-0.03c0.24-0.03,0.5-0.06,0.8-0.09l0.27-1.18c-0.15,0.03-0.32,0.09-0.47,0.09
|
||||
C35.85,27.57,35.67,27.6,35.55,27.6z"/>
|
||||
<path class="st1" d="M39.01,24.76h2.33h3.43c0.09-0.35,0.15-0.71,0.15-1.03c0.03-0.32,0.03-0.65,0-0.95
|
||||
c-0.06-0.86-0.38-1.48-0.89-1.86c-0.53-0.38-1.33-0.59-2.36-0.59c-0.12,0-0.21,0-0.32,0c-0.62,0.06-1.15,0.18-1.62,0.44
|
||||
c-0.56,0.27-1.03,0.71-1.39,1.24c-0.32,0.56-0.62,1.24-0.8,2.01c-0.21,0.8-0.27,1.51-0.21,2.13c0.06,0.83,0.38,1.48,0.92,1.92
|
||||
c0.56,0.44,1.3,0.68,2.25,0.68c0.3,0,0.59-0.03,0.86-0.06c0.65-0.09,1.21-0.3,1.68-0.62c0.68-0.44,1.12-1.06,1.33-1.86h-1.74
|
||||
c-0.15,0.44-0.41,0.8-0.77,1.03c-0.15,0.09-0.32,0.18-0.5,0.24c-0.21,0.09-0.44,0.12-0.68,0.12c-0.56,0-0.97-0.15-1.3-0.41
|
||||
c-0.3-0.27-0.47-0.65-0.53-1.15c0-0.18,0-0.38,0.03-0.59C38.89,25.21,38.92,25,39.01,24.76z M40.13,21.9
|
||||
c0.33-0.35,0.74-0.53,1.21-0.59c0.09,0,0.21-0.03,0.3-0.03c0.53,0,0.95,0.15,1.27,0.38c0.3,0.24,0.47,0.56,0.5,1
|
||||
c0.03,0.12,0.03,0.24,0,0.38c0,0.15-0.03,0.35-0.06,0.62h-2.01h-2.07C39.42,22.87,39.72,22.28,40.13,21.9z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.8 KiB |
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 25.4.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Livello_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 80 50" style="enable-background:new 0 0 80 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:url(#SVGID_1_);}
|
||||
.st1{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g>
|
||||
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="0" y1="25" x2="80" y2="25">
|
||||
<stop offset="0" style="stop-color:#222357"/>
|
||||
<stop offset="1" style="stop-color:#254AA5"/>
|
||||
</linearGradient>
|
||||
<path class="st0" d="M76.56,50H3.44C1.55,50,0,48.45,0,46.56V3.44C0,1.55,1.55,0,3.44,0h73.12C78.45,0,80,1.55,80,3.44v43.12
|
||||
C80,48.45,78.45,50,76.56,50z"/>
|
||||
<g>
|
||||
<path class="st1" d="M41.01,21.58c-0.03,2.65,2.36,4.12,4.16,5c1.85,0.9,2.47,1.48,2.47,2.28c-0.01,1.23-1.48,1.78-2.85,1.8
|
||||
c-2.39,0.04-3.78-0.64-4.88-1.16l-0.86,4.02c1.11,0.51,3.16,0.96,5.28,0.97c4.99,0,8.26-2.46,8.27-6.28
|
||||
c0.02-4.85-6.71-5.12-6.66-7.28c0.02-0.66,0.64-1.36,2.02-1.54c0.68-0.09,2.56-0.16,4.69,0.82l0.84-3.89
|
||||
c-1.14-0.42-2.62-0.82-4.45-0.82C44.34,15.5,41.04,18,41.01,21.58 M61.51,15.84c-0.91,0-1.68,0.53-2.02,1.35l-7.13,17.02h4.99
|
||||
l0.99-2.74h6.09l0.58,2.74h4.4l-3.84-18.37H61.51 M62.21,20.8l1.44,6.9h-3.94L62.21,20.8 M34.96,15.84l-3.93,18.37h4.75
|
||||
l3.93-18.37H34.96 M27.93,15.84l-4.95,12.5l-2-10.63c-0.23-1.19-1.16-1.87-2.19-1.87h-8.09l-0.11,0.53
|
||||
c1.66,0.36,3.55,0.94,4.69,1.56c0.7,0.38,0.9,0.71,1.13,1.61l3.79,14.66h5.02l7.7-18.37H27.93"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
180
Mimante/Examples/10€ Idea Shopping +10P - Bidoo_files/css
Normal file
@@ -0,0 +1,180 @@
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* math */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTVOmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF;
|
||||
}
|
||||
/* symbols */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTUGmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-muw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSKmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSumu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSOmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSymu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;
|
||||
}
|
||||
/* hebrew */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS2mu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0307-0308, U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F;
|
||||
}
|
||||
/* math */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTVOmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0302-0303, U+0305, U+0307-0308, U+0310, U+0312, U+0315, U+031A, U+0326-0327, U+032C, U+032F-0330, U+0332-0333, U+0338, U+033A, U+0346, U+034D, U+0391-03A1, U+03A3-03A9, U+03B1-03C9, U+03D1, U+03D5-03D6, U+03F0-03F1, U+03F4-03F5, U+2016-2017, U+2034-2038, U+203C, U+2040, U+2043, U+2047, U+2050, U+2057, U+205F, U+2070-2071, U+2074-208E, U+2090-209C, U+20D0-20DC, U+20E1, U+20E5-20EF, U+2100-2112, U+2114-2115, U+2117-2121, U+2123-214F, U+2190, U+2192, U+2194-21AE, U+21B0-21E5, U+21F1-21F2, U+21F4-2211, U+2213-2214, U+2216-22FF, U+2308-230B, U+2310, U+2319, U+231C-2321, U+2336-237A, U+237C, U+2395, U+239B-23B7, U+23D0, U+23DC-23E1, U+2474-2475, U+25AF, U+25B3, U+25B7, U+25BD, U+25C1, U+25CA, U+25CC, U+25FB, U+266D-266F, U+27C0-27FF, U+2900-2AFF, U+2B0E-2B11, U+2B30-2B4C, U+2BFE, U+3030, U+FF5B, U+FF5D, U+1D400-1D7FF, U+1EE00-1EEFF;
|
||||
}
|
||||
/* symbols */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTUGmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0001-000C, U+000E-001F, U+007F-009F, U+20DD-20E0, U+20E2-20E4, U+2150-218F, U+2190, U+2192, U+2194-2199, U+21AF, U+21E6-21F0, U+21F3, U+2218-2219, U+2299, U+22C4-22C6, U+2300-243F, U+2440-244A, U+2460-24FF, U+25A0-27BF, U+2800-28FF, U+2921-2922, U+2981, U+29BF, U+29EB, U+2B00-2BFF, U+4DC0-4DFF, U+FFF9-FFFB, U+10140-1018E, U+10190-1019C, U+101A0, U+101D0-101FD, U+102E0-102FB, U+10E60-10E7E, U+1D2C0-1D2D3, U+1D2E0-1D37F, U+1F000-1F0FF, U+1F100-1F1AD, U+1F1E6-1F1FF, U+1F30D-1F30F, U+1F315, U+1F31C, U+1F31E, U+1F320-1F32C, U+1F336, U+1F378, U+1F37D, U+1F382, U+1F393-1F39F, U+1F3A7-1F3A8, U+1F3AC-1F3AF, U+1F3C2, U+1F3C4-1F3C6, U+1F3CA-1F3CE, U+1F3D4-1F3E0, U+1F3ED, U+1F3F1-1F3F3, U+1F3F5-1F3F7, U+1F408, U+1F415, U+1F41F, U+1F426, U+1F43F, U+1F441-1F442, U+1F444, U+1F446-1F449, U+1F44C-1F44E, U+1F453, U+1F46A, U+1F47D, U+1F4A3, U+1F4B0, U+1F4B3, U+1F4B9, U+1F4BB, U+1F4BF, U+1F4C8-1F4CB, U+1F4D6, U+1F4DA, U+1F4DF, U+1F4E3-1F4E6, U+1F4EA-1F4ED, U+1F4F7, U+1F4F9-1F4FB, U+1F4FD-1F4FE, U+1F503, U+1F507-1F50B, U+1F50D, U+1F512-1F513, U+1F53E-1F54A, U+1F54F-1F5FA, U+1F610, U+1F650-1F67F, U+1F687, U+1F68D, U+1F691, U+1F694, U+1F698, U+1F6AD, U+1F6B2, U+1F6B9-1F6BA, U+1F6BC, U+1F6C6-1F6CF, U+1F6D3-1F6D7, U+1F6E0-1F6EA, U+1F6F0-1F6F3, U+1F6F7-1F6FC, U+1F700-1F7FF, U+1F800-1F80B, U+1F810-1F847, U+1F850-1F859, U+1F860-1F887, U+1F890-1F8AD, U+1F8B0-1F8BB, U+1F8C0-1F8C1, U+1F900-1F90B, U+1F93B, U+1F946, U+1F984, U+1F996, U+1F9E9, U+1FA00-1FA6F, U+1FA70-1FA7C, U+1FA80-1FA89, U+1FA8F-1FAC6, U+1FACE-1FADC, U+1FADF-1FAE9, U+1FAF0-1FAF8, U+1FB00-1FBFF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSCmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTSGmu1aB.woff2) format('woff2');
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Open Sans';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-stretch: 100%;
|
||||
src: url(https://fonts.gstatic.com/s/opensans/v44/memvYaGs126MiZpBA-UvWbX2vVnXBbObj2OVTS-muw.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
*
|
||||
* detectIncognito v1.0.0 - (c) 2022 Joe Rutkowski <Joe@dreggle.com> (https://github.com/Joe12387/detectIncognito)
|
||||
*
|
||||
**/
|
||||
var detectIncognito=function(){return new Promise(function(o,n){var e,t="Unknown";function i(e){o({isPrivate:e,browserName:t})}function r(e){return e===eval.toString().length}function a(){var e,o=window;void 0!==navigator.maxTouchPoints?void 0!==o.safari&&void 0===o.DeviceMotionEvent?(t="Safari for macOS",function(){try{window.safari.pushNotification.requestPermission("https://example.com","private",{},function(){})}catch(e){return i(!new RegExp("gesture").test(e))}i(!1)}()):void 0!==o.DeviceMotionEvent?(e=!(t="Safari for iOS"),(o=document.createElement("iframe")).style.display="none",document.body.appendChild(o),o.contentWindow.applicationCache.addEventListener("error",function(){return i(e=!0)}),setTimeout(function(){e||i(!1)},100)):n(new Error("detectIncognito Could not identify this version of Safari")):(t="Safari",function(){var e=window.openDatabase,o=window.localStorage;try{e(null,null,null,null)}catch(e){return i(!0)}try{o.setItem("test","1"),o.removeItem("test")}catch(e){return i(!0)}i(!1)}())}function c(){navigator.webkitTemporaryStorage.queryUsageAndQuota(function(e,o){i(o<(void 0!==(o=window).performance&&void 0!==o.performance.memory&&void 0!==o.performance.memory.jsHeapSizeLimit?performance.memory.jsHeapSizeLimit:1073741824))},function(e){n(new Error("detectIncognito somehow failed to query storage quota: "+e.message))})}function d(){void 0!==Promise&&void 0!==Promise.allSettled?c():(0,window.webkitRequestFileSystem)(0,1,function(){i(!1)},function(){i(!0)})}void 0!==(e=navigator.vendor)&&0===e.indexOf("Apple")&&r(37)?a():void 0!==(e=navigator.vendor)&&0===e.indexOf("Google")&&r(33)?(e=navigator.userAgent,t=e.match(/Chrome/)?void 0!==navigator.brave?"Brave":e.match(/Edg/)?"Edge":e.match(/OPR/)?"Opera":"Chrome":"Chromium",d()):void 0!==document.documentElement&&void 0!==document.documentElement.style.MozAppearance&&r(37)?(t="Firefox",i(void 0===navigator.serviceWorker)):void 0!==navigator.msSaveBlob&&r(39)?(t="Internet Explorer",i(void 0===window.indexedDB)):n(new Error("detectIncognito cannot determine the browser"))})};
|
||||
@@ -0,0 +1,107 @@
|
||||
(function(g){var window=this;'use strict';var BaX=function(A){A.mutedAutoplay=!1;A.endSeconds=NaN;A.limitedPlaybackDurationInSeconds=NaN;g.SC(A)},fZK=function(){return{Z:"svg",
|
||||
C:{height:"100%",version:"1.1",viewBox:"0 0 110 26",width:"100%"},B:[{Z:"path",bq:!0,j:"ytp-svg-fill",C:{d:"M 16.68,.99 C 13.55,1.03 7.02,1.16 4.99,1.68 c -1.49,.4 -2.59,1.6 -2.99,3 -0.69,2.7 -0.68,8.31 -0.68,8.31 0,0 -0.01,5.61 .68,8.31 .39,1.5 1.59,2.6 2.99,3 2.69,.7 13.40,.68 13.40,.68 0,0 10.70,.01 13.40,-0.68 1.5,-0.4 2.59,-1.6 2.99,-3 .69,-2.7 .68,-8.31 .68,-8.31 0,0 .11,-5.61 -0.68,-8.31 -0.4,-1.5 -1.59,-2.6 -2.99,-3 C 29.11,.98 18.40,.99 18.40,.99 c 0,0 -0.67,-0.01 -1.71,0 z m 72.21,.90 0,21.28 2.78,0 .31,-1.37 .09,0 c .3,.5 .71,.88 1.21,1.18 .5,.3 1.08,.40 1.68,.40 1.1,0 1.99,-0.49 2.49,-1.59 .5,-1.1 .81,-2.70 .81,-4.90 l 0,-2.40 c 0,-1.6 -0.11,-2.90 -0.31,-3.90 -0.2,-0.89 -0.5,-1.59 -1,-2.09 -0.5,-0.4 -1.10,-0.59 -1.90,-0.59 -0.59,0 -1.18,.19 -1.68,.49 -0.49,.3 -1.01,.80 -1.21,1.40 l 0,-7.90 -3.28,0 z m -49.99,.78 3.90,13.90 .18,6.71 3.31,0 0,-6.71 3.87,-13.90 -3.37,0 -1.40,6.31 c -0.4,1.89 -0.71,3.19 -0.81,3.99 l -0.09,0 c -0.2,-1.1 -0.51,-2.4 -0.81,-3.99 l -1.37,-6.31 -3.40,0 z m 29.59,0 0,2.71 3.40,0 0,17.90 3.28,0 0,-17.90 3.40,0 c 0,0 .00,-2.71 -0.09,-2.71 l -9.99,0 z m -53.49,5.12 8.90,5.18 -8.90,5.09 0,-10.28 z m 89.40,.09 c -1.7,0 -2.89,.59 -3.59,1.59 -0.69,.99 -0.99,2.60 -0.99,4.90 l 0,2.59 c 0,2.2 .30,3.90 .99,4.90 .7,1.1 1.8,1.59 3.5,1.59 1.4,0 2.38,-0.3 3.18,-1 .7,-0.7 1.09,-1.69 1.09,-3.09 l 0,-0.5 -2.90,-0.21 c 0,1 -0.08,1.6 -0.28,2 -0.1,.4 -0.5,.62 -1,.62 -0.3,0 -0.61,-0.11 -0.81,-0.31 -0.2,-0.3 -0.30,-0.59 -0.40,-1.09 -0.1,-0.5 -0.09,-1.21 -0.09,-2.21 l 0,-0.78 5.71,-0.09 0,-2.62 c 0,-1.6 -0.10,-2.78 -0.40,-3.68 -0.2,-0.89 -0.71,-1.59 -1.31,-1.99 -0.7,-0.4 -1.48,-0.59 -2.68,-0.59 z m -50.49,.09 c -1.09,0 -2.01,.18 -2.71,.68 -0.7,.4 -1.2,1.12 -1.49,2.12 -0.3,1 -0.5,2.27 -0.5,3.87 l 0,2.21 c 0,1.5 .10,2.78 .40,3.78 .2,.9 .70,1.62 1.40,2.12 .69,.5 1.71,.68 2.81,.78 1.19,0 2.08,-0.28 2.78,-0.68 .69,-0.4 1.09,-1.09 1.49,-2.09 .39,-1 .49,-2.30 .49,-3.90 l 0,-2.21 c 0,-1.6 -0.2,-2.87 -0.49,-3.87 -0.3,-0.89 -0.8,-1.62 -1.49,-2.12 -0.7,-0.5 -1.58,-0.68 -2.68,-0.68 z m 12.18,.09 0,11.90 c -0.1,.3 -0.29,.48 -0.59,.68 -0.2,.2 -0.51,.31 -0.81,.31 -0.3,0 -0.58,-0.10 -0.68,-0.40 -0.1,-0.3 -0.18,-0.70 -0.18,-1.40 l 0,-10.99 -3.40,0 0,11.21 c 0,1.4 .18,2.39 .68,3.09 .49,.7 1.21,1 2.21,1 1.4,0 2.48,-0.69 3.18,-2.09 l .09,0 .31,1.78 2.59,0 0,-14.99 c 0,0 -3.40,.00 -3.40,-0.09 z m 17.31,0 0,11.90 c -0.1,.3 -0.29,.48 -0.59,.68 -0.2,.2 -0.51,.31 -0.81,.31 -0.3,0 -0.58,-0.10 -0.68,-0.40 -0.1,-0.3 -0.21,-0.70 -0.21,-1.40 l 0,-10.99 -3.40,0 0,11.21 c 0,1.4 .21,2.39 .71,3.09 .5,.7 1.18,1 2.18,1 1.39,0 2.51,-0.69 3.21,-2.09 l .09,0 .28,1.78 2.62,0 0,-14.99 c 0,0 -3.40,.00 -3.40,-0.09 z m 20.90,2.09 c .4,0 .58,.11 .78,.31 .2,.3 .30,.59 .40,1.09 .1,.5 .09,1.21 .09,2.21 l 0,1.09 -2.5,0 0,-1.09 c 0,-1 -0.00,-1.71 .09,-2.21 0,-0.4 .11,-0.8 .31,-1 .2,-0.3 .51,-0.40 .81,-0.40 z m -50.49,.12 c .5,0 .8,.18 1,.68 .19,.5 .28,1.30 .28,2.40 l 0,4.68 c 0,1.1 -0.08,1.90 -0.28,2.40 -0.2,.5 -0.5,.68 -1,.68 -0.5,0 -0.79,-0.18 -0.99,-0.68 -0.2,-0.5 -0.31,-1.30 -0.31,-2.40 l 0,-4.68 c 0,-1.1 .11,-1.90 .31,-2.40 .2,-0.5 .49,-0.68 .99,-0.68 z m 39.68,.09 c .3,0 .61,.10 .81,.40 .2,.3 .27,.67 .37,1.37 .1,.6 .12,1.51 .12,2.71 l .09,1.90 c 0,1.1 .00,1.99 -0.09,2.59 -0.1,.6 -0.19,1.08 -0.49,1.28 -0.2,.3 -0.50,.40 -0.90,.40 -0.3,0 -0.51,-0.08 -0.81,-0.18 -0.2,-0.1 -0.39,-0.29 -0.59,-0.59 l 0,-8.5 c .1,-0.4 .29,-0.7 .59,-1 .3,-0.3 .60,-0.40 .90,-0.40 z"}}]}},
|
||||
KqI=function(){return{Z:"svg",
|
||||
C:{fill:"none",height:"100%",viewBox:"0 0 143 51",width:"100%"},B:[{Z:"path",C:{d:"M58.37 41.39H62.79V27.23C62.79 23.03 62.69 18.69 62.43 13.59H62.93L63.69 16.89L68.67 41.39H73.17L78.07 16.89L78.89 13.59H79.37C79.15 18.45 79.03 22.89 79.03 27.23V41.39H83.45V8.79H75.95L73.41 20.81C72.35 25.85 71.51 32.01 71.01 35.19H70.73C70.33 31.95 69.49 25.81 68.41 20.85L65.81 8.79H58.37V41.39Z",fill:"white"}},{Z:"path",C:{d:"M91.45 41.73C93.91 41.73 95.83 40.59 97.17 38.13H97.35L97.69 41.39H101.43V17.73H96.47V36.61C95.91 37.67 94.81 38.29 93.73 38.29C92.33 38.29 91.89 37.17 91.89 35.13V17.73H86.93V35.43C86.93 39.49 88.19 41.73 91.45 41.73Z",
|
||||
fill:"white"}},{Z:"path",C:{d:"M110.79 41.89C115.15 41.89 117.75 39.83 117.75 35.65C117.75 31.79 115.93 30.39 111.85 27.47C109.67 25.91 108.39 25.09 108.39 22.95C108.39 21.47 109.27 20.61 110.89 20.61C112.69 20.61 113.33 21.81 113.33 25.29L117.45 25.07C117.77 19.57 115.71 17.23 110.97 17.23C106.57 17.23 104.17 19.27 104.17 23.45C104.17 27.25 105.97 28.83 108.93 31.03C111.89 33.23 113.55 34.53 113.55 36.23C113.55 37.75 112.51 38.61 111.01 38.61C109.13 38.61 108.11 36.97 108.29 34.41L104.21 34.49C103.51 39.25 105.89 41.89 110.79 41.89Z",
|
||||
fill:"white"}},{Z:"path",C:{d:"M122.5 14.59C124.22 14.59 125.04 13.99 125.04 11.59C125.04 9.33 124.16 8.65 122.5 8.65C120.84 8.65 119.94 9.27 119.94 11.59C119.94 13.99 120.82 14.59 122.5 14.59ZM120.2 41.39H125V17.73H120.2V41.39Z",fill:"white"}},{Z:"path",C:{d:"M134.95 41.79C137.31 41.79 138.63 41.49 139.71 40.47C141.31 39.01 141.97 36.63 141.85 33.11L137.41 32.87C137.41 36.87 136.81 38.45 135.03 38.45C133.13 38.45 132.77 36.45 132.77 31.97V27.21C132.77 22.41 133.23 20.51 135.07 20.51C136.67 20.51 137.29 22.01 137.29 26.47L141.65 26.15C141.97 22.93 141.59 20.29 140.09 18.83C139.01 17.77 137.37 17.29 135.15 17.29C129.65 17.29 127.75 20.73 127.75 28.03V31.17C127.75 38.47 129.23 41.79 134.95 41.79Z",
|
||||
fill:"white"}},{Z:"path",C:{"clip-rule":"evenodd",d:"M24.99 49C29.74 49.00 34.38 47.59 38.32 44.95C42.27 42.32 45.35 38.57 47.17 34.18C48.98 29.80 49.46 24.97 48.53 20.32C47.61 15.66 45.32 11.38 41.97 8.03C38.61 4.67 34.33 2.38 29.68 1.46C25.02 .53 20.20 1.01 15.81 2.82C11.43 4.64 7.68 7.71 5.04 11.66C2.40 15.61 1 20.25 1 25C0.99 28.15 1.61 31.27 2.82 34.18C4.03 37.09 5.79 39.74 8.02 41.97C10.25 44.19 12.89 45.96 15.81 47.17C18.72 48.37 21.84 49 24.99 49ZM24.99 12.36C27.49 12.36 29.94 13.10 32.02 14.48C34.10 15.87 35.72 17.84 36.68 20.15C37.64 22.46 37.89 25.01 37.41 27.46C36.92 29.91 35.72 32.17 33.95 33.94C32.18 35.70 29.93 36.91 27.48 37.40C25.02 37.89 22.48 37.64 20.17 36.68C17.86 35.72 15.88 34.10 14.50 32.02C13.11 29.94 12.37 27.50 12.37 25C12.37 21.65 13.70 18.44 16.07 16.07C18.43 13.70 21.64 12.37 24.99 12.36ZM24.99 10.43C22.11 10.43 19.29 11.28 16.89 12.88C14.50 14.48 12.63 16.76 11.53 19.42C10.42 22.09 10.13 25.02 10.70 27.85C11.26 30.67 12.65 33.27 14.69 35.31C16.73 37.35 19.32 38.73 22.15 39.30C24.98 39.86 27.91 39.57 30.57 38.46C33.23 37.36 35.51 35.49 37.11 33.09C38.71 30.70 39.57 27.88 39.56 25C39.56 23.08 39.19 21.19 38.46 19.42C37.72 17.65 36.65 16.04 35.30 14.69C33.94 13.34 32.34 12.27 30.57 11.53C28.80 10.80 26.90 10.43 24.99 10.43ZM32.63 24.99L20.36 32.09V17.91L32.63 24.99Z",
|
||||
fill:"white","fill-rule":"evenodd"}}]}},V7t=function(A){g.q.call(this,{Z:"div",
|
||||
j:"ytp-related-on-error-overlay"});var L=this;this.api=A;this.D=this.W=0;this.U=new g.dN(this);this.N=[];this.suggestionData=[];this.columns=this.containerWidth=0;this.title=new g.q({Z:"h2",j:"ytp-related-title",Ir:"{{title}}"});this.previous=new g.q({Z:"button",Rr:["ytp-button","ytp-previous"],C:{"aria-label":"Mostra i video consigliati in precedenza"},B:[g.jN()]});this.G=new g.x4(function(V){L.suggestions.element.scrollLeft=-V});
|
||||
this.V=this.scrollPosition=0;this.T=!0;this.next=new g.q({Z:"button",Rr:["ytp-button","ytp-next"],C:{"aria-label":"Mostra altri video consigliati"},B:[g.gq()]});g.W(this,this.U);A=A.K();this.X=A.U;g.W(this,this.title);this.title.DM(this.element);this.suggestions=new g.q({Z:"div",j:"ytp-suggestions"});g.W(this,this.suggestions);this.suggestions.DM(this.element);g.W(this,this.previous);this.previous.DM(this.element);this.previous.listen("click",this.jX,this);g.W(this,this.G);for(var B={Kj:0};B.Kj<16;B=
|
||||
{Kj:B.Kj},B.Kj++){var f=new g.q({Z:"a",j:"ytp-suggestion-link",C:{href:"{{link}}",target:A.yj,"aria-label":"{{aria_label}}"},B:[{Z:"div",j:"ytp-suggestion-image",B:[{Z:"div",C:{"data-is-live":"{{is_live}}"},j:"ytp-suggestion-duration",Ir:"{{duration}}"}]},{Z:"div",j:"ytp-suggestion-title",C:{title:"{{hover_title}}"},Ir:"{{title}}"},{Z:"div",j:"ytp-suggestion-author",Ir:"{{views_or_author}}"}]});g.W(this,f);f.DM(this.suggestions.element);var K=f.m4("ytp-suggestion-link");g.Kv(K,"transitionDelay",B.Kj/
|
||||
20+"s");this.U.Y(K,"click",function(V){return function(J){var R=V.Kj,Z=L.suggestionData[R],N=Z.sessionData;g.MM(L.api.K())&&L.api.J("web_player_log_click_before_generating_ve_conversion_params")?(L.api.logClick(L.N[R].element),R=Z.Ej(),Z={},g.Mm(L.api,Z),R=g.ip(R,Z),g.wC(R,L.api,J)):g.If(J,L.api,L.X,N||void 0)&&L.api.Dl(Z.videoId,N,Z.playlistId)}}(B));
|
||||
this.N.push(f)}g.W(this,this.next);this.next.DM(this.element);this.next.listen("click",this.TF,this);this.U.Y(this.api,"videodatachange",this.onVideoDataChange);this.resize(this.api.Pn().getPlayerSize());this.onVideoDataChange();this.show()},JdK=function(A,L){if(A.api.K().J("web_player_log_click_before_generating_ve_conversion_params"))for(var B=Math.floor(-A.scrollPosition/(A.V+A.W)),f=Math.min(B+A.columns,A.suggestionData.length)-1;B<=f;B++)A.api.logVisibility(A.N[B].element,L)},SGR=function(A){A.next.element.style.bottom=
|
||||
A.D+"px";
|
||||
A.previous.element.style.bottom=A.D+"px";var L=A.scrollPosition,B=A.containerWidth-A.suggestionData.length*(A.V+A.W);g.D1(A.element,"ytp-scroll-min",L>=0);g.D1(A.element,"ytp-scroll-max",L<=B)},RKd=function(A){for(var L=0;L<A.suggestionData.length;L++){var B=A.suggestionData[L],f=A.N[L],K=B.shortViewCount?B.shortViewCount:B.author,V=B.Ej(),J=A.api.K();
|
||||
if(g.MM(J)&&!J.J("web_player_log_click_before_generating_ve_conversion_params")){var R={};g.jg(A.api,"addEmbedsConversionTrackingParams",[R]);V=g.ip(V,R)}f.element.style.display="";R=f.m4("ytp-suggestion-title");g.yd.test(B.title)?R.dir="rtl":g.r1I.test(B.title)&&(R.dir="ltr");R=f.m4("ytp-suggestion-author");g.yd.test(K)?R.dir="rtl":g.r1I.test(K)&&(R.dir="ltr");f.update({views_or_author:K,duration:B.isLivePlayback?"Dal vivo":B.lengthSeconds?g.hG(B.lengthSeconds):"",link:V,hover_title:B.title,title:B.title,
|
||||
aria_label:B.ariaLabel||null,is_live:B.isLivePlayback});K=B.g1();f.m4("ytp-suggestion-image").style.backgroundImage=K?"url("+K+")":"";J.J("web_player_log_click_before_generating_ve_conversion_params")&&(A.api.createServerVe(f.element,f),(B=(B=B.sessionData)&&B.itct)&&A.api.setTrackingParams(f.element,B))}for(;L<A.N.length;L++)A.N[L].element.style.display="none";SGR(A)},zs=function(A){g.ig.call(this,A);
|
||||
var L=this;this.N=null;var B=A.K(),f={target:B.yj},K=["ytp-small-redirect"];if(B.V)K.push("no-link");else{var V=g.wd(B);f.href=V;f["aria-label"]="Visita YouTube per cercare altri video"}var J=new g.q({Z:"a",Rr:K,C:f,B:[{Z:"svg",C:{fill:"#fff",height:"100%",viewBox:"0 0 24 24",width:"100%"},B:[{Z:"path",C:{d:"M0 0h24v24H0V0z",fill:"none"}},{Z:"path",C:{d:"M21.58 7.19c-.23-.86-.91-1.54-1.77-1.77C18.25 5 12 5 12 5s-6.25 0-7.81.42c-.86.23-1.54.91-1.77 1.77C2 8.75 2 12 2 12s0 3.25.42 4.81c.23.86.91 1.54 1.77 1.77C5.75 19 12 19 12 19s6.25 0 7.81-.42c.86-.23 1.54-.91 1.77-1.77C22 15.25 22 12 22 12s0-3.25-.42-4.81zM10 15V9l5.2 3-5.2 3z"}}]}]});
|
||||
J.DM(this.element);A.createClientVe(J.element,this,178053);this.Y(J.element,"click",function(R){Zuf(L,R,J.element)});
|
||||
g.W(this,J);B.V||B.disableOrganicUi||(this.N=new V7t(A),this.N.DM(this.element),g.W(this,this.N));this.Y(A,"videodatachange",function(){L.show()});
|
||||
this.resize(this.api.Pn().getPlayerSize())},Zuf=function(A,L,B){L.preventDefault();
|
||||
A.api.logClick(B);L=B.getAttribute("href");B={};g.jg(A.api,"addEmbedsConversionTrackingParams",[B]);L=g.mi(B)?L:g.ip(L,B);g.QR(window,L)},NaK=function(A,L){A.m4("ytp-error-content").style.paddingTop="0px";
|
||||
var B=A.m4("ytp-error-content"),f=B.clientHeight;A.N&&A.N.resize(L,L.height-f);B.style.paddingTop=(L.height-(A.N?A.N.element.clientHeight:0))/2-f/2+"px"},d$t=function(A,L){var B=A.api.K(),f;
|
||||
L.reason&&(Fqw(L.reason)?f=g.p1(L.reason):f=g.$S(g.wq(L.reason)),A.setContent(f,"content"));var K;L.subreason&&(Fqw(L.subreason)?K=g.p1(L.subreason):K=g.$S(g.wq(L.subreason)),A.setContent(K,"subreason"));if(L.proceedButton&&L.proceedButton.buttonRenderer){f=A.m4("ytp-error-content-wrap-subreason");L=L.proceedButton.buttonRenderer;var V=g.TO("A");if(L.text&&L.text.simpleText&&(K=L.text.simpleText,V.textContent=K,!D$I(f,K)&&(!B.V||B.embedsErrorLinks))){var J;B=(J=g.y(L==null?void 0:L.navigationEndpoint,
|
||||
g.Mt))==null?void 0:J.url;var R;J=(R=g.y(L==null?void 0:L.navigationEndpoint,g.Mt))==null?void 0:R.target;B&&(V.setAttribute("href",B),A.api.createClientVe(V,A,178424),A.Y(V,"click",function(Z){Zuf(A,Z,V)}));
|
||||
J&&V.setAttribute("target",J);R=g.TO("DIV");R.appendChild(V);f.appendChild(R)}}},Fqw=function(A){if(A.runs)for(var L=0;L<A.runs.length;L++)if(A.runs[L].navigationEndpoint)return!0;
|
||||
return!1},D$I=function(A,L){A=g.jr("A",A);
|
||||
for(var B=0;B<A.length;B++)if(A[B].textContent===L)return!0;return!1},IZK=function(A,L){g.q.call(this,{Z:"a",
|
||||
Rr:["ytp-impression-link"],C:{target:"{{target}}",href:"{{url}}","aria-label":"Guarda su YouTube"},B:[{Z:"div",j:"ytp-impression-link-content",C:{"aria-hidden":"true"},B:[{Z:"div",j:"ytp-impression-link-text",Ir:"Guarda su"},{Z:"div",j:"ytp-impression-link-logo",Ir:"{{logoSvg}}"}]}]});this.api=A;this.N=L;this.updateValue("target",A.K().yj);this.Y(A,"videodatachange",this.onVideoDataChange);this.Y(this.api,"presentingplayerstatechange",this.qP);this.Y(this.api,"videoplayerreset",this.gH);this.Y(this.element,
|
||||
"click",this.onClick);this.onVideoDataChange();this.gH()},wGR=function(A){var L={};
|
||||
g.jg(A.api,"addEmbedsConversionTrackingParams",[L]);A=A.api.getVideoUrl();return A=g.ip(A,L)},u2=function(A){g.q.call(this,{Z:"div",
|
||||
Rr:["ytp-mobile-a11y-hidden-seek-button"],B:[{Z:"button",Rr:["ytp-mobile-a11y-hidden-seek-button-rewind","ytp-button"],C:{"aria-label":"Indietro di 10 secondi","aria-hidden":"false"}},{Z:"button",Rr:["ytp-mobile-a11y-hidden-seek-button-forward","ytp-button"],C:{"aria-label":"Avanti veloce di 10 secondi","aria-hidden":"false"}}]});this.api=A;this.N=this.m4("ytp-mobile-a11y-hidden-seek-button-rewind");this.forwardButton=this.m4("ytp-mobile-a11y-hidden-seek-button-forward");this.api.createClientVe(this.N,
|
||||
this,141902);this.api.createClientVe(this.forwardButton,this,141903);this.Y(this.api,"presentingplayerstatechange",this.qP);this.Y(this.N,"click",this.W);this.Y(this.forwardButton,"click",this.V);this.qP()},ae=function(A){g.q.call(this,{Z:"div",
|
||||
j:"ytp-muted-autoplay-endscreen-overlay",B:[{Z:"div",j:"ytp-muted-autoplay-end-panel",B:[{Z:"button",Rr:["ytp-muted-autoplay-end-text","ytp-button"],Ir:"{{text}}"}]}]});this.api=A;this.U=this.m4("ytp-muted-autoplay-end-panel");this.W=!1;this.api.createClientVe(this.element,this,52428);this.Y(this.api,"presentingplayerstatechange",this.V);this.Y(A,"onMutedAutoplayStarts",this.onMutedAutoplayStarts);this.listen("click",this.onClick);this.hide()},AM=function(A){var L=A.K();
|
||||
g.q.call(this,{Z:"a",Rr:["ytp-watermark","yt-uix-sessionlink"],C:{target:L.yj,href:"{{url}}","aria-label":g.B$("Guarda su $WEBSITE",{WEBSITE:g.BN(L)}),"data-sessionlink":"feature=player-watermark"},Ir:"{{logoSvg}}"});this.api=A;this.N=null;this.W=!1;this.state=A.getPlayerStateObject();this.Y(A,"videodatachange",this.onVideoDataChange);this.Y(A,"presentingplayerstatechange",this.onStateChange);this.Y(A,"appresize",this.Bz);this.onVideoDataChange();this.Y6(this.state);this.Bz(A.Pn().getPlayerSize())},
|
||||
pGR=function(A){var L=A.api.getVideoData(),B=A.api.K().TZ&&!g.x(A.state,2)&&!A.api.getVideoData(1).OE;
|
||||
L.mutedAutoplay||A.xP(B);A.api.logVisibility(A.element,B)},gb5=function(A){g.q.call(this,{Z:"div",
|
||||
j:"ytp-muted-autoplay-overlay",B:[{Z:"div",j:"ytp-muted-autoplay-bottom-buttons",B:[{Z:"button",Rr:["ytp-muted-autoplay-equalizer","ytp-button"],C:{"aria-label":"Indicatore di riproduzione con audio disattivato"},B:[{Z:"div",Rr:["ytp-muted-autoplay-equalizer-icon"],B:[{Z:"svg",C:{height:"100%",version:"1.1",viewBox:"-4 -4 24 24",width:"100%"},B:[{Z:"g",C:{fill:"#fff"},B:[{Z:"rect",j:"ytp-equalizer-bar-left",C:{height:"9",width:"4",x:"1",y:"7"}},{Z:"rect",j:"ytp-equalizer-bar-middle",C:{height:"14",
|
||||
width:"4",x:"6",y:"2"}},{Z:"rect",j:"ytp-equalizer-bar-right",C:{height:"12",width:"4",x:"11",y:"4"}}]}]}]}]}]}]});var L=this;this.api=A;this.bottomButtons=this.m4("ytp-muted-autoplay-bottom-buttons");this.V=new g.aa(this.YxT,4E3,this);this.W=!1;A.createClientVe(this.element,this,39306);this.Y(A,"presentingplayerstatechange",this.K1);this.Y(A,"onMutedAutoplayStarts",function(){ydK(L);L.K1();jg9(L);L.W=!1});
|
||||
this.Y(A,"onAutoplayBlocked",this.onAutoplayBlocked);this.listen("click",this.onClick);this.Y(A,"onMutedAutoplayEnds",this.onMutedAutoplayEnds);this.hide();A.isMutedByEmbedsMutedAutoplay()&&(ydK(this),this.K1(),jg9(this));g.W(this,this.V)},jg9=function(A){A.bC&&A.N&&(A.N.show(),A.V.start())},ydK=function(A){A.watermark||(A.watermark=new AM(A.api),g.W(A,A.watermark),A.watermark.DM(A.bottomButtons,0),g.D1(A.watermark.element,"ytp-muted-autoplay-watermark",!0),A.N=new g.KL(A.watermark,0,!0,100),g.W(A,
|
||||
A.N))},L7=function(A){g.q.call(this,{Z:"div",
|
||||
j:"ytp-pause-overlay",C:{tabIndex:"-1"}});var L=this;this.api=A;this.V=new g.dN(this);this.fade=new g.KL(this,1E3,!1,100,function(){L.N.W=!1},function(){L.N.W=!0});
|
||||
this.W=!1;this.expandButton=new g.q({Z:"button",Rr:["ytp-button","ytp-expand"],Ir:this.api.isEmbedsShortsMode()?"Altri Short":"Altri video"});A.K().controlsType==="0"&&g.R1(A.getRootNode(),"ytp-pause-overlay-controls-hidden");g.W(this,this.V);g.W(this,this.fade);var B=new g.q({Z:"button",Rr:["ytp-button","ytp-collapse"],C:{"aria-label":this.api.isEmbedsShortsMode()?"Nascondi la sezione Altri Short":"Nascondi Altri video"},B:[{Z:"div",j:"ytp-collapse-icon",B:[g.C1()]}]});g.W(this,B);B.DM(this.element);
|
||||
B.listen("click",this.U,this);g.W(this,this.expandButton);this.expandButton.DM(this.element);this.expandButton.listen("click",this.D,this);this.N=new g.ep(A);g.W(this,this.N);this.N.W=!1;this.N.DM(this.element);this.api.isEmbedsShortsMode()?this.api.createClientVe(this.element,this,157212):this.api.createClientVe(this.element,this,172777);this.V.Y(this.api,"presentingplayerstatechange",this.zL);this.V.Y(this.api,"videodatachange",this.zL);this.hide()},on=function(A){g.q.call(this,{Z:"div",
|
||||
Rr:["ytp-player-content","ytp-iv-player-content"],B:[{Z:"div",j:"ytp-countdown-timer",B:[{Z:"svg",C:{height:"100%",version:"1.1",viewBox:"0 0 72 72",width:"100%"},B:[{Z:"circle",j:"ytp-svg-countdown-timer-ring",C:{cx:"-36",cy:"36","fill-opacity":"0",r:"33.5",stroke:"#FFFFFF","stroke-dasharray":"211","stroke-dashoffset":"-211","stroke-width":"4",transform:"rotate(-90)"}},{Z:"circle",j:"ytp-svg-countdown-timer-background",C:{cx:"-36",cy:"36","fill-opacity":"0",r:"33.5",stroke:"#FFFFFF","stroke-opacity":"0.3",
|
||||
"stroke-width":"4",transform:"rotate(-90)"}}]},{Z:"span",j:"ytp-countdown-timer-time",Ir:"{{duration}}"}]}]});this.api=A;this.T=this.m4("ytp-svg-countdown-timer-ring");this.N=null;this.U=this.V=0;this.W=!1;this.D=0;this.api.createClientVe(this.element,this,159628)},rdI=function(A){A.N||(A.V=5E3,A.U=(0,g.bc)(),A.N=new g.uN(function(){Gw5(A)},null),Gw5(A))},Gw5=function(A){if(!A.W){var L=Math.min((0,g.bc)()-A.U,A.V);
|
||||
var B=A.V-L;L=A.V===0?0:Math.max(B/A.V,0);B=Math.round(B/1E3);A.T.setAttribute("stroke-dashoffset",""+-211*(L+1));A.updateValue("duration",B);L<=0&&A.N?A.stopTimer():A.N&&A.N.start()}},HuK=function(A){g.FB.call(this,A);
|
||||
this.S=A;this.N=new g.dN(this);this.W=null;this.X=!1;this.countdownTimer=null;this.yj=!1;sgd(this);g.W(this,this.N);this.load()},buK=function(A){var L=g.wzy(A.S);
|
||||
L!==A.yj&&(A.yj=L,A.D&&(A.D.dispose(),A.D=null),A.V&&(A.V.dispose(),A.V=null),A.U&&(A.U.dispose(),A.U=null),A.W&&(A.W.stop(),A.W.dispose(),A.W=null),L&&(L=g.Hh(A.S),A.S.isEmbedsShortsMode()&&(A.U=new g.q({Z:"div",j:"ytp-pause-overlay-backdrop",C:{tabIndex:"-1"}}),g.W(A,A.U),g.Wh(A.S,A.U.element,4),A.W=new g.KL(A.U,1E3,!1,100),g.W(A,A.W),A.U.hide()),A.D=new g.q({Z:"div",j:"ytp-pause-overlay-container",C:{tabIndex:"-1"}}),g.W(A,A.D),A.V=new L7(A.S,L),g.W(A,A.V),A.V.DM(A.D.element),g.Wh(A.S,A.D.element,
|
||||
4),hKI(A,A.S.getPlayerStateObject())))},hKI=function(A,L){A.W&&(!g.x(L,4)&&!g.x(L,2)||g.x(L,1024)?A.W.hide():A.W.show())},sgd=function(A){var L=A.S;
|
||||
A=!!L.isEmbedsShortsMode();g.D1(L.getRootNode(),"ytp-shorts-mode",A);if(L=L.getVideoData())L.g4=A},Bx=function(A,L){var B=A.S.K();
|
||||
A={adSource:"EMBEDS_AD_SOURCE_YOUTUBE",breakType:A.S.getCurrentTime()===0?"EMBEDS_AD_BREAK_TYPE_PRE_ROLL":A.S.getPlayerState()===0?"EMBEDS_AD_BREAK_TYPE_POST_ROLL":"EMBEDS_AD_BREAK_TYPE_MID_ROLL",embedUrl:g.Zvk(A.S.K().loaderUrl),eventType:L,youtubeHost:g.tW(A.S.K().vI)||""};A.embeddedPlayerMode=B.wT;g.pE("embedsAdEvent",A)};
|
||||
g.G(V7t,g.q);g.p=V7t.prototype;g.p.hide=function(){this.T=!0;g.q.prototype.hide.call(this);JdK(this,!1)};
|
||||
g.p.show=function(){this.T=!1;g.q.prototype.show.call(this);JdK(this,!0)};
|
||||
g.p.isHidden=function(){return this.T};
|
||||
g.p.TF=function(){this.scrollTo(this.scrollPosition-this.containerWidth)};
|
||||
g.p.jX=function(){this.scrollTo(this.scrollPosition+this.containerWidth)};
|
||||
g.p.resize=function(A,L){var B=this.api.K(),f=16/9,K=A.width>=650,V=A.width<480||A.height<290,J=Math.min(this.suggestionData.length,this.N.length);if(Math.min(A.width,A.height)<=150||J===0||!B.k6)this.hide();else{var R;if(K){var Z=R=28;this.W=16}else this.W=Z=R=8;if(V){var N=6;K=14;var F=12;V=24;B=12}else N=8,K=18,F=16,V=36,B=16;A=A.width-(48+R+Z);R=Math.ceil(A/150);R=Math.min(3,R);Z=A/R-this.W;var D=Math.floor(Z/f);L&&D+100>L&&Z>50&&(D=Math.max(L,50/f),R=Math.ceil(A/(f*(D-100)+this.W)),Z=A/R-this.W,
|
||||
D=Math.floor(Z/f));Z<50||g.ch(this.api)?this.hide():this.show();for(L=0;L<J;L++){f=this.N[L];var I=f.m4("ytp-suggestion-image");I.style.width=Z+"px";I.style.height=D+"px";f.m4("ytp-suggestion-title").style.width=Z+"px";f.m4("ytp-suggestion-author").style.width=Z+"px";f=f.m4("ytp-suggestion-duration");f.style.display=f&&Z<100?"none":""}J=K+N+F+4;this.D=J+B+(D-V)/2;this.suggestions.element.style.height=D+J+"px";this.V=Z;this.containerWidth=A;this.columns=R;this.scrollPosition=0;this.suggestions.element.scrollLeft=
|
||||
-0;SGR(this)}};
|
||||
g.p.onVideoDataChange=function(){var A=this.api.getVideoData(),L=this.api.K();this.X=A.OE?!1:L.U;A.suggestions?this.suggestionData=g.Mi(A.suggestions,function(B){return B&&!B.playlistId}):this.suggestionData.length=0;
|
||||
RKd(this);A.OE?this.title.update({title:g.B$("Altri video da $DNI_RELATED_CHANNEL",{DNI_RELATED_CHANNEL:A.author})}):this.title.update({title:"Altri video su YouTube"})};
|
||||
g.p.scrollTo=function(A){A=g.B4(A,this.containerWidth-this.suggestionData.length*(this.V+this.W),0);this.G.start(this.scrollPosition,A,1E3);this.scrollPosition=A;SGR(this);JdK(this,!0)};g.G(zs,g.ig);zs.prototype.show=function(){g.ig.prototype.show.call(this);NaK(this,this.api.Pn().getPlayerSize())};
|
||||
zs.prototype.resize=function(A){g.ig.prototype.resize.call(this,A);this.N&&(NaK(this,A),g.D1(this.element,"related-on-error-overlay-visible",!this.N.isHidden()))};
|
||||
zs.prototype.W=function(A){g.ig.prototype.W.call(this,A);var L=this.api.getVideoData();if(L.Kt||L.playerErrorMessageRenderer)(A=L.Kt)?d$t(this,A):L.playerErrorMessageRenderer&&d$t(this,L.playerErrorMessageRenderer);else{var B;A.Qr&&(L.ZE?Fqw(L.ZE)?B=g.p1(L.ZE):B=g.$S(g.wq(L.ZE)):B=g.$S(A.Qr),this.setContent(B,"subreason"))}};g.G(IZK,g.q);g.p=IZK.prototype;g.p.onVideoDataChange=function(){var A=this.api.getVideoData(),L=fZK(),B=96714;g.Nm(A)?(L=KqI(),B=216165,g.R1(this.element,"ytp-music-impression-link")):g.NH(this.element,"ytp-music-impression-link");this.updateValue("logoSvg",L);this.api.hasVe(this.element)&&this.api.destroyVe(this.element);this.api.createClientVe(this.element,this,B)};
|
||||
g.p.qP=function(){this.api.getPlayerStateObject().isCued()||(this.hide(),this.api.logVisibility(this.element,!1))};
|
||||
g.p.gH=function(){var A=this.api.getVideoData(),L=this.api.K(),B=this.api.getVideoData().OE,f=!L.k6,K=this.N.Gy(),V=L.V;L.TZ||K||B||f||V||this.api.isEmbedsShortsMode()||!A.videoId?(this.hide(),this.api.logVisibility(this.element,!1)):(A=wGR(this),this.updateValue("url",A),this.show())};
|
||||
g.p.onClick=function(A){this.api.J("web_player_log_click_before_generating_ve_conversion_params")&&this.api.logClick(this.element);var L=wGR(this);g.wC(L,this.api,A);this.api.J("web_player_log_click_before_generating_ve_conversion_params")||this.api.logClick(this.element)};
|
||||
g.p.show=function(){this.api.getPlayerStateObject().isCued()&&(g.q.prototype.show.call(this),this.api.hasVe(this.element)&&this.api.logVisibility(this.element,!0))};g.G(u2,g.q);u2.prototype.qP=function(){var A=this.api.getPlayerStateObject();!this.api.Kw()||g.x(A,2)&&g.Xr(this.api)||g.x(A,64)?(this.api.logVisibility(this.N,!1),this.api.logVisibility(this.forwardButton,!1),this.hide()):(this.show(),this.api.logVisibility(this.N,!0),this.api.logVisibility(this.forwardButton,!0))};
|
||||
u2.prototype.W=function(){this.api.seekBy(-10*this.api.getPlaybackRate(),void 0,void 0,83);this.api.logClick(this.N)};
|
||||
u2.prototype.V=function(){this.api.seekBy(10*this.api.getPlaybackRate(),void 0,void 0,82);this.api.logClick(this.forwardButton)};g.G(ae,g.q);
|
||||
ae.prototype.V=function(){var A=this.api.getPlayerStateObject(),L=this.api.getVideoData();g.D1(this.element,"ytp-shorts-mode",this.api.isEmbedsShortsMode());!L.mutedAutoplay||L.limitedPlaybackDurationInSeconds===0&&L.endSeconds===0&&L.mutedAutoplayDurationMode===2||(g.x(A,2)&&!this.bC?(this.show(),this.N||(this.N=new g.Q2(this.api),g.W(this,this.N),this.N.DM(this.U,0),this.N.show()),A=this.api.getVideoData(),this.updateValue("text",A.Tz),g.D1(this.element,"ytp-muted-autoplay-show-end-panel",!0),this.api.logVisibility(this.element,
|
||||
this.bC),this.api.Wo("onMutedAutoplayEnds")):this.hide())};
|
||||
ae.prototype.onClick=function(){if(!this.W){this.N&&(this.N.l1(),this.N=null);g.D1(this.api.getRootNode(),"ytp-muted-autoplay",!1);var A=this.api.getVideoData(),L=this.api.getCurrentTime();BaX(A);this.api.loadVideoById(A.videoId,L);this.api.S9();this.api.logClick(this.element);this.hide();this.W=!0}};
|
||||
ae.prototype.onMutedAutoplayStarts=function(){this.W=!1;this.N&&(this.N.l1(),this.N=null)};g.G(AM,g.q);g.p=AM.prototype;g.p.onStateChange=function(A){this.Y6(A.state)};
|
||||
g.p.Y6=function(A){this.state!==A&&(this.state=A);pGR(this)};
|
||||
g.p.onVideoDataChange=function(){var A=this.api.K();A.V&&g.R1(this.element,"ytp-no-hover");var L=this.api.getVideoData();L.videoId&&!A.V?(A=this.api.getVideoUrl(!0,!1,!1,!0),this.updateValue("url",A),this.N||(this.N=this.listen("click",this.onClick))):this.N&&(this.updateValue("url",null),this.J$(this.N),this.N=null);A=fZK();var B=76758;g.Nm(L)&&(A=KqI(),B=216164);this.updateValue("logoSvg",A);this.api.hasVe(this.element)&&this.api.destroyVe(this.element);this.api.createClientVe(this.element,this,
|
||||
B);pGR(this)};
|
||||
g.p.onClick=function(A){this.api.J("web_player_log_click_before_generating_ve_conversion_params")&&this.api.logClick(this.element);var L=this.api.getVideoUrl(!g.bV(A),!1,!0,!0);if(this.api.J("web_player_log_click_before_generating_ve_conversion_params")){var B={};g.jg(this.api,"addEmbedsConversionTrackingParams",[B]);L=g.ip(L,B)}g.wC(L,this.api,A);this.api.J("web_player_log_click_before_generating_ve_conversion_params")||this.api.logClick(this.element)};
|
||||
g.p.Bz=function(A){if((A=A.width<480)&&!this.W||!A&&this.W){var L=new g.q(fZK()),B=this.m4("ytp-watermark");g.D1(B,"ytp-watermark-small",A);g.Ql(B);L.DM(B);this.W=A}};g.G(gb5,g.q);g.p=gb5.prototype;g.p.K1=function(){var A=this.api.getPlayerStateObject();!this.api.getVideoData().mutedAutoplay||g.x(A,2)?this.hide():this.bC||(g.q.prototype.show.call(this),this.api.logVisibility(this.element,this.bC))};
|
||||
g.p.YxT=function(){this.N&&this.N.hide()};
|
||||
g.p.onAutoplayBlocked=function(){this.hide();BaX(this.api.getVideoData())};
|
||||
g.p.onClick=function(){if(!this.W){g.D1(this.api.getRootNode(),"ytp-muted-autoplay",!1);var A=this.api.getVideoData(),L=this.api.getCurrentTime();BaX(A);this.api.loadVideoById(A.videoId,L);this.api.S9();this.api.logClick(this.element);this.api.Wo("onMutedAutoplayEnds");this.W=!0}};
|
||||
g.p.onMutedAutoplayEnds=function(){this.watermark&&(this.watermark.l1(),this.watermark=null)};g.G(L7,g.q);L7.prototype.hide=function(){g.NH(this.api.getRootNode(),"ytp-expand-pause-overlay");g.q.prototype.hide.call(this)};
|
||||
L7.prototype.U=function(){this.W=!0;g.NH(this.api.getRootNode(),"ytp-expand-pause-overlay");this.api.isEmbedsShortsMode()&&this.api.logVisibility(this.element,!1);this.expandButton.focus()};
|
||||
L7.prototype.D=function(){this.W=!1;g.R1(this.api.getRootNode(),"ytp-expand-pause-overlay");this.api.isEmbedsShortsMode()&&this.api.logVisibility(this.element,!0);this.focus()};
|
||||
L7.prototype.zL=function(){var A=this.api.getPlayerStateObject();g.x(A,1)||g.x(A,16)||g.x(A,32)||(!g.x(A,4)||g.x(A,2)||g.x(A,1024)?(this.W||this.api.logVisibility(this.element,!1),this.fade.hide()):this.N.hasSuggestions()&&(this.W||(g.R1(this.api.getRootNode(),"ytp-expand-pause-overlay"),g.nY(this.N),this.N.show(),this.api.logVisibility(this.element,!0)),this.fade.show()))};g.G(on,g.q);on.prototype.show=function(){g.q.prototype.show.call(this);this.api.logVisibility(this.element,!0)};
|
||||
on.prototype.stopTimer=function(){this.N&&(this.N.dispose(),this.N=null,this.W=!1)};
|
||||
on.prototype.l1=function(){this.stopTimer();g.q.prototype.l1.call(this)};g.G(HuK,g.FB);g.p=HuK.prototype;g.p.Pg=function(){return!1};
|
||||
g.p.create=function(){var A=this.S.K(),L=g.Hh(this.S),B,f=(B=this.S.getVideoData())==null?void 0:B.clientPlaybackNonce;f&&g.Qm({clientPlaybackNonce:f});A.sx&&!A.disableOrganicUi&&buK(this);var K;(K=A.getWebPlayerContextConfig())!=null&&K.embedsEnableEmc3ds||(this.G=new gb5(this.S),g.W(this,this.G),g.Wh(this.S,this.G.element,4),this.qp=new ae(this.S),g.W(this,this.qp),g.Wh(this.S,this.qp.element,4));A.TZ&&(this.watermark=new AM(this.S),g.W(this,this.watermark),g.Wh(this.S,this.watermark.element,8));
|
||||
L&&!A.disableOrganicUi&&(this.T=new IZK(this.S,L),g.W(this,this.T),g.Wh(this.S,this.T.element,8),this.S.isMutedByEmbedsMutedAutoplay()&&(this.onMutedAutoplayStarts(),this.T.hide()));A.W&&!A.disableOrganicUi&&(this.Wn=new u2(this.S),g.W(this,this.Wn),g.Wh(this.S,this.Wn.element,4));this.N.Y(this.S,"appresize",this.Bz);this.N.Y(this.S,"presentingplayerstatechange",this.qP);this.N.Y(this.S,"videodatachange",this.onVideoDataChange);this.N.Y(this.S,"videoplayerreset",this.onReset);this.N.Y(this.S,"onMutedAutoplayStarts",
|
||||
this.onMutedAutoplayStarts);this.N.Y(this.S,"onAdStart",this.onAdStart);this.N.Y(this.S,"onAdComplete",this.onAdComplete);this.N.Y(this.S,"onAdSkip",this.onAdSkip);this.N.Y(this.S,"onAdStateChange",this.onAdStateChange);if(this.X=g.IX(g.nM(A)))this.countdownTimer=new on(this.S),g.W(this,this.countdownTimer),g.Wh(this.S,this.countdownTimer.element,4),this.countdownTimer.hide(),this.N.Y(this.S,g.qR("embeds"),this.onCueRangeEnter),this.N.Y(this.S,g.PR("embeds"),this.onCueRangeExit);this.q8(this.S.getPlayerStateObject());
|
||||
var V,J;((V=this.S.K().getWebPlayerContextConfig())==null?0:(J=V.embedsHostFlags)==null?0:J.allowOverridingVisitorDataPlayerVars)&&(A=g.A_("IDENTITY_MEMENTO"))&&this.S.X3("onMementoChange",A)};
|
||||
g.p.onCueRangeEnter=function(A){A.getId()==="countdown timer"&&this.countdownTimer&&(this.countdownTimer.show(),rdI(this.countdownTimer))};
|
||||
g.p.onCueRangeExit=function(A){A.getId()==="countdown timer"&&this.countdownTimer&&(this.countdownTimer.stopTimer(),this.countdownTimer.hide())};
|
||||
g.p.Bz=function(){var A=this.S.Pn().getPlayerSize();this.Xb&&this.Xb.resize(A)};
|
||||
g.p.onReset=function(){sgd(this)};
|
||||
g.p.qP=function(A){this.q8(A.state)};
|
||||
g.p.q8=function(A){g.x(A,128)?(this.Xb||(this.Xb=new zs(this.S),g.W(this,this.Xb),g.Wh(this.S,this.Xb.element,4)),this.Xb.W(A.nh),this.Xb.show(),g.R1(this.S.getRootNode(),"ytp-embed-error")):this.Xb&&(this.Xb.dispose(),this.Xb=null,g.NH(this.S.getRootNode(),"ytp-embed-error"));if(this.countdownTimer&&this.countdownTimer.N)if(g.x(A,64))this.countdownTimer.hide(),this.countdownTimer.stopTimer();else if(A.isPaused()){var L=this.countdownTimer;L.W||(L.W=!0,L.D=(0,g.bc)())}else A.isPlaying()&&this.countdownTimer.W&&
|
||||
(L=this.countdownTimer,L.W&&(L.U+=(0,g.bc)()-L.D,L.W=!1,Gw5(L)));hKI(this,A)};
|
||||
g.p.onMutedAutoplayStarts=function(){this.S.getVideoData().mutedAutoplay&&this.G&&g.D1(this.S.getRootNode(),"ytp-muted-autoplay",!0)};
|
||||
g.p.onVideoDataChange=function(A,L){var B=this.PT!==L.videoId;A=!B&&A==="dataloaded";var f={isShortsModeEnabled:!!this.S.isEmbedsShortsMode()};g.pE("embedsVideoDataDidChange",{clientPlaybackNonce:L.clientPlaybackNonce,isReload:A,runtimeEnabledFeatures:f});B&&(this.PT=L.videoId,this.countdownTimer&&(this.countdownTimer.show(),this.countdownTimer.hide()),this.X&&(this.S.Jf("embeds"),L.isAd()||L.limitedPlaybackDurationInSeconds<5||g.ch(this.S)||(L=Math.max((L.startSeconds+L.limitedPlaybackDurationInSeconds-
|
||||
5)*1E3,0),L=new g.WR(L,L+5E3,{id:"countdown timer",namespace:"embeds"}),this.S.dX([L]))),this.S.K().sx&&!this.S.K().disableOrganicUi&&(sgd(this),buK(this)));this.S.K().V&&this.V&&this.V.detach()};
|
||||
g.p.onAdStart=function(){Bx(this,"EMBEDS_AD_EVENT_TYPE_AD_STARTED")};
|
||||
g.p.onAdComplete=function(){Bx(this,"EMBEDS_AD_EVENT_TYPE_AD_COMPLETED")};
|
||||
g.p.onAdSkip=function(){Bx(this,"EMBEDS_AD_EVENT_TYPE_AD_SKIPPED")};
|
||||
g.p.onAdStateChange=function(A){A===2&&Bx(this,"EMBEDS_AD_EVENT_TYPE_AD_PAUSED")};g.Np("embed",HuK);})(_yt_player);
|
||||
@@ -0,0 +1 @@
|
||||
/* PLEASE DO NOT COPY AND PASTE THIS CODE. */(function(){var w=window,C='___grecaptcha_cfg',cfg=w[C]=w[C]||{},N='grecaptcha';var E='enterprise',a=w[N]=w[N]||{},gr=a[E]=a[E]||{};gr.ready=gr.ready||function(f){(cfg['fns']=cfg['fns']||[]).push(f);};w['__recaptcha_api']='https://www.google.com/recaptcha/enterprise/';(cfg['enterprise']=cfg['enterprise']||[]).push(true);(cfg['enterprise2fa']=cfg['enterprise2fa']||[]).push(true);(cfg['render']=cfg['render']||[]).push('6LcjhUMpAAAAADxcuxrNs1Ou0iKbz2h3dn58Egnw');(cfg['clr']=cfg['clr']||[]).push('true');(cfg['anchor-ms']=cfg['anchor-ms']||[]).push(20000);(cfg['execute-ms']=cfg['execute-ms']||[]).push(15000);w['__google_recaptcha_client']=true;var d=document,po=d.createElement('script');po.type='text/javascript';po.async=true; po.charset='utf-8';var v=w.navigator,m=d.createElement('meta');m.httpEquiv='origin-trial';m.content='A7vZI3v+Gz7JfuRolKNM4Aff6zaGuT7X0mf3wtoZTnKv6497cVMnhy03KDqX7kBz/q/iidW7srW31oQbBt4VhgoAAACUeyJvcmlnaW4iOiJodHRwczovL3d3dy5nb29nbGUuY29tOjQ0MyIsImZlYXR1cmUiOiJEaXNhYmxlVGhpcmRQYXJ0eVN0b3JhZ2VQYXJ0aXRpb25pbmczIiwiZXhwaXJ5IjoxNzU3OTgwODAwLCJpc1N1YmRvbWFpbiI6dHJ1ZSwiaXNUaGlyZFBhcnR5Ijp0cnVlfQ==';if(v&&v.cookieDeprecationLabel){v.cookieDeprecationLabel.getValue().then(function(l){if(l!=='treatment_1.1'&&l!=='treatment_1.2'&&l!=='control_1.1'){d.head.prepend(m);}});}else{d.head.prepend(m);}po.src='https://www.gstatic.com/recaptcha/releases/TkacYOdEJbdB_JjX802TMer9/recaptcha__it.js';po.crossOrigin='anonymous';po.integrity='sha384-jBr1c0i/lBALGFjGRa0UkLw5oDOPevN9KOlmNFGKHe5+D+3OpoTeZdS00+BHr2oZ';var e=d.querySelector('script[nonce]'),n=e&&(e['nonce']||e.getAttribute('nonce'));if(n){po.setAttribute('nonce',n);}var s=d.getElementsByTagName('script')[0];s.parentNode.insertBefore(po, s);})();
|
||||
|
After Width: | Height: | Size: 37 KiB |
@@ -0,0 +1,124 @@
|
||||
function setFavoriteHandler(){
|
||||
"use strict"
|
||||
var lockRequest = false;
|
||||
$(".favorite").on({
|
||||
click: function(e) {
|
||||
var element = $(this);
|
||||
e.preventDefault(e);
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
if(element.attr('disabled')) {
|
||||
if(isMobileDevice()) {
|
||||
element.tooltip('show');
|
||||
setTimeout(function(){
|
||||
element.tooltip('hide');
|
||||
}, 3000);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (lockRequest) {
|
||||
return;
|
||||
}
|
||||
|
||||
lockRequest = true;
|
||||
|
||||
$.ajax({
|
||||
url: 'favorite.php',
|
||||
data: {
|
||||
id: element.attr("data-id")
|
||||
},
|
||||
type: "GET"
|
||||
}).success(function(data) {
|
||||
lockRequest = false;
|
||||
if (data.result) window.parent.updateFavoriteCounter(element);
|
||||
}).fail(function(){
|
||||
lockRequest = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function animateAddToFavorite(favoriteSelector){
|
||||
"use strict"
|
||||
//if(!$(".select-bids").length) return; // REM FOR TAG
|
||||
if(!$("#CategoryMenu").length) return; // ADD FOR TAG
|
||||
|
||||
// var targetSelector = ".select-bids .bi-favorite"; // REM FOR TAG
|
||||
var targetSelector = "#CategoryMenu .bi-favorite"; // ADD FOR TAG
|
||||
var body = $("body");
|
||||
var preferredPositionTab = $(targetSelector).offset();
|
||||
var categoryMenuPosition = $("#CategoryMenu").offset(); // ADD FOR TAG
|
||||
if (preferredPositionTab.left < categoryMenuPosition.left) { // ADD FOR TAG
|
||||
preferredPositionTab.left = categoryMenuPosition.left -16;
|
||||
}
|
||||
var cloneFavorite = favoriteSelector
|
||||
.clone()
|
||||
.addClass("bi-clone")
|
||||
.addClass("fixed-zindex-high");
|
||||
|
||||
cloneFavorite = body.append(cloneFavorite)
|
||||
.find(".bi-clone");
|
||||
|
||||
var favoritePosition = favoriteSelector.offset();
|
||||
|
||||
cloneFavorite.css({
|
||||
"position": "absolute",
|
||||
"left": favoritePosition.left,
|
||||
"top": favoritePosition.top
|
||||
});
|
||||
|
||||
cloneFavorite
|
||||
.animate({
|
||||
left: preferredPositionTab.left+"px",
|
||||
top: preferredPositionTab.top+"px"
|
||||
},600,function(){
|
||||
cloneFavorite.remove();
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
"use strict"
|
||||
window.updateFavoriteCounter = function(element) {
|
||||
"use strict"
|
||||
var id = element.data('id');
|
||||
var preferredCount = $('.preferredCount');
|
||||
var count = parseInt(preferredCount.eq(0).text());
|
||||
if(element.length > 1) return;
|
||||
element.toggleClass("active");
|
||||
var hasElementActive = element.hasClass("active");
|
||||
|
||||
if (hasElementActive) {
|
||||
count += 1;
|
||||
animateAddToFavorite(element);
|
||||
} else {
|
||||
count = count < 0 ? 0 : --count;
|
||||
}
|
||||
|
||||
var preferredCount = $('.preferredCount').text(count);
|
||||
preferredCount.parent().toggleClass("active", count > 0);
|
||||
|
||||
setFavoriteTabTooltipVisibility(0 == count);
|
||||
|
||||
var asta = $("#divAsta" + id);
|
||||
var data_favorite = parseInt(asta.attr('data-favorited'));
|
||||
var des_text = (hasElementActive ? "Rimuovi quest\'asta dalle tue preferite" : "Metti quest\'asta tra le tue preferite"); // data_favorite -> hasElementActive
|
||||
asta.attr('data-favorited', !data_favorite | 0)
|
||||
if($("#modal").is(":visible")){
|
||||
asta
|
||||
.find(".favorite")
|
||||
.toggleClass("active");
|
||||
}
|
||||
var id_product = getUrlParam("a").split("_").reverse()[0];
|
||||
if (id_product > 0) {
|
||||
element.attr('title', des_text);
|
||||
} else {
|
||||
element.attr('data-original-title', des_text);
|
||||
}
|
||||
//$('.auction-[data-favorited=0]').toggleClass('hide', !hasElementActive && bidSelected == 2); // REMOVED for bidSelect not defined
|
||||
}
|
||||
//this is the js that is working for favorites bids
|
||||
setFavoriteHandler();
|
||||
});
|
||||