feat : new injection logic

test : some file :)
chore : upgrade android gradle
This commit is contained in:
2025-08-19 11:22:34 +03:30
parent 9b04c0374b
commit 7c3c1280b2
47 changed files with 1139 additions and 377 deletions

View File

@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip

View File

@@ -18,8 +18,8 @@ pluginManagement {
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.7.0" apply false
id("org.jetbrains.kotlin.android") version "1.9.25" apply false
id("com.android.application") version "8.9.1" apply false
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
}
include(":app")

View File

@@ -27,11 +27,10 @@ class CustomNavigationObserver extends NavigatorObserver {
await setupInspectionDI();
} else if (!_isWorkDone &&
(routeName == LiveStockRoutes.init || routeName == LiveStockRoutes.auth)) {
_isWorkDone = true;
await setupLiveStockDI();
}
super.didPush(route, previousRoute);
tLog('CustomNavigationObserver: didPush - $routeName');
// tLog('CustomNavigationObserver: didPush - $routeName');
}
@override
@@ -43,12 +42,12 @@ class CustomNavigationObserver extends NavigatorObserver {
@override
void didPop(Route route, Route? previousRoute) {
super.didPop(route, previousRoute);
tLog('CustomNavigationObserver: didPop - ${route.settings.name}');
// tLog('CustomNavigationObserver: didPop - ${route.settings.name}');
}
@override
void didRemove(Route route, Route? previousRoute) {
super.didRemove(route, previousRoute);
tLog('CustomNavigationObserver: didRemove - ${route.settings.name}');
// tLog('CustomNavigationObserver: didRemove - ${route.settings.name}');
}
}

View File

@@ -1,8 +1,5 @@
import 'package:rasadyar_chicken/presentation/routes/routes.dart';
import 'package:rasadyar_app/presentation/routes/app_pages.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/inspection.dart';
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
class ModulesLogic extends GetxController {
TokenStorageService tokenService = Get.find<TokenStorageService>();
@@ -32,21 +29,20 @@ class ModulesLogic extends GetxController {
}
Future<void> navigateToModule(Module module) async {
if (module == Module.inspection) {
Get.offAllNamed(InspectionRoutes.init);
} else if (module == Module.liveStocks) {
await setupLiveStockDI();
Get.offAllNamed(LiveStockRoutes.init);
} else if (module == Module.chicken) {
Get.offAllNamed(ChickenRoutes.init);
var target = getTargetPage(module).entries.first;
if (target.value != null) {
await target.value;
}
Get.offAllNamed(target.key);
}
void onTapCard(Module module, int index) async {
isLoading.value = true;
selectedIndex.value = index;
saveModule(module);
await Future.delayed(Duration(milliseconds: 800)); // Simulate loading delay
await Future.delayed(Duration(milliseconds: 500)); // Simulate loading delay
navigateToModule(module);
}
}

View File

@@ -155,7 +155,10 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
tokenService.getModule();
final module = tokenService.appModule.value;
final target = getTargetPage(module);
Get.offAndToNamed(target);
if (target.values.first != null) {
await target.values.first;
}
Get.offAndToNamed(target.keys.first);
} catch (e, st) {
debugPrint("onReady error: $e\n$st");
}

View File

@@ -4,8 +4,10 @@ import 'package:rasadyar_app/presentation/pages/splash/logic.dart';
import 'package:rasadyar_app/presentation/pages/splash/view.dart';
import 'package:rasadyar_app/presentation/pages/system_design/system_design.dart';
import 'package:rasadyar_chicken/chicken.dart';
import 'package:rasadyar_chicken/data/di/chicken_di.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_inspection/inspection.dart';
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
part 'app_paths.dart';
@@ -38,15 +40,15 @@ sealed class AppPages {
];
}
String getTargetPage(Module? value) {
Map<String, Future<void>?> getTargetPage(Module? value) {
switch (value) {
case Module.inspection:
return InspectionRoutes.init;
return {InspectionRoutes.init:null};
case Module.liveStocks:
return LiveStockRoutes.init;
return {LiveStockRoutes.init: setupLiveStockDI()};
case Module.chicken:
return ChickenRoutes.init;
return {ChickenRoutes.init : null};
default:
return AppPaths.moduleList;
return {AppPaths.moduleList : null};
}
}

View File

@@ -3,7 +3,7 @@ description: A starting point for Dart libraries or applications.
version: 1.2.1+2
environment:
sdk: ^3.8.1
sdk: ^3.9.0
dependencies:

33
packages/core/.gitignore vendored Normal file
View File

@@ -0,0 +1,33 @@
# Ignore build output and other generated files
build/
# Dart/Pub related
.dart_tool/
.packages
.pub/
# IDE files
.idea/
*.iml
*.ipr
*.iws
# VS Code
.vscode/
# macOS
.DS_Store
# Other
*.log
*.swp
*.pyc
# Flutter specific
.flutter-plugins
.flutter-plugins-dependencies
pubspec.lock
# Test outputs
test_cache/

View File

@@ -1 +0,0 @@
{"packages/cupertino_icons/assets/CupertinoIcons.ttf":["packages/cupertino_icons/assets/CupertinoIcons.ttf"],"packages/flutter_map/lib/assets/flutter_map_logo.png":["packages/flutter_map/lib/assets/flutter_map_logo.png"],"packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf":["packages/font_awesome_flutter/lib/fonts/fa-brands-400.ttf"],"packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf":["packages/font_awesome_flutter/lib/fonts/fa-regular-400.ttf"],"packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf":["packages/font_awesome_flutter/lib/fonts/fa-solid-900.ttf"]}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -2,6 +2,7 @@ library;
export 'package:android_intent_plus/android_intent.dart';
export 'package:android_intent_plus/flag.dart';
export 'package:connectivity_plus/connectivity_plus.dart';
export 'package:device_info_plus/device_info_plus.dart';
export 'package:dio/dio.dart';
//other packages

View File

@@ -0,0 +1,24 @@
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:get/get.dart';
class NetworkStatus {
NetworkStatus._();
static final NetworkStatus _instance = NetworkStatus._();
factory NetworkStatus() => _instance;
final Connectivity _connectivity = Connectivity();
RxBool isConnected = false.obs;
void startListening() {
_connectivity.onConnectivityChanged.listen((result) {
isConnected.value = !result.contains(ConnectivityResult.none);
});
_connectivity.checkConnectivity().then((result) {
isConnected.value = !result.contains(ConnectivityResult.none);
});
}
}

View File

@@ -0,0 +1,168 @@
import 'dart:async';
import '../../core.dart';
/// Callback to refresh the authentication token.
/// Typically used to request a new token from the server.
typedef RefreshTokenCallback = Future<String?> Function();
/// Callback to save a new authentication token.
typedef SaveTokenCallback = Future<void> Function(String token);
/// Callback to clear the authentication token, e.g., on logout or failure.
typedef ClearTokenCallback = Future<void> Function();
/// Callback invoked when token refresh fails.
/// Typically used to redirect the user to login or show a logout message.
typedef OnRefreshFailedCallback = Future<void> Function();
/// Represents a queued request waiting for token refresh.
class QueuedRequest {
/// The original request options.
final RequestOptions options;
/// Completer used to complete the response once the request is retried.
final Completer<Response> completer;
/// Constructs a queued request.
QueuedRequest(this.options, this.completer);
}
/// An interceptor for automatic token management and refresh handling.
///
/// Features:
/// - Queues requests while a token refresh is in progress.
/// - Saves and clears tokens via provided callbacks.
/// - Calls [OnRefreshFailedCallback] if token refresh fails.
class AppInterceptorN extends Interceptor {
/// Callback to refresh the authentication token.
final RefreshTokenCallback? refreshTokenCallback;
/// Callback to save the new token.
final SaveTokenCallback saveTokenCallback;
/// Callback to clear the token.
final ClearTokenCallback clearTokenCallback;
/// Callback executed when token refresh fails.
final OnRefreshFailedCallback onRefreshFailed;
/// Optional additional arguments for authentication.
final dynamic authArguments;
/// The Dio instance used to send requests.
final Dio dio;
/// Maximum number of retry attempts for failed requests.
final int maxRetries;
/// Whether a token refresh is currently in progress.
bool _isRefreshing = false;
/// Queue of requests waiting for a new token.
final List<QueuedRequest> _queue = [];
/// Current token in use.
String? _currentToken;
/// Constructs the interceptor.
AppInterceptorN({
required this.dio,
required this.saveTokenCallback,
required this.clearTokenCallback,
required this.onRefreshFailed,
this.refreshTokenCallback,
this.authArguments,
this.maxRetries = 3,
});
/// Called before sending a request.
/// If a token refresh is in progress, the request is added to the queue.
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
if (_isRefreshing) {
final completer = Completer<Response>();
_queue.add(QueuedRequest(options, completer));
return handler.resolve(await completer.future);
}
handler.next(options);
}
/// Called when an error occurs during a request.
///
/// - If the error is a 401 (unauthorized) and retry count is below `maxRetries`,
/// the token is refreshed and queued requests are retried.
/// - If the token refresh fails, all queued requests are cancelled and
/// [onRefreshFailed] is executed.
@override
Future<void> onError(DioException err, ErrorInterceptorHandler handler) async {
int currentRetry = err.requestOptions.extra['retryCount'] ?? 0;
if (err.response?.statusCode == 401 &&
err.type != DioExceptionType.cancel &&
currentRetry < maxRetries) {
final completer = Completer<Response>();
final updatedOptions = err.requestOptions.copyWith(
extra: {...err.requestOptions.extra, 'retryCount': currentRetry + 1},
);
_queue.add(QueuedRequest(updatedOptions, completer));
if (!_isRefreshing) {
_isRefreshing = true;
try {
final newToken = await refreshTokenCallback?.call();
if (newToken != null && newToken.isNotEmpty) {
_currentToken = newToken;
await saveTokenCallback(newToken);
for (var req in _queue) {
final newOptions = req.options.copyWith(
headers: {...req.options.headers, 'Authorization': 'Bearer $newToken'},
);
dio
.fetch(newOptions)
.then(req.completer.complete)
.catchError(req.completer.completeError);
}
} else {
await clearTokenCallback();
await _handleRefreshFailure();
for (var req in _queue) {
req.completer.completeError(
DioException(requestOptions: req.options, type: DioExceptionType.cancel),
);
}
}
} catch (e) {
await clearTokenCallback();
await _handleRefreshFailure();
for (var req in _queue) {
req.completer.completeError(e);
}
} finally {
_queue.clear();
_isRefreshing = false;
}
}
return handler.resolve(await completer.future);
}
handler.next(err);
}
/// Handles token refresh failure:
/// - Cancels all ongoing requests via [ApiHandler].
/// - Executes external [onRefreshFailed] callback.
Future<void> _handleRefreshFailure() async {
ApiHandler.cancelAllRequests("Token refresh failed");
await onRefreshFailed.call();
}
@visibleForTesting
set isRefreshingForTest(bool value) => _isRefreshing = value;
@visibleForTesting
List<QueuedRequest> get queue => _queue;
}

View File

@@ -1,15 +1,15 @@
import 'package:get_it/get_it.dart';
import 'package:logger/logger.dart';
import 'package:rasadyar_core/data/services/auth_middelware.dart';
import 'package:rasadyar_core/data/services/network_status.dart';
import 'package:rasadyar_core/infrastructure/local/hive_local_storage.dart';
final diCore = GetIt.instance;
Future<void> setupAllCoreProvider() async {
await _setUpLogger();
await _setupLocalStorage();
await _setupRemote();
diCore.registerSingleton(NetworkStatus()..startListening());
await diCore.allReady();
}
@@ -23,4 +23,4 @@ Future<void> _setupLocalStorage() async {
Future<void> _setupRemote() async {
// diCore.registerSingleton<HiveLocalStorage>(HiveLocalStorage());
}
}

View File

@@ -1,16 +1,21 @@
import 'package:flutter/material.dart';
import '../../core.dart';
/// Handles global API requests management with CancelToken.
class ApiHandler {
// Global CancelToken for all requests.
static CancelToken _globalCancelToken = CancelToken();
/// Returns the current global CancelToken.
static CancelToken get globalCancelToken => _globalCancelToken;
/// Resets the global CancelToken to a new one.
static Future<void> reset() async {
_globalCancelToken = CancelToken();
}
/// Cancels all ongoing requests and resets the CancelToken.
/// [reason] is optional text explaining why requests are canceled.
static void cancelAllRequests(String reason) {
if (!_globalCancelToken.isCancelled) {
_globalCancelToken.cancel(reason);

View File

@@ -77,18 +77,18 @@ packages:
dependency: transitive
description:
name: build
sha256: "7d95cbbb1526ab5ae977df9b4cc660963b9b27f6d1075c0b34653868911385e4"
sha256: "6439a9c71a4e6eca8d9490c1b380a25b02675aa688137dfbe66d2062884a23ac"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
version: "3.0.2"
build_config:
dependency: transitive
description:
name: build_config
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.2.0"
build_daemon:
dependency: transitive
description:
@@ -101,26 +101,26 @@ packages:
dependency: transitive
description:
name: build_resolvers
sha256: "38c9c339333a09b090a638849a4c56e70a404c6bdd3b511493addfbc113b60c2"
sha256: "2b21a125d66a86b9511cc3fb6c668c42e9a1185083922bf60e46d483a81a9712"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
version: "3.0.2"
build_runner:
dependency: "direct dev"
description:
name: build_runner
sha256: b971d4a1c789eba7be3e6fe6ce5e5b50fd3719e3cb485b3fad6d04358304351d
sha256: fd3c09f4bbff7fa6e8d8ef688a0b2e8a6384e6483a25af0dac75fef362bcfe6f
url: "https://pub.dev"
source: hosted
version: "2.6.0"
version: "2.7.0"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
sha256: c04e612ca801cd0928ccdb891c263a2b1391cb27940a5ea5afcf9ba894de5d62
sha256: ab27e46c8aa233e610cf6084ee6d8a22c6f873a0a9929241d8855b7a72978ae7
url: "https://pub.dev"
source: hosted
version: "9.2.0"
version: "9.3.0"
built_collection:
dependency: transitive
description:
@@ -153,6 +153,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.4"
cli_config:
dependency: transitive
description:
name: cli_config
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
url: "https://pub.dev"
source: hosted
version: "0.2.0"
clock:
dependency: transitive
description:
@@ -209,6 +217,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.1.2"
coverage:
dependency: transitive
description:
name: coverage
sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d"
url: "https://pub.dev"
source: hosted
version: "1.15.0"
cross_file:
dependency: transitive
description:
@@ -761,66 +777,66 @@ packages:
dependency: "direct main"
description:
name: image_picker
sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a"
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.2.0"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: "6fae381e6af2bbe0365a5e4ce1db3959462fa0c4d234facf070746024bb80c8d"
sha256: e83b2b05141469c5e19d77e1dfa11096b6b1567d09065b2265d7c6904560050c
url: "https://pub.dev"
source: hosted
version: "0.8.12+24"
version: "0.8.13"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83"
sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
version: "3.1.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100"
sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e
url: "https://pub.dev"
source: hosted
version: "0.8.12+2"
version: "0.8.13"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9"
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
version: "0.2.2"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1"
sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
version: "0.2.2"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0"
sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665"
url: "https://pub.dev"
source: hosted
version: "2.10.1"
version: "2.11.0"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.dev"
source: hosted
version: "0.2.1+1"
version: "0.2.2"
image_size_getter:
dependency: transitive
description:
@@ -889,26 +905,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
version: "11.0.1"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.9"
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
lints:
dependency: transitive
description:
@@ -1021,6 +1037,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.5.0"
node_preamble:
dependency: transitive
description:
name: node_preamble
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
url: "https://pub.dev"
source: hosted
version: "2.0.2"
package_config:
dependency: transitive
description:
@@ -1161,10 +1185,10 @@ packages:
dependency: "direct main"
description:
name: persian_datetime_picker
sha256: "7ccbfd3a68dc89d405550f624e9fa590c914fed2aa2d48973c4f4400baab2e06"
sha256: "0ec2879d2bee8390dda088b412739e6316e3a54d77640ec54dc1eeca8c5baa59"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
version: "3.1.1"
petitparser:
dependency: transitive
description:
@@ -1285,6 +1309,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.4.2"
shelf_packages_handler:
dependency: transitive
description:
name: shelf_packages_handler
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
url: "https://pub.dev"
source: hosted
version: "3.0.2"
shelf_static:
dependency: transitive
description:
name: shelf_static
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
url: "https://pub.dev"
source: hosted
version: "1.1.3"
shelf_web_socket:
dependency: transitive
description:
@@ -1322,6 +1362,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.6"
source_map_stack_trace:
dependency: transitive
description:
name: source_map_stack_trace
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
url: "https://pub.dev"
source: hosted
version: "2.1.2"
source_maps:
dependency: transitive
description:
name: source_maps
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
url: "https://pub.dev"
source: hosted
version: "0.10.13"
source_span:
dependency: transitive
description:
@@ -1378,14 +1434,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.2.2"
test:
dependency: "direct dev"
description:
name: test
sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb"
url: "https://pub.dev"
source: hosted
version: "1.26.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev"
source: hosted
version: "0.7.4"
version: "0.7.6"
test_core:
dependency: transitive
description:
name: test_core
sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a"
url: "https://pub.dev"
source: hosted
version: "0.6.11"
time:
dependency: transitive
description:
@@ -1454,10 +1526,10 @@ packages:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.2.0"
vm_service:
dependency: transitive
description:
@@ -1498,6 +1570,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.3"
webkit_inspection_protocol:
dependency: transitive
description:
name: webkit_inspection_protocol
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
url: "https://pub.dev"
source: hosted
version: "1.2.1"
win32:
dependency: transitive
description:
@@ -1555,5 +1635,5 @@ packages:
source: hosted
version: "2.1.0"
sdks:
dart: ">=3.8.1 <4.0.0"
dart: ">=3.9.0 <4.0.0"
flutter: ">=3.29.0"

View File

@@ -4,7 +4,7 @@ publish_to: none
version: 1.2.0+2
environment:
sdk: ^3.8.1
sdk: ^3.9.0
dependencies:
flutter:
@@ -17,7 +17,7 @@ dependencies:
package_info_plus: ^8.3.1
##image_picker
image_picker: ^1.1.2
image_picker: ^1.2.0
image_cropper: ^9.1.0
#UI
@@ -58,7 +58,7 @@ dependencies:
#other
permission_handler: ^12.0.1
persian_datetime_picker: ^3.1.0
persian_datetime_picker: ^3.1.1
encrypt: ^5.0.3
#L10N tools
@@ -89,10 +89,11 @@ dev_dependencies:
sdk: flutter
flutter_lints: ^6.0.0
##code generation
build_runner: ^2.6.0
build_runner: ^2.7.0
hive_ce_generator: ^1.9.3
freezed: ^3.2.0
json_serializable: ^6.10.0
test: ^1.24.0
##test

View File

@@ -0,0 +1,106 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:rasadyar_core/infrastructure/remote/app_interceptor_n.dart';
class MockDio extends Mock implements Dio {}
class MockResponse extends Mock implements Response {}
class MockRequestOptions extends Mock implements RequestOptions {}
class FakeRequestOptions extends Fake implements RequestOptions {}
void main() {
late MockDio dio;
late AppInterceptorN interceptor;
late MockResponse response;
late MockRequestOptions requestOptions;
late bool saveCalled;
late bool clearCalled;
late bool refreshFailedCalled;
String? savedToken;
setUp(() {
dio = MockDio();
response = MockResponse();
requestOptions = MockRequestOptions();
saveCalled = false;
clearCalled = false;
refreshFailedCalled = false;
savedToken = null;
interceptor = AppInterceptorN(
dio: dio,
saveTokenCallback: (token) async {
savedToken = token;
saveCalled = true;
},
clearTokenCallback: () async {
clearCalled = true;
},
refreshTokenCallback: () async => 'newToken',
onRefreshFailed: () async {
refreshFailedCalled = true;
},
);
});
setUpAll(() {
registerFallbackValue(FakeRequestOptions());
});
test('should refresh token and retry queued requests on 401', () async {
final options = RequestOptions(path: "/test");
final response = Response(requestOptions: options, statusCode: 200, data: 'ok');
when(() => dio.fetch(any())).thenAnswer((_) async => response);
final handler = ErrorInterceptorHandler();
final dioException = DioException(
requestOptions: options,
response: Response(requestOptions: options, statusCode: 401),
type: DioExceptionType.badResponse,
);
await interceptor.onError(dioException, handler);
expect(saveCalled, isTrue);
expect(savedToken, 'newToken');
expect(interceptor.queue.isEmpty, isTrue);
expect(clearCalled, isFalse);
expect(refreshFailedCalled, isFalse);
});
test('should queue request if refreshing', () async {
interceptor.isRefreshingForTest = true;
final options = RequestOptions(path: "/test");
final handler = RequestInterceptorHandler();
final completer = Completer<Response>();
interceptor.queue.add(QueuedRequest(options, completer));
interceptor.onRequest(options, handler);
expect(interceptor.queue.length, 2); // One added in setUp, one here
});
test('should refresh token and retry queued requests on 401', () async {
final options = RequestOptions(path: "/test");
final response = Response(requestOptions: options, statusCode: 200, data: 'ok');
when(() => dio.fetch(any())).thenAnswer((_) async => response);
final handler = ErrorInterceptorHandler();
final dioException = DioException(
requestOptions: options,
response: Response(requestOptions: options, statusCode: 401),
type: DioExceptionType.badResponse,
);
await interceptor.onError(dioException, handler);
expect(saveCalled, isTrue);
expect(savedToken, 'newToken');
expect(interceptor.queue.isEmpty, isTrue);
expect(clearCalled, isFalse);
expect(refreshFailedCalled, isFalse);
});
}

View File

@@ -1,23 +0,0 @@
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'interfaces/i_form_data.dart';
class DioFormData implements IFormData {
final FormData _formData = FormData();
@override
void addFile(String field, Uint8List bytes, String filename) {
_formData.files.add(MapEntry(
field,
MultipartFile.fromBytes(bytes, filename: filename),
));
}
@override
void addField(String key, String value) {
_formData.fields.add(MapEntry(key, value));
}
FormData get raw => _formData;
}

View File

@@ -0,0 +1,55 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:rasadyar_core/core.dart';
void main() {
group('DioFormData', () {
late DioFormData formData;
setUp(() {
formData = DioFormData();
});
test('addField should add a field to FormData', () {
formData.addField('userName', 'mojtaba');
expect(formData.raw.fields.length, 1);
expect(formData.raw.fields.first.key, 'userName');
expect(formData.raw.fields.first.value, 'mojtaba');
});
test('addFile should add a file to FormData', () async {
final bytes = Uint8List.fromList([1, 2, 3, 4]);
formData.addFile('fileField', bytes, 'test.txt');
expect(formData.raw.files.length, 1);
final fileEntry = formData.raw.files.first;
expect(fileEntry.key, 'fileField');
final multipart = fileEntry.value;
expect(multipart.filename, 'test.txt');
final uploadedBytes = await multipart.finalize().toBytes();
expect(uploadedBytes, bytes);
});
test('raw getter should return the internal FormData instance', () {
final tmp = formData.raw;
expect(tmp, isA<FormData>());
});
});
}
extension on Stream<List<int>> {
/// Helper to collect stream into a single Uint8List for comparison
Future<Uint8List> toBytes() async {
final chunks = <int>[];
await for (final chunk in this) {
chunks.addAll(chunk);
}
return Uint8List.fromList(chunks);
}
}

View File

@@ -0,0 +1,201 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mocktail/mocktail.dart';
import 'package:rasadyar_core/core.dart';
class MockDio extends Mock implements Dio {}
class MockInterceptor extends Mock implements AppInterceptor {}
class FakeRequestOptions extends Fake implements RequestOptions {}
void main() {
setUpAll(() {
registerFallbackValue(FakeRequestOptions());
registerFallbackValue(RequestOptions(path: ''));
registerFallbackValue(Options());
registerFallbackValue(CancelToken());
});
group('Dio Remote', () {
late DioRemote dioRemote;
late MockDio mockDio;
setUp(() {
mockDio = MockDio();
dioRemote = DioRemote();
dioRemote.dio = mockDio;
});
test('init sets dio and adds interceptor if provided', () async {
final interceptor = MockInterceptor();
final client = DioRemote(interceptors: interceptor);
await client.init();
expect(client.dio, isA<Dio>());
});
test('get returns DioResponse with raw data', () async {
final response = Response(
requestOptions: RequestOptions(path: '/test'),
statusCode: 200,
data: {'message': 'ok'},
);
when(
() => mockDio.get(
any(),
queryParameters: any(named: 'queryParameters'),
options: any(named: 'options'),
onReceiveProgress: any(named: 'onReceiveProgress'),
cancelToken: any(named: 'cancelToken'),
),
).thenAnswer((_) async => response);
final result = await dioRemote.get<Map<String, dynamic>>('/test');
expect(result, isA<DioResponse<Map<String, dynamic>>>());
expect(result.data, {'message': 'ok'});
expect(result.statusCode, 200);
});
test('get applies fromJson mapper', () async {
final response = Response(
requestOptions: RequestOptions(path: '/user'),
statusCode: 200,
data: {'id': 1, 'name': 'Ali'},
);
when(
() => mockDio.get(
any(),
queryParameters: any(named: 'queryParameters'),
options: any(named: 'options'),
onReceiveProgress: any(named: 'onReceiveProgress'),
cancelToken: any(named: 'cancelToken'),
),
).thenAnswer((_) async => response);
final result = await dioRemote.get<String>(
'/user',
fromJson: (json) => "User: ${json['name']}",
);
expect(result.data, 'User: Ali');
});
test('post applies fromJson correctly', () async {
final response = Response(
requestOptions: RequestOptions(path: '/post'),
statusCode: 200,
data: {'id': 99},
);
when(
() => mockDio.post(
any(),
data: any(named: 'data'),
queryParameters: any(named: 'queryParameters'),
options: any(named: 'options'),
onSendProgress: any(named: 'onSendProgress'),
onReceiveProgress: any(named: 'onReceiveProgress'),
cancelToken: any(named: 'cancelToken'),
),
).thenAnswer((_) async => response);
final result = await dioRemote.post<int>(
'/post',
fromJson: (json) => json['id'],
);
expect(result.data, 99);
});
test('put returns parsed data', () async {
final response = Response(
requestOptions: RequestOptions(path: '/put'),
statusCode: 200,
data: {'value': 'updated'},
);
when(
() => mockDio.put(
any(),
data: any(named: 'data'),
queryParameters: any(named: 'queryParameters'),
options: any(named: 'options'),
onSendProgress: any(named: 'onSendProgress'),
onReceiveProgress: any(named: 'onReceiveProgress'),
cancelToken: any(named: 'cancelToken'),
),
).thenAnswer((_) async => response);
final result = await dioRemote.put<String>('/put', fromJson: (json) => json['value']);
expect(result.data, 'updated');
});
test('delete works with fromJson', () async {
final response = Response(
requestOptions: RequestOptions(path: '/delete'),
statusCode: 200,
data: {'removed': true},
);
when(
() => mockDio.delete(
any(),
data: any(named: 'data'),
queryParameters: any(named: 'queryParameters'),
options: any(named: 'options'),
cancelToken: any(named: 'cancelToken'),
),
).thenAnswer((_) async => response);
final result = await dioRemote.delete<bool>('/delete', fromJson: (json) => json['removed']);
expect(result.data, true);
});
test('download returns DioResponse with bytes', () async {
final response = Response<Uint8List>(
requestOptions: RequestOptions(path: '/download'),
statusCode: 200,
data: Uint8List.fromList([1, 2, 3]),
);
when(
() => mockDio.get<Uint8List>(
any(),
options: any(named: 'options'),
onReceiveProgress: any(named: 'onReceiveProgress'),
cancelToken: any(named: 'cancelToken'),
),
).thenAnswer((_) async => response);
final result = await dioRemote.download('/download');
expect(result.data, isA<Uint8List>());
expect(result.data!.length, 3);
});
test('upload sends DioFormData and returns DioResponse', () async {
final formData = DioFormData();
formData.addField('field', 'value');
final response = Response(
requestOptions: RequestOptions(path: '/upload'),
statusCode: 200,
data: 'uploaded',
);
when(
() => mockDio.post(
any(),
data: any(named: 'data'),
options: any(named: 'options'),
onSendProgress: any(named: 'onSendProgress'),
cancelToken: any(named: 'cancelToken'),
),
).thenAnswer((_) async => response);
final result = await dioRemote.upload<String>('/upload', formData: formData);
expect(result.data, 'uploaded');
});
});
}

View File

@@ -1,20 +0,0 @@
import 'interfaces/i_http_response.dart';
import 'package:dio/dio.dart';
class DioResponse<T> implements IHttpResponse<T> {
final Response<dynamic> _response;
DioResponse(this._response);
@override
T? get data => _response.data;
@override
int get statusCode => _response.statusCode ?? 0;
@override
Map<String, dynamic>? get headers => _response.headers.map;
@override
bool get isSuccessful => statusCode >= 200 && statusCode < 300;
}

View File

@@ -0,0 +1,60 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:rasadyar_core/core.dart';
void main() {
group('DioResponse', () {
test('data should return response data', () {
final response = Response(
requestOptions: RequestOptions(path: "/"),
data: 'hello',
);
final dioResponse = DioResponse<String>(response);
expect(dioResponse.data, 'hello');
});
test('status Code should return 0 if null', () {
final response = Response(requestOptions: RequestOptions(path: "/"), statusCode: null);
final dioResponse = DioResponse(response);
expect(dioResponse.statusCode, 0);
});
test('headers should return response headers map', () {
final headers = Headers.fromMap({
'content-type': ['application/json'],
});
final response = Response(
requestOptions: RequestOptions(path: "/"),
headers: headers,
);
final dioResponse = DioResponse(response);
expect(dioResponse.headers, isA<Map>());
expect(dioResponse.headers, {
'content-type': ['application/json'],
});
});
test('isSuccessful should return true for 2xx codes', () {
final response = Response(requestOptions: RequestOptions(path: "/"), statusCode: 200);
final dioResponse = DioResponse(response);
expect(dioResponse.statusCode, 200);
expect(dioResponse.isSuccessful, true);
});
test('isSuccessful should return false for non-2xx codes', () {
final response = Response(requestOptions: RequestOptions(path: "/"),statusCode: 404);
final dioResponse = DioResponse(response);
expect(dioResponse.statusCode, 404);
expect(dioResponse.isSuccessful, false);
});
});
}

View File

@@ -1,6 +0,0 @@
import 'package:flutter/foundation.dart';
abstract class IFormData{
void addFile(String field, Uint8List bytes, String filename);
void addField(String key, String value);
}

View File

@@ -1,53 +0,0 @@
import 'package:dio/dio.dart';
import 'i_form_data.dart';
import 'i_http_response.dart';
abstract class IHttpClient {
Future<void> init();
Future<IHttpResponse<T>> get<T>(
String path, {
Map<String, dynamic>? queryParameters,
Map<String, String>? headers,
ProgressCallback? onReceiveProgress,
});
Future<IHttpResponse<T>> post<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParameters,
Map<String, String>? headers,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
Future<IHttpResponse<T>> put<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParameters,
Map<String, String>? headers,
ProgressCallback? onSendProgress,
ProgressCallback? onReceiveProgress,
});
Future<IHttpResponse<T>> delete<T>(
String path, {
dynamic data,
Map<String, dynamic>? queryParameters,
Map<String, String>? headers,
});
Future<IHttpResponse<T>> download<T>(
String url, {
ProgressCallback? onReceiveProgress,
});
Future<IHttpResponse<T>> upload<T>(
String path, {
required IFormData formData,
Map<String, String>? headers,
ProgressCallback? onSendProgress,
});
}

View File

@@ -1,6 +0,0 @@
abstract class IHttpResponse<T> {
T? get data;
int get statusCode;
Map<String, dynamic>? get headers;
bool get isSuccessful;
}

View File

@@ -1,4 +0,0 @@
abstract class IRemote<T>{
Future<T> init();
}

View File

@@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: android_intent_plus
sha256: dfc1fd3a577205ae8f11e990fb4ece8c90cceabbee56fcf48e463ecf0bd6aae3
sha256: "2329378af63f49b985cb2e110ac784d08374f1e2b1984be77ba9325b1c8cce11"
url: "https://pub.dev"
source: hosted
version: "5.3.0"
version: "5.3.1"
animated_stack_widget:
dependency: transitive
description:
@@ -193,6 +193,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
connectivity_plus:
dependency: transitive
description:
name: connectivity_plus
sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec
url: "https://pub.dev"
source: hosted
version: "6.1.5"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
convert:
dependency: transitive
description:
@@ -285,10 +301,10 @@ packages:
dependency: transitive
description:
name: dio
sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9"
sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9
url: "https://pub.dev"
source: hosted
version: "5.8.0+1"
version: "5.9.0"
dio_web_adapter:
dependency: transitive
description:
@@ -533,14 +549,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
font_awesome_flutter:
dependency: transitive
description:
name: font_awesome_flutter
sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a
url: "https://pub.dev"
source: hosted
version: "10.8.0"
freezed:
dependency: "direct dev"
description:
@@ -641,10 +649,10 @@ packages:
dependency: transitive
description:
name: get_it
sha256: f126a3e286b7f5b578bf436d5592968706c4c1de28a228b870ce375d9f743103
sha256: a4292e7cf67193f8e7c1258203104eb2a51ec8b3a04baa14695f4064c144297b
url: "https://pub.dev"
source: hosted
version: "8.0.3"
version: "8.2.0"
get_test:
dependency: "direct dev"
description:
@@ -769,66 +777,66 @@ packages:
dependency: transitive
description:
name: image_picker
sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a"
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.2.0"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: "6fae381e6af2bbe0365a5e4ce1db3959462fa0c4d234facf070746024bb80c8d"
sha256: e83b2b05141469c5e19d77e1dfa11096b6b1567d09065b2265d7c6904560050c
url: "https://pub.dev"
source: hosted
version: "0.8.12+24"
version: "0.8.13"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83"
sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
version: "3.1.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100"
sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e
url: "https://pub.dev"
source: hosted
version: "0.8.12+2"
version: "0.8.13"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9"
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
version: "0.2.2"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1"
sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
version: "0.2.2"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0"
sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665"
url: "https://pub.dev"
source: hosted
version: "2.10.1"
version: "2.11.0"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.dev"
source: hosted
version: "0.2.1+1"
version: "0.2.2"
image_size_getter:
dependency: transitive
description:
@@ -897,26 +905,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
version: "11.0.1"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.9"
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
lints:
dependency: "direct dev"
description:
@@ -1021,6 +1029,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
nm:
dependency: transitive
description:
name: nm
sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
node_preamble:
dependency: transitive
description:
@@ -1041,18 +1057,18 @@ packages:
dependency: transitive
description:
name: package_info_plus
sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
url: "https://pub.dev"
source: hosted
version: "8.3.0"
version: "8.3.1"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
url: "https://pub.dev"
source: hosted
version: "3.2.0"
version: "3.2.1"
path:
dependency: transitive
description:
@@ -1169,10 +1185,10 @@ packages:
dependency: transitive
description:
name: persian_datetime_picker
sha256: "7ccbfd3a68dc89d405550f624e9fa590c914fed2aa2d48973c4f4400baab2e06"
sha256: "0ec2879d2bee8390dda088b412739e6316e3a54d77640ec54dc1eeca8c5baa59"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
version: "3.1.1"
petitparser:
dependency: transitive
description:
@@ -1429,26 +1445,26 @@ packages:
dependency: "direct dev"
description:
name: test
sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e"
sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb"
url: "https://pub.dev"
source: hosted
version: "1.25.15"
version: "1.26.2"
test_api:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev"
source: hosted
version: "0.7.4"
version: "0.7.6"
test_core:
dependency: transitive
description:
name: test_core
sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a"
url: "https://pub.dev"
source: hosted
version: "0.6.8"
version: "0.6.11"
time:
dependency: transitive
description:
@@ -1517,10 +1533,10 @@ packages:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.2.0"
vm_service:
dependency: transitive
description:
@@ -1626,5 +1642,5 @@ packages:
source: hosted
version: "2.1.0"
sdks:
dart: ">=3.8.1 <4.0.0"
dart: ">=3.9.0 <4.0.0"
flutter: ">=3.29.0"

View File

@@ -4,7 +4,7 @@ publish_to: 'none'
version: 1.2.0
environment:
sdk: ^3.8.1
sdk: ^3.9.0
dependencies:
flutter:

View File

@@ -0,0 +1,15 @@
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
class CheckDiMiddleWare extends GetMiddleware {
@override
Future<GetNavConfig?> redirectDelegate(GetNavConfig route) async {
return super.redirectDelegate(route);
}
@override
GetPage? onPageCalled(GetPage? page) {
return super.onPageCalled(page);
}
}

View File

@@ -0,0 +1,18 @@
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_livestock/data/model/local/location/tmp_locations.dart';
class TmpLocalDataSource {
Future<void> addLocations(List<TmpLocations> list) async {
IsolatedBox<TmpLocations> box = await IsolatedHive.openBox<TmpLocations>('TmpBox');
if (await box.isNotEmpty) {
box.clear();
}
box.addAll(list);
}
Future<List<TmpLocations>> getLocations() async {
IsolatedBox<TmpLocations> box = await IsolatedHive.openBox<TmpLocations>('TmpBox');
var res = await box.values;
return res.toList();
}
}

View File

@@ -1,39 +0,0 @@
import 'package:rasadyar_core/core.dart';
part 'car.g.dart';
@HiveType(typeId: 50)
class CarsLocal extends HiveObject {
@HiveField(0)
String? name;
@HiveField(1)
String? price;
CarsLocal({this.name, this.price});
factory CarsLocal.fromJson(Map<String, dynamic> json) {
return CarsLocal(name: json['name'] as String?, price: json['price'] as String?);
}
Map<String, dynamic> toJson() {
return {'name': name, 'price': price};
}
}
class Cars {
String? name;
String? price;
Cars({this.name, this.price});
factory Cars.fromJson(Map<String, dynamic> json) {
return Cars(name: json['name'] as String?, price: json['price'] as String?);
}
Map<String, dynamic> toJson() {
return {'name': name, 'price': price};
}
}

View File

@@ -0,0 +1,16 @@
import 'package:rasadyar_core/core.dart';
part 'tmp_locations.g.dart';
@HiveType(typeId: 100)
class TmpLocations extends HiveObject{
@HiveField(0)
double? lat;
@HiveField(1)
double? long;
TmpLocations({this.lat, this.long});
}

View File

@@ -1,32 +1,34 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'car.dart';
part of 'tmp_locations.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class CarsLocalAdapter extends TypeAdapter<CarsLocal> {
class TmpLocationsAdapter extends TypeAdapter<TmpLocations> {
@override
final typeId = 50;
final typeId = 100;
@override
CarsLocal read(BinaryReader reader) {
TmpLocations read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return CarsLocal(name: fields[0] as String?, price: fields[1] as String?);
return TmpLocations()
..lat = (fields[0] as num?)?.toDouble()
..long = (fields[1] as num?)?.toDouble();
}
@override
void write(BinaryWriter writer, CarsLocal obj) {
void write(BinaryWriter writer, TmpLocations obj) {
writer
..writeByte(2)
..writeByte(0)
..write(obj.name)
..write(obj.lat)
..writeByte(1)
..write(obj.price);
..write(obj.long);
}
@override
@@ -35,7 +37,7 @@ class CarsLocalAdapter extends TypeAdapter<CarsLocal> {
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is CarsLocalAdapter &&
other is TmpLocationsAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -1,6 +1,5 @@
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_livestock/data/model/response/address/address.dart';
import 'package:rasadyar_livestock/data/model/response/auth/auth_response_model.dart';
import 'package:rasadyar_livestock/data/model/response/captcha/captcha_response_model.dart';
import 'package:rasadyar_livestock/data/model/response/live_tmp/livestock_model.dart';
abstract class LivestockRepository {
@@ -11,4 +10,6 @@ abstract class LivestockRepository {
Future<bool> createTaggingLiveStock({required LivestockData data});
/* Future<List<LatLng>> getLocations();
Future<void> addLocations(List<LatLng> latList);*/
}

View File

@@ -1,4 +1,9 @@
import 'package:latlong2/latlong.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/data/services/network_status.dart';
import 'package:rasadyar_livestock/data/data_source/local/tmp/tmp_local_data-source.dart';
import 'package:rasadyar_livestock/data/data_source/remote/livestock/livestock_remote.dart';
import 'package:rasadyar_livestock/data/model/local/location/tmp_locations.dart';
import 'package:rasadyar_livestock/data/model/response/address/address.dart';
import 'package:rasadyar_livestock/data/model/response/live_tmp/livestock_model.dart';
@@ -24,4 +29,35 @@ class LivestockRepositoryImp implements LivestockRepository {
Future<bool> createTaggingLiveStock({required LivestockData data}) async {
return await livestockRemote.createTaggingLiveStock(data: data);
}
/*
@override
Future<List<LatLng>> getLocations() async {
if (NetworkStatus().isConnected.value) {
return [
LatLng(35.824891, 50.948025),
LatLng(35.825000, 50.949000),
LatLng(35.823000, 50.947000),
LatLng(35.826000, 50.950000),
LatLng(35.827000, 50.951000),
LatLng(35.828000, 50.952000),
LatLng(35.829000, 50.953000),
LatLng(35.830000, 50.954000),
LatLng(35.831000, 50.955000),
LatLng(35.832000, 50.956000),
LatLng(35.832000, 50.956055),
];
} else {
*//*var res = await tmpLocalDataSource.getLocations();
return res.map((e) => LatLng(e.lat ?? 0.0, e.long ?? 0.0)).toList();*//*
}
}
@override
Future<void> addLocations(List<LatLng> latList) async {
*//* await tmpLocalDataSource.addLocations(
latList.map((e) => TmpLocations(lat: e.latitude, long: e.longitude)).toList(),
);*//*
iLog("it is done");
}*/
}

View File

@@ -1,5 +1,4 @@
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_livestock/data/model/local/live_tmp/car.dart';
import 'package:rasadyar_livestock/data/model/local/live_tmp/livestock_local_model.dart';
import 'package:rasadyar_livestock/data/model/response/live_tmp/livestock_model.dart';
import 'package:rasadyar_livestock/data/utils/mapper.dart';
@@ -7,7 +6,7 @@ import 'package:rasadyar_livestock/data/utils/mapper.dart';
class LiveStockStorageService extends GetxService {
final String _liveStockBoxName = 'LiveStockBox';
late IsolatedBox<LivestockLocalModel> _LiveStockbox;
late IsolatedBox<CarsLocal> _carbox;
@override
void onInit() {

View File

@@ -3,27 +3,27 @@
// Check in to version control
import 'package:hive_ce/hive.dart';
import 'package:rasadyar_livestock/data/model/local/live_tmp/car.dart';
import 'package:rasadyar_livestock/data/model/local/live_tmp/livestock_local_model.dart';
import 'package:rasadyar_livestock/data/model/local/location/tmp_locations.dart';
extension HiveRegistrar on HiveInterface {
void registerAdapters() {
registerAdapter(CarsLocalAdapter());
registerAdapter(HerdLocalAdapter());
registerAdapter(LivestockLocalAdapter());
registerAdapter(LivestockLocalModelAdapter());
registerAdapter(LocationLocalAdapter());
registerAdapter(RancherLocalAdapter());
registerAdapter(TmpLocationsAdapter());
}
}
extension IsolatedHiveRegistrar on IsolatedHiveInterface {
void registerAdapters() {
registerAdapter(CarsLocalAdapter());
registerAdapter(HerdLocalAdapter());
registerAdapter(LivestockLocalAdapter());
registerAdapter(LivestockLocalModelAdapter());
registerAdapter(LocationLocalAdapter());
registerAdapter(RancherLocalAdapter());
registerAdapter(TmpLocationsAdapter());
}
}

View File

@@ -20,7 +20,7 @@ Future<void> setupLiveStockDI() async {
IsolatedHive.registerAdapters();
iLog("Sssssssssssssssssssss");
final tokenService = Get.find<TokenStorageService>();
Get.put<LiveStockStorageService>(LiveStockStorageService());
if (tokenService.baseurl.value == null) {
@@ -31,7 +31,7 @@ Future<void> setupLiveStockDI() async {
diLiveStock.registerLazySingleton<AppInterceptor>(
() => AppInterceptor(
refreshTokenCallback: () async {
// Use lazy access to avoid circular dependency
/* // Use lazy access to avoid circular dependency
final authRepository = diLiveStock.get<AuthRepository>();
final hasAuthenticated = await authRepository.hasAuthenticated();
if (hasAuthenticated) {
@@ -39,7 +39,7 @@ Future<void> setupLiveStockDI() async {
authRequest: {'refresh': tokenService.refreshToken.value},
);
return newToken?.access;
}
}*/
return null;
},
saveTokenCallback: (String newToken) async {

View File

@@ -2,7 +2,10 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_livestock/data/repository/livestock/livestock_repository.dart';
import 'package:rasadyar_livestock/data/repository/livestock/livestock_repository_imp.dart';
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
import 'package:rasadyar_livestock/presentation/page/root/logic.dart';
enum ErrorLocationType { serviceDisabled, permissionDenied, none }
@@ -11,7 +14,6 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
String tileType = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
RxDouble currentZoom = 15.0.obs;
RxList<LatLng> allMarkers = <LatLng>[].obs;
Rx<MapController> mapController = MapController().obs;
RxList<ErrorLocationType> errorLocationType = RxList();
@@ -19,19 +21,9 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
Timer? _debounceTimer;
RxBool isLoading = false.obs;
RxList<LatLng> markerLocations = <LatLng>[
LatLng(35.824891, 50.948025),
LatLng(35.825000, 50.949000),
LatLng(35.823000, 50.947000),
LatLng(35.826000, 50.950000),
LatLng(35.827000, 50.951000),
LatLng(35.828000, 50.952000),
LatLng(35.829000, 50.953000),
LatLng(35.830000, 50.954000),
LatLng(35.831000, 50.955000),
LatLng(35.832000, 50.956000),
LatLng(35.832000, 50.956055),
].obs;
RxList<LatLng> markerLocations = RxList();
RootLogic rootLogic = Get.find<RootLogic>();
late LivestockRepository repository ;
@override
void onInit() {
@@ -67,6 +59,7 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
void onReady() {
super.onReady();
determineCurrentPosition();
// getLoc();
}
@override
@@ -158,5 +151,14 @@ class MapWidgetLogic extends GetxController with GetTickerProviderStateMixin {
return rawMarkers.where((marker) => distance(center, marker) <= radiusInMeters).toList();
}
/* Future<void> getLoc() async {
await Future.delayed(Duration(seconds: 3));
await safeCall(
call: () async => repository.getLocations(),
onSuccess: (result) {
markerLocations.addAll(result);
},
onError: (error, stackTrace) {},
);
}*/
}

View File

@@ -1,6 +1,7 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_core/data/services/network_status.dart';
import 'package:rasadyar_livestock/presentation/routes/app_pages.dart';
import 'logic.dart';
@@ -148,6 +149,16 @@ class MapWidget extends GetView<MapWidgetLogic> {
);
}, controller.currentLocation),
Positioned(
top: 15,
left: 20,
child: ObxValue((status) {
return Text("Connection: ${status.value}", style: TextStyle(fontSize: 20));
}, NetworkStatus().isConnected),
),
// Uncomment the following lines to enable the search widget
/* Positioned(
top: 10,

View File

@@ -1,5 +1,11 @@
import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:rasadyar_core/core.dart';
import 'package:rasadyar_livestock/data/repository/livestock/livestock_repository.dart';
import 'package:rasadyar_livestock/data/repository/livestock/livestock_repository_imp.dart';
import 'package:rasadyar_livestock/injection/live_stock_di.dart';
import 'package:rasadyar_livestock/presentation/page/map/view.dart';
import 'package:rasadyar_livestock/presentation/page/profile/view.dart';
import 'package:rasadyar_livestock/presentation/page/request_tagging/view.dart';
@@ -28,10 +34,49 @@ class RootLogic extends GetxController {
];
RxInt currentIndex = 0.obs;
TokenStorageService tokenService = Get.find<TokenStorageService>();
late StreamSubscription<List<ConnectivityResult>> connectivitySubscription;
RxList<ConnectivityResult> connectivityResults = <ConnectivityResult>[].obs;
@override
void onInit() {
super.onInit();
connectivitySubscription = Connectivity().onConnectivityChanged.listen((result) {
if (result.isNotEmpty) {
connectivityResults.assignAll(result);
}
});
/* GetIt.instance.allReady().then((value) async {
await diLiveStock.get<LivestockRepositoryImp>().addLocations(generateRandomPoints());
});*/
}
List<LatLng> generateRandomPoints() {
final Random random = Random();
final double centerLat = 35.824891;
final double centerLon = 50.948025;
final double radiusKm = 1.0;
final double kmToDegLat = 1 / 111.0; // 1 km ≈ 0.009° latitude
final double kmToDegLon = 1 / (111.0 * cos(centerLat * pi / 180)); // Adjust for longitude
List<LatLng> points = [];
for (int i = 0; i < 100; i++) {
// Generate random angle (0 to 2π) and random radius (0 to 1 km, using sqrt for uniform distribution)
double theta = random.nextDouble() * 2 * pi;
double r =
sqrt(random.nextDouble()) * radiusKm; // Square root for uniform distribution in circle
// Convert polar coordinates to Cartesian, then to LatLng
double deltaLat = r * cos(theta) * kmToDegLat;
double deltaLon = r * sin(theta) * kmToDegLon;
double newLat = centerLat + deltaLat;
double newLon = centerLon + deltaLon;
points.add(LatLng(newLat, newLon));
}
return points;
}
@override
void onReady() {
// TODO: implement onReady
@@ -40,7 +85,7 @@ class RootLogic extends GetxController {
@override
void onClose() {
// TODO: implement onClose
connectivitySubscription.cancel();
super.onClose();
}

View File

@@ -23,6 +23,7 @@ class RootPage extends GetView<RootLogic> {
final navigatorKey = Get.nestedKey(currentIndex);
if (currentIndex.value == 0 &&
navigatorKey != null &&
navigatorKey.currentState != null) {
if (navigatorKey.currentState!.canPop()) {

View File

@@ -14,6 +14,8 @@ import 'package:rasadyar_livestock/presentation/page/tagging/view.dart';
import 'package:rasadyar_livestock/presentation/widgets/base_page/logic.dart';
import 'package:rasadyar_livestock/presentation/widgets/captcha/logic.dart';
import '../../injection/live_stock_di.dart';
part 'app_routes.dart';
sealed class LiveStockPages {

View File

@@ -5,7 +5,7 @@ publish_to: 'none'
# repository: https://github.com/my_org/my_repo
environment:
sdk: ^3.8.1
sdk: ^3.9.0
dependencies:
@@ -24,7 +24,7 @@ dev_dependencies:
lints: ^6.0.0
test: ^1.25.15
##code generation
build_runner: ^2.6.0
build_runner: ^2.7.0
hive_ce_generator: ^1.9.3
freezed: ^3.2.0
json_serializable: ^6.10.0

View File

@@ -21,10 +21,10 @@ packages:
dependency: transitive
description:
name: android_intent_plus
sha256: dfc1fd3a577205ae8f11e990fb4ece8c90cceabbee56fcf48e463ecf0bd6aae3
sha256: "2329378af63f49b985cb2e110ac784d08374f1e2b1984be77ba9325b1c8cce11"
url: "https://pub.dev"
source: hosted
version: "5.3.0"
version: "5.3.1"
animated_stack_widget:
dependency: transitive
description:
@@ -77,18 +77,18 @@ packages:
dependency: transitive
description:
name: build
sha256: "7d95cbbb1526ab5ae977df9b4cc660963b9b27f6d1075c0b34653868911385e4"
sha256: "6439a9c71a4e6eca8d9490c1b380a25b02675aa688137dfbe66d2062884a23ac"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
version: "3.0.2"
build_config:
dependency: transitive
description:
name: build_config
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33"
sha256: "4f64382b97504dc2fcdf487d5aae33418e08b4703fc21249e4db6d804a4d0187"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.2.0"
build_daemon:
dependency: transitive
description:
@@ -101,26 +101,26 @@ packages:
dependency: transitive
description:
name: build_resolvers
sha256: "38c9c339333a09b090a638849a4c56e70a404c6bdd3b511493addfbc113b60c2"
sha256: "2b21a125d66a86b9511cc3fb6c668c42e9a1185083922bf60e46d483a81a9712"
url: "https://pub.dev"
source: hosted
version: "3.0.0"
version: "3.0.2"
build_runner:
dependency: "direct dev"
description:
name: build_runner
sha256: b971d4a1c789eba7be3e6fe6ce5e5b50fd3719e3cb485b3fad6d04358304351d
sha256: fd3c09f4bbff7fa6e8d8ef688a0b2e8a6384e6483a25af0dac75fef362bcfe6f
url: "https://pub.dev"
source: hosted
version: "2.6.0"
version: "2.7.0"
build_runner_core:
dependency: transitive
description:
name: build_runner_core
sha256: c04e612ca801cd0928ccdb891c263a2b1391cb27940a5ea5afcf9ba894de5d62
sha256: ab27e46c8aa233e610cf6084ee6d8a22c6f873a0a9929241d8855b7a72978ae7
url: "https://pub.dev"
source: hosted
version: "9.2.0"
version: "9.3.0"
built_collection:
dependency: transitive
description:
@@ -201,6 +201,22 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.0"
connectivity_plus:
dependency: transitive
description:
name: connectivity_plus
sha256: b5e72753cf63becce2c61fd04dfe0f1c430cc5278b53a1342dc5ad839eab29ec
url: "https://pub.dev"
source: hosted
version: "6.1.5"
connectivity_plus_platform_interface:
dependency: transitive
description:
name: connectivity_plus_platform_interface
sha256: "42657c1715d48b167930d5f34d00222ac100475f73d10162ddf43e714932f204"
url: "https://pub.dev"
source: hosted
version: "2.0.1"
convert:
dependency: transitive
description:
@@ -285,10 +301,10 @@ packages:
dependency: transitive
description:
name: dio
sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9"
sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9
url: "https://pub.dev"
source: hosted
version: "5.8.0+1"
version: "5.9.0"
dio_web_adapter:
dependency: transitive
description:
@@ -541,14 +557,6 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
font_awesome_flutter:
dependency: transitive
description:
name: font_awesome_flutter
sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a
url: "https://pub.dev"
source: hosted
version: "10.8.0"
freezed:
dependency: "direct dev"
description:
@@ -649,10 +657,10 @@ packages:
dependency: transitive
description:
name: get_it
sha256: f126a3e286b7f5b578bf436d5592968706c4c1de28a228b870ce375d9f743103
sha256: a4292e7cf67193f8e7c1258203104eb2a51ec8b3a04baa14695f4064c144297b
url: "https://pub.dev"
source: hosted
version: "8.0.3"
version: "8.2.0"
get_test:
dependency: "direct dev"
description:
@@ -777,66 +785,66 @@ packages:
dependency: transitive
description:
name: image_picker
sha256: "021834d9c0c3de46bf0fe40341fa07168407f694d9b2bb18d532dc1261867f7a"
sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041"
url: "https://pub.dev"
source: hosted
version: "1.1.2"
version: "1.2.0"
image_picker_android:
dependency: transitive
description:
name: image_picker_android
sha256: "6fae381e6af2bbe0365a5e4ce1db3959462fa0c4d234facf070746024bb80c8d"
sha256: e83b2b05141469c5e19d77e1dfa11096b6b1567d09065b2265d7c6904560050c
url: "https://pub.dev"
source: hosted
version: "0.8.12+24"
version: "0.8.13"
image_picker_for_web:
dependency: transitive
description:
name: image_picker_for_web
sha256: "717eb042ab08c40767684327be06a5d8dbb341fe791d514e4b92c7bbe1b7bb83"
sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6"
url: "https://pub.dev"
source: hosted
version: "3.0.6"
version: "3.1.0"
image_picker_ios:
dependency: transitive
description:
name: image_picker_ios
sha256: "05da758e67bc7839e886b3959848aa6b44ff123ab4b28f67891008afe8ef9100"
sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e
url: "https://pub.dev"
source: hosted
version: "0.8.12+2"
version: "0.8.13"
image_picker_linux:
dependency: transitive
description:
name: image_picker_linux
sha256: "34a65f6740df08bbbeb0a1abd8e6d32107941fd4868f67a507b25601651022c9"
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
version: "0.2.2"
image_picker_macos:
dependency: transitive
description:
name: image_picker_macos
sha256: "1b90ebbd9dcf98fb6c1d01427e49a55bd96b5d67b8c67cf955d60a5de74207c1"
sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04
url: "https://pub.dev"
source: hosted
version: "0.2.1+2"
version: "0.2.2"
image_picker_platform_interface:
dependency: transitive
description:
name: image_picker_platform_interface
sha256: "886d57f0be73c4b140004e78b9f28a8914a09e50c2d816bdd0520051a71236a0"
sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665"
url: "https://pub.dev"
source: hosted
version: "2.10.1"
version: "2.11.0"
image_picker_windows:
dependency: transitive
description:
name: image_picker_windows
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
url: "https://pub.dev"
source: hosted
version: "0.2.1+1"
version: "0.2.2"
image_size_getter:
dependency: transitive
description:
@@ -905,26 +913,26 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
url: "https://pub.dev"
source: hosted
version: "10.0.9"
version: "11.0.1"
leak_tracker_flutter_testing:
dependency: transitive
description:
name: leak_tracker_flutter_testing
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
url: "https://pub.dev"
source: hosted
version: "3.0.9"
version: "3.0.10"
leak_tracker_testing:
dependency: transitive
description:
name: leak_tracker_testing
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
url: "https://pub.dev"
source: hosted
version: "3.0.1"
version: "3.0.2"
lints:
dependency: transitive
description:
@@ -1029,6 +1037,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
nm:
dependency: transitive
description:
name: nm
sha256: "2c9aae4127bdc8993206464fcc063611e0e36e72018696cd9631023a31b24254"
url: "https://pub.dev"
source: hosted
version: "0.5.0"
package_config:
dependency: transitive
description:
@@ -1041,18 +1057,18 @@ packages:
dependency: transitive
description:
name: package_info_plus
sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191"
sha256: "16eee997588c60225bda0488b6dcfac69280a6b7a3cf02c741895dd370a02968"
url: "https://pub.dev"
source: hosted
version: "8.3.0"
version: "8.3.1"
package_info_plus_platform_interface:
dependency: transitive
description:
name: package_info_plus_platform_interface
sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c"
sha256: "202a487f08836a592a6bd4f901ac69b3a8f146af552bbd14407b6b41e1c3f086"
url: "https://pub.dev"
source: hosted
version: "3.2.0"
version: "3.2.1"
path:
dependency: transitive
description:
@@ -1169,10 +1185,10 @@ packages:
dependency: transitive
description:
name: persian_datetime_picker
sha256: "7ccbfd3a68dc89d405550f624e9fa590c914fed2aa2d48973c4f4400baab2e06"
sha256: "0ec2879d2bee8390dda088b412739e6316e3a54d77640ec54dc1eeca8c5baa59"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
version: "3.1.1"
petitparser:
dependency: transitive
description:
@@ -1418,10 +1434,10 @@ packages:
dependency: transitive
description:
name: test_api
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev"
source: hosted
version: "0.7.4"
version: "0.7.6"
time:
dependency: transitive
description:
@@ -1490,10 +1506,10 @@ packages:
dependency: transitive
description:
name: vector_math
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
url: "https://pub.dev"
source: hosted
version: "2.1.4"
version: "2.2.0"
vm_service:
dependency: transitive
description:
@@ -1591,5 +1607,5 @@ packages:
source: hosted
version: "2.1.0"
sdks:
dart: ">=3.8.1 <4.0.0"
dart: ">=3.9.0 <4.0.0"
flutter: ">=3.29.0"

View File

@@ -4,7 +4,7 @@ publish_to: 'none'
version: 1.3.6+4
environment:
sdk: ^3.8.1
sdk: ^3.9.0
dependencies:
flutter:
@@ -36,7 +36,7 @@ dev_dependencies:
sdk: flutter
flutter_lints: ^6.0.0
##code generation
build_runner: ^2.6.0
build_runner: ^2.7.0
hive_ce_generator: ^1.9.3
freezed: ^3.2.0
json_serializable: ^6.10.0