v1.3.0+4: FOSS Compliance + Dark Mode + Enhanced Settings

 Major Features:
- Dark mode toggle with app-wide theme switching
- Sort inventory by Expiration Date, Name, or Location
- Toggle between Grid and List view for inventory
- Export inventory data to CSV with share functionality
- Custom sage leaf app icon with adaptive icon support

🔄 FOSS Compliance (F-Droid Ready):
- Replaced Firebase with Supabase (open-source backend)
- Anonymous authentication (no user accounts required)
- Cloud-first with hosted Supabase as default
- Optional self-hosting support
- 100% FOSS-compliant dependencies

🎨 UI/UX Improvements:
- Dynamic version display from package.json (was hardcoded)
- Added edit buttons for household and user names
- Removed non-functional search button
- Replaced Recipes placeholder with Settings button
- Improved settings organization with clear sections

📦 Dependencies:
Added:
- supabase_flutter: ^2.8.4 (FOSS backend sync)
- package_info_plus: ^8.1.0 (dynamic version)
- csv: ^6.0.0 (data export)
- share_plus: ^10.1.2 (file sharing)
- image: ^4.5.4 (dev, icon generation)

Removed:
- firebase_core (replaced with Supabase)
- cloud_firestore (replaced with Supabase)

🗑️ Cleanup:
- Removed Firebase setup files and google-services.json
- Removed unimplemented features (Recipes, Search)
- Removed firebase_household_service.dart
- Removed inventory_sync_service.dart (replaced with Supabase)

📄 New Files:
- lib/features/household/services/supabase_household_service.dart
- web/privacy-policy.html (Play Store requirement)
- web/terms-of-service.html (Play Store requirement)
- PLAY_STORE_LISTING.md (marketing copy)
- tool/generate_icons.dart (icon generation script)
- assets/icon/sage_leaf.png (1024x1024)
- assets/icon/sage_leaf_foreground.png (adaptive icon)

🐛 Bug Fixes:
- Fixed version display showing hardcoded "1.0.0"
- Fixed Sort By and Default View showing static text
- Fixed ConsumerWidget build signatures
- Fixed Location.displayName import issues
- Added clearAllData method to Hive database

📊 Stats: +1,728 additions, -756 deletions across 42 files

🤖 Generated with Claude Code (https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 22:27:42 -04:00
parent af63e11abd
commit 7ab641a3c8
42 changed files with 1728 additions and 756 deletions

View File

@@ -1,13 +1,13 @@
import 'package:hive/hive.dart';
import '../../../data/local/hive_database.dart';
import '../../settings/models/app_settings.dart';
import '../../household/services/firebase_household_service.dart';
import '../../household/services/supabase_household_service.dart';
import '../models/food_item.dart';
import 'inventory_repository.dart';
/// Hive implementation of InventoryRepository with Firebase sync
/// Hive implementation of InventoryRepository with Supabase sync (FOSS!)
class InventoryRepositoryImpl implements InventoryRepository {
final _firebaseService = FirebaseHouseholdService();
final _supabaseService = SupabaseHouseholdService();
Future<Box<FoodItem>> get _box async => await HiveDatabase.getFoodBox();
/// Get the current household ID from settings
@@ -52,21 +52,21 @@ class InventoryRepositoryImpl implements InventoryRepository {
print('📝 Added item to Hive: ${item.name}, key=${item.key}, householdId=${item.householdId}');
// Sync to Firebase if in a household
// Sync to Supabase if in a household
if (item.householdId != null && item.key != null) {
print('🚀 Uploading item to Firebase: ${item.name} (key: ${item.key})');
print('🚀 Uploading item to Supabase: ${item.name} (key: ${item.key})');
try {
await _firebaseService.addFoodItem(
await _supabaseService.addFoodItem(
item.householdId!,
item,
item.key.toString(),
);
print('✅ Successfully uploaded to Firebase');
print('✅ Successfully uploaded to Supabase');
} catch (e) {
print('❌ Failed to sync item to Firebase: $e');
print('❌ Failed to sync item to Supabase: $e');
}
} else {
print('⚠️ Skipping Firebase sync: householdId=${item.householdId}, key=${item.key}');
print('⚠️ Skipping Supabase sync: householdId=${item.householdId}, key=${item.key}');
}
}
@@ -75,16 +75,16 @@ class InventoryRepositoryImpl implements InventoryRepository {
item.lastModified = DateTime.now();
await item.save();
// Sync to Firebase if in a household
// Sync to Supabase if in a household
if (item.householdId != null && item.key != null) {
try {
await _firebaseService.updateFoodItem(
await _supabaseService.updateFoodItem(
item.householdId!,
item,
item.key.toString(),
);
} catch (e) {
print('Failed to sync item update to Firebase: $e');
print('Failed to sync item update to Supabase: $e');
}
}
}
@@ -94,15 +94,15 @@ class InventoryRepositoryImpl implements InventoryRepository {
final box = await _box;
final item = box.get(id);
// Sync deletion to Firebase if in a household
// Sync deletion to Supabase if in a household
if (item != null && item.householdId != null) {
try {
await _firebaseService.deleteFoodItem(
await _supabaseService.deleteFoodItem(
item.householdId!,
id.toString(),
);
} catch (e) {
print('Failed to sync item deletion to Firebase: $e');
print('Failed to sync item deletion to Supabase: $e');
}
}