Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
e8a3519
Replace services with use cases
sunstep Dec 27, 2025
56b1112
Merge branch 'dev' of https://github.com/sunstep/dawarich-android int…
sunstep Dec 27, 2025
1af9f1c
WIP: Unify all tracker settings into a single object, and finish up s…
sunstep Jan 3, 2026
5b7d171
Add riverpod dependency
sunstep Jan 3, 2026
336232a
Wrap app in riverpod and remove route observer dependency
sunstep Jan 3, 2026
13170eb
Wrap app in riverpod and remove route observer dependency
sunstep Jan 3, 2026
332f393
Refactor: Migrate to Riverpod and remove legacy providers and depende…
sunstep Jan 22, 2026
cf5df9d
Remove h_ providers and old getIt files
sunstep Jan 23, 2026
ff56580
Merge pull request #349 from sunstep/refactor/implement-riverpod
sunstep Jan 23, 2026
76dba4e
Build separate dev version of app to prevent overwriting release version
sunstep Jan 24, 2026
75f5c60
Merge pull request #351 from sunstep/refactor/fix/build-signing
sunstep Jan 24, 2026
1630f66
Fix timeline page stuck loading
sunstep Jan 25, 2026
bec81ff
Merge pull request #353 from sunstep/refactor/fix/timeline-broken
sunstep Jan 25, 2026
144ba9f
Stop disposing the map controller from viewmodel
sunstep Jan 25, 2026
c9f2dac
Merge pull request #354 from sunstep/refactor/fix/stop-map-dispose-vm
sunstep Jan 25, 2026
005d33b
Fix stats page stuck loading
sunstep Jan 25, 2026
845a268
Merge pull request #355 from sunstep/refactor/fix/stats-broken
sunstep Jan 25, 2026
bfda70b
Refactor timeline page to set animated map controller directly in dat…
sunstep Jan 25, 2026
8767d52
Merge pull request #356 from sunstep/refactor/fix/timeline-init-move
sunstep Jan 25, 2026
11e1bd1
Fix tracker page UI
sunstep Jan 25, 2026
86b9813
Merge pull request #357 from sunstep/refactor/fix/tracker-page
sunstep Jan 25, 2026
dc4a7ae
Refactor app boot process to SplashPage and improve error handling
sunstep Jan 25, 2026
3fff42c
Merge pull request #358 from sunstep/refactor/fix/hot-reload-handling
sunstep Jan 25, 2026
299649c
Add store point use case to tracker page view model and providers
sunstep Jan 25, 2026
1a40e1b
Merge pull request #359 from sunstep/refactor/fix/point-store
sunstep Jan 25, 2026
3dab696
Fix automatic tracking not asking for permissions
sunstep Jan 25, 2026
84b30e9
Add store point use case to point automation service and improve poin…
sunstep Jan 25, 2026
accb0ce
Merge pull request #360 from sunstep/refactor/fix/auto-tracking
sunstep Jan 25, 2026
df810df
Merge pull request #350 from sunstep/refactor/service-to-usecase
sunstep Jan 25, 2026
eeb29a9
Enhance session provider with keepAlive and update timeline page to u…
sunstep Jan 25, 2026
91ad8b8
Merge pull request #361 from sunstep/fix/timeline-browsing
sunstep Jan 25, 2026
ed26836
Merge branch 'main' of https://github.com/sunstep/dawarich-android in…
sunstep Jan 25, 2026
155ca12
Merge remote-tracking branch 'origin/dev' into dev
sunstep Jan 25, 2026
5c9c881
Improve loading state handling in timeline page and view model
sunstep Jan 25, 2026
53b9565
Fix color inconsistencies in timeline page
sunstep Jan 25, 2026
be69206
Merge pull request #363 from sunstep/fix/timeline-loading-lockout
sunstep Jan 25, 2026
f131db8
Update centerMap method to use Geolocator for user location
sunstep Jan 25, 2026
25b9b13
Merge pull request #364 from sunstep/fix/timeline-center-location-button
sunstep Jan 25, 2026
9403288
Add AuthGuard for protected routes and refactor user ID handling acro…
sunstep Jan 25, 2026
cc7d962
Merge pull request #365 from sunstep/auth-in-router
sunstep Jan 25, 2026
a7f06f2
Fix auto upload not working
sunstep Jan 25, 2026
e30fd09
Merge pull request #366 from sunstep/fix/auto-upload
sunstep Jan 25, 2026
a2a2076
Properly name directories, files and classes
sunstep Jan 26, 2026
d593371
Merge pull request #367
sunstep Jan 26, 2026
5c94d77
Fix blank page on notification launch
sunstep Jan 27, 2026
bd44328
Merge pull request #368
sunstep Jan 27, 2026
2668cfa
Enhance dispose safety
sunstep Jan 27, 2026
8c0cf5f
Merge pull request #369
sunstep Jan 27, 2026
b142518
Remove full migration flow, store provider and record timestamp of po…
sunstep Jan 29, 2026
89c5699
Add code gen in migration tests workflow
sunstep Jan 29, 2026
3bf6d25
Merge pull request #370 from sunstep/adjustment/store-point-timestamp
sunstep Jan 29, 2026
4e04764
Update whatsnew and pubspec
sunstep Jan 29, 2026
5aa793a
Correct the version in pubspec
sunstep Jan 29, 2026
1738bcf
Merge pull request #371 from sunstep/release/0.13.0
sunstep Jan 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/migration_tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Migration Tests

on:
push:
branches: [ main, dev ]
paths:
- 'lib/core/database/drift/**'
- 'test/core/database/drift/**'
- 'drift_schemas/**'
pull_request:
branches: [ main, dev ]
paths:
- 'lib/core/database/drift/**'
- 'test/core/database/drift/**'
- 'drift_schemas/**'

jobs:
test-migrations:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
flutter-version: '3.38.x'
channel: 'stable'

- name: Get dependencies
run: flutter pub get

- name: Generate Drift code
run: dart run build_runner build --delete-conflicting-outputs

- name: Generate schema files (if not committed)
run: |
if [ ! -d "drift_schemas" ]; then
echo "Generating schema files..."
dart run drift_dev schema dump lib/core/database/drift/database/sqlite_client.dart drift_schemas/
else
echo "Schema files already exist"
fi

- name: Run migration tests
run: flutter test test/core/database/drift/schema_verification_test.dart

- name: Upload test results
if: failure()
uses: actions/upload-artifact@v4
with:
name: test-results
path: test/failures/
92 changes: 92 additions & 0 deletions MIGRATION_TESTING_SETUP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Migration Testing Setup - Complete! ✅

## What We Built

A comprehensive migration testing infrastructure using Drift's testing capabilities to ensure database migrations work correctly **before** releasing to users.

## Files Created

1. **`test/core/database/drift/schema_verification_test.dart`** - Main test file with 3 migration tests
2. **`test/core/database/drift/MIGRATION_TESTING_README.md`** - Complete documentation
3. **`generate_schemas.bat` / `generate_schemas.sh`** - Scripts to generate schema snapshots
4. **`.github/workflows/migration_tests.yml`** - CI/CD integration
5. **`drift_schemas/drift_schema_v4.json`** - v4 schema snapshot
6. **`drift_schemas/drift_schema_v5.json`** - v5 schema snapshot

## Test Coverage

### ✅ Test 1: V4 → V5 Migration
- Creates a v4 database with old schema (`timestamp` column)
- Inserts test data
- Triggers migration to v5
- Verifies columns were renamed (`timestamp` → `record_timestamp`)
- Verifies `provider_timestamp` was added
- Verifies data was preserved

### ✅ Test 2: Recovery Logic
- Simulates a failed migration (v5 version but old schema)
- Verifies the recovery logic in `beforeOpen` fixes it
- Tests the safety net for users with broken databases

### ✅ Test 3: Fresh V5 Database
- Creates a new v5 database from scratch
- Verifies all tables and columns exist
- Tests CRUD operations work correctly

## How to Use

### Run Tests Locally
```bash
flutter test test/core/database/drift/schema_verification_test.dart
```

### Generate Schema Files (after schema changes)
```bash
.\generate_schemas.bat # Windows
./generate_schemas.sh # Linux/Mac
```

### CI/CD
Tests run automatically on every push that touches database code via GitHub Actions.

## Key Improvements

1. **Confidence in Releases** - You can now release updates knowing migrations work
2. **Catch Issues Early** - Migration bugs are caught in tests, not in production
3. **Documentation** - Clear docs for future developers
4. **Automated** - Tests run in CI/CD pipeline automatically
5. **Safety Net** - Recovery logic fixes incomplete migrations for existing users

## Migration Best Practices Applied

✅ Check if columns exist before modifying
✅ Use default values when adding NOT NULL columns
✅ Preserve data during migrations
✅ Test migrations before releasing
✅ Have recovery logic as safety net
✅ Document migration process

## Next Steps

1. **Commit all files** including `drift_schemas/` directory
2. **Run tests before every release** with schema changes
3. **Update schema files** after every schema change
4. **Add new tests** when adding future migrations (v5→v6, etc.)

## Example Workflow

When you need to add a new column in the future:

1. Update table definition
2. Increment `kSchemaVersion`
3. Add migration logic in `onUpgrade`
4. Run `generate_schemas.bat`
5. Add test for new migration
6. Run tests: `flutter test test/core/database/drift/schema_verification_test.dart`
7. Commit and push
8. CI/CD runs tests automatically
9. Release with confidence! 🚀

---

**You now have a production-ready migration testing setup!** This solves your long-standing problem of not being able to confidently test migrations before releasing updates to users.
27 changes: 25 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ android {
}

signingConfigs {
debug {
// Keep debug signing stable across rebuilds/machines.
// This matches Flutter/Gradle defaults and ensures Android Keystore-backed
// data (e.g., flutter_secure_storage encryptedSharedPreferences) stays readable.
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
storeType 'pkcs12'
}
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
Expand All @@ -57,6 +67,9 @@ android {
// attach the signing config
signingConfig signingConfigs.release

// Make sure release label stays clean.
resValue "string", "app_name", "Dawarich"

// optimizations
minifyEnabled true
shrinkResources true
Expand All @@ -65,10 +78,20 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'

// ensure no debug flags slip in
debuggable false
jniDebuggable false
renderscriptDebuggable false
}

debug {
// Install debug build alongside release.
applicationIdSuffix ".debug"
versionNameSuffix "-debug"

// Use stable debug signing. Helps prevent "lost" secure storage on reinstall.
signingConfig signingConfigs.debug

// Distinct launcher name.
resValue "string", "app_name", "Dawarich (Dev)"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
android:label="Dawarich"
android:label="@string/app_name"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher"
android:allowBackup="false"
Expand Down
5 changes: 5 additions & 0 deletions android/app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Default app name. Build types can override via resValue in build.gradle -->
<string name="app_name">Dawarich</string>
</resources>
7 changes: 5 additions & 2 deletions distribution/whatsnew/whatsnew-en-US
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
Beta 0.12.1
* Fixed map tiles not showing due to invalid API key.
Beta 0.13.0
* This release is the aftermath of a big refactor. Please report any issues you encounter, in Discord.
* DB migrations are from now on silent, the migration page caused too many issues.
* This release contains a DB migration, so lets hope there are no issues.
* You will notice that the splash page has a loading icon now.
31 changes: 31 additions & 0 deletions generate_all_schemas.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@echo off
REM Generate schema files for all versions

echo Generating schema files for all database versions...
echo.

REM Generate current version (v5)
echo [1/2] Generating schema for version 5 (current)...
dart run drift_dev schema dump lib/core/database/drift/database/sqlite_client.dart drift_schemas/

if %ERRORLEVEL% NEQ 0 (
echo ❌ Failed to generate v5 schema
exit /b 1
)
echo ✅ v5 schema generated
echo.

REM For v4, we need to manually create it since we can't time-travel
echo [2/2] To generate v4 schema, you need to:
echo 1. Temporarily change schemaVersion to 4 in sqlite_client.dart
echo 2. Comment out the v4→v5 migration in onUpgrade
echo 3. Run: dart run drift_dev schema dump lib/core/database/drift/database/sqlite_client.dart drift_schemas/
echo 4. Revert changes
echo.
echo OR use a v4 database file if you have one from an old app version
echo.

echo ✅ All schemas generated successfully!
echo.
echo Generated files:
dir drift_schemas\
17 changes: 17 additions & 0 deletions generate_schemas.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@echo off
REM Script to generate Drift schema files for migration testing (Windows)
REM These files are used by drift_dev to verify migrations work correctly

echo Generating Drift schema files...

dart run drift_dev schema dump lib/core/database/drift/database/sqlite_client.dart drift_schemas/

if %ERRORLEVEL% EQU 0 (
echo ✅ Schema files generated successfully in drift_schemas/
echo.
echo Generated files:
dir drift_schemas\
) else (
echo ❌ Failed to generate schema files
exit /b 1
)
19 changes: 19 additions & 0 deletions generate_schemas.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash

# Script to generate Drift schema files for migration testing
# These files are used by drift_dev to verify migrations work correctly

echo "Generating Drift schema files..."

# Generate schema files
dart run drift_dev schema dump lib/core/database/drift/database/sqlite_client.dart drift_schemas/

if [ $? -eq 0 ]; then
echo "✅ Schema files generated successfully in drift_schemas/"
echo ""
echo "Generated files:"
ls -lh drift_schemas/
else
echo "❌ Failed to generate schema files"
exit 1
fi
56 changes: 56 additions & 0 deletions lib/core/application/errors/failure.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
final class Failure {
final FailureKind kind; // category for logic (retry, UX, etc.)
final String code; // stable machine code: 'NETWORK_TIMEOUT', 'UNAUTHORIZED', ...
final String message; // safe, user-oriented text (localize at UI if you prefer)
final Object? cause; // original exception (not for display)
final StackTrace? stack; // for logging
final Map<String, Object?> context; // any extra key-values (e.g. endpoint, ids)

const Failure({
required this.kind,
required this.code,
required this.message,
this.cause,
this.stack,
this.context = const {},
});

/// Non-throwing clone with extra context (immutability friendly).
Failure withContext(Map<String, Object?> extra) {
return Failure(
kind: kind,
code: code,
message: message,
cause: cause,
stack: stack,
context: {...context, ...extra},
);
}
}

/// High-level categories (useful for retry/backoff/UI decisions).
enum FailureKind {
/// Client is offline / DNS / timeout / TLS issues.
network,

/// 401/403 or invalid credentials/token.
unauthorized,

/// 404/410 or missing resource.
notFound,

/// 409, version mismatch, duplicate, constraint problems.
conflict,

/// Input validation errors (client-side or server-reported).
validation,

/// Local storage/DB/read-write problems.
storage,

/// Background service/OS integration problems (permissions, notifications).
system,

/// A catch-all for “didn’t fit elsewhere”.
unknown,
}
Loading