mod divers data

This commit is contained in:
2026-02-18 12:15:38 +01:00
parent d5a247df9b
commit ff440ac48c
22 changed files with 6 additions and 1668 deletions

View File

@@ -1,56 +0,0 @@
# .dockerignore
# Git
.git
.gitignore
# IDE
.idea
.vscode
*.swp
*.swo
*~
# Flutter/Dart
.dart_tool/
.packages
build/
.flutter-plugins
.flutter-plugins-dependencies
.metadata
# Node.js (for proxy)
node_modules/
npm-debug.log
yarn-error.log
# Test
test/
integration_test/
.test_coverage/
# Documentation
*.md
!README.md
# CI/CD
.github/
# Local development
.env.local
*.log
# macOS
.DS_Store
# Windows
Thumbs.db
# Linux
*~
# Other
*.iml
*.class
*.lock
!pubspec.lock
!package-lock.json

View File

@@ -1,328 +0,0 @@
# Proxy Server Deployment - Anleitung
## 📋 Übersicht
Diese Anleitung erklärt, wie Sie den Reverse Proxy Server für PTV API Geocoding deployen. Der Proxy umgeht CORS-Probleme und läuft als eigenständiger Container.
## 🏗️ Architektur
```
Browser (Flutter Web App)
Proxy Server (localhost:3000 / your-server.com:3000)
PTV Geocoding API (api.myptv.com)
```
## 🚀 Lokale Entwicklung
### 1. Proxy Server starten
```bash
cd /home/digitalman/Development/flutter_tank_web_app
# Option A: Mit Script
./start-proxy.sh
# Option B: Manuell
cd proxy-server
node server.js
```
Der Proxy läuft auf `http://localhost:3000`
### 2. Flutter App starten
```bash
flutter run -d chrome
```
### 3. Testen
**Geocoding Request:**
```bash
curl "http://localhost:3000/?lat=47.9385165&lon=13.762887&apiKey=YOUR_API_KEY"
```
**Erwartete Response:**
```json
{
"success": true,
"location": "Straßenname Hausnummer, PLZ Stadt",
"coordinates": {
"lat": 47.9385165,
"lon": 13.762887
}
}
```
**Health Check:**
```bash
curl http://localhost:3000/health
# Response: healthy
```
## 🐳 Docker Deployment (Empfohlen)
### 1. Docker Images bauen
```bash
# Interaktives Deployment-Script
./deploy.sh
# Wählen Sie Option 3: "Alles bauen und starten"
# Oder manuell
docker-compose up -d --build
```
### 2. Services überprüfen
```bash
docker-compose ps
# Erwartete Ausgabe:
# flutter-tank-web Up 0.0.0.0:8090->80/tcp
# ptv-proxy Up 0.0.0.0:3000->3000/tcp
```
### 3. Logs prüfen
```bash
# Proxy Logs
docker-compose logs -f ptv-proxy
# Alle Services
docker-compose logs -f
```
## 🌐 Produktion - Auf Server deployen
### Schritt 1: Server vorbereiten
**SSH zum Server:**
```bash
ssh user@your-server.com
```
**Docker installieren (falls nicht vorhanden):**
```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
```
### Schritt 2: Code auf Server kopieren
**Option A: Git**
```bash
git clone https://github.com/your-repo/flutter_tank_web_app.git
cd flutter_tank_web_app
```
**Option B: SCP/Rsync**
```bash
# Von lokalem Rechner
rsync -avz --exclude 'build' --exclude '.dart_tool' \
. user@your-server.com:/opt/flutter-tank-app/
```
### Schritt 3: Proxy URL konfigurieren
Bearbeiten Sie `lib/config/environment.dart`:
```dart
class Environment {
// Produktions-URL des Proxy Servers
static const String localProxyUrl = 'http://your-server.com:3000';
static const bool useLocalProxy = true;
// ... rest bleibt gleich
}
```
### Schritt 4: Neu builden und deployen
```bash
cd /opt/flutter-tank-app
./deploy.sh
# Option 3: "Alles bauen und starten"
```
### Schritt 5: Firewall konfigurieren
```bash
# Port 8090 (Web App) und 3000 (Proxy) öffnen
sudo ufw allow 8090/tcp
sudo ufw allow 3000/tcp
sudo ufw enable
```
## 🔒 Sichere Konfiguration mit Nginx (Empfohlen)
Statt Port 3000 direkt zu exponieren, verwenden Sie Nginx als Reverse Proxy:
### 1. Nginx konfigurieren
```bash
sudo nano /etc/nginx/sites-available/tank.yourdomain.com
```
```nginx
server {
listen 80;
server_name tank.yourdomain.com;
# Flutter Web App
location / {
proxy_pass http://localhost:8090;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Proxy Server (API Endpoint)
location /api/geocode {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# CORS Headers werden vom Proxy Server gesetzt
proxy_hide_header Access-Control-Allow-Origin;
}
}
```
### 2. Site aktivieren
```bash
sudo ln -s /etc/nginx/sites-available/tanknew.joshihomeserver.ipv64.net /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
### 3. SSL Zertifikat (Let's Encrypt)
```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d tanknew.joshihomeserver.ipv64.net
```
### 4. Environment anpassen
```dart
static const String localProxyUrl = 'https://tanknew.joshihomeserver.ipv64.net/api/geocode';
```
### 5. Firewall anpassen
```bash
# Nur 80 und 443 öffnen (nicht 3000)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 3000/tcp # Proxy nur über Nginx erreichbar
```
## 🔧 Troubleshooting
### Proxy Server startet nicht
**Logs prüfen:**
```bash
docker-compose logs ptv-proxy
```
**Häufige Probleme:**
- Port 3000 bereits belegt: `sudo lsof -i :3000`
- Node.js nicht installiert: `node --version`
### CORS-Fehler trotz Proxy
**Prüfen:**
1. Ist der Proxy erreichbar? `curl http://localhost:3000/health`
2. Richtige URL in `environment.dart`?
3. Browser Cache leeren und App neu laden
### "Connection refused"
**Lösung:**
```bash
# Docker Container laufen?
docker-compose ps
# Proxy neu starten
docker-compose restart ptv-proxy
```
### PTV API gibt 401 zurück
**Problem:** Ungültiger API Key
**Lösung:** API Key in `environment.dart` überprüfen
### Im Container: "npm not found"
**Problem:** Lokales `node_modules` committet
**Lösung:**
```bash
# .dockerignore prüfen
cat .dockerignore | grep node_modules
# Sollte vorhanden sein
```
## 📊 Monitoring
### Service Status
```bash
# Docker
docker-compose ps
# System Resources
docker stats
# Health Check
curl http://localhost:3000/health
```
### Logs Live anschauen
```bash
# Proxy
docker-compose logs -f ptv-proxy
# Alle Services
docker-compose logs -f --tail=100
```
## 🔄 Updates deployen
```bash
# Code aktualisieren
git pull
# Container neu bauen und starten
docker-compose up -d --build
# Alte Images aufräumen
docker image prune -f
```
## ✅ Erfolgskriterien
Nach erfolgreichem Deployment sollten Sie:
- ✅ Proxy Health Check erfolgreich: `curl http://tanknew.joshihomeserver.ipv64.net:3000/health`
- ✅ Geocoding funktioniert in der App
- ✅ Browser Console zeigt: "🔄 Verwende lokalen Proxy..."
- ✅ Browser Console zeigt: "✅ Geocoding erfolgreich (Proxy): [Adresse]"
- ✅ Keine CORS-Fehler mehr
## 📝 Produktions-Checkliste
- [ ] Docker und Docker Compose installiert
- [ ] Code auf Server übertragen
- [ ] `localProxyUrl` in environment.dart angepasst
- [ ] Docker Containers laufen (`docker-compose ps`)
- [ ] Firewall konfiguriert
- [ ] Nginx Reverse Proxy eingerichtet (empfohlen)
- [ ] SSL Zertifikat installiert
- [ ] Health Checks erfolgreich
- [ ] Geocoding in App getestet

View File

@@ -1,363 +0,0 @@
# 🐳 Docker Deployment Anleitung
## Voraussetzungen
- Docker installiert (`docker --version`)
- Docker Compose installiert (`docker-compose --version`)
- Min. 2 GB freier RAM
- Min. 5 GB freier Speicherplatz
## 🚀 Schnellstart
### Option 1: Mit Deploy-Script (Empfohlen)
```bash
./deploy.sh
```
Folgen Sie den Anweisungen im interaktiven Menü.
### Option 2: Manuelle Commands
**Alles bauen und starten:**
```bash
docker-compose up -d --build
```
**Nur starten (bereits gebaut):**
```bash
docker-compose up -d
```
**Stoppen:**
```bash
docker-compose down
```
**Logs anzeigen:**
```bash
docker-compose logs -f
```
## 📦 Was wird deployed?
### 1. Flutter Web App Container
- **Image:** `flutter-tank-web:latest`
- **Port:** 8080 (Host) → 80 (Container)
- **URL:** `http://localhost:8080`
- **Technologie:** Flutter Web + Nginx
### 2. Proxy Server Container (Optional)
- **Image:** `ptv-proxy:latest`
- **Port:** 3000 (Host) → 3000 (Container)
- **URL:** `http://localhost:3000`
- **Technologie:** Node.js
## 🏗️ Build-Prozess
Der Build läuft in 2 Phasen:
**Phase 1: Flutter Build (Multi-Stage)**
1. Ubuntu base image
2. Flutter SDK installieren
3. Dependencies installieren (`flutter pub get`)
4. Web App bauen (`flutter build web`)
**Phase 2: Production (Nginx)**
1. Alpine Nginx image
2. Gebaute App kopieren
3. Nginx konfigurieren
4. Port 80 exponieren
**Geschätzte Build-Zeit:** 5-10 Minuten (beim ersten Mal)
## 🌐 Auf Server deployen
### 1. Server vorbereiten
**SSH zum Server:**
```bash
ssh user@your-server.com
```
**Docker installieren (falls nicht vorhanden):**
```bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER
```
**Docker Compose installieren:**
```bash
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
```
### 2. Code auf Server übertragen
**Option A: Git Clone**
```bash
git clone https://github.com/your-repo/flutter_tank_web_app.git
cd flutter_tank_web_app
```
**Option B: SCP/Rsync**
```bash
# Von lokalem Rechner aus
rsync -avz --exclude 'build' --exclude '.dart_tool' \
/home/digitalman/Development/flutter_tank_web_app/ \
user@your-server.com:/opt/flutter-tank-app/
```
### 3. Environment anpassen
Bearbeiten Sie `lib/config/environment.dart`:
```dart
static const bool useLocalProxy = false; // Für Produktion
```
### 4. Deployen
```bash
cd /opt/flutter-tank-app
./deploy.sh
# Wählen Sie Option 3: "Alles bauen und starten"
```
### 5. Mit Domain verbinden (Optional)
**Nginx Reverse Proxy konfigurieren:**
```nginx
# /etc/nginx/sites-available/tank.yourdomain.com
server {
listen 80;
server_name tank.yourdomain.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
**Aktivieren:**
```bash
sudo ln -s /etc/nginx/sites-available/tank.yourdomain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
**SSL mit Let's Encrypt:**
```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d tank.yourdomain.com
```
## 🔧 Konfiguration
### Ports ändern
In `docker-compose.yml`:
```yaml
ports:
- "8080:80" # Ändern Sie 8080 auf gewünschten Port
```
### Umgebungsvariablen
Erstellen Sie `.env` Datei:
```env
# App Settings
APP_PORT=8080
PROXY_PORT=3000
# Domain (für Traefik)
DOMAIN=tank.yourdomain.com
```
### Mit Traefik (Reverse Proxy)
Die `docker-compose.yml` enthält bereits Traefik Labels.
**Traefik setup:**
```yaml
# docker-compose.traefik.yml
version: '3.8'
services:
traefik:
image: traefik:v2.10
command:
- "--providers.docker=true"
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
- "--certificatesresolvers.letsencrypt.acme.email=your@email.com"
- "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
- "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./letsencrypt:/letsencrypt"
```
## 📊 Monitoring
### Container Status prüfen
```bash
docker-compose ps
```
### Logs anschauen
```bash
# Alle Services
docker-compose logs -f
# Nur Web App
docker-compose logs -f flutter-tank-web
# Nur Proxy
docker-compose logs -f ptv-proxy
```
### Resource Usage
```bash
docker stats
```
### Health Check
```bash
# Web App
curl http://localhost:8080/health
# Proxy
curl http://localhost:3000/health
```
## 🔄 Updates deployen
```bash
# Code aktualisieren
git pull
# Neu bauen und starten
docker-compose up -d --build
# Alte Images aufräumen
docker image prune -f
```
## 🛠️ Troubleshooting
### Container startet nicht
```bash
# Logs prüfen
docker-compose logs flutter-tank-web
# Container Status
docker-compose ps
# Neu starten
docker-compose restart flutter-tank-web
```
### Port bereits belegt
```bash
# Prozess auf Port finden
sudo lsof -i :8080
# Port in docker-compose.yml ändern
```
### Out of Memory
```bash
# Docker Memory Limit erhöhen
# In docker-compose.yml unter service:
deploy:
resources:
limits:
memory: 2G
```
### Build schlägt fehl
```bash
# Docker Cache leeren
docker builder prune -a
# Komplett neu bauen
docker-compose build --no-cache
```
## 📦 Backup & Restore
### Volumes sichern
```bash
# Data Volume backup
docker run --rm -v flutter-tank-data:/data -v $(pwd):/backup alpine tar czf /backup/data-backup.tar.gz -C /data .
```
### Image speichern
```bash
# Image exportieren
docker save flutter-tank-web:latest | gzip > flutter-tank-web.tar.gz
# Image importieren
docker load < flutter-tank-web.tar.gz
```
## 🔒 Sicherheit
### Best Practices
1. **Nicht als Root laufen** (bereits in Proxy-Dockerfile implementiert)
2. **Security Headers** (bereits in nginx.conf)
3. **Firewall konfigurieren:**
```bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
```
4. **Regular Updates:**
```bash
# Base images updaten
docker-compose pull
docker-compose up -d
```
## 🎯 Performance Optimierung
### Nginx Caching
Bereits in `nginx.conf` konfiguriert:
- Static assets: 1 Jahr Cache
- Gzip Kompression aktiv
### Docker Image Size
```bash
# Image Größe prüfen
docker images flutter-tank-web
# Multi-stage build reduziert Größe bereits deutlich
```
## 📝 Checkliste Produktion
- [ ] `useLocalProxy = false` in environment.dart
- [ ] Domain konfiguriert
- [ ] SSL Zertifikat installiert
- [ ] Firewall konfiguriert
- [ ] Backup-Strategie definiert
- [ ] Monitoring eingerichtet
- [ ] Logs rotieren konfiguriert
- [ ] Update-Prozess dokumentiert
## 🆘 Support
Bei Problemen:
1. Logs prüfen: `docker-compose logs`
2. Container Status: `docker-compose ps`
3. Health Checks: `curl http://localhost:8080/health`
4. Docker System: `docker system df`

View File

@@ -1,54 +0,0 @@
# Dockerfile für Flutter Web App
FROM ubuntu:22.04 AS build
# Avoid interactive prompts
ENV DEBIAN_FRONTEND=noninteractive
# Install dependencies
RUN apt-get update && apt-get install -y \
curl \
git \
unzip \
xz-utils \
zip \
libglu1-mesa \
wget \
&& rm -rf /var/lib/apt/lists/*
# Install Flutter
ENV FLUTTER_HOME=/usr/local/flutter
ENV PATH="${FLUTTER_HOME}/bin:${PATH}"
ENV TAR_OPTIONS=--no-same-owner
RUN git clone https://github.com/flutter/flutter.git ${FLUTTER_HOME} -b stable --depth 1 && \
flutter config --enable-web --no-analytics && \
flutter precache --web
# Set working directory
WORKDIR /app
# Copy app files
COPY pubspec.yaml pubspec.lock ./
# Run pub get (downloads web dependencies without needing gradle)
RUN flutter pub get
COPY . .
# Build web app (web-only artifacts; suppress wasm dry-run warnings)
RUN flutter build web --release --no-wasm-dry-run
# Production stage - Nginx
FROM nginx:alpine
# Copy built app to nginx
COPY --from=build /app/build/web /usr/share/nginx/html
# Copy custom nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf
# Expose port
EXPOSE 80
# Start nginx
CMD ["nginx", "-g", "daemon off;"]

View File

@@ -1,86 +0,0 @@
# 🚀 Quick Start - Lokaler Reverse Proxy
## Sofort loslegen
### Terminal 1: Proxy Server starten
```bash
./start-proxy.sh
```
Oder manuell:
```bash
cd proxy-server
node server.js
```
### Terminal 2: Flutter App starten
```bash
flutter run -d chrome
```
## ✅ Das wars!
Die App verwendet jetzt automatisch den lokalen Proxy auf `http://localhost:3000` für Geocoding.
## 🔧 Konfiguration
In [lib/config/environment.dart](lib/config/environment.dart):
```dart
static const bool useLocalProxy = true; // true = Proxy, false = Appwrite Function
```
## 📋 Checkliste
- ✅ Node.js installiert (`node --version`)
- ✅ Proxy läuft (`http://localhost:3000` im Browser)
-`useLocalProxy = true` in environment.dart
- ✅ Flutter App läuft
## 🎯 Vorteile Lokaler Proxy
**Kein CORS-Problem** - Server umgeht Browser-Beschränkungen
**Schnelles Testen** - Kein Cloud-Deployment nötig
**Einfaches Debugging** - Logs direkt im Terminal
**Kostenlos** - Läuft lokal, keine Cloud-Kosten
## 🌐 Für Produktion
Für den Live-Betrieb:
1. Setzen Sie `useLocalProxy = false`
2. Deployen Sie die Appwrite Function (siehe [DEPLOYMENT.md](DEPLOYMENT.md))
3. Tragen Sie die Function ID ein
## 📊 Vergleich
| Feature | Lokaler Proxy | Appwrite Function |
|---------|--------------|-------------------|
| Setup Zeit | < 1 Minute | ~10 Minuten |
| CORS | ✅ Gelöst | ✅ Gelöst |
| Kosten | Kostenlos | Serverless (minimal) |
| Verwendung | Nur Entwicklung | Entwicklung + Produktion |
| Debugging | Sehr einfach | Logs in Console |
| Offline | ❌ | ❌ |
## 🐛 Problemlösung
**Proxy startet nicht:**
```bash
# Port 3000 belegt?
lsof -i :3000
# Prozess beenden
kill -9 <PID>
```
**App findet Proxy nicht:**
- Proxy läuft? Prüfen Sie `http://localhost:3000` im Browser
- `useLocalProxy = true`? Prüfen Sie environment.dart
- Hot Restart in Flutter machen
**Immer noch CORS-Fehler:**
- Browser-Cache leeren
- DevTools → Network → "Disable cache"
- App neu builden: `flutter run -d chrome`

111
STATUS.md
View File

@@ -1,111 +0,0 @@
# ✅ System Status - Alles Repariert
## 📋 Überprüfungsergebnis
### ✅ Alle Fehler behoben!
**Probleme die behoben wurden:**
1. ❌ Syntax-Fehler in edit_controller.dart → ✅ Behoben
2. ❌ Fehlende Imports → ✅ Hinzugefügt
3. ❌ Unvollständige Methoden → ✅ Implementiert
4. ❌ Duplicate Code → ✅ Entfernt
## 🎯 Aktueller Status
### 1. Edit Controller ✅
- [x] Keine Compile-Fehler
- [x] Verwendet `appwriteService.geocodeLocation()`
- [x] Benutzer-Feedback mit Snackbars
- [x] Saubere Imports
### 2. Appwrite Service ✅
- [x] `geocodeLocation()` Methode implementiert
- [x] `_geocodeViaLocalProxy()` für lokalen Proxy
- [x] Fallback auf Koordinaten bei Fehlern
- [x] http package importiert
### 3. Environment Config ✅
```dart
static const bool useLocalProxy = true; // ✅ Aktiv
static const String localProxyUrl = 'http://localhost:3000';
```
### 4. Proxy Server ✅
- [x] server.js existiert
- [x] package.json existiert
- [x] README.md vorhanden
- [x] Node.js funktioniert
- [x] Start-Script ausführbar
## 🚀 So starten Sie die App
### Terminal 1: Proxy Server
```bash
cd /home/digitalman/Development/flutter_tank_web_app
./start-proxy.sh
```
### Terminal 2: Flutter App
```bash
cd /home/digitalman/Development/flutter_tank_web_app
flutter run -d chrome
```
## 📊 Funktionsweise
```
User erstellt Tankeintrag
Geolocation fragt GPS ab
EditController ruft appwriteService.geocodeLocation() auf
AppwriteService prüft useLocalProxy Flag
├─ true → Lokaler Proxy (localhost:3000) → PTV API ✅
└─ false → Fallback auf Koordinaten
Adresse oder Koordinaten werden gespeichert
```
## ✅ Erfolgskriterien
Wenn alles funktioniert, sehen Sie:
- ✅ Proxy-Server läuft auf Port 3000
- ✅ "🔄 Verwende lokalen Proxy" in Logs
- ✅ "✅ Geocoding erfolgreich (Proxy): [Adresse]"
- ✅ Grüne Snackbar mit Adresse in der App
- ✅ Keine CORS-Fehler in Browser Console
## 🐛 Wenn etwas nicht funktioniert
**Proxy nicht erreichbar:**
```bash
# Prüfen ob läuft
curl http://localhost:3000
# Neu starten
./start-proxy.sh
```
**Flutter App zeigt Koordinaten statt Adresse:**
1. Prüfen: Proxy läuft?
2. Prüfen: `useLocalProxy = true`?
3. Browser Console für Fehler prüfen
4. Hot Restart: `r` im Flutter Terminal
**Port 3000 belegt:**
```bash
# Prozess finden und beenden
lsof -i :3000
kill -9 <PID>
```
## 📝 Nächste Schritte
1. **Testen**: Neuen Tankeintrag erstellen
2. **Verifizieren**: Adresse wird korrekt angezeigt
3. **Optional**: Für Produktion auf `useLocalProxy = false` setzen
## 🎉 Status: BEREIT FÜR NUTZUNG!
Alle Systeme sind operationsbereit. Der lokale Reverse-Proxy umgeht das CORS-Problem erfolgreich.

View File

@@ -1,85 +0,0 @@
#!/bin/bash
# Farben
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'
echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
echo -e "${BLUE} Flutter Tank App - Docker Deployment${NC}"
echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
echo ""
# Prüfen ob Docker installiert ist
if ! command -v docker &> /dev/null; then
echo -e "${RED}❌ Docker ist nicht installiert!${NC}"
echo -e "${YELLOW}Installieren Sie Docker: https://docs.docker.com/get-docker/${NC}"
exit 1
fi
if ! command -v docker-compose &> /dev/null; then
echo -e "${RED}❌ Docker Compose ist nicht installiert!${NC}"
echo -e "${YELLOW}Installieren Sie Docker Compose: https://docs.docker.com/compose/install/${NC}"
exit 1
fi
echo -e "${GREEN}✅ Docker und Docker Compose gefunden${NC}"
echo ""
# Build Option
echo -e "${YELLOW}Wählen Sie eine Option:${NC}"
echo "1) Nur Flutter Web App bauen"
echo "2) Flutter Web App + Proxy Server bauen"
echo "3) Alles bauen und starten"
echo "4) Nur starten (ohne neu zu bauen)"
echo "5) Stoppen"
echo "6) Logs anzeigen"
read -p "Option (1-6): " option
case $option in
1)
echo -e "${BLUE}🔨 Baue Flutter Web App...${NC}"
docker build -t flutter-tank-web:latest .
echo -e "${GREEN}✅ Build abgeschlossen!${NC}"
echo -e "${YELLOW}Zum Starten: docker run -p 8080:80 flutter-tank-web:latest${NC}"
;;
2)
echo -e "${BLUE}🔨 Baue alle Images...${NC}"
docker-compose build
echo -e "${GREEN}✅ Build abgeschlossen!${NC}"
;;
3)
echo -e "${BLUE}🔨 Baue und starte alle Services...${NC}"
docker-compose up -d --build
echo ""
echo -e "${GREEN}✅ Services gestartet!${NC}"
echo ""
echo -e "${YELLOW}📡 Verfügbare Endpoints:${NC}"
echo -e " Flutter Web App: ${GREEN}http://localhost:8090${NC}"
echo -e " Proxy Server: ${GREEN}http://localhost:3000${NC}"
echo ""
echo -e "${YELLOW}📊 Status prüfen:${NC}"
docker-compose ps
;;
4)
echo -e "${BLUE}🚀 Starte Services...${NC}"
docker-compose up -d
echo -e "${GREEN}✅ Services gestartet!${NC}"
docker-compose ps
;;
5)
echo -e "${BLUE}🛑 Stoppe Services...${NC}"
docker-compose down
echo -e "${GREEN}✅ Services gestoppt!${NC}"
;;
6)
echo -e "${BLUE}📋 Zeige Logs...${NC}"
docker-compose logs -f
;;
*)
echo -e "${RED}❌ Ungültige Option${NC}"
exit 1
;;
esac

View File

@@ -1,39 +0,0 @@
services:
# Flutter Web App
flutter-tank-web:
build:
context: .
dockerfile: Dockerfile
container_name: flutter-tank-web
restart: unless-stopped
ports:
- "8090:80"
networks:
- app-network
environment:
- TZ=Europe/Vienna
labels:
- "traefik.enable=true"
- "traefik.http.routers.flutter-tank.rule=Host(`tanknew.joshihomeserver.ipv64.net`)"
- "traefik.http.routers.flutter-tank.entrypoints=websecure"
- "traefik.http.routers.flutter-tank.tls.certresolver=letsencrypt"
- "traefik.http.services.flutter-tank.loadbalancer.server.port=80"
# Optional: Reverse Proxy für PTV API (Production)
ptv-proxy:
build:
context: ./proxy-server
dockerfile: Dockerfile
container_name: ptv-proxy
restart: unless-stopped
ports:
- "3000:3000"
networks:
- app-network
environment:
- NODE_ENV=production
- PORT=3000
networks:
app-network:
driver: bridge

View File

@@ -5,17 +5,6 @@ class Environment {
static const String appwriteProjectName = 'Flutter Projects'; static const String appwriteProjectName = 'Flutter Projects';
static const String appwriteRealtimeCollectionId = '68a22f520035a95d6666'; static const String appwriteRealtimeCollectionId = '68a22f520035a95d6666';
static const String appwriteDatabaseId = '68a22ef90021b90f0f43'; static const String appwriteDatabaseId = '68a22ef90021b90f0f43';
static const String ptvApiKey =
'NTYxMDQ3NTY2OWI3NDI5ZGIzZWIxOWNiNTNhMDEwODY6YTQ4MTJhYzYtYmYzOC00ZmE4LTk4YzYtZDBjNzYyZTAyNjBk';
static const String locationIQKey = 'pk.dea65023dc6fed25c96902bb97fb231d'; static const String locationIQKey = 'pk.dea65023dc6fed25c96902bb97fb231d';
static const double lat=47.93875449671056; static const String locationIQBaseUrl = 'https://eu1.locationiq.com/v1/reverse?key=$locationIQKey&';
static const double lon=13.762706553431048;
//https://eu1.locationiq.com/v1/reverse?key=pk.dea65023dc6fed25c96902bb97fb231d&lat=47.93875449671056&lon=13.762706553431048&format=json
static const String locationIQBaseUrl =
'https://eu1.locationiq.com/v1/reverse?key=$locationIQKey&'; //47.93875449671056, 13.762706553431048
static const String ptvApiVersion = '3';
// Lokaler Reverse Proxy für Entwicklung (CORS-Workaround)
static const String localProxyUrl = 'http://localhost:3000';
static const bool useLocalProxy =
true; // true = lokaler Proxy, false = Appwrite Function
} }

View File

@@ -1,7 +1,7 @@
import 'package:flutter_tank_web_app/services/appwrite_service.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../models/tank_model.dart'; import '../models/tank_model.dart';
import '../pages/edit_view.dart'; import '../pages/edit_view.dart';
import '../services/appwrite_service.dart';
class DetailController extends GetxController { class DetailController extends GetxController {
late TankModel tank; late TankModel tank;

View File

@@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:geolocator/geolocator.dart'; import 'package:geolocator/geolocator.dart';
import '../models/locationiq_model.dart'; import '../models/locationiq_model.dart';
import '../models/tank_model.dart'; import '../models/tank_model.dart';
import '../services/appwrite_service.dart'; import '../services/appwrite_service.dart';
@@ -62,78 +61,6 @@ class EditController extends GetxController {
'${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}'; '${now.year}-${now.month.toString().padLeft(2, '0')}-${now.day.toString().padLeft(2, '0')}';
} }
// Future<void> _requestLocation() async {
// bool serviceEnabled;
// LocationPermission permission;
// try {
// isLoadingLocation.value = true;
// // 1. Prüfen, ob Standortdienste aktiviert sind
// serviceEnabled = await Geolocator.isLocationServiceEnabled();
// if (!serviceEnabled) {
// return Future.error('Standortdienste sind deaktiviert.');
// }
// // 2. Berechtigungen prüfen
// permission = await Geolocator.checkPermission();
// if (permission == LocationPermission.denied) {
// permission = await Geolocator.requestPermission();
// if (permission == LocationPermission.denied) {
// return Future.error('Berechtigung verweigert.');
// }
// }
// // 3. Position abrufen
// Position position = await Geolocator.getCurrentPosition(
// locationSettings: const LocationSettings(
// accuracy: LocationAccuracy.high,
// ),
// );
// // 4. Standort über Backend-Proxy abrufen
// var lat = position.latitude;
// var lon = position.longitude;
// print('📍 Verwende Backend-Proxy für Geocoding...');
// String location = await appwriteService.geocodeLocation(lat, lon);
// locationController.text = location;
// // Info anzeigen basierend auf Ergebnis
// if (location.startsWith('Lat:')) {
// Get.snackbar(
// 'Hinweis',
// 'Adresse konnte nicht abgerufen werden. Koordinaten gespeichert.',
// snackPosition: SnackPosition.BOTTOM,
// backgroundColor: Colors.orange[100],
// colorText: Colors.orange[900],
// duration: const Duration(seconds: 3),
// );
// } else {
// Get.snackbar(
// 'Erfolg',
// 'Standort: $location',
// snackPosition: SnackPosition.BOTTOM,
// backgroundColor: Colors.green[100],
// colorText: Colors.green[900],
// duration: const Duration(seconds: 2),
// );
// }
// } catch (e) {
// Get.snackbar(
// "Fehler",
// "Standort konnte nicht abgerufen werden: $e",
// snackPosition: SnackPosition.BOTTOM,
// backgroundColor: Colors.red[100],
// colorText: Colors.red[900],
// );
// print("Fehler beim Abrufen des Standorts: $e");
// locationController.text = '';
// } finally {
// isLoadingLocation.value = false;
// }
// }
Future<void> _requestLocationIQ() async { Future<void> _requestLocationIQ() async {
bool serviceEnabled; bool serviceEnabled;
LocationPermission permission; LocationPermission permission;

View File

@@ -1,5 +1,5 @@
import 'package:flutter_tank_web_app/models/tank_model.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import '../models/tank_model.dart';
class GraphController extends GetxController { class GraphController extends GetxController {
final listTankModel = <TankModel>[].obs; final listTankModel = <TankModel>[].obs;

View File

@@ -1,7 +1,6 @@
//import 'dart:convert';
import 'package:appwrite/models.dart'; import 'package:appwrite/models.dart';
import 'package:appwrite/appwrite.dart'; import 'package:appwrite/appwrite.dart';
//import 'package:http/http.dart' as http;
import '../config/environment.dart'; import '../config/environment.dart';
class AppwriteService { class AppwriteService {
@@ -167,47 +166,4 @@ class AppwriteService {
return false; return false;
} }
} }
// // Geocode coordinates using local proxy or Appwrite Function
// Future<String> geocodeLocation(double lat, double lon) async {
// // Wenn lokaler Proxy aktiviert ist, diesen verwenden
// if (Environment.useLocalProxy) {
// return _geocodeViaLocalProxy(lat, lon);
// }
// // Fallback: Koordinaten zurückgeben
// return 'Lat: ${lat.toStringAsFixed(6)}, Lon: ${lon.toStringAsFixed(6)}';
// }
// // Geocoding über lokalen Reverse Proxy
// Future<String> _geocodeViaLocalProxy(double lat, double lon) async {
// try {
// final proxyUrl = '${Environment.localProxyUrl}/?lat=$lat&lon=$lon&apiKey=${Environment.ptvApiKey}';
// print('🔄 Verwende lokalen Proxy: ${Environment.localProxyUrl}');
// final response = await http.get(Uri.parse(proxyUrl));
// if (response.statusCode == 200) {
// final data = jsonDecode(response.body);
// if (data['success'] == true) {
// final location = data['location'] as String;
// print('✅ Geocoding erfolgreich (Proxy): $location');
// return location;
// } else {
// print('❌ Geocoding fehlgeschlagen (Proxy): ${data['error']}');
// return data['fallbackLocation'] ??
// 'Lat: ${lat.toStringAsFixed(6)}, Lon: ${lon.toStringAsFixed(6)}';
// }
// } else {
// print('⚠️ Proxy Response Status: ${response.statusCode}');
// return 'Lat: ${lat.toStringAsFixed(6)}, Lon: ${lon.toStringAsFixed(6)}';
// }
// } catch (e) {
// print('❌ Lokaler Proxy nicht erreichbar: $e');
// print('💡 Tipp: Starten Sie den Proxy mit: cd proxy-server && node server.js');
// return 'Lat: ${lat.toStringAsFixed(6)}, Lon: ${lon.toStringAsFixed(6)}';
// }
// }
} }

View File

@@ -1,21 +1,16 @@
// ignore_for_file: public_member_api_docs, sort_constructors_first // ignore_for_file: public_member_api_docs, sort_constructors_first
import 'package:http/http.dart' as http;
import 'dart:convert'; import 'dart:convert';
import '../config/environment.dart'; import '../config/environment.dart';
import '../models/locationiq_model.dart'; import '../models/locationiq_model.dart';
import 'package:http/http.dart' as http;
class LocationIQService { class LocationIQService {
static final String baseUrl = Environment.locationIQBaseUrl; static final String baseUrl = Environment.locationIQBaseUrl;
late LocationIQ locationIQ; late LocationIQ locationIQ;
Future<void> fetchLocationIQ(double lat, double lon) async { Future<void> fetchLocationIQ(double lat, double lon) async {
// Hier würde die eigentliche API-Anfrage an LocationIQ erfolgen
// Zum Beispiel mit http.get() und der URL aus Environment.locationIQUrl
// Die Antwort würde dann in das LocationIQ-Modell umgewandelt werden
// https://eu1.locationiq.com/v1/reverse?key=$locationIQKey&lat=47.93875449671056&lon=13.762706553431048&format=json // https://eu1.locationiq.com/v1/reverse?key=$locationIQKey&lat=47.93875449671056&lon=13.762706553431048&format=json
// locationIQ = LocationIQ.fromJson(responseData);
// Simulierte Antwort (für Testzwecke) // Simulierte Antwort (für Testzwecke)
locationIQ = LocationIQ( locationIQ = LocationIQ(
placeId: '12345', placeId: '12345',

View File

@@ -1,35 +0,0 @@
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
# Compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml+rss application/json application/javascript;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Flutter web routing
location / {
try_files $uri $uri/ /index.html;
}
# Health check endpoint
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
}

View File

@@ -1,26 +0,0 @@
# Dockerfile für Node.js Proxy Server
FROM node:18-alpine
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies (omit dev; no lockfile required)
RUN npm install --omit=dev
# Copy application code
COPY server.js ./
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
# Run as non-root user
USER node
# Start server
CMD ["node", "server.js"]

View File

@@ -1,115 +0,0 @@
# Lokaler Reverse Proxy Server
Dieser Proxy-Server umgeht CORS-Probleme während der Entwicklung, indem er Anfragen an die PTV Geocoding API weiterleitet.
## 🚀 Installation & Start
### 1. Dependencies installieren (nur Node.js Standard-Module, keine Installation nötig)
Der Server verwendet nur Node.js Built-in Module (`http`, `https`, `url`), daher ist kein `npm install` erforderlich.
### 2. Server starten
```bash
cd proxy-server
node server.js
```
Oder mit npm:
```bash
npm start
```
Der Server läuft dann auf `http://localhost:3000`
## 📡 API Verwendung
**Endpoint:**
```
GET http://localhost:3000/?lat={latitude}&lon={longitude}&apiKey={ptv_api_key}
```
**Beispiel:**
```
http://localhost:3000/?lat=47.9385165&lon=13.762887&apiKey=YOUR_API_KEY
```
**Response (Erfolg):**
```json
{
"success": true,
"location": "Hauptstraße 123, 5020 Salzburg",
"coordinates": {
"lat": 47.9385165,
"lon": 13.762887
},
"rawData": { ... }
}
```
**Response (Fehler):**
```json
{
"success": false,
"error": "Error message",
"fallbackLocation": "Lat: 47.938517, Lon: 13.762887"
}
```
## 🔧 In Flutter App verwenden
Der Flutter Code wurde bereits angepasst, um den lokalen Proxy zu verwenden.
1. Starten Sie den Proxy-Server:
```bash
cd proxy-server
node server.js
```
2. Starten Sie die Flutter App:
```bash
flutter run -d chrome
```
3. Die App verwendet automatisch `http://localhost:3000` wenn verfügbar.
## ⚠️ Wichtige Hinweise
- **Nur für Entwicklung!** Dieser Server ist nicht für Produktionsumgebungen geeignet.
- Der Server muss laufen, während Sie die Flutter App im Development-Modus verwenden.
- Für Produktion: Verwenden Sie die Appwrite Function (siehe [DEPLOYMENT.md](../DEPLOYMENT.md))
## 🛑 Server stoppen
Drücken Sie `Strg+C` im Terminal, wo der Server läuft.
## 🐛 Troubleshooting
### Port bereits belegt
**Problem:** `Error: listen EADDRINUSE: address already in use :::3000`
**Lösung:**
1. Anderen Port verwenden: Ändern Sie `PORT = 3000` in `server.js`
2. Oder den bestehenden Prozess beenden:
```bash
# Port finden
lsof -i :3000
# Prozess beenden
kill -9 PID
```
### Flutter App findet Proxy nicht
**Problem:** "Failed to fetch" oder Connection Error
**Lösung:**
1. Prüfen Sie ob der Proxy läuft (`http://localhost:3000` im Browser öffnen)
2. Stellen Sie sicher, dass Port 3000 korrekt ist
3. Prüfen Sie die Browser Console für Fehler
### CORS immer noch ein Problem
**Problem:** CORS-Fehler trotz Proxy
**Lösung:**
1. Stellen Sie sicher, dass die Flutter App `localhost:3000` verwendet
2. Browser-Cache leeren
3. Entwickler-Tools → Network → "Disable cache" aktivieren

View File

@@ -1,21 +0,0 @@
{
"name": "ptv-proxy-server",
"version": "1.0.0",
"description": "Local reverse proxy for PTV Geocoding API to bypass CORS",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "node server.js"
},
"keywords": [
"proxy",
"cors",
"ptv",
"geocoding"
],
"author": "",
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
}

View File

@@ -1,174 +0,0 @@
/**
* Lokaler Reverse Proxy für PTV Geocoding API
* Umgeht CORS-Probleme bei der Entwicklung
*/
const http = require('http');
const https = require('https');
const url = require('url');
const PORT = 3000;
const PTV_API_BASE = 'https://api.myptv.com';
// CORS Headers für alle Responses
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type, Authorization',
'Content-Type': 'application/json',
};
const server = http.createServer((req, res) => {
console.log(`📨 ${req.method} ${req.url}`);
// Health check endpoint
if (req.url === '/health') {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('healthy');
return;
}
// Handle preflight requests
if (req.method === 'OPTIONS') {
res.writeHead(200, corsHeaders);
res.end();
return;
}
// Nur GET Requests erlauben
if (req.method !== 'GET') {
res.writeHead(405, corsHeaders);
res.end(JSON.stringify({ error: 'Method not allowed' }));
return;
}
// Parse URL
const parsedUrl = url.parse(req.url, true);
const { lat, lon, apiKey } = parsedUrl.query;
// Validierung
if (!lat || !lon || !apiKey) {
res.writeHead(400, corsHeaders);
res.end(JSON.stringify({
error: 'Missing parameters: lat, lon, apiKey are required',
}));
return;
}
// PTV API URL erstellen
const ptvUrl = `${PTV_API_BASE}/geocoding/v1/locations/by-position/${lat}/${lon}?language=de&apiKey=${apiKey}`;
console.log(`🔄 Weiterleitung an: ${ptvUrl.replace(apiKey, 'API_KEY_HIDDEN')}`);
// Request an PTV API
https.get(ptvUrl, (ptvRes) => {
let data = '';
ptvRes.on('data', (chunk) => {
data += chunk;
});
ptvRes.on('end', () => {
try {
const jsonData = JSON.parse(data);
// Erfolgreiche Response
if (ptvRes.statusCode === 200) {
console.log('✅ PTV API Response erfolgreich');
// Adresse extrahieren
if (jsonData.locations && jsonData.locations.length > 0) {
const location = jsonData.locations[0];
if (location.address) {
const address = location.address;
const street = address.street || '';
const houseNumber = address.houseNumber || '';
const postalCode = address.postalCode || '';
const city = address.city || '';
const formattedAddress = `${street} ${houseNumber}, ${postalCode} ${city}`.trim();
const response = {
success: true,
location: formattedAddress,
coordinates: {
lat: parseFloat(lat),
lon: parseFloat(lon),
},
rawData: location,
};
console.log(`📍 Adresse: ${formattedAddress}`);
res.writeHead(200, corsHeaders);
res.end(JSON.stringify(response));
return;
}
}
// Fallback auf Koordinaten
const response = {
success: true,
location: `Lat: ${parseFloat(lat).toFixed(6)}, Lon: ${parseFloat(lon).toFixed(6)}`,
coordinates: {
lat: parseFloat(lat),
lon: parseFloat(lon),
},
};
res.writeHead(200, corsHeaders);
res.end(JSON.stringify(response));
} else {
// Fehler von PTV API
console.log(`❌ PTV API Fehler: ${ptvRes.statusCode}`);
res.writeHead(ptvRes.statusCode, corsHeaders);
res.end(JSON.stringify({
success: false,
error: `PTV API Error: ${ptvRes.statusCode}`,
fallbackLocation: `Lat: ${parseFloat(lat).toFixed(6)}, Lon: ${parseFloat(lon).toFixed(6)}`,
}));
}
} catch (error) {
console.error('❌ JSON Parse Fehler:', error.message);
res.writeHead(500, corsHeaders);
res.end(JSON.stringify({
success: false,
error: 'Failed to parse PTV API response',
fallbackLocation: `Lat: ${parseFloat(lat).toFixed(6)}, Lon: ${parseFloat(lon).toFixed(6)}`,
}));
}
});
}).on('error', (error) => {
console.error('❌ Request Fehler:', error.message);
res.writeHead(500, corsHeaders);
res.end(JSON.stringify({
success: false,
error: error.message,
fallbackLocation: `Lat: ${parseFloat(lat).toFixed(6)}, Lon: ${parseFloat(lon).toFixed(6)}`,
}));
});
});
server.listen(PORT, () => {
console.log('═══════════════════════════════════════════════════════');
console.log('🚀 Lokaler Reverse Proxy Server gestartet!');
console.log(`📡 Läuft auf: http://localhost:${PORT}`);
console.log('');
console.log('📌 Verwendung:');
console.log(` http://localhost:${PORT}/?lat=47.9385&lon=13.7629&apiKey=YOUR_KEY`);
console.log('');
console.log('⚠️ Hinweis: Nur für Entwicklung verwenden!');
console.log(' Für Produktion: Appwrite Function deployen');
console.log('═══════════════════════════════════════════════════════');
console.log('');
console.log('💡 Zum Beenden: Strg+C drücken');
console.log('');
});
// Graceful shutdown
process.on('SIGINT', () => {
console.log('\n\n👋 Server wird beendet...');
server.close(() => {
console.log('✅ Server erfolgreich gestoppt');
process.exit(0);
});
});

View File

@@ -1,36 +0,0 @@
#!/bin/bash
# Farben für Output
GREEN='\033[0;32m'
BLUE='\033[0;34m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
echo -e "${BLUE} Flutter Tank App - Lokaler Proxy Starter${NC}"
echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
echo ""
# Proxy Server starten
echo -e "${YELLOW}🚀 Starte lokalen Reverse Proxy Server...${NC}"
cd "$(dirname "$0")/proxy-server"
if [ ! -f "server.js" ]; then
echo -e "${YELLOW}❌ server.js nicht gefunden!${NC}"
echo -e "${YELLOW}Bitte führen Sie dieses Script aus dem Projekt-Root-Verzeichnis aus.${NC}"
exit 1
fi
echo -e "${GREEN}✅ Proxy Server wird gestartet auf http://localhost:3000${NC}"
echo ""
echo -e "${BLUE}📌 Nächste Schritte:${NC}"
echo -e " 1. In neuem Terminal: ${GREEN}flutter run -d chrome${NC}"
echo -e " 2. Neuen Tankeintrag erstellen"
echo -e " 3. Standort wird automatisch über Proxy abgerufen"
echo ""
echo -e "${YELLOW}⚠️ Zum Beenden: Strg+C drücken${NC}"
echo ""
echo -e "${BLUE}═══════════════════════════════════════════════════════${NC}"
echo ""
node server.js

View File

@@ -37,6 +37,6 @@ _flutter.buildConfig = {"engineRevision":"3452d735bd38224ef2db85ca763d862d6326b1
_flutter.loader.load({ _flutter.loader.load({
serviceWorkerSettings: { serviceWorkerSettings: {
serviceWorkerVersion: "138245282" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */ serviceWorkerVersion: "38490492" /* Flutter's service worker is deprecated and will be removed in a future Flutter release. */
} }
}); });