diff --git a/.github/workflows/build-production-apk.yml b/.github/workflows/build-production-apk.yml index bb4ca09..bb54495 100644 --- a/.github/workflows/build-production-apk.yml +++ b/.github/workflows/build-production-apk.yml @@ -6,7 +6,7 @@ on: workflow_dispatch: # Ermöglicht manuellen Trigger permissions: - contents: write # Für Release-Erstellung erforderlich + contents: write # Fuer Release-Erstellung erforderlich jobs: build: @@ -25,7 +25,7 @@ jobs: - name: Semantic Versionsnummer aus build.gradle.kts extrahieren run: | - # Version aus build.gradle.kts für F-Droid Kompatibilität + # Version aus build.gradle.kts fuer F-Droid Kompatibilität VERSION_NAME=$(grep "versionName = " android/app/build.gradle.kts | sed 's/.*versionName = "\(.*\)".*/\1/') VERSION_CODE=$(grep "versionCode = " android/app/build.gradle.kts | sed 's/.*versionCode = \([0-9]*\).*/\1/') @@ -62,7 +62,7 @@ jobs: mkdir -p apk-output # === Standard Flavor (mit Google Services) === - # Universal APK (funktioniert auf allen Geräten) + # Universal APK (funktioniert auf allen Geraeten) cp android/app/build/outputs/apk/standard/release/app-standard-universal-release.apk \ apk-output/simple-notes-sync-v${{ env.VERSION_NAME }}-standard-universal.apk @@ -113,107 +113,41 @@ jobs: uses: softprops/action-gh-release@v1 with: tag_name: ${{ env.VERSION_TAG }} - name: "📝 Simple Notes Sync v${{ env.VERSION_NAME }} (Produktions-Release)" + name: "📝 Simple Notes Sync v${{ env.VERSION_NAME }}" files: apk-output/*.apk draft: false prerelease: false generate_release_notes: false body: | - # 📝 Produktions-Release: Simple Notes Sync v${{ env.VERSION_NAME }} + ## 📦 Downloads - ## Build-Informationen + | Variante | Datei | Info | + |----------|-------|------| + | **🏆 Empfohlen** | `simple-notes-sync-v${{ env.VERSION_NAME }}-standard-universal.apk` | Funktioniert auf allen Android-Geraeten | + | Modern (2018+) | `simple-notes-sync-v${{ env.VERSION_NAME }}-standard-arm64-v8a.apk` | Kleinere Dateigröße fuer 64-bit Geräte | + | Aelter (<2018) | `simple-notes-sync-v${{ env.VERSION_NAME }}-standard-armeabi-v7a.apk` | Fuer 32-bit ARM Geräte | + | F-Droid Universal | `simple-notes-sync-v${{ env.VERSION_NAME }}-fdroid-universal.apk` | Fuer F-Droid Store | + | F-Droid ARM64 | `simple-notes-sync-v${{ env.VERSION_NAME }}-fdroid-arm64-v8a.apk` | F-Droid 64-bit | + | F-Droid ARMv7 | `simple-notes-sync-v${{ env.VERSION_NAME }}-fdroid-armeabi-v7a.apk` | F-Droid 32-bit | - - **Version:** ${{ env.VERSION_NAME }}+${{ env.BUILD_NUMBER }} - - **Build-Datum:** ${{ env.COMMIT_DATE }} - - **Commit:** ${{ env.SHORT_SHA }} - - **Umgebung:** 🟢 **PRODUKTION** + 💡 **Nicht sicher?** → Nimm die **Universal** APK! --- - ## 📋 Änderungen + ## 📋 Aenderungen ${{ env.COMMIT_MSG }} --- - ## 📦 Download & Installation + ## 📊 Build-Info - ### Welche APK soll ich herunterladen? - - **Flavor-Wahl (beide identisch, nur für verschiedene Stores):** - - **Standard**: Für direkten Download / Obtainium / GitHub Releases - - **F-Droid**: Für F-Droid Store (identisch, nur andere Kennzeichnung) - - 💡 **Hinweis:** Beide Flavors sind 100% FOSS - keine Google Services, kein Tracking! - - **Architektur-Wahl:** - - | Dein Gerät | Standard Flavor | F-Droid Flavor | Größe | Hinweis | - |------------|----------------|----------------|-------|---------| - | 🤷 Nicht sicher? | `simple-notes-sync-v${{ env.VERSION_NAME }}-standard-universal.apk` | `...-fdroid-universal.apk` | ~5 MB | Funktioniert überall | - | Modern (2018+) | `simple-notes-sync-v${{ env.VERSION_NAME }}-standard-arm64-v8a.apk` | `...-fdroid-arm64-v8a.apk` | ~3 MB | Schneller, kleiner | - | Ältere Geräte | `simple-notes-sync-v${{ env.VERSION_NAME }}-standard-armeabi-v7a.apk` | `...-fdroid-armeabi-v7a.apk` | ~3 MB | ARM-Chips vor 2018 | - - 💡 **Empfehlung:** Nimm die **Standard Universal** APK! - - ### Installationsschritte - 1. Lade die passende APK aus den Assets unten herunter - 2. Aktiviere "Installation aus unbekannten Quellen" in den Android-Einstellungen - 3. Öffne die heruntergeladene APK-Datei - 4. Folge den Installationsanweisungen - 5. Konfiguriere die WebDAV-Einstellungen in der App + - **Version:** ${{ env.VERSION_NAME }} (Code: ${{ env.BUILD_NUMBER }}) + - **Datum:** ${{ env.COMMIT_DATE }} + - **Commit:** ${{ env.SHORT_SHA }} --- - ## ⚙️ Funktionen - - - ✅ Automatische WebDAV-Synchronisation alle 30 Minuten (~0,4% Akku/Tag) - - ✅ Intelligente Gateway-Erkennung (automatische Heimnetzwerk-Erkennung) - - ✅ Material Design 3 Oberfläche - - ✅ Datenschutzorientiert (kein Tracking, keine Analysen) - - ✅ Offline-First Architektur - - --- - - ## 🔄 Update von vorheriger Version - - Installiere diese APK einfach über die bestehende Installation - alle Daten und Einstellungen bleiben erhalten. - - --- - - ## 📱 Obtanium - Auto-Update App - - Erhalte automatische Updates mit [Obtanium](https://github.com/ImranR98/Obtanium/releases/latest). - - **Einrichtung:** - 1. Installiere Obtanium über den Link oben - 2. Füge die App mit dieser URL hinzu: `https://github.com/inentory69/simple-notes-sync` - 3. Aktiviere Auto-Updates - - --- - - ## 🆘 Support - - Bei Problemen oder Fragen öffne bitte ein Issue auf GitHub. - - --- - - ## 🔒 Datenschutz & Sicherheit - - - Alle Daten werden über deinen eigenen WebDAV-Server synchronisiert (self-hosted) - - Keine Drittanbieter-Analysen oder Tracking - - Keine Internet-Berechtigungen außer für WebDAV-Sync - - Unterstützt HTTP (lokal) und HTTPS (extern) - du entscheidest - - Open Source - prüfe den Code selbst - - --- - - ## 🛠️ Erstellt mit - - - **Sprache:** Kotlin - - **UI:** Material Design 3 - - **Sync:** WorkManager + WebDAV - - **Target SDK:** Android 16 (API 36) - - **Min SDK:** Android 8.0 (API 26) + **[� Dokumentation](https://github.com/inventory69/simple-notes-sync/blob/main/QUICKSTART.md)** · **[🐛 Issue melden](https://github.com/inventory69/simple-notes-sync/issues)** env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/DOCS.en.md b/DOCS.en.md new file mode 100644 index 0000000..5822e07 --- /dev/null +++ b/DOCS.en.md @@ -0,0 +1,474 @@ +# Simple Notes Sync - Technical Documentation + +This file contains detailed technical information about implementation, architecture, and advanced features. + +**🌍 Languages:** [Deutsch](DOCS.md) · **English** + +--- + +## 📐 Architecture + +### Overall Overview + +``` +┌─────────────────┐ +│ Android App │ +│ (Kotlin) │ +└────────┬────────┘ + │ WebDAV/HTTP + │ +┌────────▼────────┐ +│ WebDAV Server │ +│ (Docker) │ +└─────────────────┘ +``` + +### Android App Architecture + +``` +app/ +├── models/ +│ ├── Note.kt # Data class for notes +│ └── SyncStatus.kt # Sync status enum +├── storage/ +│ └── NotesStorage.kt # Local JSON file storage +├── sync/ +│ ├── WebDavSyncService.kt # WebDAV sync logic +│ ├── NetworkMonitor.kt # WiFi detection +│ ├── SyncWorker.kt # WorkManager background worker +│ └── BootReceiver.kt # Device reboot handler +├── adapters/ +│ └── NotesAdapter.kt # RecyclerView adapter +├── utils/ +│ ├── Constants.kt # App constants +│ ├── NotificationHelper.kt# Notification management +│ └── Logger.kt # Debug/release logging +└── activities/ + ├── MainActivity.kt # Main view with list + ├── NoteEditorActivity.kt# Note editor + └── SettingsActivity.kt # Server configuration +``` + +--- + +## 🔄 Auto-Sync Implementation + +### WorkManager Periodic Task + +Auto-sync is based on **WorkManager** with the following configuration: + +```kotlin +val constraints = Constraints.Builder() + .setRequiredNetworkType(NetworkType.UNMETERED) // WiFi only + .build() + +val syncRequest = PeriodicWorkRequestBuilder( + 30, TimeUnit.MINUTES, // Every 30 minutes + 10, TimeUnit.MINUTES // Flex interval +) + .setConstraints(constraints) + .build() +``` + +**Why WorkManager?** +- ✅ Runs even when app is closed +- ✅ Automatic restart after device reboot +- ✅ Battery-efficient (Android managed) +- ✅ Guaranteed execution when constraints are met + +### Network Detection + +Instead of SSID-based detection (Android 13+ privacy issues), we use **Gateway IP Comparison**: + +```kotlin +fun isInHomeNetwork(): Boolean { + val gatewayIP = getGatewayIP() // e.g. 192.168.0.1 + val serverIP = extractIPFromUrl(serverUrl) // e.g. 192.168.0.188 + + return isSameNetwork(gatewayIP, serverIP) // Checks /24 network +} +``` + +**Advantages:** +- ✅ No location permissions needed +- ✅ Works with all Android versions +- ✅ Reliable and fast + +### Sync Flow + +``` +1. WorkManager wakes up (every 30 min) + ↓ +2. Check: WiFi connected? + ↓ +3. Check: Same network as server? + ↓ +4. Load local notes + ↓ +5. Upload new/changed notes → Server + ↓ +6. Download remote notes ← Server + ↓ +7. Merge & resolve conflicts + ↓ +8. Update local storage + ↓ +9. Show notification (if changes) +``` + +--- + +## 🔋 Battery Optimization + +### Usage Analysis + +| Component | Frequency | Usage | Details | +|------------|----------|-----------|---------| +| WorkManager Wakeup | Every 30 min | ~0.15 mAh | System wakes up | +| Network Check | 48x/day | ~0.03 mAh | Gateway IP check | +| WebDAV Sync | 2-3x/day | ~1.5 mAh | Only when changes | +| **Total** | - | **~12 mAh/day** | **~0.4%** at 3000mAh | + +### Optimizations + +1. **IP Caching** + ```kotlin + private var cachedServerIP: String? = null + // DNS lookup only once at start, not every check + ``` + +2. **Throttling** + ```kotlin + private var lastSyncTime = 0L + private const val MIN_SYNC_INTERVAL_MS = 60_000L // Max 1 sync/min + ``` + +3. **Conditional Logging** + ```kotlin + object Logger { + fun d(tag: String, msg: String) { + if (BuildConfig.DEBUG) Log.d(tag, msg) + } + } + ``` + +4. **Network Constraints** + - WiFi only (not mobile data) + - Only when server is reachable + - No permanent listeners + +--- + +## 📦 WebDAV Sync Details + +### Upload Flow + +```kotlin +suspend fun uploadNotes(): Int { + val localNotes = storage.loadAllNotes() + var uploadedCount = 0 + + for (note in localNotes) { + if (note.syncStatus == SyncStatus.PENDING) { + val jsonContent = note.toJson() + val remotePath = "$serverUrl/${note.id}.json" + + sardine.put(remotePath, jsonContent.toByteArray()) + + note.syncStatus = SyncStatus.SYNCED + storage.saveNote(note) + uploadedCount++ + } + } + + return uploadedCount +} +``` + +### Download Flow + +```kotlin +suspend fun downloadNotes(): DownloadResult { + val remoteFiles = sardine.list(serverUrl) + var downloadedCount = 0 + var conflictCount = 0 + + for (file in remoteFiles) { + if (!file.name.endsWith(".json")) continue + + val content = sardine.get(file.href) + val remoteNote = Note.fromJson(content) + val localNote = storage.loadNote(remoteNote.id) + + if (localNote == null) { + // New note from server + storage.saveNote(remoteNote) + downloadedCount++ + } else if (localNote.modifiedAt < remoteNote.modifiedAt) { + // Server has newer version + storage.saveNote(remoteNote) + downloadedCount++ + } else if (localNote.modifiedAt > remoteNote.modifiedAt) { + // Local version is newer → Conflict + resolveConflict(localNote, remoteNote) + conflictCount++ + } + } + + return DownloadResult(downloadedCount, conflictCount) +} +``` + +### Conflict Resolution + +Strategy: **Last-Write-Wins** with **Conflict Copy** + +```kotlin +fun resolveConflict(local: Note, remote: Note) { + // Rename remote note (conflict copy) + val conflictNote = remote.copy( + id = "${remote.id}_conflict_${System.currentTimeMillis()}", + title = "${remote.title} (Conflict)" + ) + + storage.saveNote(conflictNote) + + // Local note remains + local.syncStatus = SyncStatus.SYNCED + storage.saveNote(local) +} +``` + +--- + +## 🔔 Notifications + +### Notification Channels + +```kotlin +val channel = NotificationChannel( + "notes_sync_channel", + "Notes Synchronization", + NotificationManager.IMPORTANCE_DEFAULT +) +``` + +### Success Notification + +```kotlin +fun showSyncSuccess(context: Context, count: Int) { + val intent = Intent(context, MainActivity::class.java) + val pendingIntent = PendingIntent.getActivity(context, 0, intent, FLAGS) + + val notification = NotificationCompat.Builder(context, CHANNEL_ID) + .setContentTitle("Sync successful") + .setContentText("$count notes synchronized") + .setContentIntent(pendingIntent) // Click opens app + .setAutoCancel(true) // Dismiss on click + .build() + + notificationManager.notify(NOTIFICATION_ID, notification) +} +``` + +--- + +## 🛡️ Permissions + +The app requires **minimal permissions**: + +```xml + + + + + + + + + + + + + + +``` + +**No Location Permissions!** +Earlier versions required `ACCESS_FINE_LOCATION` for SSID detection. Now we use Gateway IP Comparison. + +--- + +## 🧪 Testing + +### Test Server + +```bash +# WebDAV server reachable? +curl -u noteuser:password http://192.168.0.188:8080/ + +# Upload file +echo '{"test":"data"}' > test.json +curl -u noteuser:password -T test.json http://192.168.0.188:8080/test.json + +# Download file +curl -u noteuser:password http://192.168.0.188:8080/test.json +``` + +### Test Android App + +**Unit Tests:** +```bash +cd android +./gradlew test +``` + +**Instrumented Tests:** +```bash +./gradlew connectedAndroidTest +``` + +**Manual Testing Checklist:** + +- [ ] Create note → visible in list +- [ ] Edit note → changes saved +- [ ] Delete note → removed from list +- [ ] Manual sync → server status "Reachable" +- [ ] Auto-sync → notification after ~30 min +- [ ] Close app → auto-sync continues +- [ ] Device reboot → auto-sync starts automatically +- [ ] Server offline → error notification +- [ ] Notification click → app opens + +--- + +## 🚀 Build & Deployment + +### Debug Build + +```bash +cd android +./gradlew assembleDebug +# APK: app/build/outputs/apk/debug/app-debug.apk +``` + +### Release Build + +```bash +./gradlew assembleRelease +# APK: app/build/outputs/apk/release/app-release-unsigned.apk +``` + +### Sign (for Distribution) + +```bash +# Create keystore +keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias + +# Sign APK +jarsigner -verbose -sigalg SHA256withRSA -digestalg SHA-256 \ + -keystore my-release-key.jks \ + app-release-unsigned.apk my-alias + +# Optimize +zipalign -v 4 app-release-unsigned.apk app-release.apk +``` + +--- + +## 🐛 Debugging + +### LogCat Filter + +```bash +# Only app logs +adb logcat -s SimpleNotesApp NetworkMonitor SyncWorker WebDavSyncService + +# With timestamps +adb logcat -v time -s SyncWorker + +# Save to file +adb logcat -s SyncWorker > sync_debug.log +``` + +### Common Issues + +**Problem: Auto-sync not working** +``` +Solution: Disable battery optimization +Settings → Apps → Simple Notes → Battery → Don't optimize +``` + +**Problem: Server not reachable** +``` +Check: +1. Server running? → docker-compose ps +2. IP correct? → ip addr show +3. Port open? → telnet 192.168.0.188 8080 +4. Firewall? → sudo ufw allow 8080 +``` + +**Problem: Notifications not appearing** +``` +Check: +1. Notification permission granted? +2. Do Not Disturb active? +3. App in background? → Force stop & restart +``` + +--- + +## 📚 Dependencies + +```gradle +// Core +androidx.core:core-ktx:1.12.0 +androidx.appcompat:appcompat:1.6.1 +com.google.android.material:material:1.11.0 + +// Lifecycle +androidx.lifecycle:lifecycle-runtime-ktx:2.7.0 + +// RecyclerView +androidx.recyclerview:recyclerview:1.3.2 + +// Coroutines +org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3 + +// WorkManager +androidx.work:work-runtime-ktx:2.9.0 + +// WebDAV Client +com.github.thegrizzlylabs:sardine-android:0.8 + +// Broadcast (deprecated but working) +androidx.localbroadcastmanager:localbroadcastmanager:1.1.0 +``` + +--- + +## 🔮 Roadmap + +### v1.1 +- [ ] Search & Filter +- [ ] Dark Mode +- [ ] Tags/Categories +- [ ] Markdown Preview + +### v2.0 +- [ ] Desktop Client (Flutter) +- [ ] End-to-End Encryption +- [ ] Shared Notes (Collaboration) +- [ ] Attachment Support + +--- + +## 📖 Further Documentation + +- [Project Docs](https://github.com/inventory69/project-docs/tree/main/simple-notes-sync) +- [Android Guide](https://github.com/inventory69/project-docs/blob/main/simple-notes-sync/ANDROID_GUIDE.md) +- [Bugfix Documentation](https://github.com/inventory69/project-docs/blob/main/simple-notes-sync/BUGFIX_SYNC_SPAM_AND_NOTIFICATIONS.md) + +--- + +**Last updated:** December 21, 2025 diff --git a/DOCS.md b/DOCS.md index fe2f5ea..7319c26 100644 --- a/DOCS.md +++ b/DOCS.md @@ -2,6 +2,8 @@ Diese Datei enthält detaillierte technische Informationen über die Implementierung, Architektur und erweiterte Funktionen. +**🌍 Sprachen:** **Deutsch** · [English](DOCS.en.md) + --- ## 📐 Architektur diff --git a/QUICKSTART.en.md b/QUICKSTART.en.md new file mode 100644 index 0000000..e59cf91 --- /dev/null +++ b/QUICKSTART.en.md @@ -0,0 +1,269 @@ +# Quick Start Guide - Simple Notes Sync 📝 + +> Step-by-step installation and setup guide + +**🌍 Languages:** [Deutsch](QUICKSTART.md) · **English** + +--- + +## Prerequisites + +- ✅ Android 8.0+ smartphone/tablet +- ✅ WiFi connection +- ✅ Own server with Docker (optional - for self-hosting) + +--- + +## Option 1: With own server (Self-Hosted) 🏠 + +### Step 1: Setup WebDAV Server + +On your server (e.g. Raspberry Pi, NAS, VPS): + +```bash +# Clone repository +git clone https://github.com/inventory69/simple-notes-sync.git +cd simple-notes-sync/server + +# Configure environment variables +cp .env.example .env +nano .env +``` + +**Adjust in `.env`:** +```env +WEBDAV_PASSWORD=your-secure-password-here +``` + +**Start server:** +```bash +docker compose up -d +``` + +**Find IP address:** +```bash +ip addr show | grep "inet " | grep -v 127.0.0.1 +``` + +➡️ **Note down:** `http://YOUR-SERVER-IP:8080/` + +--- + +### Step 2: Install App + +1. **Download APK:** [Latest version](https://github.com/inventory69/simple-notes-sync/releases/latest) + - Choose: `simple-notes-sync-vX.X.X-standard-universal.apk` + +2. **Allow installation:** + - Android: Settings → Security → Enable "Unknown sources" for your browser + +3. **Open and install APK** + +--- + +### Step 3: Configure App + +1. **Open app** + +2. **Open settings** (⚙️ icon top right) + +3. **Configure server settings:** + + | Field | Value | + |------|------| + | **WebDAV Server URL** | `http://YOUR-SERVER-IP:8080/` | + | **Username** | `noteuser` | + | **Password** | (your password from `.env`) | + | **Gateway SSID** | Name of your WiFi network | + +4. **Press "Test connection"** + - ✅ Success? → Continue to step 4 + - ❌ Error? → See [Troubleshooting](#troubleshooting) + +5. **Enable auto-sync** (toggle switch) + +6. **Choose sync interval:** + - **15 min** - Maximum currency (~0.8% battery/day) + - **30 min** - Recommended (~0.4% battery/day) ⭐ + - **60 min** - Maximum battery life (~0.2% battery/day) + +--- + +### Step 4: Create First Note + +1. Back to main view (← arrow) + +2. **"Add note"** (+ icon) + +3. Enter title and text + +4. **Save** (💾 icon) + +5. **Wait for auto-sync** (or manually: ⚙️ → "Sync now") + +🎉 **Done!** Your notes will be automatically synchronized! + +--- + +## Option 2: Local notes only (no server) 📱 + +You can also use Simple Notes **without a server**: + +1. **Install app** (see step 2 above) + +2. **Use without server configuration:** + - Notes are only stored locally + - No auto-sync + - Perfect for offline-only use + +--- + +## 🔋 Disable Battery Optimization + +For reliable auto-sync: + +1. **Settings** → **Apps** → **Simple Notes Sync** + +2. **Battery** → **Battery usage** + +3. Select: **"Don't optimize"** or **"Unrestricted"** + +💡 **Note:** Android Doze Mode may still delay sync in standby (~60 min). This is normal and affects all apps. + +--- + +## 📊 Sync Intervals in Detail + +| Interval | Syncs/day | Battery/day | Battery/sync | Use case | +|-----------|-----------|----------|-----------|----------------| +| **15 min** | ~96 | ~0.8% (~23 mAh) | ~0.008% | ⚡ Maximum currency (multiple devices) | +| **30 min** | ~48 | ~0.4% (~12 mAh) | ~0.008% | ✓ **Recommended** - balanced | +| **60 min** | ~24 | ~0.2% (~6 mAh) | ~0.008% | 🔋 Maximum battery life | + +--- + +## 🐛 Troubleshooting + +### Connection test fails + +**Problem:** "Connection failed" during test + +**Solutions:** + +1. **Server running?** + ```bash + docker compose ps + # Should show "Up" + ``` + +2. **Same WiFi?** + - Smartphone and server must be on same network + - Check SSID in app settings + +3. **IP address correct?** + ```bash + ip addr show | grep "inet " + # Check if IP in URL matches + ``` + +4. **Firewall?** + ```bash + # Open port 8080 (if firewall active) + sudo ufw allow 8080/tcp + ``` + +5. **Check server logs:** + ```bash + docker compose logs -f + ``` + +--- + +### Auto-sync not working + +**Problem:** Notes are not automatically synchronized + +**Solutions:** + +1. **Auto-sync enabled?** + - ⚙️ Settings → Toggle "Auto-sync" must be **ON** + +2. **Battery optimization disabled?** + - See [Disable Battery Optimization](#-disable-battery-optimization) + +3. **On correct WiFi?** + - Sync only works when SSID = Gateway SSID + - Check current SSID in Android settings + +4. **Test manually:** + - ⚙️ Settings → "Sync now" + - Works? → Auto-sync should work too + +--- + +### Notes not showing up + +**Problem:** After installation, no notes visible even though they exist on server + +**Solution:** + +1. **Manually sync once:** + - ⚙️ Settings → "Sync now" + +2. **Check server data:** + ```bash + docker compose exec webdav ls -la /data/ + # Should show .json files + ``` + +--- + +### Sync errors + +**Problem:** Error message during sync + +**Solutions:** + +1. **"401 Unauthorized"** → Wrong password + - Check password in app settings + - Compare with `.env` on server + +2. **"404 Not Found"** → Wrong URL + - Should end with `/` (e.g. `http://192.168.1.100:8080/`) + +3. **"Network error"** → No connection + - See [Connection test fails](#connection-test-fails) + +--- + +## 📱 Updates + +### Automatic with Obtainium (recommended) + +1. **[Install Obtainium](https://github.com/ImranR98/Obtanium/releases/latest)** + +2. **Add app:** + - URL: `https://github.com/inventory69/simple-notes-sync` + - Enable auto-update + +3. **Done!** Obtainium notifies you of new versions + +### Manual + +1. Download new APK from [Releases](https://github.com/inventory69/simple-notes-sync/releases/latest) + +2. Install (overwrites old version) + +3. All data remains intact! + +--- + +## 🆘 Further Help + +- **GitHub Issues:** [Report problem](https://github.com/inventory69/simple-notes-sync/issues) +- **Complete docs:** [DOCS.en.md](DOCS.en.md) +- **Server setup details:** [server/README.en.md](server/README.en.md) + +--- + +**Version:** 1.1.0 · **Created:** December 2025 diff --git a/QUICKSTART.md b/QUICKSTART.md index 4828005..7bd5f5e 100644 --- a/QUICKSTART.md +++ b/QUICKSTART.md @@ -2,6 +2,8 @@ > Schritt-für-Schritt Anleitung zur Installation und Einrichtung +**🌍 Sprachen:** **Deutsch** · [English](QUICKSTART.en.md) + --- ## Voraussetzungen diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..f94d5a8 --- /dev/null +++ b/README.en.md @@ -0,0 +1,72 @@ +# Simple Notes Sync 📝 + +> Minimalist offline notes with auto-sync to your own server + +[![Android](https://img.shields.io/badge/Android-8.0%2B-green.svg)](https://www.android.com/) +[![Material Design 3](https://img.shields.io/badge/Material-Design%203-green.svg)](https://m3.material.io/) +[![License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) + +**📱 [APK Download](https://github.com/inventory69/simple-notes-sync/releases/latest)** · **📖 [Documentation](DOCS.en.md)** · **🚀 [Quick Start](QUICKSTART.en.md)** + +**🌍 Languages:** [Deutsch](README.md) · **English** + +--- + +## Features + +- 📝 Offline-First - Notes always available +- 🔄 Auto-Sync - Configurable intervals (15/30/60 min) +- 🏠 Self-Hosted - WebDAV on your server +- 🔐 Privacy-First - No cloud, no tracking +- 🔋 Battery-friendly - ~0.2-0.8% per day + +--- + +## 🚀 Quick Start + +### 1. Server Setup + +```bash +cd server +cp .env.example .env +# Set password in .env +docker compose up -d +``` + +➡️ **Details:** [Server Setup Guide](server/README.en.md) + +### 2. App Installation + +1. [Download APK](https://github.com/inventory69/simple-notes-sync/releases/latest) +2. Install & open +3. ⚙️ Settings → Configure server +4. Enable auto-sync + +➡️ **Details:** [Complete guide](QUICKSTART.en.md) + +--- + +## 📚 Documentation + +- **[Quick Start Guide](QUICKSTART.en.md)** - Step-by-step guide for end users +- **[Server Setup](server/README.en.md)** - Configure WebDAV server +- **[Complete Docs](DOCS.en.md)** - Features, troubleshooting, build instructions + +--- + +## 🛠️ Development + +```bash +cd android +./gradlew assembleStandardRelease +``` + +➡️ **Details:** [Build instructions in DOCS.en.md](DOCS.en.md) + +--- + +## 📄 License + +MIT License - see [LICENSE](LICENSE) + +**v1.1.0** · Built with Kotlin + Material Design 3 diff --git a/README.md b/README.md index 58616f1..fbc1ea6 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ **📱 [APK Download](https://github.com/inventory69/simple-notes-sync/releases/latest)** · **📖 [Dokumentation](DOCS.md)** · **🚀 [Quick Start](QUICKSTART.md)** +**🌍 Sprachen:** **Deutsch** · [English](README.en.md) + --- ## Features diff --git a/server/README.en.md b/server/README.en.md new file mode 100644 index 0000000..932c9e7 --- /dev/null +++ b/server/README.en.md @@ -0,0 +1,86 @@ +# WebDAV Server - Simple Notes Sync + +**🌍 Languages:** [Deutsch](README.md) · **English** + +--- + +## Quick Start + +```bash +# 1. Adjust environment variables +cp .env.example .env +nano .env + +# 2. Start server +docker-compose up -d + +# 3. Check logs +docker-compose logs -f + +# 4. Test +curl -u noteuser:your_password http://localhost:8080/ +``` + +## Server URL + +**Local:** `http://localhost:8080/` + +**On network:** `http://YOUR_IP:8080/` (e.g. `http://192.168.1.100:8080/`) + +Find IP address: +```bash +ip addr show | grep "inet " | grep -v 127.0.0.1 +``` + +## Credentials + +Default (see `.env`): +- Username: `noteuser` +- Password: See `.env` file + +## Management + +```bash +# Check status +docker-compose ps + +# View logs +docker-compose logs -f + +# Restart +docker-compose restart + +# Stop +docker-compose down + +# Update +docker-compose pull +docker-compose up -d +``` + +## Data Location + +Your notes are stored in: `./data/` + +**Backup:** +```bash +# Create backup +tar -czf notes-backup-$(date +%Y%m%d).tar.gz data/ + +# Restore backup +tar -xzf notes-backup-YYYYMMDD.tar.gz +``` + +## External Access (HTTPS) + +For access from outside your home network, use a reverse proxy like Caddy or nginx: + +**Example with Caddy:** + +```Caddyfile +notes.yourdomain.com { + reverse_proxy localhost:8080 +} +``` + +**Important:** Always use HTTPS for external access to protect your credentials! diff --git a/server/README.md b/server/README.md index 4d99a26..e754b5a 100644 --- a/server/README.md +++ b/server/README.md @@ -1,5 +1,9 @@ # WebDAV Server - Simple Notes Sync +**🌍 Sprachen:** **Deutsch** · [English](README.en.md) + +--- + ## Quick Start ```bash