runable
This commit is contained in:
32
lib/core/providers/network_info_provider.dart
Normal file
32
lib/core/providers/network_info_provider.dart
Normal file
@@ -0,0 +1,32 @@
|
||||
import 'package:connectivity_plus/connectivity_plus.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import '../network/network_info.dart';
|
||||
|
||||
part 'network_info_provider.g.dart';
|
||||
|
||||
/// Connectivity provider - provides Connectivity instance
|
||||
@Riverpod(keepAlive: true)
|
||||
Connectivity connectivity(Ref ref) {
|
||||
return Connectivity();
|
||||
}
|
||||
|
||||
/// Network info provider - provides NetworkInfo implementation
|
||||
@Riverpod(keepAlive: true)
|
||||
NetworkInfo networkInfo(Ref ref) {
|
||||
final connectivity = ref.watch(connectivityProvider);
|
||||
return NetworkInfo(connectivity);
|
||||
}
|
||||
|
||||
/// Provider to check if device is connected to internet
|
||||
@riverpod
|
||||
Future<bool> isConnected(Ref ref) async {
|
||||
final networkInfo = ref.watch(networkInfoProvider);
|
||||
return await networkInfo.isConnected;
|
||||
}
|
||||
|
||||
/// Stream provider for connectivity changes
|
||||
@riverpod
|
||||
Stream<List<ConnectivityResult>> connectivityStream(Ref ref) {
|
||||
final networkInfo = ref.watch(networkInfoProvider);
|
||||
return networkInfo.connectivityStream;
|
||||
}
|
||||
186
lib/core/providers/network_info_provider.g.dart
Normal file
186
lib/core/providers/network_info_provider.g.dart
Normal file
@@ -0,0 +1,186 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'network_info_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
/// Connectivity provider - provides Connectivity instance
|
||||
|
||||
@ProviderFor(connectivity)
|
||||
const connectivityProvider = ConnectivityProvider._();
|
||||
|
||||
/// Connectivity provider - provides Connectivity instance
|
||||
|
||||
final class ConnectivityProvider
|
||||
extends $FunctionalProvider<Connectivity, Connectivity, Connectivity>
|
||||
with $Provider<Connectivity> {
|
||||
/// Connectivity provider - provides Connectivity instance
|
||||
const ConnectivityProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'connectivityProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$connectivityHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<Connectivity> $createElement($ProviderPointer pointer) =>
|
||||
$ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Connectivity create(Ref ref) {
|
||||
return connectivity(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(Connectivity value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<Connectivity>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$connectivityHash() => r'15246627d0ae599bcd01382c80d3d25b9e9b4e18';
|
||||
|
||||
/// Network info provider - provides NetworkInfo implementation
|
||||
|
||||
@ProviderFor(networkInfo)
|
||||
const networkInfoProvider = NetworkInfoProvider._();
|
||||
|
||||
/// Network info provider - provides NetworkInfo implementation
|
||||
|
||||
final class NetworkInfoProvider
|
||||
extends $FunctionalProvider<NetworkInfo, NetworkInfo, NetworkInfo>
|
||||
with $Provider<NetworkInfo> {
|
||||
/// Network info provider - provides NetworkInfo implementation
|
||||
const NetworkInfoProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'networkInfoProvider',
|
||||
isAutoDispose: false,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$networkInfoHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<NetworkInfo> $createElement($ProviderPointer pointer) =>
|
||||
$ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
NetworkInfo create(Ref ref) {
|
||||
return networkInfo(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(NetworkInfo value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<NetworkInfo>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$networkInfoHash() => r'7e3a8d0e6ca244de6de51bcdb699e5c0a9a3b57f';
|
||||
|
||||
/// Provider to check if device is connected to internet
|
||||
|
||||
@ProviderFor(isConnected)
|
||||
const isConnectedProvider = IsConnectedProvider._();
|
||||
|
||||
/// Provider to check if device is connected to internet
|
||||
|
||||
final class IsConnectedProvider
|
||||
extends $FunctionalProvider<AsyncValue<bool>, bool, FutureOr<bool>>
|
||||
with $FutureModifier<bool>, $FutureProvider<bool> {
|
||||
/// Provider to check if device is connected to internet
|
||||
const IsConnectedProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'isConnectedProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$isConnectedHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$FutureProviderElement<bool> $createElement($ProviderPointer pointer) =>
|
||||
$FutureProviderElement(pointer);
|
||||
|
||||
@override
|
||||
FutureOr<bool> create(Ref ref) {
|
||||
return isConnected(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$isConnectedHash() => r'c9620cadbcdee8e738f865e747dd57262236782d';
|
||||
|
||||
/// Stream provider for connectivity changes
|
||||
|
||||
@ProviderFor(connectivityStream)
|
||||
const connectivityStreamProvider = ConnectivityStreamProvider._();
|
||||
|
||||
/// Stream provider for connectivity changes
|
||||
|
||||
final class ConnectivityStreamProvider
|
||||
extends
|
||||
$FunctionalProvider<
|
||||
AsyncValue<List<ConnectivityResult>>,
|
||||
List<ConnectivityResult>,
|
||||
Stream<List<ConnectivityResult>>
|
||||
>
|
||||
with
|
||||
$FutureModifier<List<ConnectivityResult>>,
|
||||
$StreamProvider<List<ConnectivityResult>> {
|
||||
/// Stream provider for connectivity changes
|
||||
const ConnectivityStreamProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'connectivityStreamProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$connectivityStreamHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$StreamProviderElement<List<ConnectivityResult>> $createElement(
|
||||
$ProviderPointer pointer,
|
||||
) => $StreamProviderElement(pointer);
|
||||
|
||||
@override
|
||||
Stream<List<ConnectivityResult>> create(Ref ref) {
|
||||
return connectivityStream(ref);
|
||||
}
|
||||
}
|
||||
|
||||
String _$connectivityStreamHash() =>
|
||||
r'7754266fc385401e595a30189ad0c31b1f926fdc';
|
||||
3
lib/core/providers/providers.dart
Normal file
3
lib/core/providers/providers.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
/// Export all core providers
|
||||
export 'network_info_provider.dart';
|
||||
export 'sync_status_provider.dart';
|
||||
223
lib/core/providers/sync_status_provider.dart
Normal file
223
lib/core/providers/sync_status_provider.dart
Normal file
@@ -0,0 +1,223 @@
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import '../../features/products/presentation/providers/products_provider.dart';
|
||||
import '../../features/categories/presentation/providers/categories_provider.dart';
|
||||
import '../../features/settings/presentation/providers/settings_provider.dart';
|
||||
import 'network_info_provider.dart';
|
||||
|
||||
part 'sync_status_provider.g.dart';
|
||||
|
||||
/// Sync status provider - manages data synchronization state
|
||||
@riverpod
|
||||
class SyncStatus extends _$SyncStatus {
|
||||
@override
|
||||
Future<SyncResult> build() async {
|
||||
// Initialize with idle state
|
||||
return const SyncResult(
|
||||
status: SyncState.idle,
|
||||
lastSyncTime: null,
|
||||
message: 'Ready to sync',
|
||||
);
|
||||
}
|
||||
|
||||
/// Perform full sync of all data
|
||||
Future<void> syncAll() async {
|
||||
// Check network connectivity first
|
||||
final isConnected = await ref.read(isConnectedProvider.future);
|
||||
if (!isConnected) {
|
||||
state = const AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.offline,
|
||||
lastSyncTime: null,
|
||||
message: 'No internet connection',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Start sync
|
||||
state = const AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.syncing,
|
||||
lastSyncTime: null,
|
||||
message: 'Syncing data...',
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
// Sync categories first (products depend on categories)
|
||||
await ref.read(categoriesProvider.notifier).syncCategories();
|
||||
|
||||
// Then sync products
|
||||
await ref.read(productsProvider.notifier).syncProducts();
|
||||
|
||||
// Update last sync time in settings
|
||||
await ref.read(settingsProvider.notifier).updateLastSyncTime();
|
||||
|
||||
// Sync completed successfully
|
||||
state = AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.success,
|
||||
lastSyncTime: DateTime.now(),
|
||||
message: 'Sync completed successfully',
|
||||
),
|
||||
);
|
||||
} catch (error, stackTrace) {
|
||||
// Sync failed
|
||||
state = AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.failed,
|
||||
lastSyncTime: null,
|
||||
message: 'Sync failed: ${error.toString()}',
|
||||
error: error,
|
||||
),
|
||||
);
|
||||
|
||||
// Also set error state for proper error handling
|
||||
state = AsyncValue.error(error, stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sync only products
|
||||
Future<void> syncProducts() async {
|
||||
final isConnected = await ref.read(isConnectedProvider.future);
|
||||
if (!isConnected) {
|
||||
state = const AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.offline,
|
||||
lastSyncTime: null,
|
||||
message: 'No internet connection',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
state = const AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.syncing,
|
||||
lastSyncTime: null,
|
||||
message: 'Syncing products...',
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
await ref.read(productsProvider.notifier).syncProducts();
|
||||
await ref.read(settingsProvider.notifier).updateLastSyncTime();
|
||||
|
||||
state = AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.success,
|
||||
lastSyncTime: DateTime.now(),
|
||||
message: 'Products synced successfully',
|
||||
),
|
||||
);
|
||||
} catch (error, stackTrace) {
|
||||
state = AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.failed,
|
||||
lastSyncTime: null,
|
||||
message: 'Product sync failed: ${error.toString()}',
|
||||
error: error,
|
||||
),
|
||||
);
|
||||
state = AsyncValue.error(error, stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sync only categories
|
||||
Future<void> syncCategories() async {
|
||||
final isConnected = await ref.read(isConnectedProvider.future);
|
||||
if (!isConnected) {
|
||||
state = const AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.offline,
|
||||
lastSyncTime: null,
|
||||
message: 'No internet connection',
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
state = const AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.syncing,
|
||||
lastSyncTime: null,
|
||||
message: 'Syncing categories...',
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
await ref.read(categoriesProvider.notifier).syncCategories();
|
||||
await ref.read(settingsProvider.notifier).updateLastSyncTime();
|
||||
|
||||
state = AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.success,
|
||||
lastSyncTime: DateTime.now(),
|
||||
message: 'Categories synced successfully',
|
||||
),
|
||||
);
|
||||
} catch (error, stackTrace) {
|
||||
state = AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.failed,
|
||||
lastSyncTime: null,
|
||||
message: 'Category sync failed: ${error.toString()}',
|
||||
error: error,
|
||||
),
|
||||
);
|
||||
state = AsyncValue.error(error, stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset sync status to idle
|
||||
void resetStatus() {
|
||||
state = const AsyncValue.data(
|
||||
SyncResult(
|
||||
status: SyncState.idle,
|
||||
lastSyncTime: null,
|
||||
message: 'Ready to sync',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Sync state enum
|
||||
enum SyncState {
|
||||
idle,
|
||||
syncing,
|
||||
success,
|
||||
failed,
|
||||
offline,
|
||||
}
|
||||
|
||||
/// Sync result model
|
||||
class SyncResult {
|
||||
final SyncState status;
|
||||
final DateTime? lastSyncTime;
|
||||
final String message;
|
||||
final Object? error;
|
||||
|
||||
const SyncResult({
|
||||
required this.status,
|
||||
required this.lastSyncTime,
|
||||
required this.message,
|
||||
this.error,
|
||||
});
|
||||
|
||||
bool get isSyncing => status == SyncState.syncing;
|
||||
bool get isSuccess => status == SyncState.success;
|
||||
bool get isFailed => status == SyncState.failed;
|
||||
bool get isOffline => status == SyncState.offline;
|
||||
bool get isIdle => status == SyncState.idle;
|
||||
}
|
||||
|
||||
/// Provider for last sync time from settings
|
||||
@riverpod
|
||||
DateTime? lastSyncTime(Ref ref) {
|
||||
final settingsAsync = ref.watch(settingsProvider);
|
||||
return settingsAsync.when(
|
||||
data: (settings) => settings.lastSyncAt,
|
||||
loading: () => null,
|
||||
error: (_, __) => null,
|
||||
);
|
||||
}
|
||||
106
lib/core/providers/sync_status_provider.g.dart
Normal file
106
lib/core/providers/sync_status_provider.g.dart
Normal file
@@ -0,0 +1,106 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'sync_status_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint, type=warning
|
||||
/// Sync status provider - manages data synchronization state
|
||||
|
||||
@ProviderFor(SyncStatus)
|
||||
const syncStatusProvider = SyncStatusProvider._();
|
||||
|
||||
/// Sync status provider - manages data synchronization state
|
||||
final class SyncStatusProvider
|
||||
extends $AsyncNotifierProvider<SyncStatus, SyncResult> {
|
||||
/// Sync status provider - manages data synchronization state
|
||||
const SyncStatusProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'syncStatusProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$syncStatusHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
SyncStatus create() => SyncStatus();
|
||||
}
|
||||
|
||||
String _$syncStatusHash() => r'dc92a1b83c89af94dfe94b646aa81d9501f371d7';
|
||||
|
||||
/// Sync status provider - manages data synchronization state
|
||||
|
||||
abstract class _$SyncStatus extends $AsyncNotifier<SyncResult> {
|
||||
FutureOr<SyncResult> build();
|
||||
@$mustCallSuper
|
||||
@override
|
||||
void runBuild() {
|
||||
final created = build();
|
||||
final ref = this.ref as $Ref<AsyncValue<SyncResult>, SyncResult>;
|
||||
final element =
|
||||
ref.element
|
||||
as $ClassProviderElement<
|
||||
AnyNotifier<AsyncValue<SyncResult>, SyncResult>,
|
||||
AsyncValue<SyncResult>,
|
||||
Object?,
|
||||
Object?
|
||||
>;
|
||||
element.handleValue(ref, created);
|
||||
}
|
||||
}
|
||||
|
||||
/// Provider for last sync time from settings
|
||||
|
||||
@ProviderFor(lastSyncTime)
|
||||
const lastSyncTimeProvider = LastSyncTimeProvider._();
|
||||
|
||||
/// Provider for last sync time from settings
|
||||
|
||||
final class LastSyncTimeProvider
|
||||
extends $FunctionalProvider<DateTime?, DateTime?, DateTime?>
|
||||
with $Provider<DateTime?> {
|
||||
/// Provider for last sync time from settings
|
||||
const LastSyncTimeProvider._()
|
||||
: super(
|
||||
from: null,
|
||||
argument: null,
|
||||
retry: null,
|
||||
name: r'lastSyncTimeProvider',
|
||||
isAutoDispose: true,
|
||||
dependencies: null,
|
||||
$allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@override
|
||||
String debugGetCreateSourceHash() => _$lastSyncTimeHash();
|
||||
|
||||
@$internal
|
||||
@override
|
||||
$ProviderElement<DateTime?> $createElement($ProviderPointer pointer) =>
|
||||
$ProviderElement(pointer);
|
||||
|
||||
@override
|
||||
DateTime? create(Ref ref) {
|
||||
return lastSyncTime(ref);
|
||||
}
|
||||
|
||||
/// {@macro riverpod.override_with_value}
|
||||
Override overrideWithValue(DateTime? value) {
|
||||
return $ProviderOverride(
|
||||
origin: this,
|
||||
providerOverride: $SyncValueProvider<DateTime?>(value),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
String _$lastSyncTimeHash() => r'5d9bea98c58f0c838532cdf13ac1ab3fd9447051';
|
||||
Reference in New Issue
Block a user