Start to build synchronization logic
This commit is contained in:
		
							
								
								
									
										74
									
								
								moneymgr_mobile/lib/widgets/synchronize_button.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								moneymgr_mobile/lib/widgets/synchronize_button.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
import 'package:flutter/material.dart';
 | 
			
		||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
 | 
			
		||||
import 'package:logging/logging.dart';
 | 
			
		||||
import 'package:moneymgr_mobile/services/api/api_client.dart';
 | 
			
		||||
import 'package:moneymgr_mobile/services/api/files_api.dart';
 | 
			
		||||
import 'package:moneymgr_mobile/services/storage/expenses.dart';
 | 
			
		||||
import 'package:moneymgr_mobile/utils/extensions.dart';
 | 
			
		||||
import 'package:moneymgr_mobile/utils/hooks.dart';
 | 
			
		||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
 | 
			
		||||
 | 
			
		||||
part 'synchronize_button.g.dart';
 | 
			
		||||
 | 
			
		||||
/// Synchronize expenses list with backend
 | 
			
		||||
@riverpod
 | 
			
		||||
Future<void> _performSynchronization(Ref ref) async {
 | 
			
		||||
  final expenses = ref.watch(expensesProvider).requireValue;
 | 
			
		||||
  final apiService = ref.watch(apiServiceProvider)!;
 | 
			
		||||
 | 
			
		||||
  final list = await expenses.getList();
 | 
			
		||||
 | 
			
		||||
  for (final exp in list) {
 | 
			
		||||
    // First, upload file
 | 
			
		||||
    final bytes = await expenses.loadFile(exp);
 | 
			
		||||
    final file = await apiService.uploadFile(
 | 
			
		||||
      filename: exp.localFileName,
 | 
			
		||||
      mimeType: exp.mimeType,
 | 
			
		||||
      bytes: bytes,
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // TODO continue
 | 
			
		||||
    break;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class SynchronizeButton extends HookConsumerWidget {
 | 
			
		||||
  const SynchronizeButton({super.key});
 | 
			
		||||
 | 
			
		||||
  @override
 | 
			
		||||
  Widget build(BuildContext context, WidgetRef ref) {
 | 
			
		||||
    final (:pending, :snapshot, :hasError) = useAsyncTask();
 | 
			
		||||
 | 
			
		||||
    handleSynchronize() async {
 | 
			
		||||
      try {
 | 
			
		||||
        await ref.watch(
 | 
			
		||||
          _performSynchronizationProvider.selectAsync((it) => it),
 | 
			
		||||
        );
 | 
			
		||||
      } catch (e, s) {
 | 
			
		||||
        Logger.root.warning("Failed to synchronize expenses! $e $s");
 | 
			
		||||
        if (context.mounted) {
 | 
			
		||||
          context.showTextSnackBar("Failed to synchronize expenses! $e");
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return snapshot.connectionState == ConnectionState.waiting
 | 
			
		||||
        ? Padding(
 | 
			
		||||
            padding: const EdgeInsets.all(12.0),
 | 
			
		||||
            child: SizedBox(
 | 
			
		||||
              height: 20,
 | 
			
		||||
              width: 20,
 | 
			
		||||
              child: CircularProgressIndicator(strokeWidth: 2),
 | 
			
		||||
            ),
 | 
			
		||||
          )
 | 
			
		||||
        : IconButton(
 | 
			
		||||
            onPressed: () => pending.value = handleSynchronize(),
 | 
			
		||||
            style: ButtonStyle(
 | 
			
		||||
              backgroundColor: hasError
 | 
			
		||||
                  ? WidgetStatePropertyAll(Colors.red)
 | 
			
		||||
                  : null,
 | 
			
		||||
            ),
 | 
			
		||||
            icon: Icon(Icons.sync_rounded),
 | 
			
		||||
          );
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user