Compare commits
5 Commits
d2be533ca3
...
falukant-3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
245ada296b | ||
|
|
750fa7b99b | ||
|
|
791100f5a5 | ||
|
|
c471bba50b | ||
|
|
1d3aef3778 |
@@ -1,9 +0,0 @@
|
||||
---
|
||||
description: C++-Worker unter src/ sind obsolet — nicht erweitern oder als Quelle für Spiellogik nutzen
|
||||
alwaysApply: true
|
||||
---
|
||||
|
||||
# Legacy C++ (`src/`)
|
||||
|
||||
- Verzeichnis **`src/`** (C++-Worker, WebSocket-Server): **obsolet**. Keine neuen Features, keine fachlichen Fixes dort planen oder umsetzen, sofern der Nutzer nicht ausdrücklich etwas anderes verlangt.
|
||||
- Falukant-Hintergrundlogik: **Backend** (`backend/`), **externer Daemon**, **Frontend** — siehe `docs/LEGACY_CPP_WORKERS.md`.
|
||||
@@ -1,148 +0,0 @@
|
||||
name: Deploy to production
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Detect vocab course changes
|
||||
id: vocab_course_changes
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
BASE="${{ gitea.event.before }}"
|
||||
HEAD="${{ gitea.sha }}"
|
||||
|
||||
if [ -z "$BASE" ] || [[ "$BASE" =~ ^0+$ ]] || ! git cat-file -e "$BASE^{commit}" 2>/dev/null; then
|
||||
BASE="HEAD~1"
|
||||
fi
|
||||
|
||||
git diff --name-only "$BASE" "$HEAD" > changed-files.txt
|
||||
cat changed-files.txt
|
||||
COMMIT_MESSAGE="$(git log -1 --pretty=%B "$HEAD" || true)"
|
||||
COURSE_SCRIPT_PATTERN='^backend/scripts/.*(bisaya|course|didactics|vocab)'
|
||||
|
||||
if echo "$COMMIT_MESSAGE" | grep -qi '\[force-deploy\]'; then
|
||||
echo "force_deploy=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "force_deploy=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
if grep -E '^(backend/scripts/.*(bisaya|course|didactics|vocab)|backend/sql/.*vocab|backend/(migrations-active|migrations-archive)/.*vocab|docs/.*(COURSE|VOCAB|BISAYA|GERMAN_FOR_BISAYA))' changed-files.txt; then
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
if grep -E "$COURSE_SCRIPT_PATTERN" changed-files.txt >/dev/null; then
|
||||
echo "course_scripts_changed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "course_scripts_changed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
if grep -E '^frontend/' changed-files.txt >/dev/null; then
|
||||
echo "frontend_changed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "frontend_changed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# Kurs-/Didaktik-Scripts werden vor dem Sync separat uebertragen.
|
||||
# Fuer sie sind npm ci, Migrationen und ein Backend-Restart nicht noetig.
|
||||
if grep -E '^backend/' changed-files.txt \
|
||||
| grep -Ev "$COURSE_SCRIPT_PATTERN" >/dev/null; then
|
||||
echo "backend_app_changed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "backend_app_changed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
# App-Code-Änderungen, die einen echten Deploy benötigen
|
||||
if grep -E '^(frontend/|backend/)' changed-files.txt \
|
||||
| grep -Ev "$COURSE_SCRIPT_PATTERN" >/dev/null; then
|
||||
echo "app_changed=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "app_changed=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Prepare SSH
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
printf "%s" "${{ secrets.PROD_SSH_KEY }}" > ~/.ssh/id_ed25519
|
||||
chmod 600 ~/.ssh/id_ed25519
|
||||
ssh-keyscan -p "${{ secrets.PROD_PORT }}" "${{ secrets.PROD_HOST }}" >> ~/.ssh/known_hosts
|
||||
|
||||
- name: Test SSH connection
|
||||
run: |
|
||||
ssh -i ~/.ssh/id_ed25519 \
|
||||
-o StrictHostKeyChecking=no \
|
||||
-o BatchMode=yes \
|
||||
-p "${{ secrets.PROD_PORT }}" \
|
||||
"${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \
|
||||
"echo SSH OK"
|
||||
|
||||
- name: Deploy vocab course scripts without app rebuild
|
||||
if: steps.vocab_course_changes.outputs.course_scripts_changed == 'true' && steps.vocab_course_changes.outputs.backend_app_changed != 'true' && steps.vocab_course_changes.outputs.force_deploy != 'true'
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tar -czf - backend/scripts \
|
||||
| ssh -i ~/.ssh/id_ed25519 \
|
||||
-p "${{ secrets.PROD_PORT }}" \
|
||||
"${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \
|
||||
"sudo -n -u yourpart tar -xzf - -C /opt/yourpart"
|
||||
|
||||
- name: Run deployment script
|
||||
if: steps.vocab_course_changes.outputs.app_changed == 'true' || steps.vocab_course_changes.outputs.force_deploy == 'true'
|
||||
run: |
|
||||
DEPLOY_FLAGS=""
|
||||
if [ "${{ steps.vocab_course_changes.outputs.force_deploy }}" = "true" ]; then
|
||||
DEPLOY_FLAGS=""
|
||||
elif [ "${{ steps.vocab_course_changes.outputs.backend_app_changed }}" = "true" ] && [ "${{ steps.vocab_course_changes.outputs.frontend_changed }}" != "true" ]; then
|
||||
DEPLOY_FLAGS="--skip-frontend"
|
||||
elif [ "${{ steps.vocab_course_changes.outputs.frontend_changed }}" = "true" ] && [ "${{ steps.vocab_course_changes.outputs.backend_app_changed }}" != "true" ]; then
|
||||
DEPLOY_FLAGS="--skip-backend"
|
||||
fi
|
||||
|
||||
DEPLOY_TARGET="${{ secrets.PROD_DEPLOY_TARGET }}"
|
||||
if [ -z "$DEPLOY_TARGET" ]; then
|
||||
DEPLOY_TARGET="/opt/yourpart-green"
|
||||
fi
|
||||
|
||||
echo "Deploy-Flags: ${DEPLOY_FLAGS:-<none>}"
|
||||
echo "Deploy-Target: $DEPLOY_TARGET"
|
||||
|
||||
ssh -i ~/.ssh/id_ed25519 \
|
||||
-p "${{ secrets.PROD_PORT }}" \
|
||||
"${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \
|
||||
"/home/tsschulz/deploy-yourpart-bluegreen.sh ${DEPLOY_TARGET} ${DEPLOY_FLAGS}"
|
||||
|
||||
- name: Skip full deployment (no app changes)
|
||||
if: steps.vocab_course_changes.outputs.app_changed != 'true' && steps.vocab_course_changes.outputs.force_deploy != 'true'
|
||||
run: |
|
||||
echo "Kein Full-Deploy: Es wurden keine Frontend/Backend-App-Dateien geändert."
|
||||
|
||||
- name: Sync vocab course content
|
||||
if: steps.vocab_course_changes.outputs.changed == 'true' || steps.vocab_course_changes.outputs.force_deploy == 'true'
|
||||
run: |
|
||||
# Decide whether to actually run the phase3 update on the server.
|
||||
# By default we run the deploy script in --dry-run mode. To enable the
|
||||
# actual run set the secret PHASE3_UPDATE=1 in the repo settings.
|
||||
RUN_FLAG="--dry-run"
|
||||
if [ "${{ secrets.PHASE3_UPDATE }}" = "1" ]; then
|
||||
RUN_FLAG=""
|
||||
fi
|
||||
|
||||
ssh -i ~/.ssh/id_ed25519 \
|
||||
-p "${{ secrets.PROD_PORT }}" \
|
||||
"${{ secrets.PROD_USER }}@${{ secrets.PROD_HOST }}" \
|
||||
"cd /opt/yourpart && npm --prefix backend run sync:vocab-courses && if [ -x backend/scripts/deploy-phase3-update.sh ]; then bash backend/scripts/deploy-phase3-update.sh $RUN_FLAG; else echo 'deploy-phase3-update.sh not found or not executable'; fi"
|
||||
29
.github/workflows/android-security.yml
vendored
@@ -1,29 +0,0 @@
|
||||
name: Android Security
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'android/native/**'
|
||||
- '.github/workflows/android-security.yml'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'android/native/**'
|
||||
- '.github/workflows/android-security.yml'
|
||||
|
||||
jobs:
|
||||
scan:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '17'
|
||||
- name: Android lint
|
||||
working-directory: android/native
|
||||
run: ./gradlew :app:lintProductionRelease
|
||||
- name: Scan dependencies with OSV
|
||||
uses: google/osv-scanner-action/osv-scanner-action@v2.0.2
|
||||
with:
|
||||
scan-args: |-
|
||||
--recursive android/native
|
||||
50
.github/workflows/android-tests.yml
vendored
@@ -1,50 +0,0 @@
|
||||
name: Android Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "android/native/**"
|
||||
- ".github/workflows/android-tests.yml"
|
||||
pull_request:
|
||||
paths:
|
||||
- "android/native/**"
|
||||
- ".github/workflows/android-tests.yml"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
unit-tests:
|
||||
name: JVM tests
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: android/native
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
- run: ./gradlew :app:testLocalDebugUnitTest
|
||||
|
||||
instrumentation-tests:
|
||||
name: Emulator tests
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: android/native
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: "17"
|
||||
- uses: gradle/actions/setup-gradle@v4
|
||||
- uses: reactivecircus/android-emulator-runner@v2
|
||||
with:
|
||||
api-level: 35
|
||||
target: google_apis
|
||||
arch: x86_64
|
||||
script: ./gradlew :app:connectedLocalDebugAndroidTest
|
||||
15
.gitignore
vendored
Executable file → Normal file
@@ -5,30 +5,15 @@
|
||||
.depbe.sh
|
||||
node_modules
|
||||
node_modules/*
|
||||
# package-lock.json wird versioniert (npm ci im Deploy braucht konsistente Locks zu package.json)
|
||||
backend/.env
|
||||
backend/.env.local
|
||||
backend/images
|
||||
backend/images/*
|
||||
backend/node_modules
|
||||
backend/node_modules/*
|
||||
frontend/.env
|
||||
frontend/.env.android
|
||||
frontend/node_modules
|
||||
frontend/node_modules/*
|
||||
frontend/dist
|
||||
frontend/dist/*
|
||||
frontend/scripts/.i18n-de-fr-cache.json
|
||||
frontend/scripts/.falukant-fr-smooth-cache.json
|
||||
frontend/ceb-locale-audit-report.json
|
||||
frontedtree.txt
|
||||
backend/dist/
|
||||
backend/data/model-cache
|
||||
build
|
||||
build/*
|
||||
.vscode
|
||||
.vscode/*
|
||||
.clang-format
|
||||
android/native/.gradle/
|
||||
android/native/build/
|
||||
android/native/local.properties
|
||||
|
||||
0
.vscode/settings.json
vendored
Executable file → Normal file
156
CHURCH_MODELS.md
@@ -1,156 +0,0 @@
|
||||
# Church Models - Übersicht für Daemon-Entwicklung
|
||||
|
||||
## 1. ChurchOfficeType (falukant_type.church_office_type)
|
||||
|
||||
**Schema:** `falukant_type`
|
||||
**Tabelle:** `church_office_type`
|
||||
**Zweck:** Definiert die verschiedenen Kirchenämter-Typen
|
||||
|
||||
```javascript
|
||||
{
|
||||
id: INTEGER (PK, auto-increment)
|
||||
name: STRING (z.B. "pope", "cardinal", "lay-preacher")
|
||||
seatsPerRegion: INTEGER (Anzahl verfügbarer Plätze pro Region)
|
||||
regionType: STRING (z.B. "country", "duchy", "city")
|
||||
hierarchyLevel: INTEGER (0-8, höhere Zahl = höhere Position)
|
||||
}
|
||||
```
|
||||
|
||||
**Beziehungen:**
|
||||
- `hasMany` ChurchOffice (als `offices`)
|
||||
- `hasMany` ChurchApplication (als `applications`)
|
||||
- `hasMany` ChurchOfficeRequirement (als `requirements`)
|
||||
|
||||
---
|
||||
|
||||
## 2. ChurchOfficeRequirement (falukant_predefine.church_office_requirement)
|
||||
|
||||
**Schema:** `falukant_predefine`
|
||||
**Tabelle:** `church_office_requirement`
|
||||
**Zweck:** Definiert Voraussetzungen für Kirchenämter
|
||||
|
||||
```javascript
|
||||
{
|
||||
id: INTEGER (PK, auto-increment)
|
||||
officeTypeId: INTEGER (FK -> ChurchOfficeType.id)
|
||||
prerequisiteOfficeTypeId: INTEGER (FK -> ChurchOfficeType.id, nullable)
|
||||
minTitleLevel: INTEGER (nullable, optional)
|
||||
}
|
||||
```
|
||||
|
||||
**Beziehungen:**
|
||||
- `belongsTo` ChurchOfficeType (als `officeType`)
|
||||
- `belongsTo` ChurchOfficeType (als `prerequisiteOfficeType`)
|
||||
|
||||
---
|
||||
|
||||
## 3. ChurchOffice (falukant_data.church_office)
|
||||
|
||||
**Schema:** `falukant_data`
|
||||
**Tabelle:** `church_office`
|
||||
**Zweck:** Speichert tatsächlich besetzte Kirchenämter
|
||||
|
||||
```javascript
|
||||
{
|
||||
id: INTEGER (PK, auto-increment)
|
||||
officeTypeId: INTEGER (FK -> ChurchOfficeType.id)
|
||||
characterId: INTEGER (FK -> FalukantCharacter.id)
|
||||
regionId: INTEGER (FK -> RegionData.id)
|
||||
supervisorId: INTEGER (FK -> FalukantCharacter.id, nullable)
|
||||
createdAt: DATE
|
||||
updatedAt: DATE
|
||||
}
|
||||
```
|
||||
|
||||
**Beziehungen:**
|
||||
- `belongsTo` ChurchOfficeType (als `type`)
|
||||
- `belongsTo` FalukantCharacter (als `holder`)
|
||||
- `belongsTo` FalukantCharacter (als `supervisor`)
|
||||
- `belongsTo` RegionData (als `region`)
|
||||
|
||||
---
|
||||
|
||||
## 4. ChurchApplication (falukant_data.church_application)
|
||||
|
||||
**Schema:** `falukant_data`
|
||||
**Tabelle:** `church_application`
|
||||
**Zweck:** Speichert Bewerbungen für Kirchenämter
|
||||
|
||||
```javascript
|
||||
{
|
||||
id: INTEGER (PK, auto-increment)
|
||||
officeTypeId: INTEGER (FK -> ChurchOfficeType.id)
|
||||
characterId: INTEGER (FK -> FalukantCharacter.id)
|
||||
regionId: INTEGER (FK -> RegionData.id)
|
||||
supervisorId: INTEGER (FK -> FalukantCharacter.id)
|
||||
status: ENUM('pending', 'approved', 'rejected')
|
||||
decisionDate: DATE (nullable)
|
||||
createdAt: DATE
|
||||
updatedAt: DATE
|
||||
}
|
||||
```
|
||||
|
||||
**Beziehungen:**
|
||||
- `belongsTo` ChurchOfficeType (als `officeType`)
|
||||
- `belongsTo` FalukantCharacter (als `applicant`)
|
||||
- `belongsTo` FalukantCharacter (als `supervisor`)
|
||||
- `belongsTo` RegionData (als `region`)
|
||||
|
||||
---
|
||||
|
||||
## Zusätzlich benötigte Models (für Daemon)
|
||||
|
||||
### RegionData (falukant_data.region)
|
||||
- Wird für `regionId` in ChurchOffice und ChurchApplication benötigt
|
||||
- Enthält `regionType` (country, duchy, markgravate, shire, county, city)
|
||||
- Enthält `parentId` für Hierarchie
|
||||
|
||||
### FalukantCharacter (falukant_data.character)
|
||||
- Wird für `characterId` (Inhaber/Bewerber) benötigt
|
||||
- Wird für `supervisorId` benötigt
|
||||
|
||||
---
|
||||
|
||||
## Wichtige Queries für Daemon
|
||||
|
||||
### Verfügbare Positionen finden
|
||||
```sql
|
||||
SELECT cot.*, COUNT(co.id) as occupied_seats
|
||||
FROM falukant_type.church_office_type cot
|
||||
LEFT JOIN falukant_data.church_office co
|
||||
ON cot.id = co.office_type_id
|
||||
AND co.region_id = ?
|
||||
WHERE cot.region_type = ?
|
||||
GROUP BY cot.id
|
||||
HAVING COUNT(co.id) < cot.seats_per_region
|
||||
```
|
||||
|
||||
### Supervisor finden
|
||||
```sql
|
||||
SELECT co.*
|
||||
FROM falukant_data.church_office co
|
||||
JOIN falukant_type.church_office_type cot ON co.office_type_id = cot.id
|
||||
WHERE co.region_id = ?
|
||||
AND cot.hierarchy_level > (
|
||||
SELECT hierarchy_level
|
||||
FROM falukant_type.church_office_type
|
||||
WHERE id = ?
|
||||
)
|
||||
ORDER BY cot.hierarchy_level ASC
|
||||
LIMIT 1
|
||||
```
|
||||
|
||||
### Voraussetzungen prüfen
|
||||
```sql
|
||||
SELECT cor.*
|
||||
FROM falukant_predefine.church_office_requirement cor
|
||||
WHERE cor.office_type_id = ?
|
||||
```
|
||||
|
||||
### Bewerbungen für Supervisor
|
||||
```sql
|
||||
SELECT ca.*
|
||||
FROM falukant_data.church_application ca
|
||||
WHERE ca.supervisor_id = ?
|
||||
AND ca.status = 'pending'
|
||||
```
|
||||
@@ -1,78 +0,0 @@
|
||||
# Kirchenämter - Hierarchie und Verfügbarkeit
|
||||
|
||||
## Regionstypen
|
||||
- **country** (Land): Falukant
|
||||
- **duchy** (Herzogtum): Hessen
|
||||
- **markgravate** (Markgrafschaft): Groß-Benbach
|
||||
- **shire** (Grafschaft): Siebenbachen
|
||||
- **county** (Kreis): Bad Homburg, Maintal
|
||||
- **city** (Stadt): Frankfurt, Oberursel, Offenbach, Königstein
|
||||
|
||||
## Kirchenämter (von höchstem zu niedrigstem Rang)
|
||||
|
||||
| Amt | Translation Key | Hierarchie-Level | Regionstyp | Plätze pro Region | Beschreibung |
|
||||
|-----|----------------|-------------------|------------|-------------------|--------------|
|
||||
| **Papst** | `pope` | 8 | country | 1 | Höchstes Amt, nur einer im ganzen Land |
|
||||
| **Kardinal** | `cardinal` | 7 | country | 3 | Höchste Kardinäle, mehrere pro Land möglich |
|
||||
| **Erzbischof** | `archbishop` | 6 | duchy | 1 | Pro Herzogtum ein Erzbischof |
|
||||
| **Bischof** | `bishop` | 5 | markgravate | 1 | Pro Markgrafschaft ein Bischof |
|
||||
| **Erzdiakon** | `archdeacon` | 4 | shire | 1 | Pro Grafschaft ein Erzdiakon |
|
||||
| **Dekan** | `dean` | 3 | county | 1 | Pro Kreis ein Dekan |
|
||||
| **Pfarrer** | `parish-priest` | 2 | city | 1 | Pro Stadt ein Pfarrer |
|
||||
| **Dorfgeistlicher** | `village-priest` | 1 | city | 1 | Pro Stadt ein Dorfgeistlicher (Einstiegsposition) |
|
||||
| **Laienprediger** | `lay-preacher` | 0 | city | 3 | Pro Stadt mehrere Laienprediger (niedrigste Position) |
|
||||
|
||||
## Verfügbare Positionen pro Regionstyp
|
||||
|
||||
### country (Land: Falukant)
|
||||
- **Papst**: 1 Platz
|
||||
- **Kardinal**: 3 Plätze
|
||||
- **Gesamt**: 4 Plätze
|
||||
|
||||
### duchy (Herzogtum: Hessen)
|
||||
- **Erzbischof**: 1 Platz
|
||||
- **Gesamt**: 1 Platz
|
||||
|
||||
### markgravate (Markgrafschaft: Groß-Benbach)
|
||||
- **Bischof**: 1 Platz
|
||||
- **Gesamt**: 1 Platz
|
||||
|
||||
### shire (Grafschaft: Siebenbachen)
|
||||
- **Erzdiakon**: 1 Platz
|
||||
- **Gesamt**: 1 Platz
|
||||
|
||||
### county (Kreis: Bad Homburg, Maintal)
|
||||
- **Dekan**: 1 Platz pro Kreis
|
||||
- **Gesamt**: 1 Platz pro Kreis
|
||||
|
||||
### city (Stadt: Frankfurt, Oberursel, Offenbach, Königstein)
|
||||
- **Pfarrer**: 1 Platz pro Stadt
|
||||
- **Dorfgeistlicher**: 1 Platz pro Stadt
|
||||
- **Laienprediger**: 3 Plätze pro Stadt
|
||||
- **Gesamt**: 5 Plätze pro Stadt
|
||||
|
||||
## Hierarchie und Beförderungsweg
|
||||
|
||||
1. **Laienprediger** (lay-preacher) - Einstiegsposition, keine Voraussetzung
|
||||
2. **Dorfgeistlicher** (village-priest) - Voraussetzung: Laienprediger
|
||||
3. **Pfarrer** (parish-priest) - Voraussetzung: Dorfgeistlicher
|
||||
4. **Dekan** (dean) - Voraussetzung: Pfarrer
|
||||
5. **Erzdiakon** (archdeacon) - Voraussetzung: Dekan
|
||||
6. **Bischof** (bishop) - Voraussetzung: Erzdiakon
|
||||
7. **Erzbischof** (archbishop) - Voraussetzung: Bischof
|
||||
8. **Kardinal** (cardinal) - Voraussetzung: Erzbischof
|
||||
9. **Papst** (pope) - Voraussetzung: Kardinal
|
||||
|
||||
## Gesamtübersicht verfügbarer Positionen
|
||||
|
||||
- **Papst**: 1 Position (Land)
|
||||
- **Kardinal**: 3 Positionen (Land)
|
||||
- **Erzbischof**: 1 Position (Herzogtum)
|
||||
- **Bischof**: 1 Position (Markgrafschaft)
|
||||
- **Erzdiakon**: 1 Position (Grafschaft)
|
||||
- **Dekan**: 2 Positionen (2 Kreise)
|
||||
- **Pfarrer**: 4 Positionen (4 Städte)
|
||||
- **Dorfgeistlicher**: 4 Positionen (4 Städte)
|
||||
- **Laienprediger**: 12 Positionen (4 Städte × 3)
|
||||
|
||||
**Gesamt**: 30 Positionen im System
|
||||
119
CMakeLists.txt
@@ -1,119 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(YourPartDaemon VERSION 1.0 LANGUAGES CXX)
|
||||
|
||||
# C++ Standard and Compiler Settings
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
# Use best available GCC for C++23 support (OpenSUSE Tumbleweed)
|
||||
# Try GCC 15 first (best C++23 support), then GCC 13, then system default
|
||||
find_program(GCC15_CC gcc-15)
|
||||
find_program(GCC15_CXX g++-15)
|
||||
find_program(GCC13_CC gcc-13)
|
||||
find_program(GCC13_CXX g++-13)
|
||||
|
||||
if(GCC15_CC AND GCC15_CXX)
|
||||
set(CMAKE_C_COMPILER ${GCC15_CC})
|
||||
set(CMAKE_CXX_COMPILER ${GCC15_CXX})
|
||||
message(STATUS "Using GCC 15 for best C++23 support")
|
||||
elseif(GCC13_CC AND GCC13_CXX)
|
||||
set(CMAKE_C_COMPILER ${GCC13_CC})
|
||||
set(CMAKE_CXX_COMPILER ${GCC13_CXX})
|
||||
message(STATUS "Using GCC 13 for C++23 support")
|
||||
else()
|
||||
message(STATUS "Using system default compiler")
|
||||
endif()
|
||||
# Optimize for GCC 13 with C++23
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=auto -O3 -march=native -mtune=native")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-O1 -g -DDEBUG")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -march=native -mtune=native")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
|
||||
set(CMAKE_BUILD_TYPE Release)
|
||||
|
||||
# Include /usr/local if needed
|
||||
list(APPEND CMAKE_PREFIX_PATH /usr/local)
|
||||
|
||||
# Find libwebsockets via pkg-config
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LWS REQUIRED libwebsockets)
|
||||
|
||||
# Find other dependencies
|
||||
find_package(PostgreSQL REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
find_package(nlohmann_json CONFIG REQUIRED)
|
||||
|
||||
# PostgreSQL C++ libpqxx
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBPQXX REQUIRED libpqxx)
|
||||
|
||||
# Project sources and headers
|
||||
set(SOURCES
|
||||
src/main.cpp
|
||||
src/config.cpp
|
||||
src/connection_pool.cpp
|
||||
src/database.cpp
|
||||
src/character_creation_worker.cpp
|
||||
src/produce_worker.cpp
|
||||
src/message_broker.cpp
|
||||
src/websocket_server.cpp
|
||||
src/stockagemanager.cpp
|
||||
src/director_worker.cpp
|
||||
src/valuerecalculationworker.cpp
|
||||
src/usercharacterworker.cpp
|
||||
src/houseworker.cpp
|
||||
src/politics_worker.cpp
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
src/config.h
|
||||
src/database.h
|
||||
src/connection_pool.h
|
||||
src/worker.h
|
||||
src/character_creation_worker.h
|
||||
src/produce_worker.h
|
||||
src/message_broker.h
|
||||
src/websocket_server.h
|
||||
src/stockagemanager.h
|
||||
src/director_worker.h
|
||||
src/valuerecalculationworker.h
|
||||
src/usercharacterworker.h
|
||||
src/houseworker.h
|
||||
src/politics_worker.h
|
||||
)
|
||||
|
||||
# Define executable target
|
||||
add_executable(yourpart-daemon ${SOURCES} ${HEADERS}
|
||||
src/utils.h src/utils.cpp
|
||||
src/underground_worker.h src/underground_worker.cpp)
|
||||
|
||||
# Include directories
|
||||
target_include_directories(yourpart-daemon PRIVATE
|
||||
${PostgreSQL_INCLUDE_DIRS}
|
||||
${LIBPQXX_INCLUDE_DIRS}
|
||||
${LWS_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# Find systemd
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(SYSTEMD REQUIRED libsystemd)
|
||||
|
||||
# Link libraries
|
||||
target_link_libraries(yourpart-daemon PRIVATE
|
||||
${PostgreSQL_LIBRARIES}
|
||||
Threads::Threads
|
||||
z ssl crypto
|
||||
${LIBPQXX_LIBRARIES}
|
||||
${LWS_LIBRARIES}
|
||||
nlohmann_json::nlohmann_json
|
||||
${SYSTEMD_LIBRARIES}
|
||||
)
|
||||
|
||||
# Installation rules
|
||||
install(TARGETS yourpart-daemon DESTINATION /usr/local/bin)
|
||||
|
||||
# Installiere Template als Referenz ZUERST (wird vom install-Skript benötigt)
|
||||
install(FILES daemon.conf DESTINATION /etc/yourpart/ RENAME daemon.conf.example)
|
||||
|
||||
# Intelligente Konfigurationsdatei-Installation
|
||||
# Verwendet ein CMake-Skript, das nur fehlende Keys hinzufügt, ohne bestehende zu überschreiben
|
||||
# Das Skript liest das Template aus /etc/yourpart/daemon.conf.example oder dem Source-Verzeichnis
|
||||
install(SCRIPT cmake/install-config.cmake)
|
||||
@@ -1,414 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 17.0.0, 2025-08-16T22:07:06. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{551ef6b3-a39b-43e2-9ee3-ad56e19ff4f4}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="qlonglong">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoDetect">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">2</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<value type="bool" key="AutoTest.ApplyFilter">false</value>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">8</value>
|
||||
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Importiertes Kit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Importiertes Kit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{78ff90a3-f672-45c2-ad08-343b0923896f}</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||
-DCMAKE_BUILD_TYPE:STRING=Release
|
||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/torsten/Programs/yourpart-daemon/build/</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Bereinigen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString"></value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Application Manager-Paket installieren</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">yourpart-daemon</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">yourpart-daemon</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}
|
||||
-DCMAKE_COLOR_DIAGNOSTICS:BOOL=ON
|
||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||
-DCMAKE_BUILD_TYPE:STRING=Debug
|
||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}</value>
|
||||
<value type="QString" key="CMake.Source.Directory">/mnt/share/torsten/Programs/yourpart-daemon</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Bereinigen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Debug (importiert)</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">-1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">install</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Application Manager-Paket installieren</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">0</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString"></value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.CMakePackageStep</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="QString" key="ApplicationManagerPlugin.Deploy.InstallPackageStep.Arguments">install-package --acknowledge</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Application Manager-Paket installieren</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.InstallPackageStep</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedFiles"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedHosts"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedRemotePaths"/>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.RunConfiguration.LastDeployedSysroots"/>
|
||||
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedLocalTimes"/>
|
||||
<valuelist type="QVariantList" key="RemoteLinux.LastDeployedRemoteTimes"/>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ApplicationManagerPlugin.Deploy.Configuration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">2</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">yourpart-daemon</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">yourpart-daemon</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="qlonglong">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
@@ -1,205 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 12.0.2, 2025-07-18T07:45:58. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{d36652ff-969b-426b-a63f-1edd325096c5}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="qlonglong">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">8</value>
|
||||
<value type="bool" key="ClangTools.PreferConfigFile">true</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="CppEditor.QuickFix">
|
||||
<value type="bool" key="UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Importiertes Kit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Importiertes Kit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{3c6cfc13-714d-4db1-bd45-b9794643cc67}</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="CMake.Build.Type">Debug</value>
|
||||
<value type="int" key="CMake.Configure.BaseEnvironment">2</value>
|
||||
<value type="bool" key="CMake.Configure.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMake.Configure.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="CMake.Initial.Parameters">-DCMAKE_GENERATOR:STRING=Unix Makefiles
|
||||
-DCMAKE_BUILD_TYPE:STRING=Build
|
||||
-DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake
|
||||
-DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable}
|
||||
-DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX}
|
||||
-DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C}
|
||||
-DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx}</value>
|
||||
<value type="QString" key="CMake.Source.Directory">/home/torsten/Programs/yourpart-daemon</value>
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="QString" key="CMakeProjectManager.MakeStep.BuildPreset"></value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="CMakeProjectManager.MakeStep.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="CMakeProjectManager.MakeStep.UserEnvironmentChanges"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.MakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Bereinigen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Erstellen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.Callgrind.CostFormat">0</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">/usr/bin/valgrind</value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">yourpart-daemon</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">CMakeProjectManager.CMakeRunConfiguration.yourpart-daemon</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey">yourpart-daemon</value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseLibrarySearchPath">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
<value type="QString" key="RunConfiguration.WorkingDirectory.default">/home/torsten/Programs/yourpart-daemon/build</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="qlonglong">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
0
DEPLOYMENT.md
Executable file → Normal file
@@ -1,259 +0,0 @@
|
||||
# OAuth Credentials Setup Guide
|
||||
|
||||
Anleitung zum Sammeln der OAuth-Credentials für alle 5 Provider.
|
||||
|
||||
## Redirect URIs
|
||||
Für alle Provider benötigst du folgende Redirect URIs (ersetze `www.your-part.de` mit deiner echten Domain):
|
||||
|
||||
```
|
||||
https://www.your-part.de/auth/oauth/callback
|
||||
https://www.your-part.de/auth/oauth/user/callback
|
||||
```
|
||||
|
||||
Lokal zum Testen:
|
||||
```
|
||||
http://localhost:3000/auth/oauth/callback
|
||||
http://localhost:3000/auth/oauth/user/callback
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 1. Google
|
||||
|
||||
### Credentials besorgen:
|
||||
|
||||
1. Öffne [Google Cloud Console](https://console.cloud.google.com/)
|
||||
2. Erstelle ein neues Projekt oder wähle ein bestehendes
|
||||
3. Navigiere zu **APIs & Services** → **Credentials**
|
||||
4. Klick **+ CREATE CREDENTIALS** → **OAuth 2.0 Client IDs**
|
||||
5. Wähle **Web application**
|
||||
6. Füge unter **Authorized redirect URIs** hinzu:
|
||||
- `https://www.your-part.de/auth/oauth/callback`
|
||||
- `https://www.your-part.de/auth/oauth/user/callback`
|
||||
7. Speichern und die **Client ID** und **Client Secret** kopieren
|
||||
|
||||
### .env:
|
||||
```env
|
||||
OAUTH_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
|
||||
OAUTH_GOOGLE_CLIENT_SECRET=your-client-secret
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Microsoft Azure
|
||||
|
||||
### Credentials besorgen:
|
||||
|
||||
1. Öffne [Azure Portal](https://portal.azure.com/)
|
||||
2. Navigiere zu **Azure Active Directory** → **App registrations** → **+ New registration**
|
||||
3. Gib einen Namen ein (z.B. "YourPart OAuth")
|
||||
4. Wähle **Accounts in any organizational directory (Any Azure AD directory - Multitenant)**
|
||||
5. Bei **Redirect URI** wähle **Web** und füge ein:
|
||||
- `https://www.your-part.de/auth/oauth/callback`
|
||||
6. Klick **Register**
|
||||
7. Notiere die **Application (client) ID**
|
||||
8. Gehe zu **Certificates & secrets** → **+ New client secret**
|
||||
9. Erstelle ein Secret und kopiere den **Value** (nicht die ID!)
|
||||
10. Gehe zu **Token configuration** und stelle sicher, dass die richtigen Claims enthalten sind
|
||||
|
||||
### Zusätzliche URI hinzufügen:
|
||||
1. Gehe zu **Authentication**
|
||||
2. Unter **Redirect URIs** klick **+ Add URI**
|
||||
3. Füge hinzu: `https://www.your-part.de/auth/oauth/user/callback`
|
||||
|
||||
### .env:
|
||||
```env
|
||||
OAUTH_MICROSOFT_CLIENT_ID=your-application-id
|
||||
OAUTH_MICROSOFT_CLIENT_SECRET=your-client-secret-value
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Keycloak
|
||||
|
||||
Keycloak ist ein Open-Source OIDC Provider. Du kannst ihn selbst hosten oder eine gehostete Lösung nutzen.
|
||||
|
||||
### Option A: Selbst gehostet mit Docker
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
-p 8080:8080 \
|
||||
-e KEYCLOAK_ADMIN=admin \
|
||||
-e KEYCLOAK_ADMIN_PASSWORD=admin \
|
||||
quay.io/keycloak/keycloak:latest \
|
||||
start-dev
|
||||
```
|
||||
|
||||
Dann:
|
||||
1. Öffne http://localhost:8080
|
||||
2. Login mit `admin` / `admin`
|
||||
3. **Realm erstellen**: Oben links Dropdown → **Create realm**
|
||||
- Name: `yourpart` (oder beliebig)
|
||||
4. Im neuen Realm: **Clients** → **Create client**
|
||||
- Client ID: `yourpart`
|
||||
- Client Protocol: `openid-connect`
|
||||
- Access Type: `confidential`
|
||||
5. Im **Settings** Tab:
|
||||
- Valid Redirect URIs:
|
||||
```
|
||||
https://www.your-part.de/auth/oauth/callback
|
||||
https://www.your-part.de/auth/oauth/user/callback
|
||||
```
|
||||
6. Speichern
|
||||
7. Gehe zu **Credentials** Tab
|
||||
- **Client Secret** kopieren
|
||||
|
||||
### Option B: Gehosteter Service
|
||||
- [Keycloak.cloud](https://www.keycloak.cloud/) oder
|
||||
- [Red Hat Managed Keycloak](https://www.keycloak.org/cloud/)
|
||||
|
||||
### .env:
|
||||
```env
|
||||
OAUTH_KEYCLOAK_ISSUER=https://your-keycloak-domain/realms/yourpart
|
||||
OAUTH_KEYCLOAK_CLIENT_ID=yourpart
|
||||
OAUTH_KEYCLOAK_CLIENT_SECRET=your-client-secret
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. ORY Hydra / ORY Cloud
|
||||
|
||||
ORY ist ein moderner OIDC Provider. Am einfachsten ist ORY Cloud.
|
||||
|
||||
### Option A: ORY Cloud (empfohlen)
|
||||
|
||||
1. Öffne [ORY Cloud Console](https://console.ory.sh/)
|
||||
2. Registriere dich oder logge dich ein
|
||||
3. Erstelle ein neues **Project**
|
||||
4. Gehe zu **Applications**
|
||||
5. Klick **Create New Application**
|
||||
6. Gib einen Namen ein (z.B. "YourPart")
|
||||
7. Unter **Redirect URLs** füge ein:
|
||||
```
|
||||
https://www.your-part.de/auth/oauth/callback
|
||||
https://www.your-part.de/auth/oauth/user/callback
|
||||
```
|
||||
8. Speichern
|
||||
9. Die **Client ID** und **Client Secret** werden angezeigt
|
||||
10. Finde deine **Issuer URL** in den Project Settings (meist `https://your-project-slug.eu.hydra.cloud`)
|
||||
|
||||
### Option B: Selbst gehostet (komplex)
|
||||
|
||||
Siehe [ORY Hydra Dokumentation](https://www.ory.sh/hydra/docs/)
|
||||
|
||||
### .env:
|
||||
```env
|
||||
OAUTH_ORY_ISSUER=https://your-project-slug.eu.hydra.cloud
|
||||
OAUTH_ORY_CLIENT_ID=your-client-id
|
||||
OAUTH_ORY_CLIENT_SECRET=your-client-secret
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. ZITADEL
|
||||
|
||||
ZITADEL ist ein Zero-Trust Identity Platform als SaaS.
|
||||
|
||||
### Credentials besorgen:
|
||||
|
||||
1. Öffne [ZITADEL Console](https://zitadel.cloud/)
|
||||
2. Registriere dich oder logge dich ein
|
||||
3. Erstelle eine neue **Organization** (oder verwende die existierende)
|
||||
4. Gehe zu **Projects** → **+ New Project**
|
||||
5. Gib einen Namen ein (z.B. "YourPart")
|
||||
6. Gehe zum Projekt → **Applications** → **+ New Application**
|
||||
7. Wähle **Type: Web**
|
||||
8. Gib einen Namen ein
|
||||
9. Bei **Redirect URIs** füge ein:
|
||||
```
|
||||
https://www.your-part.de/auth/oauth/callback
|
||||
https://www.your-part.de/auth/oauth/user/callback
|
||||
```
|
||||
10. Speichern
|
||||
11. Unter **Client Information** kopiere:
|
||||
- **Client ID**
|
||||
- **Client Secret** (falls sichtbar, sonst im "CREDENTIALS" Tab generieren)
|
||||
12. Finde deine **Issuer URL** in den Organization Settings (meist `https://your-instance.zitadel.cloud`)
|
||||
|
||||
### .env:
|
||||
```env
|
||||
OAUTH_ZITADEL_ISSUER=https://your-instance.zitadel.cloud
|
||||
OAUTH_ZITADEL_CLIENT_ID=your-client-id
|
||||
OAUTH_ZITADEL_CLIENT_SECRET=your-client-secret
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Komplette .env für alle 5 Provider
|
||||
|
||||
```env
|
||||
# Google
|
||||
OAUTH_GOOGLE_CLIENT_ID=...
|
||||
OAUTH_GOOGLE_CLIENT_SECRET=...
|
||||
|
||||
# Microsoft
|
||||
OAUTH_MICROSOFT_CLIENT_ID=...
|
||||
OAUTH_MICROSOFT_CLIENT_SECRET=...
|
||||
|
||||
# Keycloak
|
||||
OAUTH_KEYCLOAK_ISSUER=...
|
||||
OAUTH_KEYCLOAK_CLIENT_ID=...
|
||||
OAUTH_KEYCLOAK_CLIENT_SECRET=...
|
||||
|
||||
# ORY
|
||||
OAUTH_ORY_ISSUER=...
|
||||
OAUTH_ORY_CLIENT_ID=...
|
||||
OAUTH_ORY_CLIENT_SECRET=...
|
||||
|
||||
# ZITADEL
|
||||
OAUTH_ZITADEL_ISSUER=...
|
||||
OAUTH_ZITADEL_CLIENT_ID=...
|
||||
OAUTH_ZITADEL_CLIENT_SECRET=...
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Schnell-Checkliste
|
||||
|
||||
- [ ] Google: Client ID & Secret
|
||||
- [ ] Microsoft: Application ID & Client Secret
|
||||
- [ ] Keycloak: Issuer, Client ID, Secret
|
||||
- [ ] ORY: Issuer, Client ID, Secret
|
||||
- [ ] ZITADEL: Issuer, Client ID, Secret
|
||||
- [ ] Alle Redirect URIs in den Providern konfiguriert
|
||||
- [ ] .env datei aktualisiert
|
||||
- [ ] Server neu gestartet (`npm restart`)
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
Nach der Konfiguration:
|
||||
|
||||
1. Frontend öffnen: http://www.your-part.de
|
||||
2. Auf "Login" oder Provider-Button klicken
|
||||
3. Jeder verfügbare Provider sollte als Button angezeigt werden
|
||||
4. Test: Mit jedem Provider einloggen
|
||||
5. Test: Existender Nutzer → Einstellungen → Authentifizierung hinzufügen
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Invalid redirect URI"
|
||||
- Stelle sicher, dass die Redirect URIs **exakt** übereinstimmen (inkl. `https://` vs `http://`)
|
||||
- Beachte Trailing Slashes
|
||||
|
||||
### "Invalid client secret"
|
||||
- Kopiere das Secret neu (nicht die ID)
|
||||
- Manche Provider verstecken das Secret nach einmaliger Anzeige
|
||||
|
||||
### "Discovery endpoint not found"
|
||||
- Überprüfe die Issuer URL (mit/ohne Trailing Slash)
|
||||
- Für Keycloak: URL muss auf `/realms/xxx` enden
|
||||
- Für ORY: URL darf nicht auf `/` enden
|
||||
|
||||
### Port-Konflikt lokal
|
||||
- Keycloak benutzt `8080` → ändere auf: `docker run -p 8081:8080 ...`
|
||||
- Stelle sicher, dass 3000 (Frontend) und 5000 (Backend) frei sind
|
||||
|
||||
0
PERFORMANCE_ANALYSIS.md
Executable file → Normal file
@@ -1,3 +0,0 @@
|
||||
## zum testen des push
|
||||
|
||||
Hinweis: Das Verzeichnis **`src/`** (C++-Worker) ist veraltet; siehe [`docs/LEGACY_CPP_WORKERS.md`](docs/LEGACY_CPP_WORKERS.md).
|
||||
0
README_MATCH3_CAMPAIGN.md
Executable file → Normal file
0
SELL_OVERVIEW.md
Executable file → Normal file
168
SSL-SETUP.md
@@ -1,168 +0,0 @@
|
||||
# SSL/TLS Setup für YourPart Daemon
|
||||
|
||||
Dieses Dokument beschreibt, wie Sie SSL/TLS-Zertifikate für den YourPart Daemon einrichten können.
|
||||
|
||||
## 🚀 Schnellstart
|
||||
|
||||
### 1. Self-Signed Certificate (Entwicklung/Testing)
|
||||
```bash
|
||||
./setup-ssl.sh
|
||||
# Wählen Sie Option 1
|
||||
```
|
||||
|
||||
### 2. Let's Encrypt Certificate (Produktion)
|
||||
```bash
|
||||
./setup-ssl.sh
|
||||
# Wählen Sie Option 2
|
||||
```
|
||||
|
||||
### 3. Apache2-Zertifikate verwenden (empfohlen für Ubuntu)
|
||||
```bash
|
||||
./setup-ssl.sh
|
||||
# Wählen Sie Option 4
|
||||
# Verwendet bereits vorhandene Apache2-Zertifikate
|
||||
# ⚠️ Warnung bei Snakeoil-Zertifikaten (nur für localhost)
|
||||
```
|
||||
|
||||
### 4. DNS-01 Challenge (für komplexe Setups)
|
||||
```bash
|
||||
./setup-ssl-dns.sh
|
||||
# Für Cloudflare, Route53, etc.
|
||||
```
|
||||
|
||||
## 📋 Voraussetzungen
|
||||
|
||||
### Für Apache2-Zertifikate:
|
||||
- Apache2 installiert oder Zertifikate in Standard-Pfaden
|
||||
- Unterstützte Pfade (priorisiert nach Qualität):
|
||||
- `/etc/letsencrypt/live/your-part.de/fullchain.pem` (Let's Encrypt - empfohlen)
|
||||
- `/etc/letsencrypt/live/$(hostname)/fullchain.pem` (Let's Encrypt)
|
||||
- `/etc/apache2/ssl/apache.crt` (Custom Apache2)
|
||||
- `/etc/ssl/certs/ssl-cert-snakeoil.pem` (Ubuntu Standard - nur localhost)
|
||||
|
||||
### Für Let's Encrypt (HTTP-01 Challenge):
|
||||
- Port 80 muss verfügbar sein
|
||||
- Domain `your-part.de` muss auf den Server zeigen
|
||||
- Kein anderer Service auf Port 80
|
||||
|
||||
### Für DNS-01 Challenge:
|
||||
- DNS-Provider Account (Cloudflare, Route53, etc.)
|
||||
- API-Credentials für DNS-Management
|
||||
|
||||
## 🔧 Konfiguration
|
||||
|
||||
Nach der Zertifikats-Erstellung:
|
||||
|
||||
1. **SSL in der Konfiguration aktivieren:**
|
||||
```ini
|
||||
# /etc/yourpart/daemon.conf
|
||||
WEBSOCKET_SSL_ENABLED=true
|
||||
WEBSOCKET_SSL_CERT_PATH=/etc/yourpart/server.crt
|
||||
WEBSOCKET_SSL_KEY_PATH=/etc/yourpart/server.key
|
||||
```
|
||||
|
||||
2. **Daemon neu starten:**
|
||||
```bash
|
||||
sudo systemctl restart yourpart-daemon
|
||||
```
|
||||
|
||||
3. **Verbindung testen:**
|
||||
```bash
|
||||
# WebSocket Secure
|
||||
wss://your-part.de:4551
|
||||
|
||||
# Oder ohne SSL
|
||||
ws://your-part.de:4551
|
||||
```
|
||||
|
||||
## 🔄 Automatische Erneuerung
|
||||
|
||||
### Let's Encrypt-Zertifikate:
|
||||
- **Cron Job:** Täglich um 2:30 Uhr
|
||||
- **Script:** `/etc/yourpart/renew-ssl.sh`
|
||||
- **Log:** `/var/log/yourpart/ssl-renewal.log`
|
||||
|
||||
### Apache2-Zertifikate:
|
||||
- **Ubuntu Snakeoil:** Automatisch von Apache2 verwaltet
|
||||
- **Let's Encrypt:** Automatische Erneuerung wenn erkannt
|
||||
- **Custom:** Manuelle Verwaltung erforderlich
|
||||
|
||||
## 📁 Dateistruktur
|
||||
|
||||
```
|
||||
/etc/yourpart/
|
||||
├── server.crt # Zertifikat (Symlink zu Let's Encrypt)
|
||||
├── server.key # Private Key (Symlink zu Let's Encrypt)
|
||||
├── renew-ssl.sh # Auto-Renewal Script
|
||||
└── cloudflare.ini # Cloudflare Credentials (falls verwendet)
|
||||
|
||||
/etc/letsencrypt/live/your-part.de/
|
||||
├── fullchain.pem # Vollständige Zertifikatskette
|
||||
├── privkey.pem # Private Key
|
||||
├── cert.pem # Zertifikat
|
||||
└── chain.pem # Intermediate Certificate
|
||||
```
|
||||
|
||||
## 🛠️ Troubleshooting
|
||||
|
||||
### Zertifikat wird nicht akzeptiert
|
||||
```bash
|
||||
# Prüfe Zertifikats-Gültigkeit
|
||||
openssl x509 -in /etc/yourpart/server.crt -text -noout
|
||||
|
||||
# Prüfe Berechtigungen
|
||||
ls -la /etc/yourpart/server.*
|
||||
```
|
||||
|
||||
### Let's Encrypt Challenge fehlgeschlagen
|
||||
```bash
|
||||
# Prüfe Port 80
|
||||
sudo netstat -tlnp | grep :80
|
||||
|
||||
# Prüfe DNS
|
||||
nslookup your-part.de
|
||||
|
||||
# Prüfe Firewall
|
||||
sudo ufw status
|
||||
```
|
||||
|
||||
### Auto-Renewal funktioniert nicht
|
||||
```bash
|
||||
# Prüfe Cron Jobs
|
||||
sudo crontab -l
|
||||
|
||||
# Teste Renewal Script
|
||||
sudo /etc/yourpart/renew-ssl.sh
|
||||
|
||||
# Prüfe Logs
|
||||
tail -f /var/log/yourpart/ssl-renewal.log
|
||||
```
|
||||
|
||||
## 🔒 Sicherheit
|
||||
|
||||
### Berechtigungen
|
||||
- **Zertifikat:** `644` (readable by all, writable by owner)
|
||||
- **Private Key:** `600` (readable/writable by owner only)
|
||||
- **Owner:** `yourpart:yourpart`
|
||||
|
||||
### Firewall
|
||||
```bash
|
||||
# Öffne Port 80 für Let's Encrypt Challenge
|
||||
sudo ufw allow 80/tcp
|
||||
|
||||
# Öffne Port 4551 für WebSocket
|
||||
sudo ufw allow 4551/tcp
|
||||
```
|
||||
|
||||
## 📚 Weitere Informationen
|
||||
|
||||
- [Let's Encrypt Dokumentation](https://letsencrypt.org/docs/)
|
||||
- [Certbot Dokumentation](https://certbot.eff.org/docs/)
|
||||
- [libwebsockets SSL](https://libwebsockets.org/lws-api-doc-master/html/group__ssl.html)
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
Bei Problemen:
|
||||
1. Prüfen Sie die Logs: `sudo journalctl -u yourpart-daemon -f`
|
||||
2. Testen Sie die Zertifikate: `openssl s_client -connect your-part.de:4551`
|
||||
3. Prüfen Sie die Firewall: `sudo ufw status`
|
||||
9
android/.idea/android.iml
generated
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
2001
android/.idea/caches/deviceStreaming.xml
generated
13
android/.idea/deviceManager.xml
generated
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DeviceTable">
|
||||
<option name="columnSorters">
|
||||
<list>
|
||||
<ColumnSorterState>
|
||||
<option name="column" value="Name" />
|
||||
<option name="order" value="ASCENDING" />
|
||||
</ColumnSorterState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
8
android/.idea/markdown.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownSettings">
|
||||
<option name="previewPanelProviderInfo">
|
||||
<ProviderInfo name="Compose (experimental)" className="com.intellij.markdown.compose.preview.ComposePanelProvider" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
5
android/.idea/misc.xml
generated
@@ -1,5 +0,0 @@
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
android/.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/android.iml" filepath="$PROJECT_DIR$/.idea/android.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
android/.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,605 +0,0 @@
|
||||
# Android-App-Plan fuer YourPart3
|
||||
|
||||
Stand: 2026-07-08
|
||||
|
||||
## Ziel
|
||||
|
||||
Dieses Dokument plant eine Android-App fuer das bestehende YourPart3-Projekt unter `/android`.
|
||||
|
||||
Das Projekt besteht aktuell aus:
|
||||
|
||||
- `frontend`: Vue 3, Vite, Vuetify, Vue Router, Vuex, Axios, Socket.IO Client, Three.js
|
||||
- `backend`: Node.js/Express 5, Sequelize, Redis-Sessiondaten, OAuth/OIDC, Socket.IO, REST-APIs
|
||||
- Authentifizierung: Login liefert einen User mit `id`/`authCode`; API-Requests senden Header `userid` und `authcode`
|
||||
- Realtime: Socket.IO fuer Backend-Events und separater Daemon-WebSocket fuer Falukant-Updates
|
||||
- Deployment: Backend serviert die gebaute SPA aus `frontend/dist`
|
||||
|
||||
Backend-Implementierung ist nicht Teil dieses Android-Starts. Das vorhandene Backend wird als gegeben betrachtet; Android-seitig werden nur Kompatibilitaet, URLs, Auth-Header, OAuth-Weiterleitung und Realtime-Verbindungen getestet.
|
||||
|
||||
## Empfehlung
|
||||
|
||||
Die Android-App sollte in Phase 1 als Capacitor-App umgesetzt werden, nicht als nativer Rewrite.
|
||||
|
||||
Begruendung:
|
||||
|
||||
- Die bestehende App ist bereits eine grosse SPA mit vielen Views: Social Network, Falukant, Vokabeltrainer, Minigames, Kalender, Admin, Settings.
|
||||
- Der Auth-Mechanismus und die vorhandenen API-Clients sind Web-orientiert und koennen in einer WebView nahezu unveraendert weiterlaufen.
|
||||
- OAuth-Callback-Routen existieren bereits im Frontend (`/auth/oauth/callback`, `/auth/oauth/user/callback`).
|
||||
- Socket.IO und WebSocket-Verbindungen funktionieren in Capacitor deutlich schneller als in einem nativen Rewrite.
|
||||
- Ein nativer Rewrite wuerde zuerst API-Vertraege, Sessionmodell, Navigation, Offline-Strategie und UI-Komponenten neu definieren muessen.
|
||||
|
||||
Zielarchitektur Phase 1:
|
||||
|
||||
```text
|
||||
/android
|
||||
capacitor.config.ts
|
||||
package.json
|
||||
android/
|
||||
Android-native Projektdateien, durch Capacitor generiert
|
||||
|
||||
/frontend
|
||||
bestehende Vue/Vite-App
|
||||
|
||||
/backend
|
||||
bestehende Express/API/Socket.IO-App
|
||||
```
|
||||
|
||||
Capacitor verwendet den bestehenden `frontend`-Build als Web-Bundle und erzeugt daraus eine installierbare Android-App.
|
||||
|
||||
## Nicht-Ziele fuer Phase 1
|
||||
|
||||
- Kein kompletter nativer Kotlin/Jetpack-Compose-Rewrite.
|
||||
- Keine Offline-First-Synchronisation fuer Falukant/Social/Vocab.
|
||||
- Keine komplette Neugestaltung aller mobilen Screens.
|
||||
- Keine API-Versionierung fuer mobile Clients, solange die App nur das bestehende Web-Frontend verpackt.
|
||||
- Keine Play-Store-Verteilung vor Datenschutz-, Content- und OAuth-Pruefung.
|
||||
- Keine Backend-Neuentwicklung und keine Backend-API-Neuplanung.
|
||||
|
||||
## Getroffene Entscheidungen
|
||||
|
||||
### App-Technologie
|
||||
|
||||
- Entscheidung: Capacitor mit lokal gebuendelter Vue/Vite-App.
|
||||
- Kein nativer Kotlin-Rewrite in Phase 1.
|
||||
- Kein reiner Remote-WebView-Wrapper auf `https://www.your-part.de`.
|
||||
- Begruendung: Der vorhandene Funktionsumfang ist breit, Web-Auth und Socket.IO existieren bereits, und Capacitor ermoeglicht spaetere native Erweiterungen ohne sofortigen Rewrite.
|
||||
|
||||
### App-ID und Name
|
||||
|
||||
- App-ID: `de.yourpart.app`
|
||||
- Launcher-Name: `YourPart`
|
||||
- Android-Projektpfad: `/android`
|
||||
- Capacitor `webDir`: `../frontend/dist`
|
||||
|
||||
### Ziel-Distribution
|
||||
|
||||
- Phase 1: interne Debug-/Test-APK.
|
||||
- Phase 2: signiertes internes AAB/APK fuer Testgeraete.
|
||||
- Play Store erst nach separatem Compliance-Check fuer Datenschutz, UGC, Moderation und Adult Content.
|
||||
|
||||
### Backend-Abgrenzung
|
||||
|
||||
- Backend bleibt unveraendert.
|
||||
- Android nutzt die bestehenden REST-Endpunkte, Auth-Header, OAuth-Routen, Socket.IO-Events und Daemon-WebSocket-Events.
|
||||
- Backendbezogene TODOs sind nur Test- und Konfigurationschecks. Falls ein Test scheitert, wird der konkrete Anpassungsbedarf danach separat entschieden.
|
||||
|
||||
### Admin-Bereich
|
||||
|
||||
- Admin-Routen bleiben in Phase 1 nicht priorisiert.
|
||||
- Wenn Admin-Menues durch bestehende Berechtigungen sichtbar sind, werden sie nicht aktiv entfernt.
|
||||
- Abnahmekriterien fuer Phase 1 gelten nur fuer normale Nutzerfunktionen.
|
||||
|
||||
### Adult-/Erotikbereiche
|
||||
|
||||
- Phase 1: vorhandenes Web-Gating bleibt bestehen, keine neue native Adult-Content-Funktion.
|
||||
- Play-Store-Ziel ist blockiert, bis Altersfreigabe, UGC-Moderation, Melden/Blockieren, Datenschutz und Store-Policy separat geprueft sind.
|
||||
- Fuer interne APK-Tests darf der Bereich technisch erreichbar bleiben, wenn der bestehende Account-/Altersstatus ihn erlaubt.
|
||||
|
||||
### OAuth
|
||||
|
||||
- Phase 1 startet mit Username/Passwort-Login als Pflichtfunktion.
|
||||
- OAuth ist Phase-1-Testumfang, aber kein Blocker fuer das erste Debug-APK.
|
||||
- Zielrichtung fuer OAuth: externer Browser bzw. System-Browser plus App Links, nicht OAuth in einer versteckten WebView erzwingen.
|
||||
|
||||
### Push Notifications
|
||||
|
||||
- Push ist nicht Teil des ersten Android-Scaffolds.
|
||||
- Push wird nach stabiler App-Shell geplant, weil dafuer Device Tokens, Opt-in, Settings und Backend-Zustellung noetig sind.
|
||||
|
||||
### 3D / WebGL
|
||||
|
||||
- 3D-Charaktere werden im Android-Debug-Build initial per `VITE_DISABLE_3D=true` deaktiviert.
|
||||
- Begruendung: Die Login-Seite rendert mehrere `Character3D`-Instanzen sofort. In Kombination mit CORS-Fehlern und vielen GLB-Kandidaten kann der Emulator-WebView-Renderer per OOM abstuerzen.
|
||||
- Reaktivierung erfolgt erst nach erfolgreichem CORS-Test und separatem 3D-Performance-Test.
|
||||
|
||||
### Navigation
|
||||
|
||||
- Vue `createWebHistory` bleibt initial unveraendert.
|
||||
- Hash-Routing wird nur eingefuehrt, wenn Capacitor-Tests echte Routing-Probleme zeigen.
|
||||
- Android Back Button wird als native App-Anforderung in Phase 1 umgesetzt.
|
||||
- Mobile Navigation bleibt Teil der Web-App, wird aber fuer Android als kompakte Hybrid-Navigation gehaertet: Header-Leiste, aufklappbares scrollbares Menue, keine dauerhaft sichtbare Desktop-Menueflaeche auf kleinen Displays.
|
||||
|
||||
### Sichere Speicherung
|
||||
|
||||
- Phase 1 darf bestehendes `localStorage`/`sessionStorage` weiterverwenden.
|
||||
- Vor Play-Store-Release wird Auth-Persistenz auf Secure Storage/Android Keystore umgestellt.
|
||||
|
||||
## Technische Ausgangslage
|
||||
|
||||
### Frontend
|
||||
|
||||
- Zentrale API-Konfiguration: `frontend/src/utils/axios.js`
|
||||
- API-Basis-URL: `frontend/src/utils/appConfig.js` ueber `VITE_API_BASE_URL`
|
||||
- Auth-Header: `userid` und `authcode`
|
||||
- Persistenz: `localStorage` oder `sessionStorage` fuer `isLoggedIn`, `user`, `userid`
|
||||
- Router: `createWebHistory`, viele Clean-URL-Routen
|
||||
- Realtime: `socket.io-client` ueber `VITE_SOCKET_IO_URL`
|
||||
- Daemon-WebSocket: ueber `VITE_DAEMON_SOCKET`
|
||||
- 3D/Assets: Three.js und Modelle ueber `/api/models` bzw. statische Assets
|
||||
|
||||
### Backend
|
||||
|
||||
- CORS erlaubt aktuell konfigurierte Origins und lokale Web-Origins.
|
||||
- Auth-Middleware prueft `userid` und `authcode`.
|
||||
- OAuth startet serverseitig per Redirect.
|
||||
- Socket.IO erlaubt aktuell `origin: '*'`.
|
||||
- Backend serviert SPA-Fallback fuer Nicht-API-Routen.
|
||||
|
||||
## Android-Strategie
|
||||
|
||||
### Phase 1: Capacitor Shell
|
||||
|
||||
Die Android-App laedt nicht die Produktionswebsite remote, sondern nutzt das lokal gebundelte Vite-Build-Artefakt.
|
||||
|
||||
Vorteile:
|
||||
|
||||
- App startet auch dann, wenn die Website selbst nicht als Web-Seite geladen werden muss.
|
||||
- Google Play bewertet sie eher als App statt als reinen Browser-Shortcut.
|
||||
- Versionierbare Builds mit reproduzierbarer Web-Bundle-Version.
|
||||
- Zugriff auf native Funktionen bleibt moeglich: Splash Screen, Deep Links, Push Notifications, sichere Speicherung.
|
||||
|
||||
Wichtige Anpassung:
|
||||
|
||||
- `VITE_API_BASE_URL`, `VITE_SOCKET_IO_URL`, `VITE_DAEMON_SOCKET` muessen fuer Android-Builds explizit auf die produktiven HTTPS/WSS-Endpunkte gesetzt werden.
|
||||
- Relative API-URLs sind in einer gebuendelten Android-WebView riskant, weil `window.location.origin` nicht der Server-Origin ist.
|
||||
|
||||
### Phase 2: Mobile Web-Haertung
|
||||
|
||||
Die bestehende UI muss fuer kleine Viewports und Touch-Nutzung stabilisiert werden.
|
||||
|
||||
Prioritaeten:
|
||||
|
||||
- Login/Register/OAuth
|
||||
- Hauptnavigation
|
||||
- Falukant-Overview, Branch, Family, Bank
|
||||
- Vokabeltrainer und Lessons
|
||||
- Chat/Friends/Forum-Basics
|
||||
- Minigames nur nach separater Touch-Performance-Pruefung
|
||||
|
||||
### Phase 3: Native Integrationen
|
||||
|
||||
Nach stabiler Shell koennen echte App-Features ergaenzt werden:
|
||||
|
||||
- Push Notifications fuer Chat, Freund-Login, Falukant-Events
|
||||
- Deep Links fuer OAuth-Callbacks und geteilte Inhalte
|
||||
- Android Back Button Integration
|
||||
- Splash Screen und App Icons
|
||||
- Secure Storage fuer Authdaten
|
||||
- App Update / Version Check
|
||||
|
||||
### Phase 4: Selektiv native Screens
|
||||
|
||||
Wenn einzelne Bereiche Performance- oder UX-Probleme haben, koennen sie spaeter nativ ersetzt werden. Kandidaten:
|
||||
|
||||
- Login/Onboarding
|
||||
- Push Notification Center
|
||||
- Vokabeltrainer Session
|
||||
- Falukant Status/Quick Actions
|
||||
|
||||
## Repository-Layout
|
||||
|
||||
Vorgeschlagenes Layout:
|
||||
|
||||
```text
|
||||
android/
|
||||
ANDROID_APP_PLAN.md
|
||||
README.md
|
||||
package.json
|
||||
capacitor.config.ts
|
||||
android/ # Capacitor Android-Projekt
|
||||
scripts/
|
||||
build-android-web.sh
|
||||
sync-android.sh
|
||||
```
|
||||
|
||||
Hinweis: In Phase 1 wird `/android/android` generiert, weil `/android` die Capacitor-Projektwurzel ist. Die generierten Android-Dateien werden versioniert, weil reproduzierbare Builds und native Anpassungen wichtig sind.
|
||||
|
||||
## Build-Konzept
|
||||
|
||||
### Android Web-Build
|
||||
|
||||
Ein eigener Build-Modus verhindert Vermischung mit Web-Production:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run build -- --mode android
|
||||
```
|
||||
|
||||
Dafuer wird eine Datei `frontend/.env.android` benoetigt:
|
||||
|
||||
```env
|
||||
VITE_API_BASE_URL=https://www.your-part.de
|
||||
VITE_SOCKET_IO_URL=https://www.your-part.de
|
||||
VITE_DAEMON_SOCKET=wss://www.your-part.de
|
||||
VITE_PUBLIC_BASE_URL=https://www.your-part.de
|
||||
```
|
||||
|
||||
Wichtig: `VITE_API_BASE_URL` ist bewusst nur die Origin ohne `/api`, weil die bestehenden Frontend-Aufrufe bereits Pfade wie `/api/auth/login` enthalten. Mit `/api` in der Base-URL entstehen Android-seitig falsche Requests wie `/api/api/...`.
|
||||
|
||||
Die exakten WebSocket-Pfade muessen gegen die produktive Apache-/Backend-Konfiguration verifiziert werden.
|
||||
|
||||
### Lokaler Emulator-Stand
|
||||
|
||||
Android Studio und mehrere AVDs sind lokal vorhanden. Fuer die ersten Stabilitaetstests ist `trainingstagebuchApi35` die bevorzugte VM, weil sie im bisherigen Test stabiler lief als das Play-Store-Image `Medium_Phone`.
|
||||
|
||||
```bash
|
||||
ANDROID_AVD_HOME=/home/torsten/.config/.android/avd /home/torsten/Android/Sdk/emulator/emulator -avd trainingstagebuchApi35 -no-snapshot-save
|
||||
adb install -r android/android/app/build/outputs/apk/debug/app-debug.apk
|
||||
adb shell am start -W -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -n de.yourpart.app/.MainActivity
|
||||
```
|
||||
|
||||
Ergebnis bisher:
|
||||
|
||||
- Debug-APK wurde erfolgreich gebaut.
|
||||
- APK wurde auf einem Emulator installiert.
|
||||
- App startet als `de.yourpart.app/.MainActivity`.
|
||||
- Login-Screen rendert mobil.
|
||||
- API-Base-URL wurde von `/api` auf die Origin `https://www.your-part.de` korrigiert, damit keine `/api/api`-Requests entstehen.
|
||||
- Capacitor `server.hostname` darf nicht auf `www.your-part.de` gesetzt werden, weil sonst echte Backend- und Model-URLs als lokale App-Assets behandelt werden.
|
||||
- Nach Entfernung der Hostname-Kollision ist die Android-App-Origin `https://localhost`. Das Backend muss diese Origin in `CORS_ORIGINS` erlauben, sonst blockiert die WebView REST- und GLB-Requests.
|
||||
|
||||
### Capacitor Sync
|
||||
|
||||
Nach dem Frontend-Build:
|
||||
|
||||
```bash
|
||||
cd android
|
||||
npx cap sync android
|
||||
```
|
||||
|
||||
Danach:
|
||||
|
||||
```bash
|
||||
cd android
|
||||
npx cap open android
|
||||
```
|
||||
|
||||
Oder per CLI:
|
||||
|
||||
```bash
|
||||
cd android
|
||||
./gradlew assembleDebug
|
||||
```
|
||||
|
||||
Lokaler Build-Hinweis:
|
||||
|
||||
- Auf diesem System liegt das Android SDK unter `/home/torsten/Android/Sdk`.
|
||||
- Die lokale Datei `/android/android/local.properties` setzt `sdk.dir` darauf und ist absichtlich nicht versioniert.
|
||||
- Erstes Debug-APK wurde erfolgreich gebaut: `/android/android/app/build/outputs/apk/debug/app-debug.apk`.
|
||||
|
||||
## Authentifizierung
|
||||
|
||||
### Bestehender Login
|
||||
|
||||
Der bestehende Login kann initial unveraendert bleiben:
|
||||
|
||||
- `POST /api/auth/login`
|
||||
- Antwort enthaelt User inkl. `authCode`
|
||||
- Axios haengt `userid` und `authcode` an Folgerequests
|
||||
- Storage bleibt vorerst `localStorage`/`sessionStorage`
|
||||
|
||||
### Sicherheitsverbesserung
|
||||
|
||||
Phase 1 kann noch mit Web Storage starten. Vor Play-Store-Release sollte Auth aber in native sichere Speicherung verschoben werden:
|
||||
|
||||
- Capacitor Preferences nur fuer unkritische Werte
|
||||
- Fuer sensible Werte besser Android Keystore ueber ein Secure-Storage-Plugin
|
||||
- Migration: Store liest zuerst Secure Storage, fallback auf lokalen Web Storage, migriert dann
|
||||
|
||||
### OAuth
|
||||
|
||||
OAuth ist der groesste Integrationspunkt.
|
||||
|
||||
Kurzfristige Option:
|
||||
|
||||
- OAuth im In-App Browser oder externen Browser starten
|
||||
- Callback bleibt auf `https://www.your-part.de/auth/oauth/callback`
|
||||
- Die Callback-Seite tauscht `code/state` wie bisher gegen einen App-User
|
||||
|
||||
Bessere App-Option:
|
||||
|
||||
- Android App Links fuer `https://www.your-part.de/auth/oauth/callback`
|
||||
- `assetlinks.json` auf der Domain bereitstellen
|
||||
- Capacitor App Plugin verarbeitet den Deep Link und routet intern weiter
|
||||
|
||||
Risiko:
|
||||
|
||||
- OAuth Provider koennen eingebettete WebViews einschraenken. Deshalb sollte OAuth nicht in einer versteckten WebView erzwungen werden, sondern ueber Browser/App Links laufen.
|
||||
|
||||
## API und CORS
|
||||
|
||||
Fuer Capacitor-Bundles ist die Origin nicht immer identisch mit der Website-Origin.
|
||||
|
||||
Zu pruefen:
|
||||
|
||||
- Welche Origin sendet Android WebView bei Requests an `https://www.your-part.de/api`?
|
||||
- Muss `CORS_ORIGINS` um `https://localhost` erweitert werden?
|
||||
- Funktionieren Custom Header `userid` und `authcode` in der WebView?
|
||||
- Funktionieren Preflight-Requests mit den bestehenden erlaubten Headers?
|
||||
|
||||
Noetige Backend-Konfiguration fuer Debug-Builds:
|
||||
|
||||
```env
|
||||
CORS_ORIGINS=https://www.your-part.de,https://localhost,http://localhost:5173,http://127.0.0.1:5173
|
||||
```
|
||||
|
||||
Nur nach Test setzen; nicht blind `CORS_ALLOW_ALL=1` fuer Produktion verwenden.
|
||||
|
||||
## Navigation und Deep Links
|
||||
|
||||
Die Vue-App nutzt `createWebHistory`. In Capacitor kann das funktionieren, aber folgende Punkte muessen getestet werden:
|
||||
|
||||
- Direktstart auf `/`
|
||||
- Interne Navigation zu `/falukant/home`, `/friends`, `/socialnetwork/vocab/...`
|
||||
- Android Back Button
|
||||
- OAuth Callback URL
|
||||
- App-Resume nach Browser-OAuth
|
||||
|
||||
Falls History-Mode Probleme in der WebView macht:
|
||||
|
||||
- Option A: Capacitor-spezifisch auf Hash-History wechseln
|
||||
- Option B: History beibehalten und Deep-Link-Routing sauber behandeln
|
||||
|
||||
Hash-History waere technisch einfacher, aber wegen bestehender SEO-/Web-Routen nicht global fuer das Web-Frontend umstellen.
|
||||
|
||||
## Realtime
|
||||
|
||||
### Socket.IO
|
||||
|
||||
Bestehender Ablauf:
|
||||
|
||||
- Nach Login `initializeSocket`
|
||||
- Socket verbindet zu `VITE_SOCKET_IO_URL`
|
||||
- Client sendet `setUserId` mit `hashedId` oder `id`
|
||||
|
||||
Android-Testfaelle:
|
||||
|
||||
- Login erzeugt Socket-Verbindung
|
||||
- App im Hintergrund trennt/reconnectet sauber
|
||||
- Friend-Login-Events kommen an
|
||||
- Schlechte Verbindung erzeugt keine Endlos-Fehlerdialoge
|
||||
|
||||
### Daemon-WebSocket
|
||||
|
||||
Falukant nutzt zusaetzliche Daemon-Events. Android muss mindestens diese Events empfangen koennen:
|
||||
|
||||
- `falukantUpdateFamily`
|
||||
- `falukantUpdateStatus`
|
||||
- `falukantUpdateProductionCertificate`
|
||||
- `children_update`
|
||||
- `falukantUpdateChurch`
|
||||
- `falukantUpdateDebt`
|
||||
|
||||
Test:
|
||||
|
||||
- WSS ueber produktiven Proxy
|
||||
- Reconnect nach App-Resume
|
||||
- Filterung nach `user_id`
|
||||
|
||||
## Mobile UX Prioritaeten
|
||||
|
||||
Die App sollte nicht nur ein Desktop-Layout in einer WebView zeigen. Phase 1 braucht mindestens diese UX-Haertung:
|
||||
|
||||
- Header/Navigation auf kleinen Viewports pruefen
|
||||
- Dialoge auf 360px Breite testen
|
||||
- Tabellen und breite Falukant-Views horizontal oder responsiv absichern
|
||||
- Touch-Ziele mindestens ca. 44px
|
||||
- Keyboard-Verhalten im Login/Register testen
|
||||
- Safe Area Insets fuer Statusbar/Navigationbar beachten
|
||||
- Android Back Button: Dialog schliessen, sonst Router zurueck, sonst App minimieren
|
||||
|
||||
Aktueller Stand 2026-07-08:
|
||||
|
||||
- Hauptnavigation ist auf kleinen Viewports zu einer kompakten Menueleiste mit aufklappbarem, scrollbarem Menue umgebaut.
|
||||
- Header ist auf Smartphone-Breite kompakter, Statusanzeigen laufen zweispaltig statt als lange Desktop-Leiste.
|
||||
- Footer blendet leere System-/Fensterbereiche auf Smartphone-Breite aus und reserviert Safe-Area-Abstand nach unten.
|
||||
- App-Shell nutzt `100dvh` als Android-WebView-freundlichere Viewport-Hoehe.
|
||||
|
||||
## Datenschutz, Content und Store-Risiken
|
||||
|
||||
Das Projekt enthaelt Social-, Chat-, Galerie-, Erotik-/Adult- und Moderationsbereiche. Fuer Play Store sind diese Punkte kritisch:
|
||||
|
||||
- Altersfreigabe und Adult-Content-Gating
|
||||
- UGC-Moderation, Meldefunktion, Blockieren
|
||||
- Datenschutzrichtlinie in der App und im Store Listing
|
||||
- Account-Loeschung oder klare Anleitung
|
||||
- Sichere Uebertragung nur per HTTPS/WSS
|
||||
- Keine unsicheren Debug-Endpunkte im Release-Build
|
||||
- Keine Secrets im Android-Bundle
|
||||
|
||||
Vor Play-Store-Release muss ein eigener Compliance-Check erfolgen.
|
||||
|
||||
## Teststrategie
|
||||
|
||||
### Lokale Tests
|
||||
|
||||
- Android Emulator mit Debug-Build
|
||||
- Echtes Android-Geraet im gleichen Netz
|
||||
- Produktions-API mit Testnutzer
|
||||
- Offline/Online-Wechsel
|
||||
- App Kill/Restart/Resume
|
||||
|
||||
### Kern-Testmatrix
|
||||
|
||||
- Login mit Username/Passwort
|
||||
- Logout
|
||||
- Registrierung
|
||||
- Passwort vergessen
|
||||
- OAuth Login je Provider, soweit konfiguriert
|
||||
- Menu-Load nach Login
|
||||
- Falukant Overview laden
|
||||
- Falukant Realtime-Update empfangen
|
||||
- Vokabeltrainer Lesson starten und abschliessen
|
||||
- Chat verbinden und Nachricht empfangen
|
||||
- Galerie/Bild-Upload, falls mobil zunaechst erlaubt
|
||||
- Minigames Touch-Steuerung
|
||||
- Admin-Bereiche entweder nutzbar oder bewusst ausgeblendet
|
||||
|
||||
### Build-Checks
|
||||
|
||||
- `npm run build` im Frontend
|
||||
- Android Web-Build mit `.env.android`
|
||||
- `npx cap sync android`
|
||||
- `./gradlew assembleDebug`
|
||||
- `./gradlew lint`
|
||||
- Release-Build mit Signing-Konfiguration
|
||||
|
||||
## Verbleibende offene Punkte
|
||||
|
||||
- Produktivdomain final technisch testen: voraussichtlich `https://www.your-part.de`.
|
||||
- Daemon-WebSocket-URL und Pfad final gegen Deploy-/Proxy-Konfiguration testen.
|
||||
- Mindest-Android-Version aus Capacitor-Default uebernehmen und nach erstem Scaffold im Gradle-Projekt dokumentieren.
|
||||
- Play-Store-Entscheidung bleibt nachgelagert bis Compliance-Pruefung abgeschlossen ist.
|
||||
|
||||
## TODO
|
||||
|
||||
### 1. Grundsatzentscheidungen
|
||||
|
||||
- [x] App-ID festlegen: `de.yourpart.app`.
|
||||
- [x] App-Name und Launcher-Label festlegen: `YourPart`.
|
||||
- [x] Ziel-Distribution festlegen: zuerst interne Debug-/Test-APK.
|
||||
- [x] Entscheiden, ob Admin-Routen in der App sichtbar bleiben: nicht priorisiert, nicht aktiv entfernt.
|
||||
- [x] Entscheiden, wie Adult-/Erotikbereiche in Android behandelt werden: bestehendes Web-Gating, kein Play Store ohne Compliance-Check.
|
||||
- [x] Entscheiden, ob Backend Teil des Android-Starts ist: nein, nur Kompatibilitaetstests.
|
||||
- [x] Entscheiden, ob Push Teil des ersten Scaffolds ist: nein.
|
||||
- [x] Entscheiden, ob OAuth erster Blocker ist: nein, Username/Passwort-Login zuerst.
|
||||
|
||||
### 2. Android-Projekt scaffolden
|
||||
|
||||
- [x] In `/android` eigenes `package.json` anlegen.
|
||||
- [x] Capacitor installieren: `@capacitor/core`, `@capacitor/cli`, `@capacitor/android`.
|
||||
- [x] `capacitor.config.ts` mit App-ID `de.yourpart.app`, App-Name `YourPart` und `webDir` auf `../frontend/dist` konfigurieren.
|
||||
- [x] Android-Plattform generieren: `npx cap add android`.
|
||||
- [x] `/android/README.md` mit Build-Kommandos anlegen.
|
||||
- [x] Entscheiden, ob generiertes `/android/android` versioniert wird: ja.
|
||||
|
||||
### 3. Frontend Android-Build
|
||||
|
||||
- [x] `frontend/.env.android.example` anlegen.
|
||||
- [x] `VITE_API_BASE_URL` fuer Android explizit setzen.
|
||||
- [x] `VITE_SOCKET_IO_URL` fuer Android explizit setzen.
|
||||
- [x] `VITE_DAEMON_SOCKET` fuer Android explizit setzen.
|
||||
- [x] Root- oder Android-Script fuer `build:android:web` ergaenzen.
|
||||
- [x] Android-Web-Build mit produktiver Origin statt lokaler Dev-URL bauen.
|
||||
- [ ] Release-Build-Gate ergaenzen, das lokale Dev-URLs automatisiert verhindert.
|
||||
|
||||
### 4. Backend-Kompatibilitaet
|
||||
|
||||
- [ ] Android-Origin im CORS-Verhalten messen.
|
||||
- [x] Fehlerhafte Android-Request-Basis `/api/api` identifizieren und durch Origin-only-Config beheben.
|
||||
- [x] Capacitor-Hostname-Kollision mit Backend-Host vermeiden; `server.hostname` bleibt Default.
|
||||
- [x] `CORS_ORIGINS` fuer Capacitor als bestehenden Backend-Konfigurationspunkt notieren: `https://localhost`.
|
||||
- [ ] Produktiv-/Testbackend mit `CORS_ORIGINS` inklusive `https://localhost` neu starten und Android-Requests erneut pruefen.
|
||||
- [ ] Custom Header `userid`/`authcode` auf Android testen.
|
||||
- [ ] Socket.IO-Verbindung von Android testen.
|
||||
- [ ] Daemon-WebSocket ueber Android testen.
|
||||
- [ ] Produktionsproxy fuer HTTPS/WSS pruefen.
|
||||
- [ ] Keine Backend-Aenderung ohne konkreten fehlgeschlagenen Android-Test einplanen.
|
||||
|
||||
### 5. Auth und OAuth
|
||||
|
||||
- [ ] Username/Passwort-Login in Android testen.
|
||||
- [ ] Persistenz nach App-Neustart testen.
|
||||
- [ ] Logout inklusive Socket-Cleanup testen.
|
||||
- [ ] OAuth-Login-Flow je Provider testen.
|
||||
- [ ] Entscheiden: OAuth per externem Browser plus App Links oder innerhalb bestehender WebView.
|
||||
- [ ] Android App Links einrichten, falls OAuth nativ zurueck in die App fuehren soll.
|
||||
- [ ] Authdaten spaeter in Secure Storage migrieren.
|
||||
|
||||
### 6. Native App-Verhalten
|
||||
|
||||
- [ ] Android Back Button behandeln.
|
||||
- [ ] Splash Screen konfigurieren.
|
||||
- [ ] App Icons erzeugen.
|
||||
- [ ] Statusbar/Safe-Area pruefen; aktueller Test zeigt nicht-blockierende Safe-Area-CSS-Console-Fehler.
|
||||
- [x] WebView-Textfeld-Eingabe fuer Emulator reparieren: `android.captureInput` nicht aktivieren.
|
||||
- [x] Android-Studio-Projektpfad dokumentieren: `/android/android`.
|
||||
- [x] Android-Studio-Run-Configuration `YourPart Debug` anlegen.
|
||||
- [ ] Deep-Link-Handling vorbereiten.
|
||||
- [ ] App Resume/Pause Events fuer Socket-Reconnect nutzen.
|
||||
|
||||
### 7. Mobile UI-Haertung
|
||||
|
||||
- [ ] Login/Register auf 360px Breite testen.
|
||||
- [x] Login-Screen im Emulator visuell pruefen.
|
||||
- [x] Parameterlisten-Handling gegen Nicht-Array-Antworten haerten, damit Backend-Fehler keine UI-Exception ausloesen.
|
||||
- [x] 3D-Modelle fuer Android-Debug per `VITE_DISABLE_3D=true` deaktivieren, damit Login/Onboarding stabil bleibt.
|
||||
- [x] Hauptnavigation fuer kleine Viewports umbauen: kompakte Menueleiste plus scrollbares Menue statt voller Desktop-Navigation.
|
||||
- [ ] Hauptnavigation mobil mit mehreren Rollen/Berechtigungssets testen.
|
||||
- [ ] Dialoge auf kleinen Screens pruefen.
|
||||
- [ ] Falukant-Views mit breiten Tabellen pruefen.
|
||||
- [ ] Vokabeltrainer Touch- und Keyboard-Verhalten testen.
|
||||
- [ ] Minigames separat auf Touch-Performance testen.
|
||||
- [ ] Bild-/Dateiupload auf Android pruefen.
|
||||
|
||||
### 8. Push Notifications
|
||||
|
||||
- [ ] Entscheiden, ob Push in Phase 1 oder spaeter kommt.
|
||||
- [ ] Event-Kandidaten definieren: Chat, Friend Login, Falukant, Vocab Reminder.
|
||||
- [ ] Backend-Device-Token-Modell planen.
|
||||
- [ ] FCM-Projekt konfigurieren.
|
||||
- [ ] Opt-in und Settings-UI planen.
|
||||
|
||||
### 9. Store/Compliance
|
||||
|
||||
- [ ] Datenschutzseite in App erreichbar machen.
|
||||
- [ ] Impressum in App erreichbar machen.
|
||||
- [ ] Account-Loeschung/Anfrageprozess klaeren.
|
||||
- [ ] Adult Content Policy pruefen.
|
||||
- [ ] UGC-Moderation fuer Store Review dokumentieren.
|
||||
- [ ] Release-Build ohne Debug-Konfiguration pruefen.
|
||||
|
||||
### 10. CI/CD
|
||||
|
||||
- [x] Android-Build-Script anlegen.
|
||||
- [x] Debug-Build lokal reproduzierbar machen.
|
||||
- [ ] Release-Signing-Konzept festlegen.
|
||||
- [ ] Keystore sicher ausserhalb des Repos verwalten.
|
||||
- [ ] Optional CI-Job fuer `frontend build` + `cap sync` + Gradle Build einrichten.
|
||||
|
||||
## Empfohlene erste Umsetzungsschritte
|
||||
|
||||
1. `/android` als Capacitor-Projekt initialisieren.
|
||||
2. `frontend/.env.android.example` und Android-Build-Script anlegen.
|
||||
3. Debug-APK mit produktiver Test-API bauen.
|
||||
4. Login, Menu, Falukant Overview und Socket.IO testen.
|
||||
5. Erst danach OAuth, Deep Links und Push angehen.
|
||||
|
||||
## Abnahmekriterien fuer Phase 1
|
||||
|
||||
- App installiert und startet auf Emulator und echtem Android-Geraet.
|
||||
- Login/Logout funktionieren.
|
||||
- Persistierter Login funktioniert nach App-Neustart.
|
||||
- API-Requests senden `userid` und `authcode` korrekt.
|
||||
- Socket.IO verbindet nach Login und reconnectet nach Resume.
|
||||
- Mindestens Falukant Overview, Vokabeltrainer-Liste und Social/Friends laden.
|
||||
- Android Back Button fuehrt nicht zu kaputten Zustanden.
|
||||
- Build ist reproduzierbar dokumentiert.
|
||||
|
||||
Aktueller Stand:
|
||||
|
||||
- Android/Capacitor-Projekt ist erzeugt.
|
||||
- Android-Web-Build ist erfolgreich.
|
||||
- Capacitor Sync ist erfolgreich.
|
||||
- Debug-APK-Build ist erfolgreich.
|
||||
- Installation und Laufzeittests auf Emulator/Geraet stehen noch aus.
|
||||
@@ -1,58 +0,0 @@
|
||||
# Android App Links und OAuth
|
||||
|
||||
## Verbindliche Domain
|
||||
|
||||
Die Produktions-App verwendet ausschließlich `https://www.your-part.de`.
|
||||
Staging und lokale Builds öffnen diese URLs weiterhin im Browser und beanspruchen keine
|
||||
Domain-Verknüpfung.
|
||||
|
||||
## Unterstützte Pfade
|
||||
|
||||
| Web-Pfad | Native Route | Anmeldung |
|
||||
| --- | --- | --- |
|
||||
| `/` | `home` | ja |
|
||||
| `/socialnetwork/*` | Community, Suche, Galerie, Forum oder Vokabeln | ja |
|
||||
| `/falukant/*` | `falukant` | ja |
|
||||
| `/settings/*` | `settings` | ja |
|
||||
| `/blogs/*` | `blogs` | nein |
|
||||
| `/guides/*` | `guides` | nein |
|
||||
| `/android/oauth/callback` | OAuth-Callback | nein |
|
||||
|
||||
Geschützte Links bleiben im Speicher erhalten. Nach erfolgreichem Login navigiert die App
|
||||
automatisch zur ursprünglich angeforderten Route.
|
||||
|
||||
## OAuth
|
||||
|
||||
Die native App startet `/api/auth/oauth/{provider}/start?client=android` in einer Android
|
||||
Custom Tab. Der Server erzeugt PKCE und `state`, speichert beides in Redis und nutzt als feste
|
||||
Redirect-URI `https://www.your-part.de/android/oauth/callback`. Die App sendet nur `code`,
|
||||
`state` und optional `iss` an `/api/auth/oauth/exchange`; Tokens von OAuth-Providern gelangen
|
||||
nicht in die App.
|
||||
|
||||
In jedem aktivierten Provider muss diese URI als Redirect URI hinterlegt sein:
|
||||
|
||||
```text
|
||||
https://www.your-part.de/android/oauth/callback
|
||||
```
|
||||
|
||||
Optional kann das Backend die URL mittels `OAUTH_ANDROID_CALLBACK_URL` überschreiben. Der Wert
|
||||
muss HTTPS verwenden und exakt den Pfad `/android/oauth/callback` haben.
|
||||
|
||||
## assetlinks.json
|
||||
|
||||
Nach Erzeugung des Release-Keystores den SHA-256-Fingerprint ermitteln:
|
||||
|
||||
```bash
|
||||
keytool -list -v -keystore release.jks -alias <alias>
|
||||
```
|
||||
|
||||
`frontend/public/.well-known/assetlinks.json.example` nach
|
||||
`frontend/public/.well-known/assetlinks.json` kopieren, den Platzhalter durch den Fingerprint
|
||||
ersetzen und mit dem Frontend ausliefern. Die finale Datei muss unter dieser URL ohne Redirect
|
||||
und mit `Content-Type: application/json` abrufbar sein:
|
||||
|
||||
```text
|
||||
https://www.your-part.de/.well-known/assetlinks.json
|
||||
```
|
||||
|
||||
Erst dann kann Android `android:autoVerify` erfolgreich abschließen.
|
||||
@@ -1,869 +0,0 @@
|
||||
# Native Android App Plan fuer YourPart3
|
||||
|
||||
Stand: 2026-07-08
|
||||
|
||||
## Zielbild
|
||||
|
||||
Dieses Dokument plant eine komplette native Android-App fuer YourPart3 als langfristige Ablösung bzw. Ergänzung der aktuellen Capacitor-Hybrid-App.
|
||||
|
||||
Ziel ist eine echte Android-App mit:
|
||||
|
||||
- Kotlin
|
||||
- Jetpack Compose
|
||||
- MVVM bzw. unidirektionalem UI-State
|
||||
- Retrofit/OkHttp fuer REST
|
||||
- Kotlinx Serialization oder Moshi fuer JSON
|
||||
- Room/DataStore fuer lokale Persistenz
|
||||
- Android Keystore fuer sensible Authdaten
|
||||
- Socket.IO/WebSocket-Clients fuer Realtime
|
||||
- Coil fuer Bilder
|
||||
- WorkManager fuer Hintergrundjobs
|
||||
- FCM fuer Push Notifications
|
||||
|
||||
Das vorhandene Backend bleibt die maßgebliche Datenquelle. Eine native Komplettumsetzung bedeutet deshalb nicht, das Backend neu zu schreiben, sondern die bestehende Web-App-Funktionalitaet systematisch in native Screens, native Navigation und robuste mobile Datenmodelle zu ueberfuehren.
|
||||
|
||||
## Grundentscheidung
|
||||
|
||||
- Die bestehende Hybrid-App bleibt als lauffaehige Zwischenloesung erhalten.
|
||||
- Die native App wird parallel aufgebaut.
|
||||
- Nicht als Big Bang migrieren. Stattdessen werden Modulgruppen nacheinander nativ umgesetzt und gegen produktionsnahe APIs getestet.
|
||||
- Admin- und Adult-Bereiche werden nicht im ersten nativen MVP umgesetzt.
|
||||
- Backend-Aenderungen sind nur erlaubt, wenn sie fuer stabile mobile API-Vertraege, Sicherheit, Push oder Datei-Uploads notwendig sind.
|
||||
|
||||
## Native Zielarchitektur
|
||||
|
||||
```text
|
||||
android-native/
|
||||
app/
|
||||
core/
|
||||
network/
|
||||
auth/
|
||||
database/
|
||||
realtime/
|
||||
design/
|
||||
common/
|
||||
feature-auth/
|
||||
feature-home/
|
||||
feature-social/
|
||||
feature-chat/
|
||||
feature-falukant/
|
||||
feature-vocab/
|
||||
feature-settings/
|
||||
feature-media/
|
||||
feature-minigames/
|
||||
feature-admin/ # spaeter
|
||||
```
|
||||
|
||||
Empfohlener Pfad im Repository:
|
||||
|
||||
- Entweder `/android/native` fuer die neue native App neben der Capacitor-App.
|
||||
- Oder spaeter Migration von `/android/android` zu einem rein nativen Gradle-Projekt.
|
||||
|
||||
Empfehlung: `/android/native`, damit die Hybrid-App weiter testbar bleibt.
|
||||
|
||||
## Technische Zielentscheidungen
|
||||
|
||||
- Sprache: Kotlin.
|
||||
- UI: Jetpack Compose, Material 3, eigene YourPart-Design-Tokens.
|
||||
- Min SDK: aus Capacitor-Projekt/Play-Store-Ziel final ableiten, voraussichtlich Android 8+ oder Android 9+.
|
||||
- Navigation: Compose Navigation mit typed Routes.
|
||||
- Dependency Injection: Hilt.
|
||||
- REST: Retrofit + OkHttp Interceptors.
|
||||
- JSON: Kotlinx Serialization, falls Backend-Antworten stabil typisiert werden; sonst Moshi als toleranterer Start.
|
||||
- Lokale Einstellungen: DataStore Preferences.
|
||||
- Lokale Daten: Room fuer Cache, Entitaeten, Outbox.
|
||||
- Auth-Geheimnisse: EncryptedSharedPreferences oder direkter Keystore-basierter Token Store.
|
||||
- Bilder: Coil.
|
||||
- Datei-Uploads: OkHttp Multipart, Android Photo Picker.
|
||||
- Realtime: Socket.IO Android Client plus separater OkHttp WebSocket fuer Daemon.
|
||||
- Push: Firebase Cloud Messaging.
|
||||
- Tests: JUnit, Turbine, MockWebServer, Compose UI Tests.
|
||||
|
||||
## API-Strategie
|
||||
|
||||
Die Web-App nutzt aktuell viele direkte REST-Aufrufe aus Komponenten. Fuer native Android muss daraus ein klarer API-Client entstehen.
|
||||
|
||||
Native API-Schichten:
|
||||
|
||||
- `AuthApi`
|
||||
- `SettingsApi`
|
||||
- `MenuApi`
|
||||
- `SocialApi`
|
||||
- `GalleryApi`
|
||||
- `ForumApi`
|
||||
- `ChatApi`
|
||||
- `FalukantApi`
|
||||
- `VocabApi`
|
||||
- `CalendarApi`
|
||||
- `BlogGuideApi`
|
||||
- `MinigamesApi`
|
||||
- `AdminApi` spaeter
|
||||
|
||||
Wichtige Backend-Vertraege:
|
||||
|
||||
- Login liefert User inklusive `id` und `authCode`.
|
||||
- REST-Requests brauchen Header `userid` und `authcode`.
|
||||
- Socket.IO registriert User per `setUserId`.
|
||||
- Daemon-WebSocket nutzt eigene Events und User-Kontext.
|
||||
- Datei-/Bild-Endpunkte muessen Android Multipart und Android Content-URIs sauber unterstuetzen.
|
||||
|
||||
## Migrationsprinzip
|
||||
|
||||
Jedes Modul wird in vier Schritten umgesetzt:
|
||||
|
||||
1. API-Vertrag erfassen: Endpunkte, Payloads, Fehler, Rechte.
|
||||
2. Domain-Modelle definieren: Kotlin DTOs, Mapping, UI-State.
|
||||
3. Native Compose-UI bauen: kleine Screens, klare Loading/Error/Empty States.
|
||||
4. Gegen Backend testen: Emulator, echtes Geraet, Offline/Resume, Realtime.
|
||||
|
||||
## MVP-Schnitt
|
||||
|
||||
Ein sinnvoller nativer MVP ist nicht "alles", sondern:
|
||||
|
||||
- Login/Logout
|
||||
- Session-Persistenz
|
||||
- Home/Dashboard
|
||||
- native Navigation
|
||||
- Settings: Sprache und Account-Basis
|
||||
- Friends/Search/Profile light
|
||||
- Chat light
|
||||
- Falukant Overview + Status + Branch-Liste light
|
||||
- Vokabeltrainer Course/Lesson light
|
||||
- Push-Grundlage optional
|
||||
|
||||
Alles Weitere wird danach iterativ migriert.
|
||||
|
||||
## Nicht-Ziele fuer den nativen MVP
|
||||
|
||||
- Kein vollstaendiger Admin-Bereich.
|
||||
- Keine vollstaendige Falukant-Wirtschaftssimulation in Version 1.
|
||||
- Keine nativen Minigames in Version 1, ausser als separate Spike-/Proof-of-Concepts.
|
||||
- Keine 3D-Charakterdarstellung in Version 1.
|
||||
- Keine Offline-First-Synchronisation fuer alle Module.
|
||||
- Keine Store-Verteilung vor Datenschutz-/UGC-/Adult-Compliance.
|
||||
|
||||
## Risiken
|
||||
|
||||
- Sehr breite Web-App-Funktionalitaet: ein nativer Rewrite ist ein Mehrmonatsthema, nicht ein Scaffold-Thema.
|
||||
- API-Vertraege sind aktuell komponentennah, nicht als Mobile API versioniert.
|
||||
- Auth nutzt `userid`/`authcode` statt standardisiertem Bearer Token.
|
||||
- Viele Screens erwarten Web-Layout, Dialoge und dynamische Menues.
|
||||
- Falukant ist daten- und realtime-intensiv.
|
||||
- Chat, Galerie, Adult Content und UGC erfordern Store-Compliance.
|
||||
- Native 3D/Minigames brauchen eigene Performance-Entscheidungen.
|
||||
|
||||
## Abhakbare Roadmap
|
||||
|
||||
### 0. Projektentscheidung und Scope
|
||||
|
||||
Entscheidungen:
|
||||
|
||||
- Native App wird unter `/android/native` aufgebaut.
|
||||
- Die bestehende Capacitor-App bleibt parallel erhalten, bis die native App mindestens den MVP stabil abdeckt.
|
||||
- Der native MVP ist kein vollstaendiger Rewrite, sondern ein lauffaehiger nativer Kern: Auth, App-Shell, Home, Settings light, Social light, Chat light, Falukant light, Vokabeltrainer light.
|
||||
- Admin wird aus dem nativen MVP ausgeschlossen.
|
||||
- Adult-/Erotikbereiche werden aus dem nativen MVP ausgeschlossen und nur spaeter mit separater Compliance-Entscheidung umgesetzt.
|
||||
- Minigames werden aus dem nativen MVP ausgeschlossen und spaeter als eigener Performance-/Touch-Spike bewertet.
|
||||
- 3D-Charaktere werden aus dem nativen MVP ausgeschlossen und spaeter als eigener Rendering-Spike bewertet.
|
||||
- Zielgeraete fuer MVP: kleine Phones ab 360dp Breite, normale Phones, spaeter Tablet-Layouts ab 600dp.
|
||||
- Mindest-Android fuer MVP: Android 8.0 / API 26, sofern Dependencies und Testgeraete keine hoehere Grenze erzwingen.
|
||||
- Distribution fuer MVP: interne Debug-/Test-APK. Play Store bleibt nachgelagert bis Compliance, Signing, Datenschutz und Store-Review vorbereitet sind.
|
||||
|
||||
Todo:
|
||||
|
||||
- [x] Entscheiden, ob die native App unter `/android/native` angelegt wird.
|
||||
- [x] Entscheiden, ob die Capacitor-App langfristig parallel gepflegt bleibt.
|
||||
- [x] Native MVP-Funktionsumfang final freigeben.
|
||||
- [x] Admin-Bereich aus MVP ausschliessen oder explizit aufnehmen.
|
||||
- [x] Adult-/Erotikbereiche aus MVP ausschliessen oder explizit mit Compliance-Aufwand aufnehmen.
|
||||
- [x] Minigames aus MVP ausschliessen oder als separaten Spike aufnehmen.
|
||||
- [x] 3D-Charaktere aus MVP ausschliessen oder als separaten Spike aufnehmen.
|
||||
- [x] Zielgeraete festlegen: kleine Phones, Tablets, Mindest-Android-Version.
|
||||
- [x] Play-Store-Zieltermin oder interne Distribution als Ziel definieren.
|
||||
|
||||
### 1. Native Projektbasis
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Native Projektbasis ist unter `/android/native` angelegt.
|
||||
- Gradle Kotlin DSL ist aktiv.
|
||||
- Separate Native-App-ID ist bewusst gewaehlt: `de.yourpart.nativeapp` mit Flavor-/Build-Type-Suffixen fuer parallele Installation.
|
||||
- Flavors `local`, `staging`, `production` sind angelegt.
|
||||
- Build Types `debug`, `release` sind angelegt.
|
||||
- Versionierung ist initial definiert: `versionCode`, `versionName`, `BuildConfig.GIT_SHA`.
|
||||
- Compose, Material 3, Hilt, Retrofit/OkHttp, Kotlinx Serialization JSON, Room, DataStore, Coil, WorkManager und FCM-Dependency sind im Projekt hinterlegt.
|
||||
- Ein reproduzierbarer lokaler Build laeuft erfolgreich: `:app:assembleLocalDebug`.
|
||||
|
||||
- [x] Neues natives Gradle-Projekt unter `/android/native` erstellen.
|
||||
- [x] Kotlin DSL fuer Gradle verwenden.
|
||||
- [x] App-ID `de.yourpart.app` oder separate Dev-ID `de.yourpart.native.dev` entscheiden.
|
||||
- [x] Produktflavors anlegen: `local`, `staging`, `production`.
|
||||
- [x] Build Types anlegen: `debug`, `release`.
|
||||
- [x] Versionierung definieren: `versionCode`, `versionName`, Git-Hash im Build.
|
||||
- [x] Compose aktivieren.
|
||||
- [x] Material 3 aktivieren.
|
||||
- [x] Hilt einrichten.
|
||||
- [x] Retrofit/OkHttp einrichten.
|
||||
- [x] JSON-Library festlegen und einrichten.
|
||||
- [x] Room einrichten.
|
||||
- [x] DataStore einrichten.
|
||||
- [x] Coil einrichten.
|
||||
- [x] WorkManager einrichten.
|
||||
- [x] FCM Dependency vorbereiten, aber noch nicht aktiv schalten.
|
||||
- [x] Lint, Detekt oder Ktlint einrichten.
|
||||
- [x] CI-Build-Script fuer native App definieren.
|
||||
|
||||
### 2. Design System
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Die Web-Farbpalette ist in native Tokens uebertragen.
|
||||
- Typography, Spacing und Shapes sind als Theme-Tokens angelegt.
|
||||
- Wiederverwendbare Compose-Bausteine existieren fuer Buttons, Textfelder, Dialoge, Info-/Loading-/Empty-States, Avatar und Status-Chips.
|
||||
- Das Light Theme ist aktiv und die Demo-Shell nutzt die neuen Komponenten bereits.
|
||||
- Ein minimales Dark-Theme-Grundgeruest existiert technisch, die Produktentscheidung dafuer bleibt aber offen.
|
||||
|
||||
- [x] YourPart-Farbpalette aus Web-App ableiten.
|
||||
- [x] Typography fuer Android definieren.
|
||||
- [x] Spacing-Skala definieren.
|
||||
- [x] Shape-/Radius-System definieren.
|
||||
- [x] Button-Komponenten definieren.
|
||||
- [x] TextField-Komponenten definieren.
|
||||
- [x] Dialog-Komponenten definieren.
|
||||
- [x] Error-/Info-/Success-Komponenten definieren.
|
||||
- [x] Loading/Empty-State-Komponenten definieren.
|
||||
- [x] Avatar-/Image-Komponenten definieren.
|
||||
- [x] Status-Chips fuer Backend/Daemon definieren.
|
||||
- [x] Light Theme implementieren.
|
||||
- [x] Dark Theme bewusst entscheiden: nein, nicht Teil des MVP.
|
||||
- [x] Kleine Displaybreiten 360dp und 393dp als Design-Baseline testen: nein, nicht Teil des MVP.
|
||||
|
||||
### 3. App Shell und Navigation
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Die Demo-App ist zu einer nativen Shell mit Navigation ausgebaut.
|
||||
- Top App Bar, Bottom Navigation und Drawer existieren.
|
||||
- Primaere und sekundaere Bereiche sind als Route-Objekte modelliert.
|
||||
- Eine erste Menue-Policy auf Basis von Session/Rollen ist vorhanden.
|
||||
- Drawer-Back-Handling und Session-expired Rueckfuehrung zur Auth-Route sind umgesetzt.
|
||||
- Offline-Banner sowie kompakte Backend-/Daemon-Status-Chips sind sichtbar.
|
||||
|
||||
- [x] Root Compose App mit Theme erstellen.
|
||||
- [x] Top App Bar definieren.
|
||||
- [x] Bottom Navigation fuer Hauptbereiche definieren.
|
||||
- [x] Navigation Drawer fuer Sekundaerbereiche definieren.
|
||||
- [x] Typed Routes fuer Auth, Home, Social, Falukant, Vocab, Settings anlegen.
|
||||
- [x] Rollen-/Rechte-basierte Menueeintraege modellieren.
|
||||
- [x] Backend-Menue-Response analysieren und native Menue-Policy definieren.
|
||||
- [x] Android Back Button Verhalten definieren.
|
||||
- [x] Dialog-Back-Handling implementieren.
|
||||
- [x] Session-expired Navigation implementieren.
|
||||
- [x] Offline-Banner implementieren.
|
||||
- [x] Backend-/Daemon-Status sichtbar, aber kompakt darstellen.
|
||||
|
||||
### 4. Konfiguration und Environments
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Flavor-spezifische URLs fuer `local`, `staging`, `production` sind im Build hinterlegt.
|
||||
- `local` nutzt bewusst `10.0.2.2` fuer Emulator-Zugriff.
|
||||
- Release-Builds validieren automatisch, dass `staging` und `production` keine lokalen oder unverschluesselten URLs verwenden.
|
||||
- Debug und Release nutzen getrennte Network-Security-Configs.
|
||||
- Release verbietet Cleartext komplett.
|
||||
- Feature Flags fuer `Admin`, `Adult`, `3D`, `Minigames` und `Push` sind als BuildConfig-Felder angelegt.
|
||||
- Eine zentrale `AppConfig` liest die Flavor-/Build-Konfiguration aus `BuildConfig`.
|
||||
|
||||
- [x] API Base URLs fuer `local`, `staging`, `production` definieren.
|
||||
- [x] Socket.IO URLs je Flavor definieren.
|
||||
- [x] Daemon WebSocket URLs je Flavor definieren.
|
||||
- [x] Lokale Emulator-Regel dokumentieren: Host-Rechner ist `10.0.2.2`.
|
||||
- [x] Release-Build gegen lokale URLs blockieren.
|
||||
- [x] Network Security Config fuer Debug und Release definieren.
|
||||
- [x] TLS-only fuer Release sicherstellen.
|
||||
- [x] Secrets aus APK fernhalten.
|
||||
- [x] Feature Flags definieren: Admin, Adult, 3D, Minigames, Push.
|
||||
|
||||
### 5. Auth und Session
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Login, Logout und Session-Persistenz sind nativ angebunden.
|
||||
- REST-Requests setzen automatisch `userid` und `authcode`.
|
||||
- 401-Antworten fuehren zu Session-Loeschung und Session-expired-Hinweis.
|
||||
- Registrierung, Passwort-Reset und OAuth-Provider-Liste sind als native Auth-Bausteine vorhanden.
|
||||
|
||||
- [x] Login-Endpunkt dokumentieren.
|
||||
- [x] Login DTOs erstellen.
|
||||
- [x] Login Repository implementieren.
|
||||
- [x] Auth Interceptor fuer `userid` und `authcode` implementieren.
|
||||
- [x] Session Store mit sicherer Speicherung implementieren.
|
||||
- [x] Auto-Login beim App-Start implementieren.
|
||||
- [x] Logout implementieren.
|
||||
- [x] Session-expired Handling implementieren.
|
||||
- [x] User-Aktivstatus pruefen.
|
||||
- [x] Account gesperrt Handling implementieren.
|
||||
- [x] Registrierung API-Vertrag erfassen.
|
||||
- [x] Registrierung Screen implementieren.
|
||||
- [ ] Account-Aktivierung Flow bewerten.
|
||||
- [x] Passwort-Reset Flow implementieren.
|
||||
- [x] OAuth-Provider-Liste laden.
|
||||
- [ ] OAuth per Custom Tabs planen.
|
||||
- [ ] App Links fuer OAuth Callback planen.
|
||||
- [ ] OAuth erst nach Username/Passwort stabil aktivieren.
|
||||
|
||||
### 6. Netzwerk-Grundlage
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Eine zentrale `ApiResult`/`NetworkError`-Basis ist angelegt.
|
||||
- Backend-Fehler werden zentral geparst und in lesbare Meldungen ueberfuehrt.
|
||||
- Timeout- und Retry-Policy sind als feste Netzwerk-Defaults definiert.
|
||||
- Debug-Logging laeuft nur ausserhalb von Release.
|
||||
- Multipart- und Download-Helfer sind vorhanden.
|
||||
- Ein MockWebServer-Test prueft den Auth-Header-Interceptor.
|
||||
- Ein zentraler `NetworkRequestExecutor` fasst OkHttp-Fehlerbehandlung fuer Repository-Aufrufe zusammen.
|
||||
|
||||
- [x] Zentrale `ApiResult`/`NetworkError` Struktur definieren.
|
||||
- [x] Fehlercodes und Backend-Fehlerformate erfassen.
|
||||
- [x] Retry-Policy definieren.
|
||||
- [x] Timeout-Policy definieren.
|
||||
- [x] Request Logging nur fuer Debug aktivieren.
|
||||
- [x] Auth Header Tests mit MockWebServer schreiben.
|
||||
- [x] CORS ist nativ irrelevant, aber Backend-Origin-Checks gegen mobile Clients pruefen.
|
||||
- [x] Multipart Upload Helper bauen.
|
||||
- [x] Download Helper fuer Bilder/Dateien bauen.
|
||||
- [x] Pagination Pattern definieren.
|
||||
- [x] Refresh Pattern definieren.
|
||||
|
||||
### 7. Lokale Persistenz und Cache
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Ein zentraler Preferences-Store fuer UI-Sprache und Feature-Flags ist angelegt.
|
||||
- Eine Room-Cache-Basis mit ersten Tabellen fuer Profil, Friends-Search, Falukant-Status und Vokabeldaten ist definiert.
|
||||
- Cache-TTLs und Invalidierungsregeln sind als feste Policy hinterlegt.
|
||||
- Die MVP-Entscheidung lautet: Offline-Anzeige statt Offline-First.
|
||||
- Outbox/Offline-Write-Queues werden im MVP nur geplant, nicht erzwungen.
|
||||
|
||||
- [x] DataStore fuer UI-Sprache verwenden.
|
||||
- [x] DataStore fuer Feature Flags verwenden.
|
||||
- [x] Room Schema fuer User/Profile Cache definieren.
|
||||
- [x] Room Schema fuer Friends/Search Cache definieren.
|
||||
- [x] Room Schema fuer Falukant Status light definieren.
|
||||
- [x] Room Schema fuer Vocab Course/Lesson Cache definieren.
|
||||
- [x] Cache-Invalidation Regeln definieren.
|
||||
- [x] Offline-Anzeige statt Offline-First fuer MVP festlegen.
|
||||
- [x] Outbox fuer spaetere Offline-Aktionen nur planen, nicht im MVP erzwingen.
|
||||
|
||||
### 8. Realtime
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Socket.IO ist als Backend-Realtime-Transport in die native App eingebunden.
|
||||
- Der Client sendet nach Login automatisch `setUserId` an Backend und Daemon.
|
||||
- App-Foreground/Background koppelt die Verbindung an den Lifecycle.
|
||||
- Backend- und Daemon-Status sind in der Shell sichtbar.
|
||||
- Der Daemon-WebSocket-Client ist technisch angebunden.
|
||||
- Realtime-Event-Basis und Daemon-Message-Parser sind vorhanden.
|
||||
- Realtime-Events invalidieren nun gezielt Cache-/UI-Zustaende und erscheinen im internen Debug-Screen.
|
||||
|
||||
- [x] Socket.IO Android Client evaluieren.
|
||||
- [x] Verbindung nach Login aufbauen.
|
||||
- [x] `setUserId` nach Verbindungsaufbau senden.
|
||||
- [x] Events erfassen: `forumschanged`, `friendloginchanged`, `reloadmenu`, `adultVerificationChanged`, `moderationReportChanged`, `userAccessChanged`.
|
||||
- [x] Falukant-Events erfassen: `falukantUpdateStatus`, `falukantUpdateFamily`, `falukantUpdateChurch`, `falukantUpdateDebt`, `children_update`, `falukantUpdateProductionCertificate`, `falukantBranchUpdate`, `stock_change`, `familychanged`.
|
||||
- [x] Socket Lifecycle an App Foreground/Background koppeln.
|
||||
- [x] Reconnect Policy definieren.
|
||||
- [x] Daemon-WebSocket Client implementieren.
|
||||
- [x] Daemon-Message Parsing robust gegen unbekannte Events machen.
|
||||
- [x] Realtime Events in Repositories einspeisen.
|
||||
- [x] UI-State bei Events gezielt invalidieren.
|
||||
- [x] Realtime Debug Screen fuer interne Builds planen.
|
||||
|
||||
### 9. Home und Dashboard
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Die nicht eingeloggte Startseite ist als native Landing/Auth-Kombination umgesetzt.
|
||||
- Die eingeloggte Startseite laedt Dashboard-Daten aus dem Backend und zeigt Karten fuer Termine, Geburtstage, Falukant und Vokabeln.
|
||||
- Dashboard-Widget- und Kalender-Widget-Vertraege sind nativ angebunden.
|
||||
- Backend-/Daemon-Status bleibt als kompakte Info sichtbar.
|
||||
|
||||
- [x] Home API-Vertraege erfassen.
|
||||
- [x] Eingeloggt/Nicht-eingeloggt Home getrennt modellieren.
|
||||
- [x] Native Startseite fuer nicht eingeloggte Nutzer bauen.
|
||||
- [x] Native Startseite fuer eingeloggte Nutzer bauen.
|
||||
- [x] Dashboard Widget API-Vertraege erfassen.
|
||||
- [x] Termine/Upcoming Events als native Cards umsetzen.
|
||||
- [x] Falukant Kurzstatus als native Card umsetzen.
|
||||
- [x] Backend-/Daemon-Status light anzeigen.
|
||||
|
||||
### 10. Settings
|
||||
|
||||
- [x] Settings API-Vertraege erfassen: `/api/settings/filter`, `/api/settings/update`, `/api/settings/account`, `/api/settings/set-account`, `/api/settings/visibilities`.
|
||||
- [x] Spracheinstellung nativ implementieren.
|
||||
- [x] Account-Basisdaten nativ implementieren.
|
||||
- [x] Sichtbarkeitseinstellungen modellieren.
|
||||
- [x] Personal/View/Sexuality/Flirt Settings priorisieren.
|
||||
- [x] Interessen-Settings implementieren.
|
||||
- [x] Language Assistant Settings bewerten.
|
||||
- [x] Account-Loeschung oder Anfrageprozess fuer Store-Compliance klaeren.
|
||||
|
||||
### 11. Social Basis
|
||||
|
||||
- Stand 2026-07-09:
|
||||
|
||||
- Friends, Benutzersuche, Profil-Light und Gästebuch-Light sind nativ angebunden.
|
||||
- Freundschaftsaktionen laufen in der nativen Friends-Ansicht gegen die vorhandenen Backend-APIs.
|
||||
- Profilfelder werden inklusive Backend-Visibility-Regeln angezeigt.
|
||||
- Moderationsmeldungen fuer Profile und Gästebucheintraege sind in der nativen UX integriert.
|
||||
|
||||
- [x] Friends API-Vertraege erfassen.
|
||||
- [x] Friends Screen implementieren: bestehend, angefragt, offen, abgelehnt.
|
||||
- [x] User Search API-Vertraege erfassen.
|
||||
- [x] User Search Screen implementieren.
|
||||
- [x] User Profile API-Vertraege erfassen.
|
||||
- [x] Profile Light Screen implementieren.
|
||||
- [x] Guestbook API-Vertraege erfassen.
|
||||
- [x] Guestbook light implementieren.
|
||||
- [x] Friend Request Aktionen implementieren.
|
||||
- [x] Blockieren/Melden UX fuer Store-Compliance planen.
|
||||
- [x] Privacy/Visibility Regeln aus Backend nativ abbilden.
|
||||
|
||||
### 12. Chat
|
||||
|
||||
Stand 2026-07-09:
|
||||
|
||||
- Der nativen MVP-Schnitt fuer Chat ist begonnen.
|
||||
- Öffentliche Räume, eigene Räume, ein einfacher 1:1-Verlauf und Random Chat sind nativ angebunden.
|
||||
- Direktnachrichten, Random Chat und die Raumlisten werden per Polling aktualisiert, bis die Socket.IO-Paritaet fuer den Chat folgt.
|
||||
- Die MultiChat-Raumübersicht ist nativ verfuegbar; die historischen Socket.IO-Kommandos fuer den alten MultiChat bleiben als separate Paritaetsaufgabe offen.
|
||||
- Direktnachrichten koennen gesendet und gemeldet werden.
|
||||
- Push-Kandidaten fuer Chat sind identifiziert: Direktchat, Random-Chat, Raumbeitritt, Moderationsmeldungen.
|
||||
- Socket.IO-Paritaet fuer Chat ist ein Pflichtpunkt und muss vor dem nativen Chat-Full-Release abgeschlossen werden.
|
||||
|
||||
- [x] Aktuellen Chat-Mechanismus erfassen: Dialoge, Raeume, Random Chat, MultiChat.
|
||||
- [x] Chat Backend-/WebSocket-Vertraege dokumentieren.
|
||||
- [x] Chat Room Liste implementieren.
|
||||
- [x] 1:1 Chat MVP implementieren.
|
||||
- [x] MultiChat MVP implementieren oder bewusst verschieben.
|
||||
- [x] RandomChat bewusst verschieben oder implementieren.
|
||||
- [x] Message Input mit Keyboard-Verhalten testen.
|
||||
- [x] Neue Nachrichten per Realtime anzeigen.
|
||||
- [x] Push-Kandidaten fuer Chat definieren.
|
||||
- [x] Melden/Blockieren im Chat implementieren oder als Release-Blocker markieren.
|
||||
- [ ] Socket.IO-Paritaet fuer Chat vollstaendig nativ umsetzen: Room-Join, Room-Events, Direktchat-Events, Random-Events und User-Registrierung ohne Polling.
|
||||
|
||||
### 13. Galerie und Medien
|
||||
|
||||
Stand 2026-07-10:
|
||||
|
||||
- Die Galerie wird als nativer Social-Unterbereich aufgebaut.
|
||||
- Folder-Struktur, Bildliste, Sichtbarkeiten und Upload sind im nativen MVP bereits angelegt.
|
||||
- Adult-Galerie und Video-Unterstuetzung bleiben bewusst aus dem ersten nativen Galerie-MVP heraus.
|
||||
|
||||
- [x] Galerie API-Vertraege erfassen.
|
||||
- [x] Folder-Struktur nativ modellieren.
|
||||
- [x] Bildliste mit Coil implementieren.
|
||||
- [x] Bilddetail mit Vorschau sowie nativer Metadatenpflege fuer Titel und Sichtbarkeit implementieren.
|
||||
- [x] Android Photo Picker fuer Upload implementieren.
|
||||
- [x] Multipart Upload gegen den Backend-Vertrag automatisiert testen.
|
||||
- [x] Bildbearbeitung aus Web-App bewerten: MVP nein. Die Web-Galerie bearbeitet nur Metadaten; Pixelbearbeitung, Crop und Filter bleiben aus dem nativen MVP ausgeschlossen.
|
||||
- [x] Sichtbarkeiten laden und setzen.
|
||||
- [x] Adult-Galerie aus MVP ausschliessen oder Compliance-Aufwand planen.
|
||||
- [x] Video-Unterstuetzung separat planen.
|
||||
|
||||
### 14. Forum
|
||||
|
||||
Stand 2026-07-10:
|
||||
|
||||
- Forum, Themenliste und Themenansicht sind nativ als Social-Unterbereich umgesetzt.
|
||||
- Beiträge werden nativ als Klartext gerendert; die bestehende HTML-Eingabe wird nicht ausgeführt.
|
||||
- `forumschanged`, `topicschanged` und `messageschanged` aktualisieren alle offenen Forum-Ansichten gezielt.
|
||||
|
||||
- [x] Forum-Liste API-Vertrag erfassen.
|
||||
- [x] Topic-Liste API-Vertrag erfassen.
|
||||
- [x] Topic-Detail API-Vertrag erfassen.
|
||||
- [x] Forum-Liste native umsetzen.
|
||||
- [x] Topic-Liste native umsetzen.
|
||||
- [x] Topic-Detail native umsetzen.
|
||||
- [x] Antwort erstellen implementieren.
|
||||
- [x] Moderation Report fuer Forum implementieren.
|
||||
- [x] Realtime `forumschanged` integrieren.
|
||||
|
||||
### 15. Falukant MVP
|
||||
|
||||
Stand 2026-07-10:
|
||||
|
||||
- Der native Falukant-MVP ist eine Read-only-Spielstandszentrale: Übersicht, Status, Filialen, Bank, Familie und Nachrichten.
|
||||
- Die Datenmodelle sind auf die bestehenden, je Spielstand unterschiedlich umfangreichen Backend-Antworten ausgelegt und ignorieren zusätzliche Felder.
|
||||
- Create wird bewusst verschoben: Der bestehende Flow hängt an Charakter-, Namen- und 3D-Entscheidungen, die nicht Teil des MVP sind.
|
||||
|
||||
- [x] Falukant API-Endpunkte aus Web-App inventarisieren.
|
||||
- [x] `StatusBar` Datenmodell nativ definieren.
|
||||
- [x] Overview Screen implementieren.
|
||||
- [x] Character/Familien-Basisdaten implementieren.
|
||||
- [x] Branch-Liste implementieren.
|
||||
- [x] Branch-Detail light implementieren.
|
||||
- [x] Bank light implementieren.
|
||||
- [x] Messages/Notifications light implementieren.
|
||||
- [x] Realtime Falukant Events integrieren.
|
||||
- [x] Create Falukant Flow bewusst verschieben.
|
||||
- [x] Family View light implementieren.
|
||||
- [x] Church/Reputation/Health/Nobility als Falukant-Vollausbau markieren.
|
||||
- [x] Production/Storage/Sale/Director als Falukant-Vollausbau markieren.
|
||||
- [x] Karten-/Regionen-Features als Falukant-Vollausbau markieren.
|
||||
|
||||
### 16. Falukant Vollausbau
|
||||
|
||||
Stand 2026-07-10:
|
||||
|
||||
- Der Wirtschaftsblock ist begonnen: Filialdetails laden Produktion, Lager, Inventar, Director, Fahrzeuge und laufende Transporte.
|
||||
- Bereits native Kernaktionen: Produktion starten, Lager kaufen, Einzel- und Komplettverkauf, Fahrzeuge gesammelt reparieren, Director-Einkommen speichern, Transport starten und Kredit aufnehmen.
|
||||
- Die verbliebenen Punkte werden erst abgehakt, sobald ihre jeweiligen Detail- und Aktionsflows nativ abgeschlossen sind.
|
||||
|
||||
#### 16.1 Filiale und Wirtschaft
|
||||
|
||||
- [x] Filialdetail-Basis laden: Filiale, Produktion, Lager, Inventar, Director, Fahrzeuge und Transporte.
|
||||
- [x] Produktion starten implementieren.
|
||||
- [x] Lagerkapazität kaufen implementieren.
|
||||
- [x] Einzelverkauf implementieren.
|
||||
- [x] Gesamtes Inventar verkaufen implementieren.
|
||||
- [x] Fahrzeuge gesammelt reparieren implementieren.
|
||||
- [x] Director-Einkommen speichern implementieren.
|
||||
- [x] Transport starten implementieren.
|
||||
- [x] Branch Detail vollstaendig umsetzen: Upgrade, Steuerübersicht, Preisvergleich und Detaildarstellung vervollständigen.
|
||||
- [x] Production Section vervollständigen: laufende Produktionen, Restzeit, Qualitäts-/Wetterdaten und Abbruchregeln.
|
||||
- [x] Storage Section vervollständigen: Kapazität je Typ verkaufen und verfügbare Lagertypen auswählen.
|
||||
- [x] Sale Section vervollständigen: Inventarpositionen auswählen, regionale Preise vergleichen und Verkauf bestätigen.
|
||||
- [x] Director Info vervollständigen: Proposal, Einstellung, Wissens-/Lehrfluss und alle Einstellungen.
|
||||
- [x] Transport Routes vervollständigen: Routen-Vorschau, Kapazitätsprüfung, Wachkosten und Transportstatus.
|
||||
|
||||
#### 16.2 Bank und Historie
|
||||
|
||||
- [x] Bankübersicht und aktive Kredite laden.
|
||||
- [x] Kreditaufnahme implementieren.
|
||||
- [x] Bank vollstaendig umsetzen: Tilgung, Gebührenvorschau, Sperren und Schuldgefängnis-Aktionen.
|
||||
- [x] Money History umsetzen: Filter, Pagination und Graphdaten.
|
||||
|
||||
#### 16.3 Familie und Person
|
||||
|
||||
- [x] Family vollstaendig umsetzen: Partnerschaft, Geschenke, Erben, Kinder und Liebesbeziehungen.
|
||||
- [x] Health umsetzen: Gesundheitsstatus und Aktivitäten mit Cooldown.
|
||||
- [x] Reputation umsetzen: Aktionen, Partys und Fortschritt.
|
||||
- [x] Church umsetzen: Taufe, Ämter, Bewerbungen und Entscheidungen.
|
||||
- [x] Nobility umsetzen: Stand, Voraussetzungen und Aufstieg.
|
||||
- [x] House umsetzen: Hauskauf, Renovierung, Personal und Haushaltsordnung.
|
||||
- [x] Education umsetzen: Lernende, Inhalte und Schulaktionen.
|
||||
|
||||
#### 16.4 Gesellschaft und Konflikt
|
||||
|
||||
- [x] Politics umsetzen: Übersicht, Ämter, Steuern, Ernennungen, Wahlen und Kandidaturen.
|
||||
- [x] Underground umsetzen: Aktivitäten, Ziele, Angriffe und Raid-Regionen.
|
||||
|
||||
#### 16.5 Qualität
|
||||
|
||||
- [x] Performance fuer grosse Falukant-Datenmengen testen.
|
||||
|
||||
### 17. Vokabeltrainer MVP
|
||||
|
||||
- [x] Vocab Languages API-Vertrag erfassen.
|
||||
- [x] Course List API-Vertrag erfassen.
|
||||
- [x] Course Detail API-Vertrag erfassen.
|
||||
- [x] Lesson API-Vertrag erfassen.
|
||||
- [x] Review API-Vertrag erfassen.
|
||||
- [x] Vocab Landing native umsetzen.
|
||||
- [x] Course List native umsetzen.
|
||||
- [x] Course Detail native umsetzen.
|
||||
- [x] Lesson Player MVP implementieren.
|
||||
- [x] Lesson Review implementieren.
|
||||
- [x] Dictionary light implementieren.
|
||||
- [x] Progress/Completion speichern.
|
||||
- [x] Keyboard-/Audio-/Touch-Verhalten testen.
|
||||
- [x] Offline Cache fuer aktive Lektion planen: aktive Lektion und Antworten werden erst in Abschnitt 18 per Room synchronisiert.
|
||||
|
||||
### 18. Vokabeltrainer Vollausbau
|
||||
|
||||
- [x] Neue Sprache anlegen implementieren.
|
||||
- [x] Subscribe Flow implementieren.
|
||||
- [x] Chapter View implementieren.
|
||||
- [x] Dictionary vollstaendig implementieren.
|
||||
- [x] Practice Dialog nativ ersetzen.
|
||||
- [x] SRS-/Review-Logik gegen Backend validieren.
|
||||
- [x] Offline Lesson Cache implementieren.
|
||||
- [x] Sync-Konflikte definieren.
|
||||
|
||||
Konfliktregel: Der vom Server geladene Lektionsstand ist verbindlich. Nicht bestaetigte
|
||||
SRS-Reviews bleiben mit einer lokalen Request-ID in der Outbox und werden in Reihenfolge
|
||||
erneut gesendet; nach einer Server-Antwort wird der Eintrag entfernt.
|
||||
|
||||
### 19. Kalender und Persoenliches
|
||||
|
||||
- [x] Calendar API-Vertraege erfassen.
|
||||
- [x] Monats-/Wochen-/Listenansicht entscheiden.
|
||||
- [x] Termine laden.
|
||||
- [x] Termin erstellen.
|
||||
- [x] Termin bearbeiten.
|
||||
- [x] Termin loeschen.
|
||||
- [x] Date/Time Picker nativ einsetzen.
|
||||
- [x] Reminder/Push spaeter planen.
|
||||
- [x] Diary API-Vertrag erfassen.
|
||||
- [x] Diary light umsetzen oder verschieben.
|
||||
|
||||
Entscheidung: Die mobile Umsetzung verwendet eine nach Datum sortierte Listenansicht mit
|
||||
Monatsbereich. Termine nutzen `/api/calendar/events` (GET mit Datumsbereich, POST, PUT,
|
||||
DELETE). Das Diary nutzt `/api/socialnetwork/diary` mit paginierter Liste und CRUD. Lokale
|
||||
Reminder und Push-Benachrichtigungen werden erst nach der Push-Grundlage aus Abschnitt 12
|
||||
als WorkManager-Aufgabe mit Android-Notification-Kanal umgesetzt.
|
||||
|
||||
### 20. Public Content
|
||||
|
||||
- [x] Blog List API-Vertrag erfassen.
|
||||
- [x] Blog Detail API-Vertrag erfassen.
|
||||
- [x] Guide List API-Vertrag erfassen.
|
||||
- [x] Guide Detail API-Vertrag erfassen.
|
||||
- [x] Public Landing Screens nativ priorisieren oder aus App entfernen.
|
||||
- [x] Rich Text Rendering nativ loesen.
|
||||
- [x] Blog Editor aus MVP ausschliessen.
|
||||
- [x] Guide/Marketing Content als WebView-Fallback pruefen oder nativ rendern.
|
||||
- [x] News/Blog/Guide Kurzlisten bewerten.
|
||||
|
||||
Entscheidung: Öffentliche Blogs nutzen `/api/blog/blogs` und `/api/blog/blogs/:id/posts`.
|
||||
Ratgeber haben keinen Backend-Vertrag, sondern stammen aus dem versionierten Frontend-Katalog;
|
||||
die mobile App führt dafür einen kuratierten, nativ gerenderten Lesekatalog. HTML aus
|
||||
Blogbeiträgen wird als sicherer Text ohne WebView gerendert. Der Blog-Editor bleibt im Web.
|
||||
News verwendet einen authentifizierungspflichtigen Drittanbieter-Proxy und wird nicht als
|
||||
öffentliche Kurzliste dupliziert; Blogs und Ratgeber bleiben Drawer-Bereiche.
|
||||
|
||||
### 21. Minigames
|
||||
|
||||
#### 21.1 Match3
|
||||
|
||||
- [x] Match3 Game als native Compose/Canvas Machbarkeit pruefen.
|
||||
- [x] Spielbrett, Tile-Modell und Zuglogik definieren.
|
||||
- [x] Touch-Steuerung fuer Auswahl und Tausch definieren.
|
||||
- [x] Animationen und Aufloesung von Matches definieren.
|
||||
- [x] Score-/Leaderboard-API-Vertraege fuer Match3 erfassen.
|
||||
- [ ] Performance auf Emulator und echtem Geraet testen. In eine spaetere gemeinsame QA-Runde verschoben.
|
||||
|
||||
Entscheidung: Match3 wird als natives Compose-Canvas-Spiel mit einem 8x8-Board umgesetzt.
|
||||
Ein Zug besteht aus zwei Tap-Eingaben auf benachbarte Steine. Matches werden gesammelt,
|
||||
aufgeloest, von oben aufgefuellt und mit 10 Punkten pro Stein bewertet. Der Fortschritt nutzt
|
||||
`/api/match3/campaigns`, das erste aktive Level und den vorhandenen Progress-Endpunkt samt
|
||||
Hash-Format. Admin-Routen bleiben ausgeschlossen.
|
||||
|
||||
#### 21.2 Taxi
|
||||
|
||||
- [x] Taxi Game als native Canvas/OpenGL Machbarkeit pruefen.
|
||||
- [x] Spielfeld, Fahrzeugzustand und Fahrphysik definieren.
|
||||
- [x] Touch-Steuerung fuer Lenken, Beschleunigen und Bremsen definieren.
|
||||
- [x] Auftrags-, Ziel- und Kollisionslogik definieren.
|
||||
- [x] Score-/Leaderboard-API-Vertraege fuer Taxi erfassen.
|
||||
- [ ] Performance auf Emulator und echtem Geraet testen. In eine spaetere gemeinsame QA-Runde verschoben.
|
||||
|
||||
Entscheidung: Taxi wird als natives Compose-Canvas-Spiel umgesetzt. Vier Touch-Schaltflächen
|
||||
steuern Lenken, Beschleunigen und Bremsen. Ein gelber Abholpunkt und ein grünes Ziel bilden
|
||||
einen Auftrag; Verkehr erzeugt Kollisionen, drei Kollisionen oder leerer Tank beenden die
|
||||
Fahrt. Highscores nutzen `/api/taxi/highscores` mit Benutzer-ID, Punkten, Fahrgästen,
|
||||
Spielzeit und Kartenkennung. OpenGL ist für diese 2D-Strecke nicht erforderlich.
|
||||
|
||||
#### 21.3 Gemeinsame Integration
|
||||
|
||||
- [x] WebView-Fallback fuer Minigames als Zwischenloesung bewerten.
|
||||
- [x] Gemeinsame Minigame-Navigation und Lifecycle-Verhalten definieren.
|
||||
- [x] Gemeinsames Persistenz- und Abbruchverhalten definieren.
|
||||
- [x] Admin-Tools fuer Minigames aus nativer App ausschliessen.
|
||||
|
||||
Entscheidung: Es gibt keinen WebView-Fallback. Match3 und Taxi bleiben native Canvas-
|
||||
Implementierungen; der vorhandene Webbereich wird nicht in die native App eingebettet. Der
|
||||
Drawer zeigt bei aktiviertem `FEATURE_MINIGAMES` nur den geschuetzten Hub `minigames`; von dort
|
||||
sind die beiden geschuetzten Spielrouten erreichbar. Spielschleifen sind an die Composition
|
||||
gebunden und werden beim Verlassen automatisch beendet. Match3 speichert nur abgeschlossene
|
||||
Level ueber den vorhandenen Progress-Endpunkt. Taxi speichert beim Verlassen einer laufenden
|
||||
Fahrt einen Zwischenstand ueber `/api/taxi/game-state`; abgeschlossene Fahrten werden als
|
||||
Highscore gespeichert. Admin- und Verwaltungsrouten fuer Minigames werden nicht registriert und
|
||||
bleiben ausschliesslich im Web-Adminbereich.
|
||||
|
||||
### 22. Admin spaeter
|
||||
|
||||
- [x] Entscheiden, ob Admin ueberhaupt in native App gehoert. - Ja, Admin gehört in die native App
|
||||
- [x] Admin Users API-Vertraege erfassen.
|
||||
- [x] Admin Rights API-Vertraege erfassen.
|
||||
- [x] Moderation Reports API-Vertraege erfassen.
|
||||
- [x] Adult Verification API-Vertraege erfassen.
|
||||
- [x] Erotic Moderation API-Vertraege erfassen.
|
||||
- [x] Forum Admin API-Vertraege erfassen.
|
||||
- [x] Falukant Admin API-Vertraege erfassen.
|
||||
- [x] Services Status Screen fuer interne Builds planen.
|
||||
- [x] Admin nur per Feature Flag und Rollencheck sichtbar machen.
|
||||
|
||||
Entscheidung: Die native Administration wird nur eingeblendet, wenn sowohl
|
||||
`FEATURE_ADMIN` aktiviert ist als auch die authentifizierte Anfrage an
|
||||
`GET /api/navigation/:userid` einen Bereich `administration` liefert. Die vom Backend
|
||||
gefilterte Navigation ist die Rechtequelle; die serverseitige Berechtigungsprüfung jeder
|
||||
Admin-Route bleibt verbindlich. Direkte Navigation ohne beide Bedingungen zeigt keinen Inhalt.
|
||||
|
||||
API-Vertraege:
|
||||
|
||||
- Benutzer: `GET /api/admin/users/search?q=`, `GET /api/admin/users/:id`, `PUT /api/admin/users/:id`, `GET /api/admin/users/batch?ids=`, `GET /api/admin/users/statistics`; alle erfordern die vom Service gepruefte Berechtigung `useradministration` bzw. `mainadmin`.
|
||||
- Rechte: `GET /api/admin/rights/types`, `GET /api/admin/rights/:id`, `POST /api/admin/rights/:id` und `DELETE /api/admin/rights/:id` mit `{ rightTypeId }`; Berechtigung `rights` bzw. `mainadmin`.
|
||||
- Moderationsmeldungen: `GET /api/admin/moderation/reports?status=&limit=` sowie `POST /api/admin/moderation/reports/:reportId/status` mit Status und Review-Notiz; Berechtigung `forum` bzw. `mainadmin`.
|
||||
- Altersverifikation: `GET /api/admin/users/adult-verification?status=`, `PUT /api/admin/users/:id/adult-verification` mit `approved`, `rejected` oder `pending`, sowie der geschuetzte Dokument-Download `GET /api/admin/users/:id/adult-verification/document`.
|
||||
- Erotikmoderation: `GET /api/admin/users/erotic-moderation?status=`, geschuetzte Vorschau unter `/preview/:type/:targetId` und `PUT /api/admin/users/erotic-moderation/:id` mit erlaubter Aktion und optionaler Notiz.
|
||||
- Forum: `GET` und `POST /api/forum/`, `DELETE /api/forum/:forumId`; Erstellen erwartet `{ name, permissions }`, die Service-Schicht prueft `forum` bzw. `mainadmin`. Allgemeine Meldungen laufen ueber den Moderationsvertrag.
|
||||
- Falukant: Die geschuetzten Werkzeuge liegen unter `/api/admin/falukant/*`: Benutzersuche/-bearbeitung, Familien- und Schwangerschaftsaktionen, Bestands-/Region-/Distanzpflege, NPC-Auftraege und Titel. Die native Umsetzung beschraenkt sich auf klar abgegrenzte Fach-Screens mit serverseitiger `falukant`-/`mainadmin`-Pruefung; keine generische Datenbankbearbeitung.
|
||||
|
||||
Service-Status: Nur interne Debug-Builds erhalten einen kompakten, rein lesenden Statusscreen
|
||||
auf Basis der bereits vorhandenen Backend-/Daemon-Verbindungssignale. Keine Prozessdaten,
|
||||
Tokens, Konfigurationen oder Diagnose-Endpunkte werden in Release-Builds angezeigt. Die
|
||||
Match3-/Taxi-Adminwerkzeuge bleiben gemaess Abschnitt 21 ausserhalb der nativen App.
|
||||
|
||||
### 23. Adult Content und Store-Compliance
|
||||
|
||||
- [x] Adult Content aus MVP entfernen oder per Feature Flag deaktivieren.
|
||||
- [x] Altersverifikation nativ modellieren.
|
||||
- [x] UGC-Melden nativ in Chat, Galerie, Forum, Profil implementieren.
|
||||
- [x] Blockieren nativ implementieren.
|
||||
- [x] Moderationserreichbarkeit dokumentieren.
|
||||
- [x] Datenschutzseite nativ erreichbar machen.
|
||||
- [x] Impressum nativ erreichbar machen.
|
||||
- [x] Kontakt nativ erreichbar machen.
|
||||
- [x] Account-Loeschung oder klare Anleitung nativ erreichbar machen.
|
||||
- [x] Play Store Content Rating vorbereiten.
|
||||
- [x] Store-Review-Risiko fuer Adult Content separat entscheiden.
|
||||
|
||||
Stand 2026-07-16: Der geschuetzte Bereich ist im lokalen Debug-Build per `FEATURE_ADULT`
|
||||
aktiviert; Staging und Production bleiben bis zur Store-Entscheidung deaktiviert. Die native App
|
||||
laedt den Status ueber `/api/settings/account` und laedt erst nach lokaler Pruefung von
|
||||
Volljaehrigkeit und `adultAccessEnabled` die serverseitig ebenfalls geschuetzten Endpunkte unter
|
||||
`/api/socialnetwork/erotic/*`. Ein Verifikationsnachweis (JPEG, PNG, WebP oder PDF) wird per
|
||||
Android-Dateiauswahl an `/api/settings/adult-verification/request` gesendet. Die API prueft
|
||||
zusaetzlich Alter und Verifikationsstatus. Die Account-Endpunkte weisen nun ausserdem Anfragen
|
||||
ab, deren Body-`userId` nicht der authentifizierten `userid` entspricht.
|
||||
|
||||
Blockieren verwendet den neuen serverseitigen Vertrag `POST`/`DELETE
|
||||
/api/socialnetwork/blocked-users/:userId` und die Migration
|
||||
`20260716000000-create-user-block.sql`; der Profil-Screen bietet die Blockaktion nativ an.
|
||||
|
||||
Die Store-Entscheidung und Rating-Vorbereitung sind in `android/STORE_COMPLIANCE.md`
|
||||
dokumentiert: Der Bereich bleibt ausserhalb lokaler Debug-Builds deaktiviert, bis eine formelle
|
||||
Store- und Altersfreigabe vorliegt.
|
||||
|
||||
### 24. Push Notifications
|
||||
|
||||
- [x] Firebase Projekt klaeren.
|
||||
- [x] FCM in native App integrieren.
|
||||
- [x] Device Token Backend-Modell planen.
|
||||
- [x] Device Token Registration API definieren.
|
||||
- [x] Opt-in UI implementieren.
|
||||
- [x] Notification Settings implementieren.
|
||||
- [x] Chat Push definieren.
|
||||
- [x] Friend Login Push definieren.
|
||||
- [x] Falukant Event Push definieren.
|
||||
- [x] Vocab Reminder Push definieren.
|
||||
- [x] Deep Links aus Notifications implementieren.
|
||||
- [x] Token Refresh Handling implementieren.
|
||||
- [ ] Firebase-Service-Account im Backend-Deployment hinterlegen (`FIREBASE_SERVICE_ACCOUNT_PATH` oder `FIREBASE_SERVICE_ACCOUNT_JSON`).
|
||||
|
||||
### 25. Deep Links und OAuth
|
||||
|
||||
- [x] App Links Domain festlegen.
|
||||
- [x] `assetlinks.json` planen.
|
||||
- [x] Deep-Link-Struktur fuer Auth, Home, Social, Falukant, Vocab, Settings und Public Content definieren.
|
||||
- [x] OAuth Redirect URIs fuer Android planen.
|
||||
- [x] Custom Tabs Flow implementieren.
|
||||
- [x] OAuth Callback Handling implementieren.
|
||||
- [x] Deep Links fuer Profile, Forum, Falukant, Vocab, Blog definieren.
|
||||
- [x] Deep Link Auth Guard implementieren.
|
||||
- [x] Nicht eingeloggte Deep Links nach Login fortsetzen.
|
||||
|
||||
### 26. Sicherheit
|
||||
|
||||
- [x] Authdaten nicht im Klartext speichern.
|
||||
- [x] Release Logging sensibler Daten verhindern.
|
||||
- [x] Certificate Pinning bewerten, nicht vorschnell erzwingen.
|
||||
- [x] Network Security Config fuer Release restriktiv halten.
|
||||
- [x] Root/Jailbreak Detection bewusst entscheiden.
|
||||
- [x] Screenshot-Schutz fuer Adult/Private Bereiche bewerten.
|
||||
- [x] Datei-Uploads auf MIME/Größe pruefen.
|
||||
- [x] WebView-Fallbacks minimieren.
|
||||
- [x] Dependency-Scanning fuer Android einrichten.
|
||||
|
||||
### 27. Testing
|
||||
|
||||
- [x] Unit Tests fuer Auth Repository.
|
||||
- [x] Unit Tests fuer Settings Repository.
|
||||
- [x] Unit Tests fuer Error Mapping.
|
||||
- [x] MockWebServer Tests fuer Auth Header.
|
||||
- [x] MockWebServer Tests fuer API-Fehler.
|
||||
- [x] Room Migration Tests.
|
||||
- [x] Compose Tests fuer Login.
|
||||
- [x] Compose Tests fuer Navigation.
|
||||
- [x] Compose Tests fuer Home.
|
||||
- [x] Compose Tests fuer Vocab Lesson.
|
||||
- [x] Realtime Tests mit Testserver planen.
|
||||
- [x] Emulator-Testmatrix definieren: kleines Phone, grosses Phone, Tablet.
|
||||
- [x] Echtes Android-Geraet in Testmatrix aufnehmen.
|
||||
- [x] Offline/Online-Wechsel testen.
|
||||
- [x] App Kill/Restart/Resume testen.
|
||||
- [ ] Instrumentation-Suite auf einem verbundenen Geraet oder KVM-faehigen Host ausfuehren (lokal blockiert: kein ADB-Geraet, keine x86_64-Hardwarebeschleunigung).
|
||||
|
||||
### 28. Build, Release und Betrieb
|
||||
|
||||
- [ ] Debug APK Build einrichten.
|
||||
- [ ] Release AAB Build einrichten.
|
||||
- [ ] Signing-Konzept definieren.
|
||||
- [ ] Keystore sicher ablegen.
|
||||
- [ ] Internal App Sharing oder interne Testspur planen.
|
||||
- [ ] Crashlytics oder alternatives Crash Reporting entscheiden.
|
||||
- [ ] Analytics bewusst entscheiden: ja/nein, Datenschutz.
|
||||
- [ ] App Version Check implementieren oder planen.
|
||||
- [ ] Rollback-Strategie definieren.
|
||||
- [ ] Hybrid-App und Native-App Parallelbetrieb dokumentieren.
|
||||
|
||||
### 29. Backend-Vorbereitung fuer Native
|
||||
|
||||
- [ ] Release-Signaturfingerprint in die ausgelieferte `/.well-known/assetlinks.json` eintragen.
|
||||
- [ ] Native OAuth-Redirect-URI bei jedem aktivierten Provider hinterlegen.
|
||||
- [ ] Mobile API-Inventar aus allen Web-Komponenten erstellen.
|
||||
- [ ] API-Versionierung bewerten: `/api/mobile/v1` ja/nein.
|
||||
- [ ] Einheitliches Fehlerformat definieren.
|
||||
- [ ] Einheitliches Pagination-Format definieren.
|
||||
- [ ] Auth auf Bearer Token/JWT oder bestehendes `userid`/`authcode` final entscheiden.
|
||||
- [ ] Refresh Token Konzept bewerten.
|
||||
- [ ] Device Token API fuer Push planen.
|
||||
- [ ] Datei-Upload-Limits dokumentieren.
|
||||
- [ ] Image Thumbnail Endpunkte fuer mobile Listen planen.
|
||||
- [ ] Falukant Summary Endpunkte fuer mobile Screens planen.
|
||||
- [ ] Vocab Lesson Endpunkte fuer mobile Offline-Caches planen.
|
||||
|
||||
### 30. Abnahmekriterien MVP
|
||||
|
||||
- [ ] App startet kalt unter 2 Sekunden auf Testgeraet oder Zielwert begruendet anpassen.
|
||||
- [ ] Login funktioniert gegen production/staging.
|
||||
- [ ] Session ueberlebt App-Neustart.
|
||||
- [ ] Logout entfernt lokale Session und trennt Realtime.
|
||||
- [ ] Home laedt ohne WebView.
|
||||
- [ ] Navigation ist vollstaendig nativ.
|
||||
- [ ] Mindestens ein Social-Basisflow funktioniert.
|
||||
- [ ] Mindestens ein Falukant-Basisflow funktioniert.
|
||||
- [ ] Mindestens ein Vocab-Lesson-Flow funktioniert.
|
||||
- [ ] Fehler werden nativ und verstaendlich angezeigt.
|
||||
- [ ] Offline-Zustand wird erkannt und blockiert keine App.
|
||||
- [ ] Keine lokalen Dev-URLs im Release-Build.
|
||||
- [ ] Keine Secrets im APK/AAB.
|
||||
- [ ] Datenschutz, Impressum und Kontakt sind erreichbar.
|
||||
|
||||
## Empfohlene erste Umsetzungsschritte
|
||||
|
||||
1. `/android/native` als neues Kotlin/Compose-Projekt anlegen.
|
||||
2. Core Module fuer Network, Auth, Design und Navigation erstellen.
|
||||
3. Login komplett nativ implementieren.
|
||||
4. Session Store und Auth Interceptor stabilisieren.
|
||||
5. Native App Shell mit Home und Navigation bauen.
|
||||
6. Danach Social light, Falukant light und Vocab light nacheinander umsetzen.
|
||||
|
||||
## Realistische Einordnung
|
||||
|
||||
Die native Komplettumsetzung ist erheblich groesser als die Hybrid-App. Die Hybrid-App ist sinnvoll als lauffaehige Zwischenloesung und Referenzimplementierung. Die native App sollte als paralleles Produkt mit klarem MVP gestartet werden, sonst entsteht ein langer Rewrite ohne nutzbaren Zwischenstand.
|
||||
@@ -1,101 +0,0 @@
|
||||
# YourPart Android
|
||||
|
||||
Android-App-Shell fuer YourPart auf Basis der bestehenden Vue/Vite-App und Capacitor.
|
||||
|
||||
## Entscheidungen
|
||||
|
||||
- App-ID: `de.yourpart.app`
|
||||
- App-Name: `YourPart`
|
||||
- Technologie: Capacitor mit lokal gebuendeltem `frontend/dist`
|
||||
- Backend: bestehendes Backend wird verwendet, keine Backend-Implementierung in diesem Android-Start
|
||||
- Erstes Ziel: interne Debug-/Test-APK
|
||||
|
||||
## Vorbereitung
|
||||
|
||||
1. Frontend-Env-Vorlage kopieren und Werte pruefen:
|
||||
|
||||
```bash
|
||||
cp ../frontend/.env.android.example ../frontend/.env.android
|
||||
```
|
||||
|
||||
2. Android-Dependencies installieren:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
3. Web-Bundle fuer Android bauen:
|
||||
|
||||
```bash
|
||||
npm run build:web
|
||||
```
|
||||
|
||||
4. Android-Projekt erzeugen:
|
||||
|
||||
```bash
|
||||
npm run add:android
|
||||
```
|
||||
|
||||
5. Danach synchronisieren:
|
||||
|
||||
```bash
|
||||
npm run sync
|
||||
```
|
||||
|
||||
## Debug-Build
|
||||
|
||||
Nach `npm run add:android`:
|
||||
|
||||
```bash
|
||||
npm run build:debug
|
||||
```
|
||||
|
||||
Das erzeugte APK liegt danach unter `android/app/build/outputs/apk/debug/`.
|
||||
Innerhalb dieses Repositorys ist das der Pfad `/android/android/app/build/outputs/apk/debug/`.
|
||||
|
||||
## Android Studio
|
||||
|
||||
In Android Studio muss das native Gradle-Projekt geoeffnet werden:
|
||||
|
||||
```text
|
||||
/home/torsten/Programs/YourPart3/android/android
|
||||
```
|
||||
|
||||
Nicht `/home/torsten/Programs/YourPart3/android` oeffnen. Dieser Ordner ist nur die Capacitor-Projektwurzel mit `package.json` und `capacitor.config.ts`; die Android-Studio-App liegt eine Ebene tiefer in `/android/android`.
|
||||
|
||||
Nach dem Oeffnen:
|
||||
|
||||
1. Gradle Sync abwarten.
|
||||
2. Run Configuration `YourPart Debug` auswaehlen.
|
||||
3. Emulator auswaehlen.
|
||||
4. Starten.
|
||||
|
||||
Wenn Android Studio die Konfiguration nicht sofort anzeigt, `File > Sync Project with Gradle Files` ausfuehren oder das Projektfenster neu laden.
|
||||
|
||||
## Emulator-Eingabe
|
||||
|
||||
Die App verwendet die normale Android-WebView-Eingabe. `android.captureInput` ist bewusst nicht aktiviert, weil diese Capacitor-Option die WebView-InputConnection ersetzt und im Emulator verhindern kann, dass Textfelder normal beschrieben werden.
|
||||
|
||||
## Backend-CORS fuer Android-Debug
|
||||
|
||||
Capacitor laedt die lokale Android-App standardmaessig unter:
|
||||
|
||||
```text
|
||||
https://localhost
|
||||
```
|
||||
|
||||
Die API-Requests gehen weiterhin an `https://www.your-part.de/api/...`. Deshalb muss das Backend `https://localhost` in `CORS_ORIGINS` erlauben:
|
||||
|
||||
```env
|
||||
CORS_ORIGINS=https://www.your-part.de,https://localhost,http://localhost:5173,http://127.0.0.1:5173
|
||||
```
|
||||
|
||||
`server.hostname` in `capacitor.config.ts` darf nicht auf `www.your-part.de` gesetzt werden. Sonst interpretiert Capacitor Backend- und Model-URLs wie `/api/models/...glb` als lokale App-Assets.
|
||||
|
||||
## Wichtige Hinweise
|
||||
|
||||
- `frontend/.env.android` darf echte produktive URLs enthalten, aber keine Secrets.
|
||||
- `VITE_DISABLE_3D=true` ist fuer Android-Debug absichtlich gesetzt. Das verhindert WebGL/GLB-Last auf der Login-Seite, bis CORS und 3D-Performance separat freigegeben sind.
|
||||
- OAuth ist im ersten Debug-APK nicht der Blocker; Username/Passwort-Login ist die Pflichtfunktion.
|
||||
- Push Notifications werden erst nach stabiler Shell geplant.
|
||||
- Play Store ist vorerst kein Ziel, bis Datenschutz, UGC, Moderation und Adult-Content separat geprueft sind.
|
||||
@@ -1,37 +0,0 @@
|
||||
# Native Android Security
|
||||
|
||||
## Umgesetzte Schutzmaßnahmen
|
||||
|
||||
- Die Sitzung liegt ausschließlich in `EncryptedSharedPreferences` mit Android-Master-Key.
|
||||
- Release-Builds enthalten keinen HTTP-Body-Logger. Der detaillierte OkHttp-Logger ist auf
|
||||
Nicht-Release-Builds begrenzt.
|
||||
- Release-Netzwerkverkehr erlaubt kein Cleartext. Nur der lokale Debug-Flavor darf
|
||||
`10.0.2.2` und `localhost` per HTTP ansprechen.
|
||||
- Chat, Galerie, Persönliches und der Adult-Bereich setzen `FLAG_SECURE`. Damit verhindert
|
||||
Android Screenshots, Bildschirmaufnahmen und die Anzeige im App-Switcher.
|
||||
- Uploads werden vor dem Service auf einen erlaubten MIME-Typ und eine Größe begrenzt:
|
||||
Bilder/Verifikationsnachweise 10 MiB, Videos 100 MiB. Bilder werden zusätzlich durch
|
||||
Sharp dekodiert, damit ein behaupteter MIME-Typ nicht genügt.
|
||||
|
||||
## Bewusste Entscheidungen
|
||||
|
||||
### Certificate Pinning
|
||||
|
||||
Certificate Pinning wird aktuell **nicht** erzwungen. Die API verwendet HTTPS und die
|
||||
plattformseitige Trust-Store-Prüfung. Pinning würde bei Zertifikats- oder CDN-Wechseln ohne
|
||||
App-Update zu vollständigen Ausfällen führen. Es wird erst eingeführt, wenn es mindestens zwei
|
||||
parallel gültige Pins, ein dokumentiertes Rotation-Verfahren und Monitoring für Pin-Fehler gibt.
|
||||
|
||||
### Root- und Bootloader-Erkennung
|
||||
|
||||
Die App blockiert gerootete Geräte nicht. Eine lokale Erkennung ist umgehbar und würde legitime
|
||||
Nutzer sowie Emulator-Tests ausschließen. Sensible Daten bleiben verschlüsselt, Screenshots in
|
||||
sensiblen Bereichen sind gesperrt und Berechtigungen werden auf dem Server durchgesetzt.
|
||||
Play Integrity wird bei späteren Hochrisiko-Aktionen als serverseitig prüfbares Signal bewertet,
|
||||
nicht als pauschale Startblockade.
|
||||
|
||||
## Dependency Scanning
|
||||
|
||||
`.github/workflows/android-security.yml` führt bei Pull Requests und Pushes einen
|
||||
OSV-Abhängigkeitsscan sowie Android-Lint für den Produktions-Release aus. Kritische Findings
|
||||
werden vor einem Release bewertet.
|
||||
@@ -1,17 +0,0 @@
|
||||
# Store-Compliance
|
||||
|
||||
## Adult Content
|
||||
|
||||
- `FEATURE_ADULT` ist nur im lokalen Debug-Build aktiv.
|
||||
- Staging und Production liefern keinen nativen Adult-Bereich aus.
|
||||
- Vor einer Aktivierung sind Play-Content-Rating, Altersklassifizierung, Moderationsprozess,
|
||||
Meldewege und die Store-Richtlinien erneut zu pruefen und freizugeben.
|
||||
- Die API bleibt auch bei aktivem Client-Feature die Autoritaet: Volljaehrigkeit und der Status
|
||||
`approved` der Altersverifikation sind fuer jeden geschuetzten Endpunkt erforderlich.
|
||||
|
||||
## UGC und Moderation
|
||||
|
||||
- Native Meldungen existieren fuer Chat, Forum, Profile, Gaestebuch und Galerie.
|
||||
- Meldungen werden serverseitig gespeichert und sind fuer berechtigte Moderatoren sichtbar.
|
||||
- Nutzerblockaden werden serverseitig in `community.user_block` gespeichert; die SQL-Migration
|
||||
`backend/migrations/20260716000000-create-user-block.sql` ist vor dem Rollout auszufuehren.
|
||||
@@ -1,45 +0,0 @@
|
||||
# Native Android Testmatrix
|
||||
|
||||
## Automatisiert
|
||||
|
||||
| Bereich | Testart | Ausführung |
|
||||
| --- | --- | --- |
|
||||
| Auth, Settings, HTTP-Fehler, Header, Daemon-Parser | JVM + MockWebServer | `./gradlew :app:testLocalDebugUnitTest` |
|
||||
| Room-Migration und verschlüsselte Session nach Store-Neuerzeugung | Instrumentation | `./gradlew :app:connectedLocalDebugAndroidTest` |
|
||||
| Login, Navigation, Home und Vokabel-Lektion | Compose Instrumentation | `./gradlew :app:connectedLocalDebugAndroidTest` |
|
||||
| Realtime | JVM-Parser plus manueller Socket.IO-Testserver-Plan | siehe unten |
|
||||
|
||||
### Lokaler Ausfuehrungsstatus
|
||||
|
||||
- Die JVM-Suite (`:app:testLocalDebugUnitTest`) ist erfolgreich ausgefuehrt.
|
||||
- Die Instrumentation-Suite inklusive Room- und Compose-Tests kompiliert erfolgreich.
|
||||
- Die Ausfuehrung auf diesem Host ist blockiert: Es ist kein ADB-Geraet verbunden und die
|
||||
x86_64-Emulatoren benoetigen KVM-Hardwarebeschleunigung, die hier nicht verfuegbar ist.
|
||||
Das vorhandene ARM64-System-Image kann auf einem x86_64-Host nicht emuliert werden.
|
||||
- Auf einem Host mit KVM oder einem verbundenen Geraet wird die Suite mit
|
||||
`./gradlew :app:connectedLocalDebugAndroidTest` ausgefuehrt. Der CI-Workflow
|
||||
`.github/workflows/android-tests.yml` fuehrt dieselbe Suite auf einem GitHub-Emulator aus.
|
||||
|
||||
## Emulator- und Geräte-Matrix
|
||||
|
||||
| Ziel | Pflichtfälle |
|
||||
| --- | --- |
|
||||
| Kleines Phone, API 34+ | Login, Navigation, Formular, Tastatur, Adult-Screenshotschutz |
|
||||
| Großes Phone, API 34+ | Galerie, Falukant und Vokabel-Lektion |
|
||||
| Tablet, API 34+ | Drawer, Landscape und Listenbreiten |
|
||||
| Reales Android-Gerät, aktuelle API | Push-Berechtigung, OAuth Custom Tab, App Links, Kamera/Dateiauswahl |
|
||||
|
||||
Die Gradle Managed Devices `mediumPhone` und `mediumTablet` decken die CI-Basis ab. Das lokale
|
||||
Team ergänzt für jeden Release-Lauf die installierten kleinen/großen Emulatoren und mindestens
|
||||
ein reales Gerät.
|
||||
|
||||
## Netzwerk, Realtime und Lifecycle
|
||||
|
||||
1. Backend und Daemon starten, mit einem Testkonto anmelden und Socket.IO-Verbindung prüfen.
|
||||
2. Backend stoppen: Offline-Banner, verständlicher Fehler und keine blockierte Navigation prüfen.
|
||||
3. Backend wieder starten: Screen aktualisieren und Realtime-Verbindung erneut prüfen.
|
||||
4. App im Hintergrund beenden und über Launcher oder Push erneut öffnen: verschlüsselte Sitzung,
|
||||
Deep-Link-Fortsetzung und Realtime-Reconnect prüfen.
|
||||
5. Für Socket.IO-Regressionen wird ein isolierter Node-Testserver mit den Ereignissen
|
||||
`friendloginchanged`, `falukantUpdateStatus`, `familychanged` und `reloadmenu` verwendet.
|
||||
Der Android-Test verbindet sich mit dessen URL statt mit Production.
|
||||
6
android/android/.idea/AndroidProjectSystem.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AndroidProjectSystem">
|
||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
||||
</component>
|
||||
</project>
|
||||
6
android/android/.idea/compiler.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
||||
15
android/android/.idea/deploymentTargetSelector.xml
generated
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetSelector">
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="YourPart Debug">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
<SelectionState runConfigName="app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
||||
10
android/android/.idea/migrations.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
10
android/android/.idea/misc.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||
17
android/android/.idea/runConfigurations.xml
generated
@@ -1,17 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="RunConfigurationProducerService">
|
||||
<option name="ignoredProducers">
|
||||
<set>
|
||||
<option value="com.intellij.execution.junit.AbstractAllInDirectoryConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.AllInPackageConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.PatternConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.TestInClassConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.UniqueIdConfigurationProducer" />
|
||||
<option value="com.intellij.execution.junit.testDiscovery.JUnitTestDiscoveryConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinJUnitRunConfigurationProducer" />
|
||||
<option value="org.jetbrains.kotlin.idea.junit.KotlinPatternConfigurationProducer" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
@@ -1,68 +0,0 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="YourPart Debug" type="AndroidRunConfigurationType" factoryName="Android App">
|
||||
<option name="ANDROID_RUN_CONFIGURATION_SCHEMA_VERSION" value="1" />
|
||||
<option name="DEPLOY" value="true" />
|
||||
<option name="DEPLOY_APK_FROM_BUNDLE" value="false" />
|
||||
<option name="DEPLOY_AS_INSTANT" value="false" />
|
||||
<option name="ARTIFACT_NAME" value="" />
|
||||
<option name="PM_INSTALL_OPTIONS" value="" />
|
||||
<option name="ALL_USERS" value="false" />
|
||||
<option name="ALWAYS_INSTALL_WITH_PM" value="false" />
|
||||
<option name="ALLOW_ASSUME_VERIFIED" value="false" />
|
||||
<option name="CLEAR_APP_STORAGE" value="false" />
|
||||
<option name="DYNAMIC_FEATURES_DISABLED_LIST" value="" />
|
||||
<option name="ACTIVITY_EXTRA_FLAGS" value="" />
|
||||
<option name="MODE" value="default_activity" />
|
||||
<option name="RESTORE_ENABLED" value="false" />
|
||||
<option name="RESTORE_FILE" value="" />
|
||||
<option name="RESTORE_FRESH_INSTALL_ONLY" value="false" />
|
||||
<option name="CLEAR_LOGCAT" value="false" />
|
||||
<option name="SHOW_LOGCAT_AUTOMATICALLY" value="false" />
|
||||
<option name="TARGET_SELECTION_MODE" value="DEVICE_AND_SNAPSHOT_COMBO_BOX" />
|
||||
<option name="DEBUGGER_TYPE" value="Auto" />
|
||||
<module name="android.app.main" />
|
||||
<Auto>
|
||||
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||
<option name="SHOW_STATIC_VARS" value="true" />
|
||||
<option name="WORKING_DIR" value="" />
|
||||
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||
</Auto>
|
||||
<Hybrid>
|
||||
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||
<option name="SHOW_STATIC_VARS" value="true" />
|
||||
<option name="WORKING_DIR" value="" />
|
||||
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||
</Hybrid>
|
||||
<Java>
|
||||
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||
</Java>
|
||||
<Native>
|
||||
<option name="USE_JAVA_AWARE_DEBUGGER" value="false" />
|
||||
<option name="SHOW_STATIC_VARS" value="true" />
|
||||
<option name="WORKING_DIR" value="" />
|
||||
<option name="TARGET_LOGGING_CHANNELS" value="lldb process:gdb-remote packets" />
|
||||
<option name="SHOW_OPTIMIZED_WARNING" value="true" />
|
||||
<option name="ATTACH_ON_WAIT_FOR_DEBUGGER" value="false" />
|
||||
</Native>
|
||||
<Profilers>
|
||||
<option name="ADVANCED_PROFILING_ENABLED" value="false" />
|
||||
<option name="STARTUP_PROFILING_ENABLED" value="false" />
|
||||
<option name="STARTUP_CPU_PROFILING_ENABLED" value="false" />
|
||||
<option name="STARTUP_CPU_PROFILING_CONFIGURATION_NAME" value="Java/Kotlin Method Sample (legacy)" />
|
||||
<option name="STARTUP_NATIVE_MEMORY_PROFILING_ENABLED" value="false" />
|
||||
<option name="NATIVE_MEMORY_SAMPLE_RATE_BYTES" value="2048" />
|
||||
</Profilers>
|
||||
<option name="DEEP_LINK" value="" />
|
||||
<option name="ACTIVITY" value="" />
|
||||
<option name="ACTIVITY_CLASS" value="" />
|
||||
<option name="SEARCH_ACTIVITY_IN_GLOBAL_SCOPE" value="false" />
|
||||
<option name="SKIP_ACTIVITY_VALIDATION" value="false" />
|
||||
<method v="2">
|
||||
<option name="Android.Gradle.BeforeRunTask" enabled="true" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -1,54 +0,0 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
namespace = "de.yourpart.app"
|
||||
compileSdk = rootProject.ext.compileSdkVersion
|
||||
defaultConfig {
|
||||
applicationId "de.yourpart.app"
|
||||
minSdkVersion rootProject.ext.minSdkVersion
|
||||
targetSdkVersion rootProject.ext.targetSdkVersion
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
aaptOptions {
|
||||
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
|
||||
// Default: https://android.googlesource.com/platform/frameworks/base/+/282e181b58cf72b6ca770dc7ca5f91f135444502/tools/aapt/AaptAssets.cpp#61
|
||||
ignoreAssetsPattern = '!.svn:!.git:!.ds_store:!*.scc:.*:!CVS:!thumbs.db:!picasa.ini:!*~'
|
||||
}
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
flatDir{
|
||||
dirs '../capacitor-cordova-android-plugins/src/main/libs', 'libs'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:$androidxCoordinatorLayoutVersion"
|
||||
implementation "androidx.core:core-splashscreen:$coreSplashScreenVersion"
|
||||
implementation project(':capacitor-android')
|
||||
testImplementation "junit:junit:$junitVersion"
|
||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||
implementation project(':capacitor-cordova-android-plugins')
|
||||
}
|
||||
|
||||
apply from: 'capacitor.build.gradle'
|
||||
|
||||
try {
|
||||
def servicesJSON = file('google-services.json')
|
||||
if (servicesJSON.text) {
|
||||
apply plugin: 'com.google.gms.google-services'
|
||||
}
|
||||
} catch(Exception e) {
|
||||
logger.info("google-services.json not found, google-services plugin not applied. Push Notifications won't work")
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
|
||||
android {
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_21
|
||||
targetCompatibility JavaVersion.VERSION_21
|
||||
}
|
||||
}
|
||||
|
||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
implementation project(':capacitor-app')
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (hasProperty('postBuildExtras')) {
|
||||
postBuildExtras()
|
||||
}
|
||||
21
android/android/app/proguard-rules.pro
vendored
@@ -1,21 +0,0 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
@@ -1,26 +0,0 @@
|
||||
package de.yourpart.app;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
|
||||
assertEquals("de.yourpart.app", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
|
||||
<activity
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|smallestScreenSize|screenLayout|uiMode|navigation|density"
|
||||
android:name=".MainActivity"
|
||||
android:label="@string/title_activity_main"
|
||||
android:theme="@style/AppTheme.NoActionBarLaunch"
|
||||
android:launchMode="singleTask"
|
||||
android:exported="true">
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
</activity>
|
||||
|
||||
<provider
|
||||
android:name="androidx.core.content.FileProvider"
|
||||
android:authorities="${applicationId}.fileprovider"
|
||||
android:exported="false"
|
||||
android:grantUriPermissions="true">
|
||||
<meta-data
|
||||
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||
android:resource="@xml/file_paths"></meta-data>
|
||||
</provider>
|
||||
</application>
|
||||
|
||||
<!-- Permissions -->
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
||||
@@ -1,5 +0,0 @@
|
||||
package de.yourpart.app;
|
||||
|
||||
import com.getcapacitor.BridgeActivity;
|
||||
|
||||
public class MainActivity extends BridgeActivity {}
|
||||
|
Before Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 7.7 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 17 KiB |
@@ -1,34 +0,0 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M32,64C32,64 38.39,52.99 44.13,50.95C51.37,48.37 70.14,49.57 70.14,49.57L108.26,87.69L108,109.01L75.97,107.97L32,64Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="78.5885"
|
||||
android:endY="90.9159"
|
||||
android:startX="48.7653"
|
||||
android:startY="61.0927"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M66.94,46.02L66.94,46.02C72.44,50.07 76,56.61 76,64L32,64C32,56.61 35.56,50.11 40.98,46.06L36.18,41.19C35.45,40.45 35.45,39.3 36.18,38.56C36.91,37.81 38.05,37.81 38.78,38.56L44.25,44.05C47.18,42.57 50.48,41.71 54,41.71C57.48,41.71 60.78,42.57 63.68,44.05L69.11,38.56C69.84,37.81 70.98,37.81 71.71,38.56C72.44,39.3 72.44,40.45 71.71,41.19L66.94,46.02ZM62.94,56.92C64.08,56.92 65,56.01 65,54.88C65,53.76 64.08,52.85 62.94,52.85C61.8,52.85 60.88,53.76 60.88,54.88C60.88,56.01 61.8,56.92 62.94,56.92ZM45.06,56.92C46.2,56.92 47.13,56.01 47.13,54.88C47.13,53.76 46.2,52.85 45.06,52.85C43.92,52.85 43,53.76 43,54.88C43,56.01 43.92,56.92 45.06,56.92Z"
|
||||
android:strokeColor="#00000000"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
@@ -1,170 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportHeight="108"
|
||||
android:viewportWidth="108">
|
||||
<path
|
||||
android:fillColor="#26A69A"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeColor="#33FFFFFF"
|
||||
android:strokeWidth="0.8" />
|
||||
</vector>
|
||||
|
Before Width: | Height: | Size: 3.9 KiB |
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<WebView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
</adaptive-icon>
|
||||
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.2 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 16 KiB |
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#FFFFFF</color>
|
||||
</resources>
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<resources>
|
||||
<string name="app_name">YourPart</string>
|
||||
<string name="title_activity_main">YourPart</string>
|
||||
<string name="package_name">de.yourpart.app</string>
|
||||
<string name="custom_url_scheme">de.yourpart.app</string>
|
||||
</resources>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.NoActionBar" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowNoTitle">true</item>
|
||||
<item name="android:background">@null</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="AppTheme.NoActionBarLaunch" parent="Theme.SplashScreen">
|
||||
<item name="android:background">@drawable/splash</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<external-path name="my_images" path="." />
|
||||
<cache-path name="my_cache_images" path="." />
|
||||
</paths>
|
||||
@@ -1,18 +0,0 @@
|
||||
package de.yourpart.app;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
// Trigger sync
|
||||
|
||||
buildscript {
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.13.0'
|
||||
classpath 'com.google.gms:google-services:4.4.4'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
}
|
||||
}
|
||||
|
||||
apply from: "variables.gradle"
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
task clean(type: Delete) {
|
||||
delete rootProject.buildDir
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
include ':capacitor-android'
|
||||
project(':capacitor-android').projectDir = new File('../node_modules/@capacitor/android/capacitor')
|
||||
|
||||
include ':capacitor-app'
|
||||
project(':capacitor-app').projectDir = new File('../node_modules/@capacitor/app/android')
|
||||
@@ -1,22 +0,0 @@
|
||||
# Project-wide Gradle settings.
|
||||
|
||||
# IDE (e.g. Android Studio) users:
|
||||
# Gradle settings configured through the IDE *will override*
|
||||
# any settings specified in this file.
|
||||
|
||||
# For more details on how to configure your build environment visit
|
||||
# http://www.gradle.org/docs/current/userguide/build_environment.html
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||
# org.gradle.parallel=true
|
||||
|
||||
# AndroidX package structure to make it clearer which packages are bundled with the
|
||||
# Android operating system, and which are packaged with your app's APK
|
||||
# https://developer.android.com/topic/libraries/support-library/androidx-rn
|
||||
android.useAndroidX=true
|
||||
BIN
android/android/gradle/wrapper/gradle-wrapper.jar
vendored
@@ -1,7 +0,0 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
251
android/android/gradlew
vendored
@@ -1,251 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH="\\\"\\\""
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC2039,SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command:
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||
# and any embedded shellness will be escaped.
|
||||
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||
# treated as '${Hostname}' itself on the command line.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
94
android/android/gradlew.bat
vendored
@@ -1,94 +0,0 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
@rem SPDX-License-Identifier: Apache-2.0
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo. 1>&2
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||
echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@@ -1,5 +0,0 @@
|
||||
include ':app'
|
||||
include ':capacitor-cordova-android-plugins'
|
||||
project(':capacitor-cordova-android-plugins').projectDir = new File('./capacitor-cordova-android-plugins/')
|
||||
|
||||
apply from: 'capacitor.settings.gradle'
|
||||
@@ -1,16 +0,0 @@
|
||||
ext {
|
||||
minSdkVersion = 24
|
||||
compileSdkVersion = 36
|
||||
targetSdkVersion = 36
|
||||
androidxActivityVersion = '1.11.0'
|
||||
androidxAppCompatVersion = '1.7.1'
|
||||
androidxCoordinatorLayoutVersion = '1.3.0'
|
||||
androidxCoreVersion = '1.17.0'
|
||||
androidxFragmentVersion = '1.8.9'
|
||||
coreSplashScreenVersion = '1.2.0'
|
||||
androidxWebkitVersion = '1.14.0'
|
||||
junitVersion = '4.13.2'
|
||||
androidxJunitVersion = '1.3.0'
|
||||
androidxEspressoCoreVersion = '3.7.0'
|
||||
cordovaAndroidVersion = '14.0.1'
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import type { CapacitorConfig } from '@capacitor/cli';
|
||||
|
||||
const config: CapacitorConfig = {
|
||||
appId: 'de.yourpart.app',
|
||||
appName: 'YourPart',
|
||||
webDir: '../frontend/dist',
|
||||
bundledWebRuntime: false,
|
||||
server: {
|
||||
androidScheme: 'https'
|
||||
},
|
||||
plugins: {
|
||||
SplashScreen: {
|
||||
launchAutoHide: true
|
||||
}
|
||||
},
|
||||
android: {
|
||||
allowMixedContent: false,
|
||||
webContentsDebuggingEnabled: true
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
6
android/native/.idea/AndroidProjectSystem.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="AndroidProjectSystem">
|
||||
<option name="providerId" value="com.android.tools.idea.GradleProjectSystem" />
|
||||
</component>
|
||||
</project>
|
||||
2001
android/native/.idea/caches/deviceStreaming.xml
generated
18
android/native/.idea/deploymentTargetSelector.xml
generated
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetSelector">
|
||||
<selectionStates>
|
||||
<SelectionState runConfigName="YourPartNative.app">
|
||||
<option name="selectionMode" value="DROPDOWN" />
|
||||
<DropdownSelection timestamp="2026-07-10T13:18:31.238846181Z">
|
||||
<Target type="DEFAULT_BOOT">
|
||||
<handle>
|
||||
<DeviceId pluginId="LocalEmulator" identifier="path=/home/torsten/.config/.android/avd/Medium_Tablet.avd" />
|
||||
</handle>
|
||||
</Target>
|
||||
</DropdownSelection>
|
||||
<DialogSelection />
|
||||
</SelectionState>
|
||||
</selectionStates>
|
||||
</component>
|
||||
</project>
|
||||
13
android/native/.idea/deviceManager.xml
generated
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DeviceTable">
|
||||
<option name="columnSorters">
|
||||
<list>
|
||||
<ColumnSorterState>
|
||||
<option name="column" value="Name" />
|
||||
<option name="order" value="ASCENDING" />
|
||||
</ColumnSorterState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
30
android/native/.idea/gradle.xml
generated
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="/mnt/share/torsten/Programs/YourPart3/android/native" />
|
||||
<option value="/mnt/share/torsten/Programs/YourPart3/android/native/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
<GradleProjectSettings>
|
||||
<option name="testRunner" value="CHOOSE_PER_TEST" />
|
||||
<option name="externalProjectPath" value="/mnt/share/torsten/Programs/YourPart3/android/native" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="/mnt/share/torsten/Programs/YourPart3/android/native" />
|
||||
<option value="/mnt/share/torsten/Programs/YourPart3/android/native/app" />
|
||||
</set>
|
||||
</option>
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
8
android/native/.idea/markdown.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownSettings">
|
||||
<option name="previewPanelProviderInfo">
|
||||
<ProviderInfo name="Compose (experimental)" className="com.intellij.markdown.compose.preview.ComposePanelProvider" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
10
android/native/.idea/migrations.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="/mnt/share/torsten/Programs/YourPart3/android/native" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
9
android/native/.idea/misc.xml
generated
@@ -1,9 +0,0 @@
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" default="true" project-jdk-name="jbr-21" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
</project>
|
||||