Compare commits
41 Commits
feature/pe
...
sizing
| Author | SHA1 | Date | |
|---|---|---|---|
| ecb9d7316e | |||
| 1810dc6e2a | |||
| 4d2d25f47b | |||
| c79cbeffcc | |||
| b7614a39f1 | |||
| a05c167f30 | |||
| c1c903ac93 | |||
| a0a782c91b | |||
| c140daa7ae | |||
| 6d30a59651 | |||
| 8d453dc980 | |||
| 0a50de3d70 | |||
| 02053182db | |||
| 33f3dfa252 | |||
| cb70973d3b | |||
| 1ffeea8b77 | |||
| 5f484036f8 | |||
| 73927557ca | |||
| 5111d5d65f | |||
| ced0895063 | |||
| 34e7a7c60f | |||
| c89f1c666e | |||
| 33c2403aef | |||
| 0088d146f0 | |||
| 94c042d403 | |||
| 48cb23379c | |||
| e526dce2c9 | |||
| cacc2460f1 | |||
| dd53db6795 | |||
| 435a9c04f9 | |||
| 8e3a27e0d3 | |||
| 48d2430c9c | |||
| cf0c55eafe | |||
| 03c6633504 | |||
| b8184f02ec | |||
| c12d1924c4 | |||
| 869f33f1f1 | |||
| a07246130e | |||
| 67aafafd1e | |||
| c929e1e2d7 | |||
| 990266ba95 |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"env": "development",
|
||||
"apiBaseUrl": "https://api-neki-b2b.neki.es/gateway/api/",
|
||||
"apiOrigin": "bde6ea73-d09c-475f-aabf-1d11137e4d0d"
|
||||
}
|
||||
"apiOrigin": "https://neki-b2b.neki.es"
|
||||
}
|
||||
@@ -6,6 +6,8 @@ PODS:
|
||||
- Flutter
|
||||
- flutter_treezor_entrust_sdk_bridge (0.0.1):
|
||||
- Flutter
|
||||
- image_picker_ios (0.0.1):
|
||||
- Flutter
|
||||
- mobile_scanner (7.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -14,6 +16,8 @@ PODS:
|
||||
- FlutterMacOS
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -28,9 +32,11 @@ DEPENDENCIES:
|
||||
- flutter_contacts (from `.symlinks/plugins/flutter_contacts/ios`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_treezor_entrust_sdk_bridge (from `.symlinks/plugins/flutter_treezor_entrust_sdk_bridge/ios`)
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- share_plus (from `.symlinks/plugins/share_plus/ios`)
|
||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
|
||||
@@ -44,12 +50,16 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_treezor_entrust_sdk_bridge:
|
||||
:path: ".symlinks/plugins/flutter_treezor_entrust_sdk_bridge/ios"
|
||||
image_picker_ios:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
mobile_scanner:
|
||||
:path: ".symlinks/plugins/mobile_scanner/darwin"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
share_plus:
|
||||
:path: ".symlinks/plugins/share_plus/ios"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
url_launcher_ios:
|
||||
@@ -62,9 +72,11 @@ SPEC CHECKSUMS:
|
||||
flutter_contacts: edb1c5ce76aa433e20e6cb14c615f4c0b66e0983
|
||||
flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29
|
||||
flutter_treezor_entrust_sdk_bridge: 4c2c94fb74ab57576e8d49f5f2a4b214e41141fe
|
||||
image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b
|
||||
mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e
|
||||
path_provider_foundation: 0b743cbb62d8e47eab856f09262bb8c1ddcfe6ba
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
share_plus: 8b6f8b3447e494cca5317c8c3073de39b3600d1f
|
||||
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
|
||||
url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa
|
||||
webview_flutter_wkwebview: 29eb20d43355b48fe7d07113835b9128f84e3af4
|
||||
|
||||
@@ -543,7 +543,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-development;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/Runner-development.entitlements";
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
@@ -727,7 +727,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-development;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/Runner-development.entitlements";
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
@@ -751,7 +751,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-development;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/Runner-development.entitlements";
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
@@ -1100,7 +1100,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-staging;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/Runner-staging.entitlements";
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
@@ -1124,7 +1124,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-production;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
@@ -1148,7 +1148,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-staging;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/Runner-staging.entitlements";
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
@@ -1171,7 +1171,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-production;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
@@ -1194,7 +1194,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-staging;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = "Runner/Runner-staging.entitlements";
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
@@ -1217,7 +1217,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-production;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
|
||||
@@ -30,7 +30,9 @@ Future<void> initApp(EnvironmentEnum env) async {
|
||||
await configureDependencies(
|
||||
QuestiaEnvConfig(),
|
||||
log: env.isDevelopment || kDebugMode,
|
||||
onTokenExpired: () => appRouter.go(AppRoutes.scaTreezor),
|
||||
onTokenExpired: () => appRouter.go(
|
||||
AppRoutes.legacyLogin,
|
||||
), //change to payments app to AppRoutes.scaTreezor
|
||||
onUnauthorized: () async {
|
||||
final currentLocation =
|
||||
appRouter.routerDelegate.currentConfiguration.uri.path;
|
||||
@@ -39,7 +41,7 @@ Future<void> initApp(EnvironmentEnum env) async {
|
||||
await GetIt.I<TreezorWalletConnectionService>().logout();
|
||||
} catch (_) {}
|
||||
await clearSessionData();
|
||||
appRouter.go(AppRoutes.login);
|
||||
appRouter.go(AppRoutes.legacyLogin);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -141,6 +141,21 @@ void configureAppRouter() {
|
||||
name: 'apps_use',
|
||||
pageBuilder: const AppsUseBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'volume_control',
|
||||
name: 'volume_control',
|
||||
pageBuilder: const VolumeControlBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'call_history',
|
||||
name: 'call_history',
|
||||
pageBuilder: const CallHistoryBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'background_image',
|
||||
name: 'background_image',
|
||||
pageBuilder: const BackgroundImageBuilder().buildPage,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -237,9 +252,9 @@ void configureAppRouter() {
|
||||
pageBuilder: RemoteOnOffBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'sms_alert',
|
||||
name: 'sms_alert',
|
||||
pageBuilder: SmsAlertBuilder().buildPage,
|
||||
path: 'alerts',
|
||||
name: 'alerts',
|
||||
pageBuilder: AlertsBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'timezone',
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
@@ -35,8 +36,10 @@ class LegacyHeartbeatService {
|
||||
debugPrint('[LegacyHeartbeat] /auth/me => OK');
|
||||
} catch (e) {
|
||||
debugPrint('[LegacyHeartbeat] error: $e');
|
||||
stop();
|
||||
_onUnauthorized();
|
||||
if (e is DioException && e.response?.statusCode == 401) {
|
||||
stop();
|
||||
_onUnauthorized();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,9 @@ class SaveFamilyAppState extends ConsumerState<SaveFamilyApp>
|
||||
walletHeartbeat = WalletHeartbeatService(
|
||||
repository: ref.read(treezorRepositoryProvider),
|
||||
sessionLocal: SessionLocalDatasourceImpl(),
|
||||
onError: () => appRouter.go(AppRoutes.scaTreezor),
|
||||
onError: () => appRouter.go(
|
||||
AppRoutes.legacyLogin,
|
||||
), //change to payments app to AppRoutes.scaTreezor
|
||||
);
|
||||
legacyHeartbeat = LegacyHeartbeatService(
|
||||
repository: GetIt.I<QuestiaRepository>(),
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.4/
|
||||
@@ -0,0 +1 @@
|
||||
/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.2/
|
||||
@@ -1 +1 @@
|
||||
C:/Users/Aitor Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1/
|
||||
/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/
|
||||
@@ -0,0 +1 @@
|
||||
/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/share_plus-10.1.4/
|
||||
@@ -1 +1 @@
|
||||
C:/Users/Aitor Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_linux-2.4.1/
|
||||
/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1/
|
||||
@@ -1 +1 @@
|
||||
C:/Users/Aitor Arana/AppData/Local/Pub/Cache/hosted/pub.dev/url_launcher_linux-3.2.2/
|
||||
/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/url_launcher_linux-3.2.2/
|
||||
@@ -6,9 +6,13 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_linux
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
|
||||
@@ -245,6 +245,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.15.0"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: "28bb3ae56f117b5aec029d702a90f57d285cd975c3c5c281eaca38dbc47c5937"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.5+2"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -385,6 +393,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
file_selector_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_linux
|
||||
sha256: "2567f398e06ac72dcf2e98a0c95df2a9edd03c2c2e0cacd4780f20cdf56263a0"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.4"
|
||||
file_selector_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_macos
|
||||
sha256: "5e0bbe9c312416f1787a68259ea1505b52f258c587f12920422671807c4d618a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.5"
|
||||
file_selector_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_platform_interface
|
||||
sha256: "35e0bd61ebcdb91a3505813b055b09b79dfdc7d0aee9c09a7ba59ae4bb13dc85"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
file_selector_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_windows
|
||||
sha256: "62197474ae75893a62df75939c777763d39c2bc5f73ce5b88497208bc269abfd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+5"
|
||||
fixnum:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -451,6 +491,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.7"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: ee8068e0e1cd16c4a82714119918efdeed33b3ba7772c54b5d094ab53f9b7fd1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.33"
|
||||
flutter_riverpod:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -602,6 +650,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.8.0"
|
||||
image_picker:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker
|
||||
sha256: "784210112be18ea55f69d7076e2c656a4e24949fa9e76429fe53af0c0f4fa320"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.1"
|
||||
image_picker_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_android
|
||||
sha256: eda9b91b7e266d9041084a42d605a74937d996b87083395c5e47835916a86156
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.13+14"
|
||||
image_picker_for_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_for_web
|
||||
sha256: "66257a3191ab360d23a55c8241c91a6e329d31e94efa7be9cf7a212e65850214"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
image_picker_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_ios
|
||||
sha256: "956c16a42c0c708f914021666ffcd8265dde36e673c9fa68c81f7d085d9774ad"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.13+3"
|
||||
image_picker_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_linux
|
||||
sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.2"
|
||||
image_picker_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_macos
|
||||
sha256: "86f0f15a309de7e1a552c12df9ce5b59fe927e71385329355aec4776c6a8ec91"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.2+1"
|
||||
image_picker_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_platform_interface
|
||||
sha256: "567e056716333a1647c64bb6bd873cff7622233a5c3f694be28a583d4715690c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.11.1"
|
||||
image_picker_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_windows
|
||||
sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.2"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1117,6 +1229,22 @@ packages:
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.0.1"
|
||||
share_plus:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share_plus
|
||||
sha256: fce43200aa03ea87b91ce4c3ac79f0cecd52e2a7a56c7a4185023c271fbfa6da
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "10.1.4"
|
||||
share_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: share_plus_platform_interface
|
||||
sha256: cc012a23fc2d479854e6c80150696c4a5f5bb62cb89af4de1c505cf78d0a5d0b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.2"
|
||||
shared_preferences:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1560,6 +1688,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.23.8"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: d7cb55e04cd34096cd3a79b3330245f54cb96a370a1c27adb3c84b917de8b08e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.15.0"
|
||||
wkt_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||
# In Windows, build-name is used as the major, minor, and patch parts
|
||||
# of the product and file versions while build-number is used as the build suffix.
|
||||
version: 1.0.0+4
|
||||
version: 1.0.0+6
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
@@ -123,6 +123,7 @@ flutter:
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
assets:
|
||||
- assets/shared/images/
|
||||
- assets/shared/animations/
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/to/resolution-aware-images
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":2,"entries":[{"package":"design_system","rootUri":"../../../packages/design_system/","packageUri":"lib/"},{"package":"flutter_treezor_entrust_sdk_bridge","rootUri":"../../../packages/flutter_treezor_entrust_sdk_bridge/","packageUri":"lib/"},{"package":"fonts","rootUri":"../../../packages/fonts/","packageUri":"lib/"},{"package":"get_it","rootUri":"file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/get_it-9.2.0/","packageUri":"lib/","config":{"name":"get_it","issueTracker":"https://github.com/fluttercommunity/get_it/issues","version":"0.0.1","materialIconCodePoint":"0xe189"}},{"package":"sca_treezor","rootUri":"../../../packages/sca_treezor/","packageUri":"lib/"},{"package":"sf_infrastructure","rootUri":"../../../packages/sf_infrastructure/","packageUri":"lib/"},{"package":"sf_localizations","rootUri":"../../../packages/sf_localizations/","packageUri":"lib/"},{"package":"sf_shared","rootUri":"../../../packages/sf_shared/","packageUri":"lib/"},{"package":"shared_preferences","rootUri":"file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences-2.5.4/","packageUri":"lib/","config":{"name":"shared_preferences","issueTracker":"https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22","version":"1.0.0","materialIconCodePoint":"0xe683"}},{"package":"utils","rootUri":"../../../packages/utils/","packageUri":"lib/"},{"package":"activity","rootUri":"../","packageUri":"lib/"}]}
|
||||
{"version":2,"entries":[{"package":"design_system","rootUri":"../../../packages/design_system/","packageUri":"lib/"},{"package":"flutter_treezor_entrust_sdk_bridge","rootUri":"../../../packages/flutter_treezor_entrust_sdk_bridge/","packageUri":"lib/"},{"package":"fonts","rootUri":"../../../packages/fonts/","packageUri":"lib/"},{"package":"get_it","rootUri":"file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/get_it-9.2.0/","packageUri":"lib/","config":{"name":"get_it","issueTracker":"https://github.com/fluttercommunity/get_it/issues","version":"0.0.1","materialIconCodePoint":"0xe189"}},{"package":"sca_treezor","rootUri":"../../../packages/sca_treezor/","packageUri":"lib/"},{"package":"sf_infrastructure","rootUri":"../../../packages/sf_infrastructure/","packageUri":"lib/"},{"package":"sf_localizations","rootUri":"../../../packages/sf_localizations/","packageUri":"lib/"},{"package":"sf_shared","rootUri":"../../../packages/sf_shared/","packageUri":"lib/"},{"package":"shared_preferences","rootUri":"file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences-2.5.4/","packageUri":"lib/","config":{"name":"shared_preferences","issueTracker":"https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+shared_preferences%22","version":"1.0.0","materialIconCodePoint":"0xe683"}},{"package":"utils","rootUri":"../../../packages/utils/","packageUri":"lib/"},{"package":"activity","rootUri":"../","packageUri":"lib/"}]}
|
||||
@@ -1 +1 @@
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"C:\\\\dev\\\\sf-app-platform\\\\packages\\\\flutter_treezor_entrust_sdk_bridge\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.5.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"C:\\\\dev\\\\sf-app-platform\\\\packages\\\\flutter_treezor_entrust_sdk_bridge\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.22\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.4.20\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.5.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_linux-2.4.1\\\\","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_windows-2.4.1\\\\","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false}],"web":[{"name":"shared_preferences_web","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.4.3\\\\","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"flutter_treezor_entrust_sdk_bridge","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2026-03-16 09:33:25.098373","version":"3.35.6","swift_package_manager_enabled":{"ios":false,"macos":false}}
|
||||
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"C:\\\\dev\\\\sf-app-platform\\\\packages\\\\flutter_treezor_entrust_sdk_bridge\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.5.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"android":[{"name":"flutter_treezor_entrust_sdk_bridge","path":"C:\\\\dev\\\\sf-app-platform\\\\packages\\\\flutter_treezor_entrust_sdk_bridge\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.22\\\\","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_android-2.4.20\\\\","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.5.1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_foundation","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_foundation-2.5.6\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[],"dev_dependency":false}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_linux-2.4.1\\\\","native_build":false,"dependencies":["path_provider_linux"],"dev_dependency":false}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.3.0\\\\","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_windows-2.4.1\\\\","native_build":false,"dependencies":["path_provider_windows"],"dev_dependency":false}],"web":[{"name":"shared_preferences_web","path":"C:\\\\Users\\\\Aitor Arana\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\shared_preferences_web-2.4.3\\\\","dependencies":[],"dev_dependency":false}]},"dependencyGraph":[{"name":"flutter_treezor_entrust_sdk_bridge","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"shared_preferences","dependencies":["shared_preferences_android","shared_preferences_foundation","shared_preferences_linux","shared_preferences_web","shared_preferences_windows"]},{"name":"shared_preferences_android","dependencies":[]},{"name":"shared_preferences_foundation","dependencies":[]},{"name":"shared_preferences_linux","dependencies":["path_provider_linux"]},{"name":"shared_preferences_web","dependencies":[]},{"name":"shared_preferences_windows","dependencies":["path_provider_windows"]}],"date_created":"2026-03-26 13:15:48.703271","version":"3.35.6","swift_package_manager_enabled":{"ios":false,"macos":false}}
|
||||
3
modules/auth/devtools_options.yaml
Normal file
3
modules/auth/devtools_options.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
3
modules/home/devtools_options.yaml
Normal file
3
modules/home/devtools_options.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
||||
@@ -32,6 +32,9 @@
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/legacy_design_system/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/legacy_design_system/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/packages/legacy_design_system/build" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/modules/settings/.dart_tool" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/modules/settings/.pub" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/modules/settings/build" />
|
||||
</content>
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Dart SDK" level="project" />
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:account/src/features/linked_devices/domain/entities/update_device_request_entity.dart';
|
||||
|
||||
abstract class DevicesRemoteDatasource {
|
||||
Future<void> deleteDevice({required String userId, required String deviceId});
|
||||
Future<void> deleteDevice({required String deviceId});
|
||||
|
||||
Future<void> updateDevice({required String userId, required UpdateDeviceRequestEntity request});
|
||||
Future<void> updateDevice({required UpdateDeviceRequestEntity request});
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ class DevicesRemoteDatasourceImpl implements DevicesRemoteDatasource {
|
||||
final QuestiaRepository _repository;
|
||||
|
||||
@override
|
||||
Future<void> deleteDevice({required String userId, required String deviceId}) async {
|
||||
Future<void> deleteDevice({required String deviceId}) async {
|
||||
try {
|
||||
await _repository.delete<void>(
|
||||
'/devices/$deviceId',
|
||||
@@ -23,7 +23,7 @@ class DevicesRemoteDatasourceImpl implements DevicesRemoteDatasource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateDevice({required String userId, required UpdateDeviceRequestEntity request}) async {
|
||||
Future<void> updateDevice({required UpdateDeviceRequestEntity request}) async {
|
||||
try {
|
||||
final body = request.toModel().toJson();
|
||||
await _repository.put<void>(
|
||||
|
||||
@@ -9,12 +9,12 @@ class DevicesRepositoryImpl implements DevicesRepository {
|
||||
final DevicesRemoteDatasource _remote;
|
||||
|
||||
@override
|
||||
Future<void> deleteDevice({required String userId, required String deviceId}) {
|
||||
return _remote.deleteDevice(userId: userId, deviceId: deviceId);
|
||||
Future<void> deleteDevice({required String deviceId}) {
|
||||
return _remote.deleteDevice(deviceId: deviceId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateDevice({required String userId, required UpdateDeviceRequestEntity request}) {
|
||||
return _remote.updateDevice(userId: userId, request: request);
|
||||
Future<void> updateDevice({required UpdateDeviceRequestEntity request}) {
|
||||
return _remote.updateDevice(request: request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import 'package:account/src/features/linked_devices/domain/entities/update_device_request_entity.dart';
|
||||
|
||||
abstract class DevicesRepository {
|
||||
Future<void> deleteDevice({required String userId, required String deviceId});
|
||||
Future<void> deleteDevice({required String deviceId});
|
||||
|
||||
Future<void> updateDevice({
|
||||
required String userId,
|
||||
required UpdateDeviceRequestEntity request
|
||||
});
|
||||
}
|
||||
|
||||
@@ -163,9 +163,10 @@ class AccountSettingsScreen extends ConsumerWidget {
|
||||
onPressed: onPressed,
|
||||
icon: Icon(
|
||||
icon,
|
||||
size: SizeUtils.getByScreen(small: 28, big: 26),
|
||||
size: SizeUtils.getByScreen(small: 36, big: 34),
|
||||
color: color,
|
||||
),
|
||||
iconPadding: SizeUtils.getByScreen(small: 12, big: 14),
|
||||
body: Text(
|
||||
context.translate(text),
|
||||
style: TextStyle(
|
||||
|
||||
@@ -16,6 +16,9 @@ class ChangePasswordScreen extends ConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final password = ref.watch(
|
||||
changePasswordViewModelProvider.select((s)=>s.newPassword)
|
||||
);
|
||||
|
||||
return LegacyPageLayout(
|
||||
theme: theme,
|
||||
@@ -28,11 +31,11 @@ class ChangePasswordScreen extends ConsumerWidget {
|
||||
child: SingleChildScrollView(child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
const _PasswordSection(),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)),
|
||||
const _NewPasswordSection(),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)),
|
||||
const _RepeatPasswordSection(),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)),
|
||||
_PasswordCriteriaList(password: password),
|
||||
const _ErrorMessageSection()
|
||||
],
|
||||
))
|
||||
@@ -42,29 +45,6 @@ class ChangePasswordScreen extends ConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _PasswordSection extends ConsumerWidget {
|
||||
|
||||
const _PasswordSection();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
|
||||
final vm = ref.read(changePasswordViewModelProvider.notifier);
|
||||
final showPassword = ref.watch(
|
||||
changePasswordViewModelProvider.select((s)=>s.showCurrentPassword)
|
||||
);
|
||||
|
||||
return CustomTextField(
|
||||
controller: vm.currentPasswordController,
|
||||
hint: '********',
|
||||
label: context.translate(I18n.password),
|
||||
showPassword: showPassword,
|
||||
onVisibilityChanged: vm.toggleCurrentPasswordVisibility,
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class _NewPasswordSection extends ConsumerWidget {
|
||||
|
||||
const _NewPasswordSection();
|
||||
@@ -111,6 +91,89 @@ class _RepeatPasswordSection extends ConsumerWidget {
|
||||
|
||||
}
|
||||
|
||||
class _PasswordCriteriaList extends StatelessWidget {
|
||||
final String password;
|
||||
|
||||
const _PasswordCriteriaList({required this.password});
|
||||
|
||||
static final _upperRegex = RegExp(r'[A-Z]');
|
||||
static final _digitRegex = RegExp(r'[0-9]');
|
||||
static final _specialRegex =
|
||||
RegExp(r'[!@#$%^&*(),.?":{}|<>\-_+=\[\]\\\/~`]');
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final hasInput = password.isNotEmpty;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 6,
|
||||
children: [
|
||||
_CriteriaRow(
|
||||
label: context.translate(I18n.passwordLength),
|
||||
met: password.length >= 8,
|
||||
hasInput: hasInput,
|
||||
),
|
||||
_CriteriaRow(
|
||||
label: context.translate(I18n.passwordCapital),
|
||||
met: _upperRegex.hasMatch(password),
|
||||
hasInput: hasInput,
|
||||
),
|
||||
_CriteriaRow(
|
||||
label: context.translate(I18n.passwordNumber),
|
||||
met: _digitRegex.hasMatch(password),
|
||||
hasInput: hasInput,
|
||||
),
|
||||
_CriteriaRow(
|
||||
label: context.translate(I18n.passwordSpecial),
|
||||
met: _specialRegex.hasMatch(password),
|
||||
hasInput: hasInput,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CriteriaRow extends StatelessWidget {
|
||||
final String label;
|
||||
final bool met;
|
||||
final bool hasInput;
|
||||
|
||||
const _CriteriaRow({
|
||||
required this.label,
|
||||
required this.met,
|
||||
required this.hasInput,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final Color color;
|
||||
final IconData icon;
|
||||
|
||||
if (!hasInput) {
|
||||
color = Colors.grey;
|
||||
icon = Icons.circle_outlined;
|
||||
} else if (met) {
|
||||
color = Colors.green;
|
||||
icon = Icons.check_circle;
|
||||
} else {
|
||||
color = Colors.red.shade400;
|
||||
icon = Icons.cancel;
|
||||
}
|
||||
|
||||
return Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(icon, size: 16, color: color),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(fontSize: 13, color: color),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ErrorMessageSection extends ConsumerWidget {
|
||||
|
||||
const _ErrorMessageSection();
|
||||
@@ -136,7 +199,9 @@ class _ErrorMessageSection extends ConsumerWidget {
|
||||
),
|
||||
],
|
||||
);
|
||||
} else return SizedBox.shrink();
|
||||
} else {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ NotifierProvider.autoDispose<ChangePasswordViewModel, ChangePasswordViewState>(
|
||||
class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
|
||||
late final ChangePasswordUseCase _changePasswordUseCase;
|
||||
|
||||
late final TextEditingController currentPasswordController;
|
||||
late final TextEditingController newPasswordController;
|
||||
late final TextEditingController repeatPasswordController;
|
||||
late final TextEditingController passwordController;
|
||||
@@ -29,10 +28,6 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
|
||||
}
|
||||
|
||||
void _initControllers() {
|
||||
|
||||
currentPasswordController = TextEditingController();
|
||||
currentPasswordController.addListener(_onCurrentPasswordChanged);
|
||||
|
||||
newPasswordController = TextEditingController();
|
||||
newPasswordController.addListener(_onNewPasswordChanged);
|
||||
|
||||
@@ -60,17 +55,6 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
|
||||
);
|
||||
}
|
||||
|
||||
void _onCurrentPasswordChanged() {
|
||||
final value = currentPasswordController.text;
|
||||
|
||||
if (value == state.currentPassword) return;
|
||||
|
||||
state = state.copyWith(
|
||||
currentPassword: value,
|
||||
errorMessage: ''
|
||||
);
|
||||
}
|
||||
|
||||
void _onNewPasswordChanged() {
|
||||
final value = newPasswordController.text;
|
||||
|
||||
@@ -94,11 +78,14 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
|
||||
}
|
||||
|
||||
bool _validateForm() {
|
||||
if (state.currentPassword.trim().isEmpty){
|
||||
state = state.copyWith(errorMessage: 'errorMessageCurrentPasswordIsEmpty');
|
||||
return false;
|
||||
}
|
||||
if (state.newPassword.trim().isEmpty){
|
||||
final _upperRegex = RegExp(r'[A-Z]');
|
||||
final _digitRegex = RegExp(r'[0-9]');
|
||||
final _specialRegex =
|
||||
RegExp(r'[!@#$%^&*(),.?":{}|<>\-_+=\[\]\\\/~`]');
|
||||
|
||||
final password = state.newPassword.trim();
|
||||
|
||||
if (password.isEmpty){
|
||||
state = state.copyWith(errorMessage: 'errorMessageNewPasswordIsEmpty');
|
||||
return false;
|
||||
}
|
||||
@@ -106,10 +93,26 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
|
||||
state = state.copyWith(errorMessage: 'errorMessageRepeatPasswordIsEmpty');
|
||||
return false;
|
||||
}
|
||||
if (state.newPassword.trim() != state.repeatPassword.trim()){
|
||||
if (password != state.repeatPassword.trim()){
|
||||
state = state.copyWith(errorMessage: 'errorMessagePasswordsDontMatch');
|
||||
return false;
|
||||
}
|
||||
if (password.length < 8){
|
||||
state = state.copyWith(errorMessage: 'errorPasswordMinLength');
|
||||
return false;
|
||||
}
|
||||
if (!_upperRegex.hasMatch(password)) {
|
||||
state = state.copyWith(errorMessage: 'errorPasswordUppercase');
|
||||
return false;
|
||||
}
|
||||
if (!_digitRegex.hasMatch(password)) {
|
||||
state = state.copyWith(errorMessage: 'errorPasswordDigits');
|
||||
return false;
|
||||
}
|
||||
if (!_specialRegex.hasMatch(password)) {
|
||||
state = state.copyWith(errorMessage: 'errorPasswordSpecial');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -155,9 +158,6 @@ class ChangePasswordViewModel extends Notifier<ChangePasswordViewState> {
|
||||
}
|
||||
|
||||
void disposeControllers() {
|
||||
currentPasswordController.removeListener(_onCurrentPasswordChanged);
|
||||
currentPasswordController.dispose();
|
||||
|
||||
newPasswordController.removeListener(_onNewPasswordChanged);
|
||||
newPasswordController.dispose();
|
||||
|
||||
|
||||
@@ -7,10 +7,8 @@ abstract class ChangePasswordViewState with _$ChangePasswordViewState {
|
||||
const factory ChangePasswordViewState({
|
||||
@Default(false) bool isLoading,
|
||||
@Default(false) bool isComplete,
|
||||
@Default(false) bool showCurrentPassword,
|
||||
@Default(false) bool showNewPassword,
|
||||
@Default(false) bool showRepeatedPassword,
|
||||
@Default('') String currentPassword,
|
||||
@Default('') String newPassword,
|
||||
@Default('') String repeatPassword,
|
||||
@Default('') String errorMessage
|
||||
|
||||
@@ -27,28 +27,36 @@ class LinkedDevicesScreen extends ConsumerWidget {
|
||||
title: context.translate(I18n.linkedDevices),
|
||||
showEdit: true,
|
||||
onEditChange: vm.toggleIsEditing,
|
||||
body: ListView.separated(
|
||||
itemBuilder: (BuildContext context, int index)=>_LinkedDeviceCard(
|
||||
device: state.linkedDevices[index],
|
||||
isEditing: state.isEditing,
|
||||
onDelete: ()=>vm.deleteDevice(state.linkedDevices[index]),
|
||||
),
|
||||
separatorBuilder: (BuildContext context, int index)=>SizedBox(
|
||||
height: SizeUtils.getByScreen(small: 18, big: 17)
|
||||
),
|
||||
itemCount: state.linkedDevices.length
|
||||
),
|
||||
body: state.isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: SizeUtils.getByScreen(small: 10, big: 12)),
|
||||
child: ListView.separated(
|
||||
itemBuilder: (BuildContext context, int index)=>_LinkedDeviceCard(
|
||||
navigationContract: navigationContract,
|
||||
device: state.linkedDevices[index],
|
||||
isEditing: state.isEditing,
|
||||
onDelete: ()=>vm.deleteDevice(state.linkedDevices[index]),
|
||||
),
|
||||
separatorBuilder: (BuildContext context, int index)=>SizedBox(
|
||||
height: SizeUtils.getByScreen(small: 18, big: 17)
|
||||
),
|
||||
itemCount: state.linkedDevices.length
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LinkedDeviceCard extends ConsumerWidget {
|
||||
|
||||
final NavigationContract navigationContract;
|
||||
final DeviceEntity device;
|
||||
final bool isEditing;
|
||||
final Function onDelete;
|
||||
|
||||
const _LinkedDeviceCard({
|
||||
required this.navigationContract,
|
||||
required this.device,
|
||||
required this.isEditing,
|
||||
required this.onDelete,
|
||||
@@ -76,7 +84,7 @@ class _LinkedDeviceCard extends ConsumerWidget {
|
||||
shape: BoxShape.circle,
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
),
|
||||
padding: EdgeInsets.all(SizeUtils.getByScreen(small: 4, big: 12)),
|
||||
padding: EdgeInsets.all(SizeUtils.getByScreen(small: 8, big: 12)),
|
||||
child: Icon(SFIcons.watch,
|
||||
size: SizeUtils.getByScreen(small: 40, big: 44),
|
||||
color: theme.getColorFor(ThemeCode.legacyPrimary),
|
||||
@@ -110,7 +118,10 @@ class _LinkedDeviceCard extends ConsumerWidget {
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: (){showDialog(context: context, builder: (context)=>Dialog(
|
||||
child: DeleteDeviceDialog(device: device),
|
||||
child: DeleteDeviceDialog(
|
||||
navigationContract: navigationContract,
|
||||
device: device,
|
||||
),
|
||||
));},
|
||||
icon: Icon(
|
||||
Icons.close,
|
||||
|
||||
@@ -70,19 +70,32 @@ class LinkedDevicesViewModel extends Notifier<LinkedDevicesViewState> {
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> deleteDevice(DeviceEntity device) async {
|
||||
Future<void> deleteDevice(DeviceEntity device) async {
|
||||
try {
|
||||
await _devicesRepository.deleteDevice(userId: state.loggedUser!.id, deviceId: device.identificator);
|
||||
List<DeviceEntity> newList = state.linkedDevices;
|
||||
newList.remove(device);
|
||||
|
||||
state = state.copyWith(
|
||||
linkedDevices: newList
|
||||
isLoading: true,
|
||||
isComplete: false,
|
||||
);
|
||||
|
||||
return true;
|
||||
await _devicesRepository.deleteDevice(deviceId: device.id);
|
||||
List<DeviceEntity> newList = state.linkedDevices.toList();
|
||||
newList.remove(device);
|
||||
|
||||
if (device == state.selectedDevice) {
|
||||
ref.invalidate(selectedDeviceProvider);
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
linkedDevices: newList,
|
||||
isLoading: false,
|
||||
isComplete: true,
|
||||
);
|
||||
} catch (e) {
|
||||
return false;
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: e.toString(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,9 +115,7 @@ class LinkedDevicesViewModel extends Notifier<LinkedDevicesViewState> {
|
||||
if (deviceName.isEmpty) return;
|
||||
|
||||
try {
|
||||
final userId = state.loggedUser!.id;
|
||||
_devicesRepository.updateDevice(
|
||||
userId: userId,
|
||||
request: _toRequest(device));
|
||||
|
||||
} catch(e) {
|
||||
@@ -114,8 +125,6 @@ class LinkedDevicesViewModel extends Notifier<LinkedDevicesViewState> {
|
||||
errorMessage: e.toString()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void disposeControllers() {
|
||||
|
||||
@@ -2,15 +2,20 @@ import 'package:account/src/features/linked_devices/presentation/state/linked_de
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
class DeleteDeviceDialog extends ConsumerWidget {
|
||||
|
||||
final NavigationContract navigationContract;
|
||||
final DeviceEntity device;
|
||||
|
||||
const DeleteDeviceDialog({required this.device});
|
||||
const DeleteDeviceDialog({
|
||||
required this.navigationContract,
|
||||
required this.device
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -21,15 +26,19 @@ class DeleteDeviceDialog extends ConsumerWidget {
|
||||
return Container(
|
||||
padding: SizeUtils.getByScreen(
|
||||
small: EdgeInsets.symmetric(horizontal: 32, vertical: 30),
|
||||
big: EdgeInsets.symmetric(horizontal: 30, vertical: 28)
|
||||
big: EdgeInsets.symmetric(horizontal: 24, vertical: 18)
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
borderRadius: BorderRadius.all(Radius.circular(14))
|
||||
),
|
||||
width: SizeUtils.getByScreen(small: 360, big: 350),
|
||||
height: SizeUtils.getByScreen(small: 195, big: 185),
|
||||
height: SizeUtils.getByScreen(small: 184, big: 160),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(context.translate(I18n.deleteDeviceDialog),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 19, big: 18)),
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 17, big: 16)),
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 28, big: 27)),
|
||||
Row(
|
||||
@@ -46,7 +55,20 @@ class DeleteDeviceDialog extends ConsumerWidget {
|
||||
Expanded(child: PrimaryButton(
|
||||
onPressed: () async {
|
||||
await vm.deleteDevice(device);
|
||||
Navigator.pop(context);
|
||||
|
||||
final isComplete = ref.read(
|
||||
linkedDevicesViewModelProvider.select((s)=>s.isComplete)
|
||||
);
|
||||
if (isComplete) {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
||||
final noMoreDevices = ref.read(
|
||||
linkedDevicesViewModelProvider.select((s)=>s.linkedDevices)
|
||||
).isEmpty;
|
||||
if (noMoreDevices) {
|
||||
navigationContract.goTo(AppRoutes.legacyDeviceSetup);
|
||||
}
|
||||
},
|
||||
text: context.translate(I18n.delete),
|
||||
color: theme.getColorFor(ThemeCode.legacyPrimary),
|
||||
|
||||
@@ -59,11 +59,11 @@ class PersonalDataScreen extends ConsumerWidget {
|
||||
const _ProfilePicture(),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 18, big: 16)),
|
||||
const _EmailLabel(),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 22, big: 20)),
|
||||
const _FirstNameField(),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 22, big: 20)),
|
||||
const _LastNameField(),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 24, big: 22)),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 22, big: 20)),
|
||||
const _PhoneField(),
|
||||
],
|
||||
),
|
||||
@@ -117,7 +117,9 @@ class _EmailLabel extends ConsumerWidget {
|
||||
),
|
||||
Text(
|
||||
email,
|
||||
style: TextStyle(fontSize: SizeUtils.getByScreen(small: 18, big: 17)),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 18, big: 17, xl: 16)
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
export 'src/core/data/models/latest_positions_response_model.dart';
|
||||
export 'src/core/domain/entities/address_entity.dart';
|
||||
export 'src/core/domain/entities/network_entity.dart';
|
||||
export 'src/core/domain/entities/position_entity.dart';
|
||||
export 'src/core/utils/battery_utils.dart';
|
||||
export 'src/core/utils/date_format_utils.dart';
|
||||
export 'src/features/control_panel/control_panel_builder.dart';
|
||||
export 'src/features/control_panel/presentation/state/control_panel_view_model.dart';
|
||||
export 'src/shared/widgets/device_map.dart';
|
||||
@@ -72,11 +72,11 @@ extension LatestPositionsResponseModelMapper on LatestPositionsResponseModel {
|
||||
@freezed
|
||||
abstract class LatestPositionsAddressResponseModel with _$LatestPositionsAddressResponseModel {
|
||||
const factory LatestPositionsAddressResponseModel({
|
||||
required String street,
|
||||
required String city,
|
||||
required String province,
|
||||
required String state,
|
||||
required String country,
|
||||
String? street,
|
||||
String? city,
|
||||
String? province,
|
||||
String? state,
|
||||
String? country,
|
||||
}) = _LatestPositionsAddressResponseModel;
|
||||
|
||||
factory LatestPositionsAddressResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -628,7 +628,7 @@ $LatestPositionsAddressResponseModelCopyWith<$Res>? get address {
|
||||
/// @nodoc
|
||||
mixin _$LatestPositionsAddressResponseModel {
|
||||
|
||||
String get street; String get city; String get province; String get state; String get country;
|
||||
String? get street; String? get city; String? get province; String? get state; String? get country;
|
||||
/// Create a copy of LatestPositionsAddressResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -661,7 +661,7 @@ abstract mixin class $LatestPositionsAddressResponseModelCopyWith<$Res> {
|
||||
factory $LatestPositionsAddressResponseModelCopyWith(LatestPositionsAddressResponseModel value, $Res Function(LatestPositionsAddressResponseModel) _then) = _$LatestPositionsAddressResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String street, String city, String province, String state, String country
|
||||
String? street, String? city, String? province, String? state, String? country
|
||||
});
|
||||
|
||||
|
||||
@@ -678,14 +678,14 @@ class _$LatestPositionsAddressResponseModelCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of LatestPositionsAddressResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? street = null,Object? city = null,Object? province = null,Object? state = null,Object? country = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? street = freezed,Object? city = freezed,Object? province = freezed,Object? state = freezed,Object? country = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
street: null == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String,province: null == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
street: freezed == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String?,city: freezed == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String?,province: freezed == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String?,state: freezed == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String?,country: freezed == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -770,7 +770,7 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String street, String city, String province, String state, String country)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String? street, String? city, String? province, String? state, String? country)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LatestPositionsAddressResponseModel() when $default != null:
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country);case _:
|
||||
@@ -791,7 +791,7 @@ return $default(_that.street,_that.city,_that.province,_that.state,_that.country
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String street, String city, String province, String state, String country) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String? street, String? city, String? province, String? state, String? country) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LatestPositionsAddressResponseModel():
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country);case _:
|
||||
@@ -811,7 +811,7 @@ return $default(_that.street,_that.city,_that.province,_that.state,_that.country
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String street, String city, String province, String state, String country)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String? street, String? city, String? province, String? state, String? country)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _LatestPositionsAddressResponseModel() when $default != null:
|
||||
return $default(_that.street,_that.city,_that.province,_that.state,_that.country);case _:
|
||||
@@ -826,14 +826,14 @@ return $default(_that.street,_that.city,_that.province,_that.state,_that.country
|
||||
@JsonSerializable()
|
||||
|
||||
class _LatestPositionsAddressResponseModel implements LatestPositionsAddressResponseModel {
|
||||
const _LatestPositionsAddressResponseModel({required this.street, required this.city, required this.province, required this.state, required this.country});
|
||||
const _LatestPositionsAddressResponseModel({this.street, this.city, this.province, this.state, this.country});
|
||||
factory _LatestPositionsAddressResponseModel.fromJson(Map<String, dynamic> json) => _$LatestPositionsAddressResponseModelFromJson(json);
|
||||
|
||||
@override final String street;
|
||||
@override final String city;
|
||||
@override final String province;
|
||||
@override final String state;
|
||||
@override final String country;
|
||||
@override final String? street;
|
||||
@override final String? city;
|
||||
@override final String? province;
|
||||
@override final String? state;
|
||||
@override final String? country;
|
||||
|
||||
/// Create a copy of LatestPositionsAddressResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -868,7 +868,7 @@ abstract mixin class _$LatestPositionsAddressResponseModelCopyWith<$Res> impleme
|
||||
factory _$LatestPositionsAddressResponseModelCopyWith(_LatestPositionsAddressResponseModel value, $Res Function(_LatestPositionsAddressResponseModel) _then) = __$LatestPositionsAddressResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String street, String city, String province, String state, String country
|
||||
String? street, String? city, String? province, String? state, String? country
|
||||
});
|
||||
|
||||
|
||||
@@ -885,14 +885,14 @@ class __$LatestPositionsAddressResponseModelCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of LatestPositionsAddressResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? street = null,Object? city = null,Object? province = null,Object? state = null,Object? country = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? street = freezed,Object? city = freezed,Object? province = freezed,Object? state = freezed,Object? country = freezed,}) {
|
||||
return _then(_LatestPositionsAddressResponseModel(
|
||||
street: null == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String,province: null == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String,state: null == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
street: freezed == street ? _self.street : street // ignore: cast_nullable_to_non_nullable
|
||||
as String?,city: freezed == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String?,province: freezed == province ? _self.province : province // ignore: cast_nullable_to_non_nullable
|
||||
as String?,state: freezed == state ? _self.state : state // ignore: cast_nullable_to_non_nullable
|
||||
as String?,country: freezed == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -81,11 +81,11 @@ Map<String, dynamic> _$LatestPositionsItemResponseModelToJson(
|
||||
_LatestPositionsAddressResponseModel
|
||||
_$LatestPositionsAddressResponseModelFromJson(Map<String, dynamic> json) =>
|
||||
_LatestPositionsAddressResponseModel(
|
||||
street: json['street'] as String,
|
||||
city: json['city'] as String,
|
||||
province: json['province'] as String,
|
||||
state: json['state'] as String,
|
||||
country: json['country'] as String,
|
||||
street: json['street'] as String?,
|
||||
city: json['city'] as String?,
|
||||
province: json['province'] as String?,
|
||||
state: json['state'] as String?,
|
||||
country: json['country'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$LatestPositionsAddressResponseModelToJson(
|
||||
|
||||
@@ -254,11 +254,10 @@ class _MapSection extends ConsumerWidget {
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 4, big: 8)),
|
||||
AbsorbPointer(
|
||||
child: SizedBox(
|
||||
height: SizeUtils.getByScreen(small: 200, big: 300),
|
||||
height: SizeUtils.getByScreen(small: 260, big: 300),
|
||||
child: DeviceMap(
|
||||
selectedPosition: state.selectedPosition,
|
||||
selectedDevice: state.selectedDevice,
|
||||
markerSize: 40,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -69,8 +69,9 @@ class ControlPanelViewModel extends Notifier<ControlPanelViewState> {
|
||||
final latestPositions = positionLists
|
||||
.where((list) => list.isNotEmpty)
|
||||
.map((list) {
|
||||
final valid = list.where((p) => p.latitude != 0 || p.longitude != 0);
|
||||
return valid.isNotEmpty ? valid.last : list.last;
|
||||
final valid = list.where((p) => p.latitude != 0 || p.longitude != 0).toList()
|
||||
..sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||
return valid.isNotEmpty ? valid.first : list.last;
|
||||
})
|
||||
.toList();
|
||||
|
||||
@@ -92,6 +93,7 @@ class ControlPanelViewModel extends Notifier<ControlPanelViewState> {
|
||||
|
||||
Future<void> refreshPositions() async {
|
||||
if (state.devices.isEmpty) return;
|
||||
state = state.copyWith(errorMessage: '');
|
||||
try {
|
||||
final positionLists = await Future.wait(
|
||||
state.devices.map(
|
||||
|
||||
@@ -5,25 +5,21 @@ import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
import 'package:legacy_shared/legacy_shared.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
const _defaultCenter = LatLng(40.4168, -3.7038);
|
||||
const _defaultZoom = 15.0;
|
||||
const _tileServerUrl = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png';
|
||||
|
||||
class DeviceMap extends ConsumerStatefulWidget {
|
||||
final PositionEntity? selectedPosition;
|
||||
final DeviceEntity? selectedDevice;
|
||||
final double markerSize;
|
||||
|
||||
const DeviceMap({
|
||||
super.key,
|
||||
required this.selectedPosition,
|
||||
required this.selectedDevice,
|
||||
this.markerSize = 80,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -62,6 +58,8 @@ class _DeviceMapState extends ConsumerState<DeviceMap> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mapStyle = ref.watch(mapStyleProvider);
|
||||
final primaryColor = ref.read(themePortProvider).getColorFor(ThemeCode.legacyPrimary);
|
||||
final initialCenter = widget.selectedPosition != null
|
||||
? LatLng(
|
||||
widget.selectedPosition!.latitude,
|
||||
@@ -78,7 +76,7 @@ class _DeviceMapState extends ConsumerState<DeviceMap> {
|
||||
),
|
||||
children: [
|
||||
TileLayer(
|
||||
urlTemplate: _tileServerUrl,
|
||||
urlTemplate: mapStyle.urlTemplate,
|
||||
userAgentPackageName: 'com.savefamily.sf_platform',
|
||||
),
|
||||
MarkerLayer(
|
||||
@@ -89,15 +87,9 @@ class _DeviceMapState extends ConsumerState<DeviceMap> {
|
||||
widget.selectedPosition!.latitude,
|
||||
widget.selectedPosition!.longitude,
|
||||
),
|
||||
width: widget.markerSize * 2.5,
|
||||
height: widget.markerSize * 1.8,
|
||||
child: Align(
|
||||
alignment: Alignment.topCenter,
|
||||
child: SvgPicture.asset(
|
||||
'assets/shared/images/location.svg',
|
||||
height: widget.markerSize,
|
||||
),
|
||||
),
|
||||
width: 100,
|
||||
height: 100,
|
||||
child: PulsingLocationMarker(color: primaryColor),
|
||||
rotate: true,
|
||||
),
|
||||
],
|
||||
@@ -107,7 +99,7 @@ class _DeviceMapState extends ConsumerState<DeviceMap> {
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: LocationBanner(
|
||||
position: widget.selectedPosition!,
|
||||
battery: widget.selectedDevice?.battery ?? 0,
|
||||
device: widget.selectedDevice,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -117,86 +109,156 @@ class _DeviceMapState extends ConsumerState<DeviceMap> {
|
||||
|
||||
class LocationBanner extends ConsumerWidget {
|
||||
final PositionEntity position;
|
||||
final int battery;
|
||||
final DeviceEntity? device;
|
||||
|
||||
const LocationBanner({
|
||||
super.key,
|
||||
required this.position,
|
||||
required this.battery,
|
||||
this.device,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.read(themePortProvider);
|
||||
final batteryIcon = toBatteryIcon(battery);
|
||||
final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary);
|
||||
final batteryValue = device?.battery ?? 0;
|
||||
final batteryIcon = toBatteryIcon(batteryValue);
|
||||
final dateText = formatPositionDate(position.positionDate);
|
||||
|
||||
final localDevice = device;
|
||||
final name = localDevice?.carrierName;
|
||||
final deviceName = localDevice != null
|
||||
? (name != null && name.isNotEmpty ? name : localDevice.identificator)
|
||||
: null;
|
||||
final initial = deviceName != null && deviceName.isNotEmpty
|
||||
? deviceName[0].toUpperCase()
|
||||
: null;
|
||||
|
||||
final addressText = [
|
||||
position.address?.street,
|
||||
position.address?.province,
|
||||
position.address?.country,
|
||||
].whereType<String>().where((s) => s.isNotEmpty).join(', ');
|
||||
|
||||
return Container(
|
||||
height: SizeUtils.getByScreen(small: 60, big: 58),
|
||||
width: SizeUtils.getByScreen(small: 300, big: 298),
|
||||
margin: EdgeInsets.only(
|
||||
bottom: SizeUtils.getByScreen(small: 20, big: 16),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(SizeUtils.getByScreen(small: 9, big: 8)),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(
|
||||
SFIcons.location,
|
||||
size: SizeUtils.getByScreen(small: 40, big: 38),
|
||||
color: theme.getColorFor(ThemeCode.legacyPrimary),
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final isCompact = constraints.maxWidth < 320;
|
||||
|
||||
return Container(
|
||||
width: isCompact ? constraints.maxWidth * 0.85 : 340,
|
||||
margin: EdgeInsets.only(bottom: isCompact ? 8 : 16),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: isCompact ? 8 : 12,
|
||||
vertical: isCompact ? 6 : 10,
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
addressText,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(isCompact ? 10 : 16),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.1),
|
||||
blurRadius: isCompact ? 6 : 10,
|
||||
offset: const Offset(0, 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
if (initial != null)
|
||||
Container(
|
||||
width: isCompact ? 30 : 42,
|
||||
height: isCompact ? 30 : 42,
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor.withValues(alpha: 0.12),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
initial,
|
||||
style: TextStyle(
|
||||
fontSize: isCompact ? 13 : 18,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
SizedBox(width: isCompact ? 6 : 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
dateText,
|
||||
if (deviceName != null)
|
||||
Text(
|
||||
deviceName,
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 12, big: 11),
|
||||
fontSize: isCompact ? 12 : 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey.shade800,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (position.networks.isNotEmpty)
|
||||
Text(
|
||||
' | ${position.networks.first.signal}',
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 12, big: 11),
|
||||
if (addressText.isNotEmpty)
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: deviceName != null ? 1 : 0),
|
||||
child: Text(
|
||||
addressText,
|
||||
style: TextStyle(
|
||||
fontSize: isCompact ? 9 : 11,
|
||||
color: Colors.grey.shade500,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
Icon(batteryIcon),
|
||||
Text(
|
||||
'$battery%',
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 12, big: 11),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
batteryIcon,
|
||||
size: isCompact ? 13 : 16,
|
||||
color: batteryValue > 20
|
||||
? primaryColor
|
||||
: Colors.orange,
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
Text(
|
||||
'$batteryValue%',
|
||||
style: TextStyle(
|
||||
fontSize: isCompact ? 10 : 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: batteryValue > 20
|
||||
? primaryColor
|
||||
: Colors.orange,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (!isCompact)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 3),
|
||||
child: Text(
|
||||
dateText,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
color: Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -163,7 +163,7 @@ class _MessageSection extends ConsumerWidget {
|
||||
controller: vm.bodyController,
|
||||
keyboardType: TextInputType.multiline,
|
||||
hint: context.translate(I18n.enterMessage),
|
||||
lines: 8,
|
||||
lines: 7,
|
||||
onSubmitted: (_) => onSubmit(),
|
||||
);
|
||||
}
|
||||
@@ -212,7 +212,7 @@ class _SendSection extends ConsumerWidget {
|
||||
return Container(
|
||||
padding: SizeUtils.getByScreen(
|
||||
small: EdgeInsets.symmetric(horizontal: 38, vertical: 14),
|
||||
big: EdgeInsets.symmetric(horizontal: 36, vertical: 12)
|
||||
big: EdgeInsets.symmetric(horizontal: 36, vertical: 10)
|
||||
),
|
||||
child: PrimaryButton(
|
||||
onPressed: onSend,
|
||||
|
||||
@@ -86,7 +86,7 @@ class CustomerServiceScreen extends ConsumerWidget {
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.email_outlined,
|
||||
size: SizeUtils.getByScreen(small: 44, big: 48),
|
||||
size: SizeUtils.getByScreen(small: 46, big: 48),
|
||||
color: theme.getColorFor(ThemeCode.legacyPrimary),
|
||||
weight: 30,
|
||||
),
|
||||
|
||||
@@ -9,4 +9,7 @@ export 'src/features/locate_device/locate_device_builder.dart';
|
||||
export 'src/features/health/health_builder.dart';
|
||||
export 'src/features/rewards/rewards_builder.dart';
|
||||
export 'src/features/activity_meter/activity_meter_builder.dart';
|
||||
export 'src/features/apps_use/apps_use_builder.dart';
|
||||
export 'src/features/apps_use/apps_use_builder.dart';
|
||||
export 'src/features/volume_control/volume_control_builder.dart';
|
||||
export 'src/features/call_history/call_history_builder.dart';
|
||||
export 'src/features/background_image/background_image_builder.dart';
|
||||
@@ -0,0 +1,14 @@
|
||||
import '../models/get_background_image_response_model.dart';
|
||||
|
||||
abstract class BackgroundImageRemoteDatasource {
|
||||
Future<GetBackgroundImageResponseModel> getBackgroundImage();
|
||||
|
||||
Future<String> uploadImage({
|
||||
required String path,
|
||||
});
|
||||
|
||||
Future<void> setBackgroundImage({
|
||||
required String deviceId,
|
||||
required String photoId,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:legacy_shared/legacy_shared.dart';
|
||||
import 'package:sf_infrastructure/configure_dependencies.dart';
|
||||
|
||||
import '../models/get_background_image_response_model.dart';
|
||||
import 'background_image_remote_datasource.dart';
|
||||
|
||||
class BackgroundImageRemoteDatasourceImpl
|
||||
implements BackgroundImageRemoteDatasource {
|
||||
BackgroundImageRemoteDatasourceImpl(this._repository);
|
||||
|
||||
final QuestiaRepository _repository;
|
||||
|
||||
@override
|
||||
Future<GetBackgroundImageResponseModel> getBackgroundImage() async {
|
||||
final response = await safeCall(
|
||||
() => _repository.get<dynamic>('/photos/files'),
|
||||
'Error getting background image',
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || (data is Map && data.isEmpty)) {
|
||||
return const GetBackgroundImageResponseModel(items: []);
|
||||
}
|
||||
|
||||
return GetBackgroundImageResponseModel.fromJson(
|
||||
data is Map<String, dynamic> ? data : data as Map<String, dynamic>,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> uploadImage({required String path}) async {
|
||||
final formData = FormData.fromMap({
|
||||
'file': await MultipartFile.fromFile(path, filename: 'photo.jpg'),
|
||||
});
|
||||
|
||||
final dio = GetIt.I<Dio>();
|
||||
dio.options.headers.remove('content-type');
|
||||
try {
|
||||
final response = await dio.post<dynamic>('/photos', data: formData);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null) {
|
||||
throw Exception('Empty response from upload');
|
||||
}
|
||||
final map = data is Map<String, dynamic> ? data : <String, dynamic>{};
|
||||
final id = map['id'] as String?;
|
||||
if (id == null) {
|
||||
throw Exception('No photo ID in upload response');
|
||||
}
|
||||
return id;
|
||||
} on DioException catch (e) {
|
||||
throw mapDioError(e, defaultMessage: 'Error uploading image');
|
||||
} finally {
|
||||
dio.options.headers['content-type'] = 'application/json';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setBackgroundImage({
|
||||
required String deviceId,
|
||||
required String photoId,
|
||||
}) async {
|
||||
await safeCall(
|
||||
() => _repository.put<dynamic>(
|
||||
'/devices/$deviceId/background-image',
|
||||
body: {'photoId': photoId},
|
||||
),
|
||||
'Error setting background image',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -68,17 +68,31 @@ class ContactsRemoteDatasourceImpl implements ContactsRemoteDatasource {
|
||||
required String deviceId,
|
||||
required List<Map<String, String>> contacts,
|
||||
}) async {
|
||||
await safeCall(
|
||||
() => _repository.post<dynamic>(
|
||||
'/contact-lists',
|
||||
body: {
|
||||
'userId': userId,
|
||||
'deviceId': deviceId,
|
||||
'type': 'secondary',
|
||||
'contacts': contacts,
|
||||
},
|
||||
await Future.wait([
|
||||
safeCall(
|
||||
() => _repository.post<dynamic>(
|
||||
'/contact-lists',
|
||||
body: {
|
||||
'userId': userId,
|
||||
'deviceId': deviceId,
|
||||
'type': 'secondary',
|
||||
'contacts': contacts,
|
||||
},
|
||||
),
|
||||
'Error syncing contacts to device',
|
||||
),
|
||||
'Error syncing contacts to device',
|
||||
);
|
||||
safeCall(
|
||||
() => _repository.post<dynamic>(
|
||||
'/contact-lists',
|
||||
body: {
|
||||
'userId': userId,
|
||||
'deviceId': deviceId,
|
||||
'type': 'white',
|
||||
'contacts': contacts,
|
||||
},
|
||||
),
|
||||
'Error syncing whitelist to device',
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
|
||||
abstract class FunctionsRemoteDatasource {
|
||||
Future<List<PictureEntity>> getPictures({required String userId});
|
||||
|
||||
Future<PictureEntity> takePicture({required String userId});
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
import 'package:device_management/src/core/data/datasources/functions_remote_datasource.dart';
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
class FunctionsRemoteDatasourceImpl implements FunctionsRemoteDatasource {
|
||||
FunctionsRemoteDatasourceImpl(this._repository);
|
||||
|
||||
final QuestiaRepository _repository;
|
||||
|
||||
@override
|
||||
Future<List<PictureEntity>> getPictures({required String userId}) async {
|
||||
/*try {
|
||||
final response = await _repository.get<Map<String, dynamic>>(
|
||||
'',
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || data.isEmpty) {
|
||||
throw Exception('Empty response from /users/:userId/contacts');
|
||||
}
|
||||
|
||||
final model = GetPicturesResponseModel.fromJson(data);
|
||||
return model.toEntity();
|
||||
} on DioException catch (error) {
|
||||
throw mapDioError(error, defaultMessage: 'Error to get pictures');
|
||||
}*/
|
||||
return [];
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PictureEntity> takePicture({required String userId}) async {
|
||||
/*try {
|
||||
final response = await _repository.get<Map<String, dynamic>>(
|
||||
'',
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || data.isEmpty) {
|
||||
throw Exception('Empty response from /users/:userId/contacts');
|
||||
}
|
||||
|
||||
final model = GetContactsResponseModel.fromJson(data);
|
||||
return model.toEntity();
|
||||
} on DioException catch (error) {
|
||||
throw mapDioError(error, defaultMessage: 'Error to get contacts');
|
||||
}*/
|
||||
return PictureEntity(
|
||||
id: '1',
|
||||
deviceId: '1111',
|
||||
createdAt: DateTime.now(),
|
||||
takenAt: DateTime.now(),
|
||||
asset: 'assets/shared/images/iso_sf.png',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ class HealthQueryBuilder {
|
||||
String orderField = 'occurredAt',
|
||||
}) {
|
||||
final orderBy = base64Encode(
|
||||
utf8.encode('[{"field":"$orderField","order":"${orderDirection.value}"}]'),
|
||||
utf8.encode('[{"field":"$orderField","sortDirection":"${orderDirection.value}"}]'),
|
||||
);
|
||||
|
||||
final params = <String, dynamic>{'orderBy': orderBy};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
|
||||
abstract class PicturesRemoteDatasource {
|
||||
Future<List<PictureEntity>> getPictures({required String deviceId});
|
||||
|
||||
Future<PictureEntity> takePicture({required String deviceId});
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import 'package:device_management/src/core/data/datasources/pictures_remote_datasource.dart';
|
||||
import 'package:device_management/src/core/data/models/get_pictures_response_model.dart';
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:legacy_shared/legacy_shared.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
class PicturesRemoteDatasourceImpl implements PicturesRemoteDatasource {
|
||||
PicturesRemoteDatasourceImpl(this._repository);
|
||||
|
||||
final QuestiaRepository _repository;
|
||||
|
||||
@override
|
||||
Future<List<PictureEntity>> getPictures({required String deviceId}) async {
|
||||
try {
|
||||
final response = await _repository.get<Map<String, dynamic>>(
|
||||
'/devices/identificator/$deviceId/photos/files',
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || data.isEmpty) {
|
||||
return [];
|
||||
}
|
||||
|
||||
final model = GetPicturesResponseModel.fromJson(data);
|
||||
return model.toEntity();
|
||||
} on DioException catch (error) {
|
||||
if (error.response?.statusCode == 404) return [];
|
||||
throw mapDioError(error, defaultMessage: 'Error getting pictures');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PictureEntity> takePicture({required String deviceId}) async {
|
||||
throw UnimplementedError('takePicture is handled via commands');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'get_pictures_response_model.dart';
|
||||
|
||||
part 'get_background_image_response_model.freezed.dart';
|
||||
part 'get_background_image_response_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class GetBackgroundImageResponseModel with _$GetBackgroundImageResponseModel {
|
||||
const factory GetBackgroundImageResponseModel({
|
||||
@Default([]) List<GetPicturesItemResponseModel> items,
|
||||
@Default(0) int total,
|
||||
@Default(1) int page,
|
||||
@Default(1) int pages,
|
||||
}) = _GetBackgroundImageResponseModel;
|
||||
|
||||
factory GetBackgroundImageResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$GetBackgroundImageResponseModelFromJson(json);
|
||||
}
|
||||
|
||||
extension GetBackgroundImageResponseModelMapper on GetBackgroundImageResponseModel {
|
||||
List<PictureEntity> toEntities() {
|
||||
return items
|
||||
.map((item) => PictureEntity(
|
||||
id: item.id,
|
||||
deviceIdentificator: item.deviceIdentificator,
|
||||
imgType: item.imgType,
|
||||
timestamp: item.timestamp,
|
||||
fileId: item.fileId,
|
||||
fileName: item.fileName,
|
||||
contentType: item.contentType,
|
||||
createdAt: item.createdAt,
|
||||
fileBytes: extractFileBytes(item.file),
|
||||
))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'get_background_image_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$GetBackgroundImageResponseModel {
|
||||
|
||||
List<GetPicturesItemResponseModel> get items; int get total; int get page; int get pages;
|
||||
/// Create a copy of GetBackgroundImageResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$GetBackgroundImageResponseModelCopyWith<GetBackgroundImageResponseModel> get copyWith => _$GetBackgroundImageResponseModelCopyWithImpl<GetBackgroundImageResponseModel>(this as GetBackgroundImageResponseModel, _$identity);
|
||||
|
||||
/// Serializes this GetBackgroundImageResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is GetBackgroundImageResponseModel&&const DeepCollectionEquality().equals(other.items, items)&&(identical(other.total, total) || other.total == total)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(items),total,page,pages);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GetBackgroundImageResponseModel(items: $items, total: $total, page: $page, pages: $pages)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $GetBackgroundImageResponseModelCopyWith<$Res> {
|
||||
factory $GetBackgroundImageResponseModelCopyWith(GetBackgroundImageResponseModel value, $Res Function(GetBackgroundImageResponseModel) _then) = _$GetBackgroundImageResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
List<GetPicturesItemResponseModel> items, int total, int page, int pages
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$GetBackgroundImageResponseModelCopyWithImpl<$Res>
|
||||
implements $GetBackgroundImageResponseModelCopyWith<$Res> {
|
||||
_$GetBackgroundImageResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final GetBackgroundImageResponseModel _self;
|
||||
final $Res Function(GetBackgroundImageResponseModel) _then;
|
||||
|
||||
/// Create a copy of GetBackgroundImageResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? items = null,Object? total = null,Object? page = null,Object? pages = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<GetPicturesItemResponseModel>,total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable
|
||||
as int,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable
|
||||
as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [GetBackgroundImageResponseModel].
|
||||
extension GetBackgroundImageResponseModelPatterns on GetBackgroundImageResponseModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _GetBackgroundImageResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetBackgroundImageResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _GetBackgroundImageResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetBackgroundImageResponseModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _GetBackgroundImageResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetBackgroundImageResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<GetPicturesItemResponseModel> items, int total, int page, int pages)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetBackgroundImageResponseModel() when $default != null:
|
||||
return $default(_that.items,_that.total,_that.page,_that.pages);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<GetPicturesItemResponseModel> items, int total, int page, int pages) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetBackgroundImageResponseModel():
|
||||
return $default(_that.items,_that.total,_that.page,_that.pages);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<GetPicturesItemResponseModel> items, int total, int page, int pages)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetBackgroundImageResponseModel() when $default != null:
|
||||
return $default(_that.items,_that.total,_that.page,_that.pages);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _GetBackgroundImageResponseModel implements GetBackgroundImageResponseModel {
|
||||
const _GetBackgroundImageResponseModel({final List<GetPicturesItemResponseModel> items = const [], this.total = 0, this.page = 1, this.pages = 1}): _items = items;
|
||||
factory _GetBackgroundImageResponseModel.fromJson(Map<String, dynamic> json) => _$GetBackgroundImageResponseModelFromJson(json);
|
||||
|
||||
final List<GetPicturesItemResponseModel> _items;
|
||||
@override@JsonKey() List<GetPicturesItemResponseModel> get items {
|
||||
if (_items is EqualUnmodifiableListView) return _items;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_items);
|
||||
}
|
||||
|
||||
@override@JsonKey() final int total;
|
||||
@override@JsonKey() final int page;
|
||||
@override@JsonKey() final int pages;
|
||||
|
||||
/// Create a copy of GetBackgroundImageResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$GetBackgroundImageResponseModelCopyWith<_GetBackgroundImageResponseModel> get copyWith => __$GetBackgroundImageResponseModelCopyWithImpl<_GetBackgroundImageResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$GetBackgroundImageResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetBackgroundImageResponseModel&&const DeepCollectionEquality().equals(other._items, _items)&&(identical(other.total, total) || other.total == total)&&(identical(other.page, page) || other.page == page)&&(identical(other.pages, pages) || other.pages == pages));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_items),total,page,pages);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GetBackgroundImageResponseModel(items: $items, total: $total, page: $page, pages: $pages)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$GetBackgroundImageResponseModelCopyWith<$Res> implements $GetBackgroundImageResponseModelCopyWith<$Res> {
|
||||
factory _$GetBackgroundImageResponseModelCopyWith(_GetBackgroundImageResponseModel value, $Res Function(_GetBackgroundImageResponseModel) _then) = __$GetBackgroundImageResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
List<GetPicturesItemResponseModel> items, int total, int page, int pages
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$GetBackgroundImageResponseModelCopyWithImpl<$Res>
|
||||
implements _$GetBackgroundImageResponseModelCopyWith<$Res> {
|
||||
__$GetBackgroundImageResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _GetBackgroundImageResponseModel _self;
|
||||
final $Res Function(_GetBackgroundImageResponseModel) _then;
|
||||
|
||||
/// Create a copy of GetBackgroundImageResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? items = null,Object? total = null,Object? page = null,Object? pages = null,}) {
|
||||
return _then(_GetBackgroundImageResponseModel(
|
||||
items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<GetPicturesItemResponseModel>,total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable
|
||||
as int,page: null == page ? _self.page : page // ignore: cast_nullable_to_non_nullable
|
||||
as int,pages: null == pages ? _self.pages : pages // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,33 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'get_background_image_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_GetBackgroundImageResponseModel _$GetBackgroundImageResponseModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _GetBackgroundImageResponseModel(
|
||||
items:
|
||||
(json['items'] as List<dynamic>?)
|
||||
?.map(
|
||||
(e) => GetPicturesItemResponseModel.fromJson(
|
||||
e as Map<String, dynamic>,
|
||||
),
|
||||
)
|
||||
.toList() ??
|
||||
const [],
|
||||
total: (json['total'] as num?)?.toInt() ?? 0,
|
||||
page: (json['page'] as num?)?.toInt() ?? 1,
|
||||
pages: (json['pages'] as num?)?.toInt() ?? 1,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$GetBackgroundImageResponseModelToJson(
|
||||
_GetBackgroundImageResponseModel instance,
|
||||
) => <String, dynamic>{
|
||||
'items': instance.items,
|
||||
'total': instance.total,
|
||||
'page': instance.page,
|
||||
'pages': instance.pages,
|
||||
};
|
||||
@@ -0,0 +1,74 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'get_pictures_response_model.freezed.dart';
|
||||
part 'get_pictures_response_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class GetPicturesResponseModel with _$GetPicturesResponseModel {
|
||||
const factory GetPicturesResponseModel({
|
||||
required List<GetPicturesItemResponseModel> items,
|
||||
}) = _GetPicturesResponseModel;
|
||||
|
||||
factory GetPicturesResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$GetPicturesResponseModelFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class GetPicturesItemResponseModel
|
||||
with _$GetPicturesItemResponseModel {
|
||||
const factory GetPicturesItemResponseModel({
|
||||
required String id,
|
||||
@Default('') String deviceIdentificator,
|
||||
String? imgType,
|
||||
String? timestamp,
|
||||
@Default('') String fileId,
|
||||
String? fileName,
|
||||
String? contentType,
|
||||
@Default(0) int createdAt,
|
||||
Map<String, dynamic>? file,
|
||||
}) = _GetPicturesItemResponseModel;
|
||||
|
||||
factory GetPicturesItemResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$GetPicturesItemResponseModelFromJson(json);
|
||||
}
|
||||
|
||||
Uint8List? extractFileBytes(Map<String, dynamic>? file) {
|
||||
if (file == null) return null;
|
||||
final fileData = file['file'];
|
||||
if (fileData is String) {
|
||||
try {
|
||||
return base64Decode(fileData);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (fileData is Map) {
|
||||
final data = fileData['data'];
|
||||
if (data is List) {
|
||||
return Uint8List.fromList(data.cast<int>());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
extension GetPicturesResponseModelMapper on GetPicturesResponseModel {
|
||||
List<PictureEntity> toEntity() {
|
||||
return items
|
||||
.map((item) => PictureEntity(
|
||||
id: item.id,
|
||||
deviceIdentificator: item.deviceIdentificator,
|
||||
imgType: item.imgType,
|
||||
timestamp: item.timestamp,
|
||||
fileId: item.fileId,
|
||||
fileName: item.fileName,
|
||||
contentType: item.contentType,
|
||||
createdAt: item.createdAt,
|
||||
fileBytes: extractFileBytes(item.file),
|
||||
))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,578 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'get_pictures_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$GetPicturesResponseModel {
|
||||
|
||||
List<GetPicturesItemResponseModel> get items;
|
||||
/// Create a copy of GetPicturesResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$GetPicturesResponseModelCopyWith<GetPicturesResponseModel> get copyWith => _$GetPicturesResponseModelCopyWithImpl<GetPicturesResponseModel>(this as GetPicturesResponseModel, _$identity);
|
||||
|
||||
/// Serializes this GetPicturesResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is GetPicturesResponseModel&&const DeepCollectionEquality().equals(other.items, items));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(items));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GetPicturesResponseModel(items: $items)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $GetPicturesResponseModelCopyWith<$Res> {
|
||||
factory $GetPicturesResponseModelCopyWith(GetPicturesResponseModel value, $Res Function(GetPicturesResponseModel) _then) = _$GetPicturesResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
List<GetPicturesItemResponseModel> items
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$GetPicturesResponseModelCopyWithImpl<$Res>
|
||||
implements $GetPicturesResponseModelCopyWith<$Res> {
|
||||
_$GetPicturesResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final GetPicturesResponseModel _self;
|
||||
final $Res Function(GetPicturesResponseModel) _then;
|
||||
|
||||
/// Create a copy of GetPicturesResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? items = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<GetPicturesItemResponseModel>,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [GetPicturesResponseModel].
|
||||
extension GetPicturesResponseModelPatterns on GetPicturesResponseModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _GetPicturesResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _GetPicturesResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesResponseModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _GetPicturesResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<GetPicturesItemResponseModel> items)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesResponseModel() when $default != null:
|
||||
return $default(_that.items);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<GetPicturesItemResponseModel> items) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesResponseModel():
|
||||
return $default(_that.items);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<GetPicturesItemResponseModel> items)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesResponseModel() when $default != null:
|
||||
return $default(_that.items);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _GetPicturesResponseModel implements GetPicturesResponseModel {
|
||||
const _GetPicturesResponseModel({required final List<GetPicturesItemResponseModel> items}): _items = items;
|
||||
factory _GetPicturesResponseModel.fromJson(Map<String, dynamic> json) => _$GetPicturesResponseModelFromJson(json);
|
||||
|
||||
final List<GetPicturesItemResponseModel> _items;
|
||||
@override List<GetPicturesItemResponseModel> get items {
|
||||
if (_items is EqualUnmodifiableListView) return _items;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_items);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of GetPicturesResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$GetPicturesResponseModelCopyWith<_GetPicturesResponseModel> get copyWith => __$GetPicturesResponseModelCopyWithImpl<_GetPicturesResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$GetPicturesResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetPicturesResponseModel&&const DeepCollectionEquality().equals(other._items, _items));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_items));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GetPicturesResponseModel(items: $items)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$GetPicturesResponseModelCopyWith<$Res> implements $GetPicturesResponseModelCopyWith<$Res> {
|
||||
factory _$GetPicturesResponseModelCopyWith(_GetPicturesResponseModel value, $Res Function(_GetPicturesResponseModel) _then) = __$GetPicturesResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
List<GetPicturesItemResponseModel> items
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$GetPicturesResponseModelCopyWithImpl<$Res>
|
||||
implements _$GetPicturesResponseModelCopyWith<$Res> {
|
||||
__$GetPicturesResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _GetPicturesResponseModel _self;
|
||||
final $Res Function(_GetPicturesResponseModel) _then;
|
||||
|
||||
/// Create a copy of GetPicturesResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? items = null,}) {
|
||||
return _then(_GetPicturesResponseModel(
|
||||
items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<GetPicturesItemResponseModel>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$GetPicturesItemResponseModel {
|
||||
|
||||
String get id; String get deviceIdentificator; String? get imgType; String? get timestamp; String get fileId; String? get fileName; String? get contentType; int get createdAt; Map<String, dynamic>? get file;
|
||||
/// Create a copy of GetPicturesItemResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$GetPicturesItemResponseModelCopyWith<GetPicturesItemResponseModel> get copyWith => _$GetPicturesItemResponseModelCopyWithImpl<GetPicturesItemResponseModel>(this as GetPicturesItemResponseModel, _$identity);
|
||||
|
||||
/// Serializes this GetPicturesItemResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is GetPicturesItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.imgType, imgType) || other.imgType == imgType)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp)&&(identical(other.fileId, fileId) || other.fileId == fileId)&&(identical(other.fileName, fileName) || other.fileName == fileName)&&(identical(other.contentType, contentType) || other.contentType == contentType)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&const DeepCollectionEquality().equals(other.file, file));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,imgType,timestamp,fileId,fileName,contentType,createdAt,const DeepCollectionEquality().hash(file));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GetPicturesItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, imgType: $imgType, timestamp: $timestamp, fileId: $fileId, fileName: $fileName, contentType: $contentType, createdAt: $createdAt, file: $file)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $GetPicturesItemResponseModelCopyWith<$Res> {
|
||||
factory $GetPicturesItemResponseModelCopyWith(GetPicturesItemResponseModel value, $Res Function(GetPicturesItemResponseModel) _then) = _$GetPicturesItemResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String deviceIdentificator, String? imgType, String? timestamp, String fileId, String? fileName, String? contentType, int createdAt, Map<String, dynamic>? file
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$GetPicturesItemResponseModelCopyWithImpl<$Res>
|
||||
implements $GetPicturesItemResponseModelCopyWith<$Res> {
|
||||
_$GetPicturesItemResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final GetPicturesItemResponseModel _self;
|
||||
final $Res Function(GetPicturesItemResponseModel) _then;
|
||||
|
||||
/// Create a copy of GetPicturesItemResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? deviceIdentificator = null,Object? imgType = freezed,Object? timestamp = freezed,Object? fileId = null,Object? fileName = freezed,Object? contentType = freezed,Object? createdAt = null,Object? file = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable
|
||||
as String,imgType: freezed == imgType ? _self.imgType : imgType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,timestamp: freezed == timestamp ? _self.timestamp : timestamp // ignore: cast_nullable_to_non_nullable
|
||||
as String?,fileId: null == fileId ? _self.fileId : fileId // ignore: cast_nullable_to_non_nullable
|
||||
as String,fileName: freezed == fileName ? _self.fileName : fileName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,file: freezed == file ? _self.file : file // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [GetPicturesItemResponseModel].
|
||||
extension GetPicturesItemResponseModelPatterns on GetPicturesItemResponseModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _GetPicturesItemResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesItemResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _GetPicturesItemResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesItemResponseModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _GetPicturesItemResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesItemResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String deviceIdentificator, String? imgType, String? timestamp, String fileId, String? fileName, String? contentType, int createdAt, Map<String, dynamic>? file)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesItemResponseModel() when $default != null:
|
||||
return $default(_that.id,_that.deviceIdentificator,_that.imgType,_that.timestamp,_that.fileId,_that.fileName,_that.contentType,_that.createdAt,_that.file);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String deviceIdentificator, String? imgType, String? timestamp, String fileId, String? fileName, String? contentType, int createdAt, Map<String, dynamic>? file) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesItemResponseModel():
|
||||
return $default(_that.id,_that.deviceIdentificator,_that.imgType,_that.timestamp,_that.fileId,_that.fileName,_that.contentType,_that.createdAt,_that.file);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String deviceIdentificator, String? imgType, String? timestamp, String fileId, String? fileName, String? contentType, int createdAt, Map<String, dynamic>? file)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GetPicturesItemResponseModel() when $default != null:
|
||||
return $default(_that.id,_that.deviceIdentificator,_that.imgType,_that.timestamp,_that.fileId,_that.fileName,_that.contentType,_that.createdAt,_that.file);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _GetPicturesItemResponseModel implements GetPicturesItemResponseModel {
|
||||
const _GetPicturesItemResponseModel({required this.id, this.deviceIdentificator = '', this.imgType, this.timestamp, this.fileId = '', this.fileName, this.contentType, this.createdAt = 0, final Map<String, dynamic>? file}): _file = file;
|
||||
factory _GetPicturesItemResponseModel.fromJson(Map<String, dynamic> json) => _$GetPicturesItemResponseModelFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override@JsonKey() final String deviceIdentificator;
|
||||
@override final String? imgType;
|
||||
@override final String? timestamp;
|
||||
@override@JsonKey() final String fileId;
|
||||
@override final String? fileName;
|
||||
@override final String? contentType;
|
||||
@override@JsonKey() final int createdAt;
|
||||
final Map<String, dynamic>? _file;
|
||||
@override Map<String, dynamic>? get file {
|
||||
final value = _file;
|
||||
if (value == null) return null;
|
||||
if (_file is EqualUnmodifiableMapView) return _file;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(value);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of GetPicturesItemResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$GetPicturesItemResponseModelCopyWith<_GetPicturesItemResponseModel> get copyWith => __$GetPicturesItemResponseModelCopyWithImpl<_GetPicturesItemResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$GetPicturesItemResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GetPicturesItemResponseModel&&(identical(other.id, id) || other.id == id)&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.imgType, imgType) || other.imgType == imgType)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp)&&(identical(other.fileId, fileId) || other.fileId == fileId)&&(identical(other.fileName, fileName) || other.fileName == fileName)&&(identical(other.contentType, contentType) || other.contentType == contentType)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&const DeepCollectionEquality().equals(other._file, _file));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,imgType,timestamp,fileId,fileName,contentType,createdAt,const DeepCollectionEquality().hash(_file));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GetPicturesItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, imgType: $imgType, timestamp: $timestamp, fileId: $fileId, fileName: $fileName, contentType: $contentType, createdAt: $createdAt, file: $file)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$GetPicturesItemResponseModelCopyWith<$Res> implements $GetPicturesItemResponseModelCopyWith<$Res> {
|
||||
factory _$GetPicturesItemResponseModelCopyWith(_GetPicturesItemResponseModel value, $Res Function(_GetPicturesItemResponseModel) _then) = __$GetPicturesItemResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String deviceIdentificator, String? imgType, String? timestamp, String fileId, String? fileName, String? contentType, int createdAt, Map<String, dynamic>? file
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$GetPicturesItemResponseModelCopyWithImpl<$Res>
|
||||
implements _$GetPicturesItemResponseModelCopyWith<$Res> {
|
||||
__$GetPicturesItemResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _GetPicturesItemResponseModel _self;
|
||||
final $Res Function(_GetPicturesItemResponseModel) _then;
|
||||
|
||||
/// Create a copy of GetPicturesItemResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? deviceIdentificator = null,Object? imgType = freezed,Object? timestamp = freezed,Object? fileId = null,Object? fileName = freezed,Object? contentType = freezed,Object? createdAt = null,Object? file = freezed,}) {
|
||||
return _then(_GetPicturesItemResponseModel(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable
|
||||
as String,imgType: freezed == imgType ? _self.imgType : imgType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,timestamp: freezed == timestamp ? _self.timestamp : timestamp // ignore: cast_nullable_to_non_nullable
|
||||
as String?,fileId: null == fileId ? _self.fileId : fileId // ignore: cast_nullable_to_non_nullable
|
||||
as String,fileName: freezed == fileName ? _self.fileName : fileName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,file: freezed == file ? _self._file : file // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,49 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'get_pictures_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_GetPicturesResponseModel _$GetPicturesResponseModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _GetPicturesResponseModel(
|
||||
items: (json['items'] as List<dynamic>)
|
||||
.map(
|
||||
(e) => GetPicturesItemResponseModel.fromJson(e as Map<String, dynamic>),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$GetPicturesResponseModelToJson(
|
||||
_GetPicturesResponseModel instance,
|
||||
) => <String, dynamic>{'items': instance.items};
|
||||
|
||||
_GetPicturesItemResponseModel _$GetPicturesItemResponseModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _GetPicturesItemResponseModel(
|
||||
id: json['id'] as String,
|
||||
deviceIdentificator: json['deviceIdentificator'] as String? ?? '',
|
||||
imgType: json['imgType'] as String?,
|
||||
timestamp: json['timestamp'] as String?,
|
||||
fileId: json['fileId'] as String? ?? '',
|
||||
fileName: json['fileName'] as String?,
|
||||
contentType: json['contentType'] as String?,
|
||||
createdAt: (json['createdAt'] as num?)?.toInt() ?? 0,
|
||||
file: json['file'] as Map<String, dynamic>?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$GetPicturesItemResponseModelToJson(
|
||||
_GetPicturesItemResponseModel instance,
|
||||
) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'deviceIdentificator': instance.deviceIdentificator,
|
||||
'imgType': instance.imgType,
|
||||
'timestamp': instance.timestamp,
|
||||
'fileId': instance.fileId,
|
||||
'fileName': instance.fileName,
|
||||
'contentType': instance.contentType,
|
||||
'createdAt': instance.createdAt,
|
||||
'file': instance.file,
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
import 'package:device_management/src/core/data/models/get_background_image_response_model.dart';
|
||||
|
||||
import '../../../features/remote_connection/domain/entities/picture_entity.dart';
|
||||
import '../../domain/repositories/background_image_repository.dart';
|
||||
import '../datasources/background_image_remote_datasource.dart';
|
||||
|
||||
class BackgroundImageRepositoryImpl implements BackgroundImageRepository {
|
||||
const BackgroundImageRepositoryImpl(this._remote);
|
||||
|
||||
final BackgroundImageRemoteDatasource _remote;
|
||||
|
||||
@override
|
||||
Future<List<PictureEntity>> getPhotos() async {
|
||||
final model = await _remote.getBackgroundImage();
|
||||
return model.toEntities();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<String> uploadImage({required String path}) {
|
||||
return _remote.uploadImage(path: path);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setBackgroundImage({required String deviceId, required String photoId}) {
|
||||
return _remote.setBackgroundImage(deviceId: deviceId, photoId: photoId);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import 'package:device_management/src/core/data/datasources/functions_remote_datasource.dart';
|
||||
import 'package:device_management/src/core/domain/repositories/functions_repository.dart';
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
|
||||
class FunctionsRepositoryImpl implements FunctionsRepository {
|
||||
const FunctionsRepositoryImpl(this._remote);
|
||||
|
||||
final FunctionsRemoteDatasource _remote;
|
||||
|
||||
@override
|
||||
Future<List<PictureEntity>> getPictures({required String userId}) async {
|
||||
await Future<void>.delayed(const Duration(milliseconds: 2000));
|
||||
return _remote.getPictures(userId: userId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PictureEntity> takePicture({required String userId}) async {
|
||||
await Future<void>.delayed(const Duration(milliseconds: 2000));
|
||||
return _remote.takePicture(userId: userId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
|
||||
import '../../domain/repositories/pictures_repository.dart';
|
||||
import '../datasources/pictures_remote_datasource.dart';
|
||||
|
||||
class PicturesRepositoryImpl implements PicturesRepository {
|
||||
const PicturesRepositoryImpl(this._remote);
|
||||
|
||||
final PicturesRemoteDatasource _remote;
|
||||
|
||||
@override
|
||||
Future<List<PictureEntity>> getPictures({required String deviceId}) {
|
||||
return _remote.getPictures(deviceId: deviceId);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<PictureEntity> takePicture({required String deviceId}) {
|
||||
return _remote.takePicture(deviceId: deviceId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
|
||||
abstract class BackgroundImageRepository {
|
||||
Future<List<PictureEntity>> getPhotos();
|
||||
Future<String> uploadImage({required String path});
|
||||
Future<void> setBackgroundImage({required String deviceId, required String photoId});
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
|
||||
abstract class FunctionsRepository {
|
||||
Future<List<PictureEntity>> getPictures({required String userId});
|
||||
|
||||
Future<PictureEntity> takePicture({required String userId});
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
|
||||
abstract class PicturesRepository {
|
||||
Future<List<PictureEntity>> getPictures({required String deviceId});
|
||||
|
||||
Future<PictureEntity> takePicture({required String deviceId});
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
import '../data/datasources/background_image_remote_datasource.dart';
|
||||
import '../data/datasources/background_image_remote_datasource_impl.dart';
|
||||
|
||||
final backgroundImageRemoteDatasourceProvider =
|
||||
Provider<BackgroundImageRemoteDatasource>((ref) {
|
||||
final questiaRepository = getIt<QuestiaRepository>();
|
||||
return BackgroundImageRemoteDatasourceImpl(questiaRepository);
|
||||
});
|
||||
@@ -0,0 +1,11 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../data/repositories/background_image_repository_impl.dart';
|
||||
import '../domain/repositories/background_image_repository.dart';
|
||||
import 'background_image_remote_datasource_provider.dart';
|
||||
|
||||
final backgroundImageRepositoryProvider =
|
||||
Provider<BackgroundImageRepository>((ref) {
|
||||
final remote = ref.read(backgroundImageRemoteDatasourceProvider);
|
||||
return BackgroundImageRepositoryImpl(remote);
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:device_management/src/core/data/datasources/functions_remote_datasource.dart';
|
||||
import 'package:device_management/src/core/data/datasources/functions_remote_datasource_impl.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
final functionsRemoteDatasourceProvider = Provider<FunctionsRemoteDatasource>((ref) {
|
||||
final questiaRepository = getIt<QuestiaRepository>();
|
||||
return FunctionsRemoteDatasourceImpl(questiaRepository);
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:device_management/src/core/providers/functions_remote_datasource_provider.dart';
|
||||
import 'package:device_management/src/core/data/repositories/functions_repository_impl.dart';
|
||||
import 'package:device_management/src/core/domain/repositories/functions_repository.dart';
|
||||
|
||||
final functionsRepositoryProvider = Provider<FunctionsRepository>((ref) {
|
||||
final remote = ref.read(functionsRemoteDatasourceProvider);
|
||||
return FunctionsRepositoryImpl(remote);
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
import '../data/datasources/pictures_remote_datasource.dart';
|
||||
import '../data/datasources/pictures_remote_datasource_impl.dart';
|
||||
|
||||
final picturesRemoteDatasourceProvider = Provider<PicturesRemoteDatasource>((ref) {
|
||||
final questiaRepository = getIt<QuestiaRepository>();
|
||||
return PicturesRemoteDatasourceImpl(questiaRepository);
|
||||
});
|
||||
@@ -0,0 +1,10 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../data/repositories/pictures_repository_impl.dart';
|
||||
import '../domain/repositories/pictures_repository.dart';
|
||||
import 'pictures_remote_datasource_provider.dart';
|
||||
|
||||
final picturesRepositoryProvider = Provider<PicturesRepository>((ref) {
|
||||
final remote = ref.read(picturesRemoteDatasourceProvider);
|
||||
return PicturesRepositoryImpl(remote);
|
||||
});
|
||||
@@ -7,6 +7,7 @@ import 'package:utils/utils.dart';
|
||||
|
||||
import '../../../core/presentation/widgets/time_range_selector.dart';
|
||||
import 'state/activity_meter_view_model.dart';
|
||||
import 'state/activity_meter_view_state.dart';
|
||||
import 'widgets/steps_bar_chart.dart';
|
||||
import 'widgets/steps_history_section.dart';
|
||||
import 'widgets/steps_progress_ring.dart';
|
||||
@@ -20,12 +21,18 @@ class ActivityMeterScreen extends ConsumerWidget {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final state = ref.watch(activityMeterViewModelProvider);
|
||||
final vm = ref.read(activityMeterViewModelProvider.notifier);
|
||||
final device = ref.watch(selectedDeviceProvider);
|
||||
|
||||
ref.listen(
|
||||
activityMeterViewModelProvider.select((s) => s.errorMessage),
|
||||
activityMeterViewModelProvider.select((s) => s.errorEvent),
|
||||
(previous, next) {
|
||||
if (next.isNotEmpty) {
|
||||
showTopSnackbar(context, message: next, type: MessageType.error);
|
||||
if (next != null) {
|
||||
final message = switch (next) {
|
||||
ActivityMeterErrorEvent.loadData => context.translate(I18n.errorActivityData),
|
||||
ActivityMeterErrorEvent.loadMore => context.translate(I18n.errorActivityData),
|
||||
ActivityMeterErrorEvent.pedometer => context.translate(I18n.errorPedometer),
|
||||
};
|
||||
showTopSnackbar(context, message: message, type: MessageType.error);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -69,6 +76,43 @@ class ActivityMeterScreen extends ConsumerWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: SizeUtils.getByScreen(small: 16, big: 14),
|
||||
vertical: SizeUtils.getByScreen(small: 4, big: 4),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
context.translate(I18n.activityMeterPedometer),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 14, big: 15),
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Switch.adaptive(
|
||||
value: device?.settings.pedometer ?? false,
|
||||
activeTrackColor: theme.getColorFor(ThemeCode.legacyPrimary),
|
||||
onChanged: (value) async {
|
||||
final success = await vm.togglePedometer(enabled: value);
|
||||
if (!context.mounted) return;
|
||||
if (success) {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: context.translate(
|
||||
value
|
||||
? I18n.activityMeterPedometerEnabled
|
||||
: I18n.activityMeterPedometerDisabled,
|
||||
),
|
||||
type: MessageType.success,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
StepsProgressRing(
|
||||
steps: state.todayTotal,
|
||||
goal: state.dailyGoal,
|
||||
|
||||
@@ -79,7 +79,7 @@ class ActivityMeterViewModel extends Notifier<ActivityMeterViewState> {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isLoadingMore: false,
|
||||
errorMessage: _formatError(e),
|
||||
errorEvent: ActivityMeterErrorEvent.loadMore,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ class ActivityMeterViewModel extends Notifier<ActivityMeterViewState> {
|
||||
await _loadFilteredData();
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isLoading: false, errorMessage: _formatError(e));
|
||||
state = state.copyWith(isLoading: false, errorEvent: ActivityMeterErrorEvent.loadData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,11 +157,11 @@ class ActivityMeterViewModel extends Notifier<ActivityMeterViewState> {
|
||||
hasMoreHistory: histSteps.length >= _historyPageSize,
|
||||
stats: _computeStats(chartDaily),
|
||||
isLoading: false,
|
||||
errorMessage: '',
|
||||
errorEvent: null,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isLoading: false, errorMessage: _formatError(e));
|
||||
state = state.copyWith(isLoading: false, errorEvent: ActivityMeterErrorEvent.loadData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,8 +243,25 @@ class ActivityMeterViewModel extends Notifier<ActivityMeterViewState> {
|
||||
}
|
||||
}
|
||||
|
||||
String _formatError(Object e) {
|
||||
final msg = e.toString();
|
||||
return msg.startsWith('Exception: ') ? msg.substring(11) : msg;
|
||||
Future<bool> togglePedometer({required bool enabled}) async {
|
||||
final device = ref.read(selectedDeviceProvider);
|
||||
if (device == null) return false;
|
||||
|
||||
state = state.copyWith(errorEvent: null);
|
||||
try {
|
||||
final updatedSettings = device.settings.copyWith(pedometer: enabled);
|
||||
await ref.read(deviceSettingsUpdateProvider).updateDeviceSettings(
|
||||
device: device,
|
||||
updatedSettings: updatedSettings,
|
||||
);
|
||||
if (!ref.mounted) return false;
|
||||
ref.syncDeviceSettings(device, updatedSettings);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return false;
|
||||
state = state.copyWith(errorEvent: ActivityMeterErrorEvent.pedometer);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,12 @@ import '../../../../core/presentation/time_range.dart';
|
||||
|
||||
part 'activity_meter_view_state.freezed.dart';
|
||||
|
||||
enum ActivityMeterErrorEvent {
|
||||
loadData,
|
||||
loadMore,
|
||||
pedometer,
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class DailySteps with _$DailySteps {
|
||||
const factory DailySteps({
|
||||
@@ -36,6 +42,6 @@ abstract class ActivityMeterViewState with _$ActivityMeterViewState {
|
||||
DateTime? customEnd,
|
||||
@Default(true) bool isLoading,
|
||||
@Default(false) bool isLoadingMore,
|
||||
@Default('') String errorMessage,
|
||||
ActivityMeterErrorEvent? errorEvent,
|
||||
}) = _ActivityMeterViewState;
|
||||
}
|
||||
|
||||
@@ -537,7 +537,7 @@ as int,
|
||||
/// @nodoc
|
||||
mixin _$ActivityMeterViewState {
|
||||
|
||||
int get todayTotal; int get dailyGoal; List<DailySteps> get chartData; List<DailySteps> get historyData; int get currentHistoryPage; bool get hasMoreHistory; StepsStats get stats; TimeRange get timeRange; DateTime? get customStart; DateTime? get customEnd; bool get isLoading; bool get isLoadingMore; String get errorMessage;
|
||||
int get todayTotal; int get dailyGoal; List<DailySteps> get chartData; List<DailySteps> get historyData; int get currentHistoryPage; bool get hasMoreHistory; StepsStats get stats; TimeRange get timeRange; DateTime? get customStart; DateTime? get customEnd; bool get isLoading; bool get isLoadingMore; ActivityMeterErrorEvent? get errorEvent;
|
||||
/// Create a copy of ActivityMeterViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -548,16 +548,16 @@ $ActivityMeterViewStateCopyWith<ActivityMeterViewState> get copyWith => _$Activi
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ActivityMeterViewState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other.chartData, chartData)&&const DeepCollectionEquality().equals(other.historyData, historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ActivityMeterViewState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other.chartData, chartData)&&const DeepCollectionEquality().equals(other.historyData, historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(chartData),const DeepCollectionEquality().hash(historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorMessage);
|
||||
int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(chartData),const DeepCollectionEquality().hash(historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorEvent);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ActivityMeterViewState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorMessage: $errorMessage)';
|
||||
return 'ActivityMeterViewState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorEvent: $errorEvent)';
|
||||
}
|
||||
|
||||
|
||||
@@ -568,7 +568,7 @@ abstract mixin class $ActivityMeterViewStateCopyWith<$Res> {
|
||||
factory $ActivityMeterViewStateCopyWith(ActivityMeterViewState value, $Res Function(ActivityMeterViewState) _then) = _$ActivityMeterViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage
|
||||
int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent
|
||||
});
|
||||
|
||||
|
||||
@@ -585,7 +585,7 @@ class _$ActivityMeterViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of ActivityMeterViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorMessage = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorEvent = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
todayTotal: null == todayTotal ? _self.todayTotal : todayTotal // ignore: cast_nullable_to_non_nullable
|
||||
as int,dailyGoal: null == dailyGoal ? _self.dailyGoal : dailyGoal // ignore: cast_nullable_to_non_nullable
|
||||
@@ -599,8 +599,8 @@ as TimeRange,customStart: freezed == customStart ? _self.customStart : customSta
|
||||
as DateTime?,customEnd: freezed == customEnd ? _self.customEnd : customEnd // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
as bool,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable
|
||||
as ActivityMeterErrorEvent?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of ActivityMeterViewState
|
||||
@@ -694,10 +694,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ActivityMeterViewState() when $default != null:
|
||||
return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _:
|
||||
return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorEvent);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -715,10 +715,10 @@ return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyDa
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ActivityMeterViewState():
|
||||
return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _:
|
||||
return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorEvent);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -735,10 +735,10 @@ return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyDa
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ActivityMeterViewState() when $default != null:
|
||||
return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorMessage);case _:
|
||||
return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyData,_that.currentHistoryPage,_that.hasMoreHistory,_that.stats,_that.timeRange,_that.customStart,_that.customEnd,_that.isLoading,_that.isLoadingMore,_that.errorEvent);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -750,7 +750,7 @@ return $default(_that.todayTotal,_that.dailyGoal,_that.chartData,_that.historyDa
|
||||
|
||||
|
||||
class _ActivityMeterViewState implements ActivityMeterViewState {
|
||||
const _ActivityMeterViewState({this.todayTotal = 0, this.dailyGoal = 8000, final List<DailySteps> chartData = const [], final List<DailySteps> historyData = const [], this.currentHistoryPage = 1, this.hasMoreHistory = false, this.stats = const StepsStats(), this.timeRange = TimeRange.today, this.customStart, this.customEnd, this.isLoading = true, this.isLoadingMore = false, this.errorMessage = ''}): _chartData = chartData,_historyData = historyData;
|
||||
const _ActivityMeterViewState({this.todayTotal = 0, this.dailyGoal = 8000, final List<DailySteps> chartData = const [], final List<DailySteps> historyData = const [], this.currentHistoryPage = 1, this.hasMoreHistory = false, this.stats = const StepsStats(), this.timeRange = TimeRange.today, this.customStart, this.customEnd, this.isLoading = true, this.isLoadingMore = false, this.errorEvent}): _chartData = chartData,_historyData = historyData;
|
||||
|
||||
|
||||
@override@JsonKey() final int todayTotal;
|
||||
@@ -777,7 +777,7 @@ class _ActivityMeterViewState implements ActivityMeterViewState {
|
||||
@override final DateTime? customEnd;
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool isLoadingMore;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override final ActivityMeterErrorEvent? errorEvent;
|
||||
|
||||
/// Create a copy of ActivityMeterViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -789,16 +789,16 @@ _$ActivityMeterViewStateCopyWith<_ActivityMeterViewState> get copyWith => __$Act
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActivityMeterViewState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other._chartData, _chartData)&&const DeepCollectionEquality().equals(other._historyData, _historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActivityMeterViewState&&(identical(other.todayTotal, todayTotal) || other.todayTotal == todayTotal)&&(identical(other.dailyGoal, dailyGoal) || other.dailyGoal == dailyGoal)&&const DeepCollectionEquality().equals(other._chartData, _chartData)&&const DeepCollectionEquality().equals(other._historyData, _historyData)&&(identical(other.currentHistoryPage, currentHistoryPage) || other.currentHistoryPage == currentHistoryPage)&&(identical(other.hasMoreHistory, hasMoreHistory) || other.hasMoreHistory == hasMoreHistory)&&(identical(other.stats, stats) || other.stats == stats)&&(identical(other.timeRange, timeRange) || other.timeRange == timeRange)&&(identical(other.customStart, customStart) || other.customStart == customStart)&&(identical(other.customEnd, customEnd) || other.customEnd == customEnd)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(_chartData),const DeepCollectionEquality().hash(_historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorMessage);
|
||||
int get hashCode => Object.hash(runtimeType,todayTotal,dailyGoal,const DeepCollectionEquality().hash(_chartData),const DeepCollectionEquality().hash(_historyData),currentHistoryPage,hasMoreHistory,stats,timeRange,customStart,customEnd,isLoading,isLoadingMore,errorEvent);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ActivityMeterViewState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorMessage: $errorMessage)';
|
||||
return 'ActivityMeterViewState(todayTotal: $todayTotal, dailyGoal: $dailyGoal, chartData: $chartData, historyData: $historyData, currentHistoryPage: $currentHistoryPage, hasMoreHistory: $hasMoreHistory, stats: $stats, timeRange: $timeRange, customStart: $customStart, customEnd: $customEnd, isLoading: $isLoading, isLoadingMore: $isLoadingMore, errorEvent: $errorEvent)';
|
||||
}
|
||||
|
||||
|
||||
@@ -809,7 +809,7 @@ abstract mixin class _$ActivityMeterViewStateCopyWith<$Res> implements $Activity
|
||||
factory _$ActivityMeterViewStateCopyWith(_ActivityMeterViewState value, $Res Function(_ActivityMeterViewState) _then) = __$ActivityMeterViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, String errorMessage
|
||||
int todayTotal, int dailyGoal, List<DailySteps> chartData, List<DailySteps> historyData, int currentHistoryPage, bool hasMoreHistory, StepsStats stats, TimeRange timeRange, DateTime? customStart, DateTime? customEnd, bool isLoading, bool isLoadingMore, ActivityMeterErrorEvent? errorEvent
|
||||
});
|
||||
|
||||
|
||||
@@ -826,7 +826,7 @@ class __$ActivityMeterViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of ActivityMeterViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorMessage = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? todayTotal = null,Object? dailyGoal = null,Object? chartData = null,Object? historyData = null,Object? currentHistoryPage = null,Object? hasMoreHistory = null,Object? stats = null,Object? timeRange = null,Object? customStart = freezed,Object? customEnd = freezed,Object? isLoading = null,Object? isLoadingMore = null,Object? errorEvent = freezed,}) {
|
||||
return _then(_ActivityMeterViewState(
|
||||
todayTotal: null == todayTotal ? _self.todayTotal : todayTotal // ignore: cast_nullable_to_non_nullable
|
||||
as int,dailyGoal: null == dailyGoal ? _self.dailyGoal : dailyGoal // ignore: cast_nullable_to_non_nullable
|
||||
@@ -840,8 +840,8 @@ as TimeRange,customStart: freezed == customStart ? _self.customStart : customSta
|
||||
as DateTime?,customEnd: freezed == customEnd ? _self.customEnd : customEnd // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
as bool,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable
|
||||
as ActivityMeterErrorEvent?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
|
||||
import 'presentation/background_image_screen.dart';
|
||||
|
||||
class BackgroundImageBuilder {
|
||||
const BackgroundImageBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final NavigationContract navigationContract = GetIt.I<NavigationContract>();
|
||||
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: BackgroundImageScreen(navigationContract: navigationContract),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,250 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:utils/utils.dart';
|
||||
|
||||
import 'state/background_image_view_model.dart';
|
||||
import 'state/background_image_view_state.dart';
|
||||
|
||||
class BackgroundImageScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const BackgroundImageScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.read(themePortProvider);
|
||||
final primaryColor = theme.getColorFor(ThemeCode.legacyPrimary);
|
||||
|
||||
final state = ref.watch(backgroundImageViewModelProvider);
|
||||
final vm = ref.read(backgroundImageViewModelProvider.notifier);
|
||||
|
||||
ref.listen(
|
||||
backgroundImageViewModelProvider.select((s) => s.errorEvent),
|
||||
(previous, next) {
|
||||
if (next != null) {
|
||||
final message = switch (next) {
|
||||
BackgroundImageErrorEvent.load =>
|
||||
context.translate(I18n.errorBackgroundImageLoad),
|
||||
BackgroundImageErrorEvent.upload =>
|
||||
context.translate(I18n.errorBackgroundImageUpload),
|
||||
BackgroundImageErrorEvent.set =>
|
||||
context.translate(I18n.errorBackgroundImageSet),
|
||||
};
|
||||
showTopSnackbar(context, message: message, type: MessageType.error);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
ref.listen(
|
||||
backgroundImageViewModelProvider.select((s) => s.successEvent),
|
||||
(previous, next) {
|
||||
if (next != null) {
|
||||
final message = switch (next) {
|
||||
BackgroundImageSuccessEvent.uploaded =>
|
||||
context.translate(I18n.backgroundImageUploaded),
|
||||
BackgroundImageSuccessEvent.backgroundSet =>
|
||||
context.translate(I18n.backgroundImageSet),
|
||||
};
|
||||
showTopSnackbar(context, message: message, type: MessageType.success);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.white,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.white,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
centerTitle: true,
|
||||
automaticallyImplyLeading: false,
|
||||
leading: IconButton(
|
||||
onPressed: () => navigationContract.goBack(),
|
||||
icon: Icon(
|
||||
Icons.adaptive.arrow_back,
|
||||
color: primaryColor,
|
||||
size: SizeUtils.getByScreen(small: 32, big: 28),
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
context.translate(I18n.customBackground).toUpperCase(),
|
||||
style: TextStyle(
|
||||
fontSize: SizeUtils.getByScreen(small: 20, big: 19),
|
||||
fontWeight: FontWeight.w500,
|
||||
letterSpacing: 0,
|
||||
color: primaryColor,
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
right: SizeUtils.getByScreen(small: 16, big: 14),
|
||||
),
|
||||
child: DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: state.isSaving ? null : vm.uploadPhoto,
|
||||
icon: Icon(
|
||||
Icons.add_photo_alternate_outlined,
|
||||
color: Colors.white,
|
||||
size: SizeUtils.getByScreen(small: 24, big: 22),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SafeArea(
|
||||
top: false,
|
||||
child: state.isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: state.isSaving
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: state.photos.isEmpty
|
||||
? _EmptyState(
|
||||
onUpload: vm.uploadPhoto,
|
||||
primaryColor: primaryColor,
|
||||
)
|
||||
: _PhotoGrid(
|
||||
state: state,
|
||||
onPhotoTap: vm.setAsBackground,
|
||||
primaryColor: primaryColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _EmptyState extends StatelessWidget {
|
||||
final VoidCallback onUpload;
|
||||
final Color primaryColor;
|
||||
|
||||
const _EmptyState({required this.onUpload, required this.primaryColor});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 28),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.add_photo_alternate_outlined,
|
||||
size: 100,
|
||||
color: Colors.grey.shade400,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Text(
|
||||
context.translate(I18n.backgroundImageDescription),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
PrimaryButton(
|
||||
onPressed: onUpload,
|
||||
text: context.translate(I18n.backgroundImageTapToSelect),
|
||||
color: primaryColor,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _PhotoGrid extends StatelessWidget {
|
||||
final BackgroundImageViewState state;
|
||||
final ValueChanged<String> onPhotoTap;
|
||||
final Color primaryColor;
|
||||
|
||||
const _PhotoGrid({
|
||||
required this.state,
|
||||
required this.onPhotoTap,
|
||||
required this.primaryColor,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
child: Text(
|
||||
context.translate(I18n.backgroundImageTapToChange),
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(fontSize: 14),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: GridView.builder(
|
||||
padding: const EdgeInsets.all(12),
|
||||
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10,
|
||||
mainAxisSpacing: 10,
|
||||
),
|
||||
itemCount: state.photos.length,
|
||||
itemBuilder: (context, index) {
|
||||
final photo = state.photos[index];
|
||||
final isActive = state.currentBackgroundId == photo.id;
|
||||
return GestureDetector(
|
||||
onTap: () => onPhotoTap(photo.id),
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(
|
||||
color: isActive ? primaryColor : Colors.grey.shade300,
|
||||
width: isActive ? 3 : 1,
|
||||
),
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: photo.fileBytes != null
|
||||
? Image.memory(
|
||||
photo.fileBytes!,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: Center(
|
||||
child: Icon(
|
||||
Icons.image_outlined,
|
||||
size: 48,
|
||||
color: Colors.grey.shade400,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (isActive)
|
||||
Positioned(
|
||||
top: 8,
|
||||
right: 8,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
decoration: BoxDecoration(
|
||||
color: primaryColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: const Icon(
|
||||
Icons.check,
|
||||
color: Colors.white,
|
||||
size: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:legacy_shared/legacy_shared.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
import '../../../../core/domain/repositories/background_image_repository.dart';
|
||||
import '../../../../core/providers/background_image_repository_provider.dart';
|
||||
import 'background_image_view_state.dart';
|
||||
|
||||
final backgroundImageViewModelProvider =
|
||||
NotifierProvider.autoDispose<
|
||||
BackgroundImageViewModel,
|
||||
BackgroundImageViewState
|
||||
>(BackgroundImageViewModel.new);
|
||||
|
||||
class BackgroundImageViewModel extends Notifier<BackgroundImageViewState> {
|
||||
late final BackgroundImageRepository _repository;
|
||||
late final SharedDevicesRepository _devicesRepository;
|
||||
|
||||
@override
|
||||
BackgroundImageViewState build() {
|
||||
_repository = ref.read(backgroundImageRepositoryProvider);
|
||||
_devicesRepository = ref.read(sharedDevicesRepositoryProvider);
|
||||
Future.microtask(_load);
|
||||
return const BackgroundImageViewState();
|
||||
}
|
||||
|
||||
Future<void> _load() async {
|
||||
try {
|
||||
final device = ref.read(selectedDeviceProvider);
|
||||
if (device == null) return;
|
||||
|
||||
final photos = await _repository.getPhotos();
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
photos: photos,
|
||||
currentBackgroundId: device.backgroundImageId,
|
||||
isLoading: false,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorEvent: BackgroundImageErrorEvent.load,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> reload() async {
|
||||
state = state.copyWith(isLoading: true, errorEvent: null);
|
||||
await _load();
|
||||
}
|
||||
|
||||
Future<void> uploadPhoto() async {
|
||||
if (state.isSaving) return;
|
||||
|
||||
final picker = ImagePicker();
|
||||
final image = await picker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
maxWidth: 800,
|
||||
imageQuality: 80,
|
||||
);
|
||||
if (image == null) return;
|
||||
|
||||
final device = ref.read(selectedDeviceProvider);
|
||||
if (device == null) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isSaving: true,
|
||||
errorEvent: null,
|
||||
successEvent: null,
|
||||
);
|
||||
|
||||
try {
|
||||
final photoId = await _repository.uploadImage(path: image.path);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
await _repository.setBackgroundImage(
|
||||
deviceId: device.id,
|
||||
photoId: photoId,
|
||||
);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
await _refreshDevice(device);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isSaving: false,
|
||||
successEvent: BackgroundImageSuccessEvent.uploaded,
|
||||
);
|
||||
|
||||
await reload();
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isSaving: false,
|
||||
errorEvent: BackgroundImageErrorEvent.upload,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> setAsBackground(String photoId) async {
|
||||
final device = ref.read(selectedDeviceProvider);
|
||||
if (device == null) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isSaving: true,
|
||||
errorEvent: null,
|
||||
successEvent: null,
|
||||
);
|
||||
|
||||
try {
|
||||
await _repository.setBackgroundImage(
|
||||
deviceId: device.id,
|
||||
photoId: photoId,
|
||||
);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
await _refreshDevice(device);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
isSaving: false,
|
||||
successEvent: BackgroundImageSuccessEvent.backgroundSet,
|
||||
);
|
||||
|
||||
await reload();
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isSaving: false,
|
||||
errorEvent: BackgroundImageErrorEvent.set,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _refreshDevice(DeviceEntity currentDevice) async {
|
||||
final devices = await _devicesRepository.getDevices();
|
||||
if (!ref.mounted) return;
|
||||
|
||||
final updated = devices.firstWhere(
|
||||
(d) => d.identificator == currentDevice.identificator,
|
||||
orElse: () => currentDevice,
|
||||
);
|
||||
ref.read(selectedDeviceProvider.notifier).setSelectedDevice(updated);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'package:device_management/src/features/remote_connection/domain/entities/picture_entity.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'background_image_view_state.freezed.dart';
|
||||
|
||||
enum BackgroundImageErrorEvent { load, upload, set }
|
||||
enum BackgroundImageSuccessEvent { uploaded, backgroundSet }
|
||||
|
||||
@freezed
|
||||
abstract class BackgroundImageViewState with _$BackgroundImageViewState {
|
||||
const factory BackgroundImageViewState({
|
||||
@Default([]) List<PictureEntity> photos,
|
||||
@Default(true) bool isLoading,
|
||||
@Default(false) bool isSaving,
|
||||
String? currentBackgroundId,
|
||||
BackgroundImageSuccessEvent? successEvent,
|
||||
BackgroundImageErrorEvent? errorEvent,
|
||||
}) = _BackgroundImageViewState;
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'background_image_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$BackgroundImageViewState {
|
||||
|
||||
List<PictureEntity> get photos; bool get isLoading; bool get isSaving; String? get currentBackgroundId; BackgroundImageSuccessEvent? get successEvent; BackgroundImageErrorEvent? get errorEvent;
|
||||
/// Create a copy of BackgroundImageViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$BackgroundImageViewStateCopyWith<BackgroundImageViewState> get copyWith => _$BackgroundImageViewStateCopyWithImpl<BackgroundImageViewState>(this as BackgroundImageViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is BackgroundImageViewState&&const DeepCollectionEquality().equals(other.photos, photos)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.currentBackgroundId, currentBackgroundId) || other.currentBackgroundId == currentBackgroundId)&&(identical(other.successEvent, successEvent) || other.successEvent == successEvent)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(photos),isLoading,isSaving,currentBackgroundId,successEvent,errorEvent);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BackgroundImageViewState(photos: $photos, isLoading: $isLoading, isSaving: $isSaving, currentBackgroundId: $currentBackgroundId, successEvent: $successEvent, errorEvent: $errorEvent)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $BackgroundImageViewStateCopyWith<$Res> {
|
||||
factory $BackgroundImageViewStateCopyWith(BackgroundImageViewState value, $Res Function(BackgroundImageViewState) _then) = _$BackgroundImageViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
List<PictureEntity> photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$BackgroundImageViewStateCopyWithImpl<$Res>
|
||||
implements $BackgroundImageViewStateCopyWith<$Res> {
|
||||
_$BackgroundImageViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final BackgroundImageViewState _self;
|
||||
final $Res Function(BackgroundImageViewState) _then;
|
||||
|
||||
/// Create a copy of BackgroundImageViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? photos = null,Object? isLoading = null,Object? isSaving = null,Object? currentBackgroundId = freezed,Object? successEvent = freezed,Object? errorEvent = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
photos: null == photos ? _self.photos : photos // ignore: cast_nullable_to_non_nullable
|
||||
as List<PictureEntity>,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable
|
||||
as bool,currentBackgroundId: freezed == currentBackgroundId ? _self.currentBackgroundId : currentBackgroundId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,successEvent: freezed == successEvent ? _self.successEvent : successEvent // ignore: cast_nullable_to_non_nullable
|
||||
as BackgroundImageSuccessEvent?,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable
|
||||
as BackgroundImageErrorEvent?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [BackgroundImageViewState].
|
||||
extension BackgroundImageViewStatePatterns on BackgroundImageViewState {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _BackgroundImageViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _BackgroundImageViewState() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _BackgroundImageViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _BackgroundImageViewState():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _BackgroundImageViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _BackgroundImageViewState() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<PictureEntity> photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _BackgroundImageViewState() when $default != null:
|
||||
return $default(_that.photos,_that.isLoading,_that.isSaving,_that.currentBackgroundId,_that.successEvent,_that.errorEvent);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<PictureEntity> photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _BackgroundImageViewState():
|
||||
return $default(_that.photos,_that.isLoading,_that.isSaving,_that.currentBackgroundId,_that.successEvent,_that.errorEvent);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<PictureEntity> photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _BackgroundImageViewState() when $default != null:
|
||||
return $default(_that.photos,_that.isLoading,_that.isSaving,_that.currentBackgroundId,_that.successEvent,_that.errorEvent);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _BackgroundImageViewState implements BackgroundImageViewState {
|
||||
const _BackgroundImageViewState({final List<PictureEntity> photos = const [], this.isLoading = true, this.isSaving = false, this.currentBackgroundId, this.successEvent, this.errorEvent}): _photos = photos;
|
||||
|
||||
|
||||
final List<PictureEntity> _photos;
|
||||
@override@JsonKey() List<PictureEntity> get photos {
|
||||
if (_photos is EqualUnmodifiableListView) return _photos;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_photos);
|
||||
}
|
||||
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool isSaving;
|
||||
@override final String? currentBackgroundId;
|
||||
@override final BackgroundImageSuccessEvent? successEvent;
|
||||
@override final BackgroundImageErrorEvent? errorEvent;
|
||||
|
||||
/// Create a copy of BackgroundImageViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$BackgroundImageViewStateCopyWith<_BackgroundImageViewState> get copyWith => __$BackgroundImageViewStateCopyWithImpl<_BackgroundImageViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _BackgroundImageViewState&&const DeepCollectionEquality().equals(other._photos, _photos)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.currentBackgroundId, currentBackgroundId) || other.currentBackgroundId == currentBackgroundId)&&(identical(other.successEvent, successEvent) || other.successEvent == successEvent)&&(identical(other.errorEvent, errorEvent) || other.errorEvent == errorEvent));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_photos),isLoading,isSaving,currentBackgroundId,successEvent,errorEvent);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'BackgroundImageViewState(photos: $photos, isLoading: $isLoading, isSaving: $isSaving, currentBackgroundId: $currentBackgroundId, successEvent: $successEvent, errorEvent: $errorEvent)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$BackgroundImageViewStateCopyWith<$Res> implements $BackgroundImageViewStateCopyWith<$Res> {
|
||||
factory _$BackgroundImageViewStateCopyWith(_BackgroundImageViewState value, $Res Function(_BackgroundImageViewState) _then) = __$BackgroundImageViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
List<PictureEntity> photos, bool isLoading, bool isSaving, String? currentBackgroundId, BackgroundImageSuccessEvent? successEvent, BackgroundImageErrorEvent? errorEvent
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$BackgroundImageViewStateCopyWithImpl<$Res>
|
||||
implements _$BackgroundImageViewStateCopyWith<$Res> {
|
||||
__$BackgroundImageViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _BackgroundImageViewState _self;
|
||||
final $Res Function(_BackgroundImageViewState) _then;
|
||||
|
||||
/// Create a copy of BackgroundImageViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? photos = null,Object? isLoading = null,Object? isSaving = null,Object? currentBackgroundId = freezed,Object? successEvent = freezed,Object? errorEvent = freezed,}) {
|
||||
return _then(_BackgroundImageViewState(
|
||||
photos: null == photos ? _self._photos : photos // ignore: cast_nullable_to_non_nullable
|
||||
as List<PictureEntity>,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isSaving: null == isSaving ? _self.isSaving : isSaving // ignore: cast_nullable_to_non_nullable
|
||||
as bool,currentBackgroundId: freezed == currentBackgroundId ? _self.currentBackgroundId : currentBackgroundId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,successEvent: freezed == successEvent ? _self.successEvent : successEvent // ignore: cast_nullable_to_non_nullable
|
||||
as BackgroundImageSuccessEvent?,errorEvent: freezed == errorEvent ? _self.errorEvent : errorEvent // ignore: cast_nullable_to_non_nullable
|
||||
as BackgroundImageErrorEvent?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,15 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import 'presentation/call_history_screen.dart';
|
||||
|
||||
class CallHistoryBuilder {
|
||||
const CallHistoryBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
return MaterialPage<void>(
|
||||
key: state.pageKey,
|
||||
child: const CallHistoryScreen(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:legacy_shared/legacy_shared.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
import 'call_history_entity.dart';
|
||||
import 'call_history_response_model.dart';
|
||||
|
||||
class CallHistoryDatasource {
|
||||
CallHistoryDatasource(this._repository);
|
||||
|
||||
final QuestiaRepository _repository;
|
||||
|
||||
Future<List<CallHistoryEntity>> getCallHistory({
|
||||
required String deviceIdentificator,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _repository.get<Map<String, dynamic>>(
|
||||
'/devices/identificator/$deviceIdentificator/call-histories',
|
||||
);
|
||||
|
||||
final data = response.data;
|
||||
if (data == null || data.isEmpty) return [];
|
||||
|
||||
final model = CallHistoryResponseModel.fromJson(data);
|
||||
return model.items
|
||||
.map((item) => CallHistoryEntity(
|
||||
deviceIdentificator: item.deviceIdentificator,
|
||||
phone: item.phone,
|
||||
name: item.name,
|
||||
isIncoming: item.isIncoming,
|
||||
isAccepted: item.isAccepted,
|
||||
duration: item.duration,
|
||||
occurredAt: item.occurredAt,
|
||||
createdAt: item.createdAt,
|
||||
))
|
||||
.toList();
|
||||
} on DioException catch (error) {
|
||||
if (error.response?.statusCode == 404) return [];
|
||||
throw mapDioError(error, defaultMessage: 'Error getting call history');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:sf_infrastructure/sf_infrastructure.dart';
|
||||
|
||||
import 'call_history_datasource.dart';
|
||||
|
||||
final callHistoryDatasourceProvider = Provider<CallHistoryDatasource>((ref) {
|
||||
return CallHistoryDatasource(GetIt.I<QuestiaRepository>());
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'call_history_entity.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class CallHistoryEntity with _$CallHistoryEntity {
|
||||
const factory CallHistoryEntity({
|
||||
required String deviceIdentificator,
|
||||
required String phone,
|
||||
String? name,
|
||||
required bool isIncoming,
|
||||
required bool isAccepted,
|
||||
required int duration,
|
||||
required int occurredAt,
|
||||
required int createdAt,
|
||||
}) = _CallHistoryEntity;
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'call_history_entity.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$CallHistoryEntity {
|
||||
|
||||
String get deviceIdentificator; String get phone; String? get name; bool get isIncoming; bool get isAccepted; int get duration; int get occurredAt; int get createdAt;
|
||||
/// Create a copy of CallHistoryEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$CallHistoryEntityCopyWith<CallHistoryEntity> get copyWith => _$CallHistoryEntityCopyWithImpl<CallHistoryEntity>(this as CallHistoryEntity, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallHistoryEntity&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.name, name) || other.name == name)&&(identical(other.isIncoming, isIncoming) || other.isIncoming == isIncoming)&&(identical(other.isAccepted, isAccepted) || other.isAccepted == isAccepted)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,deviceIdentificator,phone,name,isIncoming,isAccepted,duration,occurredAt,createdAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CallHistoryEntity(deviceIdentificator: $deviceIdentificator, phone: $phone, name: $name, isIncoming: $isIncoming, isAccepted: $isAccepted, duration: $duration, occurredAt: $occurredAt, createdAt: $createdAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $CallHistoryEntityCopyWith<$Res> {
|
||||
factory $CallHistoryEntityCopyWith(CallHistoryEntity value, $Res Function(CallHistoryEntity) _then) = _$CallHistoryEntityCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$CallHistoryEntityCopyWithImpl<$Res>
|
||||
implements $CallHistoryEntityCopyWith<$Res> {
|
||||
_$CallHistoryEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final CallHistoryEntity _self;
|
||||
final $Res Function(CallHistoryEntity) _then;
|
||||
|
||||
/// Create a copy of CallHistoryEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? deviceIdentificator = null,Object? phone = null,Object? name = freezed,Object? isIncoming = null,Object? isAccepted = null,Object? duration = null,Object? occurredAt = null,Object? createdAt = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,isIncoming: null == isIncoming ? _self.isIncoming : isIncoming // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isAccepted: null == isAccepted ? _self.isAccepted : isAccepted // ignore: cast_nullable_to_non_nullable
|
||||
as bool,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable
|
||||
as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [CallHistoryEntity].
|
||||
extension CallHistoryEntityPatterns on CallHistoryEntity {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _CallHistoryEntity value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryEntity() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _CallHistoryEntity value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryEntity():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _CallHistoryEntity value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryEntity() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryEntity() when $default != null:
|
||||
return $default(_that.deviceIdentificator,_that.phone,_that.name,_that.isIncoming,_that.isAccepted,_that.duration,_that.occurredAt,_that.createdAt);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryEntity():
|
||||
return $default(_that.deviceIdentificator,_that.phone,_that.name,_that.isIncoming,_that.isAccepted,_that.duration,_that.occurredAt,_that.createdAt);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryEntity() when $default != null:
|
||||
return $default(_that.deviceIdentificator,_that.phone,_that.name,_that.isIncoming,_that.isAccepted,_that.duration,_that.occurredAt,_that.createdAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _CallHistoryEntity implements CallHistoryEntity {
|
||||
const _CallHistoryEntity({required this.deviceIdentificator, required this.phone, this.name, required this.isIncoming, required this.isAccepted, required this.duration, required this.occurredAt, required this.createdAt});
|
||||
|
||||
|
||||
@override final String deviceIdentificator;
|
||||
@override final String phone;
|
||||
@override final String? name;
|
||||
@override final bool isIncoming;
|
||||
@override final bool isAccepted;
|
||||
@override final int duration;
|
||||
@override final int occurredAt;
|
||||
@override final int createdAt;
|
||||
|
||||
/// Create a copy of CallHistoryEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$CallHistoryEntityCopyWith<_CallHistoryEntity> get copyWith => __$CallHistoryEntityCopyWithImpl<_CallHistoryEntity>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallHistoryEntity&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.name, name) || other.name == name)&&(identical(other.isIncoming, isIncoming) || other.isIncoming == isIncoming)&&(identical(other.isAccepted, isAccepted) || other.isAccepted == isAccepted)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,deviceIdentificator,phone,name,isIncoming,isAccepted,duration,occurredAt,createdAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CallHistoryEntity(deviceIdentificator: $deviceIdentificator, phone: $phone, name: $name, isIncoming: $isIncoming, isAccepted: $isAccepted, duration: $duration, occurredAt: $occurredAt, createdAt: $createdAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$CallHistoryEntityCopyWith<$Res> implements $CallHistoryEntityCopyWith<$Res> {
|
||||
factory _$CallHistoryEntityCopyWith(_CallHistoryEntity value, $Res Function(_CallHistoryEntity) _then) = __$CallHistoryEntityCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$CallHistoryEntityCopyWithImpl<$Res>
|
||||
implements _$CallHistoryEntityCopyWith<$Res> {
|
||||
__$CallHistoryEntityCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _CallHistoryEntity _self;
|
||||
final $Res Function(_CallHistoryEntity) _then;
|
||||
|
||||
/// Create a copy of CallHistoryEntity
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? deviceIdentificator = null,Object? phone = null,Object? name = freezed,Object? isIncoming = null,Object? isAccepted = null,Object? duration = null,Object? occurredAt = null,Object? createdAt = null,}) {
|
||||
return _then(_CallHistoryEntity(
|
||||
deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,isIncoming: null == isIncoming ? _self.isIncoming : isIncoming // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isAccepted: null == isAccepted ? _self.isAccepted : isAccepted // ignore: cast_nullable_to_non_nullable
|
||||
as bool,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable
|
||||
as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,32 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'call_history_response_model.freezed.dart';
|
||||
part 'call_history_response_model.g.dart';
|
||||
|
||||
@freezed
|
||||
abstract class CallHistoryResponseModel with _$CallHistoryResponseModel {
|
||||
const factory CallHistoryResponseModel({
|
||||
required int total,
|
||||
required List<CallHistoryItemModel> items,
|
||||
}) = _CallHistoryResponseModel;
|
||||
|
||||
factory CallHistoryResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$CallHistoryResponseModelFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
abstract class CallHistoryItemModel with _$CallHistoryItemModel {
|
||||
const factory CallHistoryItemModel({
|
||||
required String deviceIdentificator,
|
||||
required String phone,
|
||||
String? name,
|
||||
required bool isIncoming,
|
||||
required bool isAccepted,
|
||||
required int duration,
|
||||
required int occurredAt,
|
||||
required int createdAt,
|
||||
}) = _CallHistoryItemModel;
|
||||
|
||||
factory CallHistoryItemModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$CallHistoryItemModelFromJson(json);
|
||||
}
|
||||
@@ -0,0 +1,570 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'call_history_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$CallHistoryResponseModel {
|
||||
|
||||
int get total; List<CallHistoryItemModel> get items;
|
||||
/// Create a copy of CallHistoryResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$CallHistoryResponseModelCopyWith<CallHistoryResponseModel> get copyWith => _$CallHistoryResponseModelCopyWithImpl<CallHistoryResponseModel>(this as CallHistoryResponseModel, _$identity);
|
||||
|
||||
/// Serializes this CallHistoryResponseModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallHistoryResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other.items, items));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(items));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CallHistoryResponseModel(total: $total, items: $items)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $CallHistoryResponseModelCopyWith<$Res> {
|
||||
factory $CallHistoryResponseModelCopyWith(CallHistoryResponseModel value, $Res Function(CallHistoryResponseModel) _then) = _$CallHistoryResponseModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
int total, List<CallHistoryItemModel> items
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$CallHistoryResponseModelCopyWithImpl<$Res>
|
||||
implements $CallHistoryResponseModelCopyWith<$Res> {
|
||||
_$CallHistoryResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final CallHistoryResponseModel _self;
|
||||
final $Res Function(CallHistoryResponseModel) _then;
|
||||
|
||||
/// Create a copy of CallHistoryResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? total = null,Object? items = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable
|
||||
as int,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<CallHistoryItemModel>,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [CallHistoryResponseModel].
|
||||
extension CallHistoryResponseModelPatterns on CallHistoryResponseModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _CallHistoryResponseModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _CallHistoryResponseModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryResponseModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _CallHistoryResponseModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryResponseModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int total, List<CallHistoryItemModel> items)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryResponseModel() when $default != null:
|
||||
return $default(_that.total,_that.items);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int total, List<CallHistoryItemModel> items) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryResponseModel():
|
||||
return $default(_that.total,_that.items);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int total, List<CallHistoryItemModel> items)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryResponseModel() when $default != null:
|
||||
return $default(_that.total,_that.items);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _CallHistoryResponseModel implements CallHistoryResponseModel {
|
||||
const _CallHistoryResponseModel({required this.total, required final List<CallHistoryItemModel> items}): _items = items;
|
||||
factory _CallHistoryResponseModel.fromJson(Map<String, dynamic> json) => _$CallHistoryResponseModelFromJson(json);
|
||||
|
||||
@override final int total;
|
||||
final List<CallHistoryItemModel> _items;
|
||||
@override List<CallHistoryItemModel> get items {
|
||||
if (_items is EqualUnmodifiableListView) return _items;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_items);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of CallHistoryResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$CallHistoryResponseModelCopyWith<_CallHistoryResponseModel> get copyWith => __$CallHistoryResponseModelCopyWithImpl<_CallHistoryResponseModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$CallHistoryResponseModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallHistoryResponseModel&&(identical(other.total, total) || other.total == total)&&const DeepCollectionEquality().equals(other._items, _items));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,total,const DeepCollectionEquality().hash(_items));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CallHistoryResponseModel(total: $total, items: $items)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$CallHistoryResponseModelCopyWith<$Res> implements $CallHistoryResponseModelCopyWith<$Res> {
|
||||
factory _$CallHistoryResponseModelCopyWith(_CallHistoryResponseModel value, $Res Function(_CallHistoryResponseModel) _then) = __$CallHistoryResponseModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
int total, List<CallHistoryItemModel> items
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$CallHistoryResponseModelCopyWithImpl<$Res>
|
||||
implements _$CallHistoryResponseModelCopyWith<$Res> {
|
||||
__$CallHistoryResponseModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _CallHistoryResponseModel _self;
|
||||
final $Res Function(_CallHistoryResponseModel) _then;
|
||||
|
||||
/// Create a copy of CallHistoryResponseModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? total = null,Object? items = null,}) {
|
||||
return _then(_CallHistoryResponseModel(
|
||||
total: null == total ? _self.total : total // ignore: cast_nullable_to_non_nullable
|
||||
as int,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<CallHistoryItemModel>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$CallHistoryItemModel {
|
||||
|
||||
String get deviceIdentificator; String get phone; String? get name; bool get isIncoming; bool get isAccepted; int get duration; int get occurredAt; int get createdAt;
|
||||
/// Create a copy of CallHistoryItemModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$CallHistoryItemModelCopyWith<CallHistoryItemModel> get copyWith => _$CallHistoryItemModelCopyWithImpl<CallHistoryItemModel>(this as CallHistoryItemModel, _$identity);
|
||||
|
||||
/// Serializes this CallHistoryItemModel to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallHistoryItemModel&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.name, name) || other.name == name)&&(identical(other.isIncoming, isIncoming) || other.isIncoming == isIncoming)&&(identical(other.isAccepted, isAccepted) || other.isAccepted == isAccepted)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,deviceIdentificator,phone,name,isIncoming,isAccepted,duration,occurredAt,createdAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CallHistoryItemModel(deviceIdentificator: $deviceIdentificator, phone: $phone, name: $name, isIncoming: $isIncoming, isAccepted: $isAccepted, duration: $duration, occurredAt: $occurredAt, createdAt: $createdAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $CallHistoryItemModelCopyWith<$Res> {
|
||||
factory $CallHistoryItemModelCopyWith(CallHistoryItemModel value, $Res Function(CallHistoryItemModel) _then) = _$CallHistoryItemModelCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$CallHistoryItemModelCopyWithImpl<$Res>
|
||||
implements $CallHistoryItemModelCopyWith<$Res> {
|
||||
_$CallHistoryItemModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final CallHistoryItemModel _self;
|
||||
final $Res Function(CallHistoryItemModel) _then;
|
||||
|
||||
/// Create a copy of CallHistoryItemModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? deviceIdentificator = null,Object? phone = null,Object? name = freezed,Object? isIncoming = null,Object? isAccepted = null,Object? duration = null,Object? occurredAt = null,Object? createdAt = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,isIncoming: null == isIncoming ? _self.isIncoming : isIncoming // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isAccepted: null == isAccepted ? _self.isAccepted : isAccepted // ignore: cast_nullable_to_non_nullable
|
||||
as bool,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable
|
||||
as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [CallHistoryItemModel].
|
||||
extension CallHistoryItemModelPatterns on CallHistoryItemModel {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _CallHistoryItemModel value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryItemModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _CallHistoryItemModel value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryItemModel():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _CallHistoryItemModel value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryItemModel() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryItemModel() when $default != null:
|
||||
return $default(_that.deviceIdentificator,_that.phone,_that.name,_that.isIncoming,_that.isAccepted,_that.duration,_that.occurredAt,_that.createdAt);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryItemModel():
|
||||
return $default(_that.deviceIdentificator,_that.phone,_that.name,_that.isIncoming,_that.isAccepted,_that.duration,_that.occurredAt,_that.createdAt);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryItemModel() when $default != null:
|
||||
return $default(_that.deviceIdentificator,_that.phone,_that.name,_that.isIncoming,_that.isAccepted,_that.duration,_that.occurredAt,_that.createdAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _CallHistoryItemModel implements CallHistoryItemModel {
|
||||
const _CallHistoryItemModel({required this.deviceIdentificator, required this.phone, this.name, required this.isIncoming, required this.isAccepted, required this.duration, required this.occurredAt, required this.createdAt});
|
||||
factory _CallHistoryItemModel.fromJson(Map<String, dynamic> json) => _$CallHistoryItemModelFromJson(json);
|
||||
|
||||
@override final String deviceIdentificator;
|
||||
@override final String phone;
|
||||
@override final String? name;
|
||||
@override final bool isIncoming;
|
||||
@override final bool isAccepted;
|
||||
@override final int duration;
|
||||
@override final int occurredAt;
|
||||
@override final int createdAt;
|
||||
|
||||
/// Create a copy of CallHistoryItemModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$CallHistoryItemModelCopyWith<_CallHistoryItemModel> get copyWith => __$CallHistoryItemModelCopyWithImpl<_CallHistoryItemModel>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$CallHistoryItemModelToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallHistoryItemModel&&(identical(other.deviceIdentificator, deviceIdentificator) || other.deviceIdentificator == deviceIdentificator)&&(identical(other.phone, phone) || other.phone == phone)&&(identical(other.name, name) || other.name == name)&&(identical(other.isIncoming, isIncoming) || other.isIncoming == isIncoming)&&(identical(other.isAccepted, isAccepted) || other.isAccepted == isAccepted)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.occurredAt, occurredAt) || other.occurredAt == occurredAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,deviceIdentificator,phone,name,isIncoming,isAccepted,duration,occurredAt,createdAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CallHistoryItemModel(deviceIdentificator: $deviceIdentificator, phone: $phone, name: $name, isIncoming: $isIncoming, isAccepted: $isAccepted, duration: $duration, occurredAt: $occurredAt, createdAt: $createdAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$CallHistoryItemModelCopyWith<$Res> implements $CallHistoryItemModelCopyWith<$Res> {
|
||||
factory _$CallHistoryItemModelCopyWith(_CallHistoryItemModel value, $Res Function(_CallHistoryItemModel) _then) = __$CallHistoryItemModelCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String deviceIdentificator, String phone, String? name, bool isIncoming, bool isAccepted, int duration, int occurredAt, int createdAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$CallHistoryItemModelCopyWithImpl<$Res>
|
||||
implements _$CallHistoryItemModelCopyWith<$Res> {
|
||||
__$CallHistoryItemModelCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _CallHistoryItemModel _self;
|
||||
final $Res Function(_CallHistoryItemModel) _then;
|
||||
|
||||
/// Create a copy of CallHistoryItemModel
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? deviceIdentificator = null,Object? phone = null,Object? name = freezed,Object? isIncoming = null,Object? isAccepted = null,Object? duration = null,Object? occurredAt = null,Object? createdAt = null,}) {
|
||||
return _then(_CallHistoryItemModel(
|
||||
deviceIdentificator: null == deviceIdentificator ? _self.deviceIdentificator : deviceIdentificator // ignore: cast_nullable_to_non_nullable
|
||||
as String,phone: null == phone ? _self.phone : phone // ignore: cast_nullable_to_non_nullable
|
||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,isIncoming: null == isIncoming ? _self.isIncoming : isIncoming // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isAccepted: null == isAccepted ? _self.isAccepted : isAccepted // ignore: cast_nullable_to_non_nullable
|
||||
as bool,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable
|
||||
as int,occurredAt: null == occurredAt ? _self.occurredAt : occurredAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,46 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'call_history_response_model.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_CallHistoryResponseModel _$CallHistoryResponseModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _CallHistoryResponseModel(
|
||||
total: (json['total'] as num).toInt(),
|
||||
items: (json['items'] as List<dynamic>)
|
||||
.map((e) => CallHistoryItemModel.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CallHistoryResponseModelToJson(
|
||||
_CallHistoryResponseModel instance,
|
||||
) => <String, dynamic>{'total': instance.total, 'items': instance.items};
|
||||
|
||||
_CallHistoryItemModel _$CallHistoryItemModelFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _CallHistoryItemModel(
|
||||
deviceIdentificator: json['deviceIdentificator'] as String,
|
||||
phone: json['phone'] as String,
|
||||
name: json['name'] as String?,
|
||||
isIncoming: json['isIncoming'] as bool,
|
||||
isAccepted: json['isAccepted'] as bool,
|
||||
duration: (json['duration'] as num).toInt(),
|
||||
occurredAt: (json['occurredAt'] as num).toInt(),
|
||||
createdAt: (json['createdAt'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CallHistoryItemModelToJson(
|
||||
_CallHistoryItemModel instance,
|
||||
) => <String, dynamic>{
|
||||
'deviceIdentificator': instance.deviceIdentificator,
|
||||
'phone': instance.phone,
|
||||
'name': instance.name,
|
||||
'isIncoming': instance.isIncoming,
|
||||
'isAccepted': instance.isAccepted,
|
||||
'duration': instance.duration,
|
||||
'occurredAt': instance.occurredAt,
|
||||
'createdAt': instance.createdAt,
|
||||
};
|
||||
@@ -0,0 +1,321 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:legacy_shared/legacy_shared.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
|
||||
import '../data/call_history_entity.dart';
|
||||
import 'state/call_history_view_model.dart';
|
||||
import 'state/call_history_view_state.dart';
|
||||
|
||||
class CallHistoryScreen extends ConsumerWidget {
|
||||
const CallHistoryScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final state = ref.watch(callHistoryViewModelProvider);
|
||||
final vm = ref.read(callHistoryViewModelProvider.notifier);
|
||||
final filtered = state.filteredCalls;
|
||||
|
||||
return LegacyPageLayout(
|
||||
theme: theme,
|
||||
title: context.translate(I18n.callHistory),
|
||||
body: state.isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: state.errorMessage.isNotEmpty
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.error_outline,
|
||||
size: 64, color: Colors.grey.shade300),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
state.errorMessage,
|
||||
style: TextStyle(
|
||||
color: Colors.grey.shade500, fontSize: 14),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
children: [
|
||||
_FilterBar(
|
||||
selected: state.filter,
|
||||
onChanged: vm.setFilter,
|
||||
),
|
||||
Expanded(
|
||||
child: filtered.isEmpty
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.phone_missed_outlined,
|
||||
size: 64,
|
||||
color: Colors.grey.shade300),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
context
|
||||
.translate(I18n.callHistoryEmpty),
|
||||
style: TextStyle(
|
||||
color: Colors.grey.shade500,
|
||||
fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16, vertical: 4),
|
||||
itemCount: filtered.length,
|
||||
itemBuilder: (context, index) {
|
||||
final call = filtered[index];
|
||||
final showDateHeader = index == 0 ||
|
||||
!_isSameDay(
|
||||
filtered[index - 1].occurredAt,
|
||||
call.occurredAt,
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (showDateHeader)
|
||||
_DateHeader(
|
||||
timestamp: call.occurredAt),
|
||||
_CallTile(
|
||||
call: call,
|
||||
primaryColor: theme.getColorFor(
|
||||
ThemeCode.legacyPrimary),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static bool _isSameDay(int ts1, int ts2) {
|
||||
final d1 = DateTime.fromMillisecondsSinceEpoch(ts1);
|
||||
final d2 = DateTime.fromMillisecondsSinceEpoch(ts2);
|
||||
return d1.year == d2.year && d1.month == d2.month && d1.day == d2.day;
|
||||
}
|
||||
}
|
||||
|
||||
class _FilterBar extends StatelessWidget {
|
||||
final CallFilter selected;
|
||||
final ValueChanged<CallFilter> onChanged;
|
||||
|
||||
const _FilterBar({required this.selected, required this.onChanged});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final filters = CallFilter.values;
|
||||
final selectedIndex = filters.indexOf(selected);
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||
padding: const EdgeInsets.all(4),
|
||||
height: 40,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade200,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final tabWidth = constraints.maxWidth / filters.length;
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.easeInOut,
|
||||
left: selectedIndex * tabWidth,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
width: tabWidth,
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.08),
|
||||
blurRadius: 4,
|
||||
offset: const Offset(0, 1),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: filters.map((filter) {
|
||||
final isSelected = filter == selected;
|
||||
final label = switch (filter) {
|
||||
CallFilter.all =>
|
||||
context.translate(I18n.locationListAll),
|
||||
CallFilter.incoming =>
|
||||
context.translate(I18n.callIncoming),
|
||||
CallFilter.outgoing =>
|
||||
context.translate(I18n.callOutgoing),
|
||||
CallFilter.missed =>
|
||||
context.translate(I18n.callMissed),
|
||||
};
|
||||
|
||||
return Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () => onChanged(filter),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Center(
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: isSelected
|
||||
? FontWeight.w600
|
||||
: FontWeight.w500,
|
||||
color: isSelected
|
||||
? Colors.black87
|
||||
: Colors.grey.shade600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DateHeader extends StatelessWidget {
|
||||
final int timestamp;
|
||||
|
||||
const _DateHeader({required this.timestamp});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final date = DateTime.fromMillisecondsSinceEpoch(timestamp);
|
||||
final now = DateTime.now();
|
||||
final today = DateTime(now.year, now.month, now.day);
|
||||
final dateDay = DateTime(date.year, date.month, date.day);
|
||||
final diff = today.difference(dateDay).inDays;
|
||||
|
||||
String label;
|
||||
if (diff == 0) {
|
||||
label = context.translate(I18n.today);
|
||||
} else if (diff == 1) {
|
||||
label = context.translate(I18n.yesterday);
|
||||
} else {
|
||||
label =
|
||||
'${date.day.toString().padLeft(2, '0')}/${date.month.toString().padLeft(2, '0')}/${date.year}';
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 12, bottom: 6, left: 4),
|
||||
child: Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.grey.shade500,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CallTile extends StatelessWidget {
|
||||
final CallHistoryEntity call;
|
||||
final Color primaryColor;
|
||||
|
||||
const _CallTile({required this.call, required this.primaryColor});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final date = DateTime.fromMillisecondsSinceEpoch(call.occurredAt);
|
||||
final timeStr =
|
||||
'${date.hour.toString().padLeft(2, '0')}:${date.minute.toString().padLeft(2, '0')}';
|
||||
|
||||
final displayName = call.name ?? call.phone;
|
||||
final subtitle = call.name != null ? call.phone : null;
|
||||
|
||||
final durationMin = call.duration ~/ 60;
|
||||
final durationSec = call.duration % 60;
|
||||
final durationStr = durationMin > 0
|
||||
? '${durationMin}m ${durationSec}s'
|
||||
: '${durationSec}s';
|
||||
|
||||
final isAccepted = call.isAccepted;
|
||||
final isIncoming = call.isIncoming;
|
||||
|
||||
final IconData icon;
|
||||
final Color iconColor;
|
||||
if (!isAccepted) {
|
||||
icon = isIncoming ? Icons.phone_missed : Icons.phone_disabled;
|
||||
iconColor = Colors.red;
|
||||
} else {
|
||||
icon = isIncoming ? Icons.call_received : Icons.call_made;
|
||||
iconColor = primaryColor;
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 2),
|
||||
child: ListTile(
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
leading: Container(
|
||||
width: 44,
|
||||
height: 44,
|
||||
decoration: BoxDecoration(
|
||||
color: iconColor.withValues(alpha: 0.08),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(icon, color: iconColor, size: 22),
|
||||
),
|
||||
title: Text(
|
||||
displayName,
|
||||
style: TextStyle(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: isAccepted ? Colors.black87 : Colors.red.shade700,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
subtitle: Row(
|
||||
children: [
|
||||
Icon(
|
||||
isIncoming ? Icons.south_west : Icons.north_east,
|
||||
size: 12,
|
||||
color: iconColor.withValues(alpha: 0.7),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
if (subtitle != null) ...[
|
||||
Text(subtitle,
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: Colors.grey.shade600)),
|
||||
const SizedBox(width: 8),
|
||||
],
|
||||
if (isAccepted)
|
||||
Text(durationStr,
|
||||
style:
|
||||
TextStyle(fontSize: 12, color: Colors.grey.shade500)),
|
||||
],
|
||||
),
|
||||
trailing: Text(
|
||||
timeStr,
|
||||
style: TextStyle(fontSize: 13, color: Colors.grey.shade500),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:legacy_shared/legacy_shared.dart';
|
||||
|
||||
import '../../data/call_history_datasource.dart';
|
||||
import '../../data/call_history_datasource_provider.dart';
|
||||
import '../../data/call_history_entity.dart';
|
||||
import 'call_history_view_state.dart';
|
||||
|
||||
final callHistoryViewModelProvider =
|
||||
NotifierProvider.autoDispose<CallHistoryViewModel, CallHistoryViewState>(
|
||||
CallHistoryViewModel.new,
|
||||
);
|
||||
|
||||
class CallHistoryViewModel extends Notifier<CallHistoryViewState> {
|
||||
late final CallHistoryDatasource _datasource;
|
||||
|
||||
@override
|
||||
CallHistoryViewState build() {
|
||||
_datasource = ref.read(callHistoryDatasourceProvider);
|
||||
Future.microtask(() => _load());
|
||||
return const CallHistoryViewState();
|
||||
}
|
||||
|
||||
Future<void> _load() async {
|
||||
final device = ref.read(selectedDeviceProvider);
|
||||
if (device == null) {
|
||||
state = state.copyWith(isLoading: false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
final calls = await _datasource.getCallHistory(
|
||||
deviceIdentificator: device.identificator,
|
||||
);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(
|
||||
calls: calls,
|
||||
filteredCalls: calls,
|
||||
isLoading: false,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: e.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void setFilter(CallFilter filter) {
|
||||
state = state.copyWith(
|
||||
filter: filter,
|
||||
filteredCalls: _applyFilter(state.calls, filter),
|
||||
);
|
||||
}
|
||||
|
||||
List<CallHistoryEntity> _applyFilter(
|
||||
List<CallHistoryEntity> calls, CallFilter filter) {
|
||||
switch (filter) {
|
||||
case CallFilter.all:
|
||||
return calls;
|
||||
case CallFilter.incoming:
|
||||
return calls.where((c) => c.isIncoming).toList();
|
||||
case CallFilter.outgoing:
|
||||
return calls.where((c) => !c.isIncoming).toList();
|
||||
case CallFilter.missed:
|
||||
return calls.where((c) => !c.isAccepted).toList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import '../../data/call_history_entity.dart';
|
||||
|
||||
part 'call_history_view_state.freezed.dart';
|
||||
|
||||
enum CallFilter { all, incoming, outgoing, missed }
|
||||
|
||||
@freezed
|
||||
abstract class CallHistoryViewState with _$CallHistoryViewState {
|
||||
const factory CallHistoryViewState({
|
||||
@Default(true) bool isLoading,
|
||||
@Default([]) List<CallHistoryEntity> calls,
|
||||
@Default([]) List<CallHistoryEntity> filteredCalls,
|
||||
@Default(CallFilter.all) CallFilter filter,
|
||||
@Default('') String errorMessage,
|
||||
}) = _CallHistoryViewState;
|
||||
}
|
||||
@@ -0,0 +1,295 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'call_history_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$CallHistoryViewState {
|
||||
|
||||
bool get isLoading; List<CallHistoryEntity> get calls; List<CallHistoryEntity> get filteredCalls; CallFilter get filter; String get errorMessage;
|
||||
/// Create a copy of CallHistoryViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$CallHistoryViewStateCopyWith<CallHistoryViewState> get copyWith => _$CallHistoryViewStateCopyWithImpl<CallHistoryViewState>(this as CallHistoryViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallHistoryViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&const DeepCollectionEquality().equals(other.calls, calls)&&const DeepCollectionEquality().equals(other.filteredCalls, filteredCalls)&&(identical(other.filter, filter) || other.filter == filter)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,const DeepCollectionEquality().hash(calls),const DeepCollectionEquality().hash(filteredCalls),filter,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CallHistoryViewState(isLoading: $isLoading, calls: $calls, filteredCalls: $filteredCalls, filter: $filter, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $CallHistoryViewStateCopyWith<$Res> {
|
||||
factory $CallHistoryViewStateCopyWith(CallHistoryViewState value, $Res Function(CallHistoryViewState) _then) = _$CallHistoryViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isLoading, List<CallHistoryEntity> calls, List<CallHistoryEntity> filteredCalls, CallFilter filter, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$CallHistoryViewStateCopyWithImpl<$Res>
|
||||
implements $CallHistoryViewStateCopyWith<$Res> {
|
||||
_$CallHistoryViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final CallHistoryViewState _self;
|
||||
final $Res Function(CallHistoryViewState) _then;
|
||||
|
||||
/// Create a copy of CallHistoryViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? calls = null,Object? filteredCalls = null,Object? filter = null,Object? errorMessage = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,calls: null == calls ? _self.calls : calls // ignore: cast_nullable_to_non_nullable
|
||||
as List<CallHistoryEntity>,filteredCalls: null == filteredCalls ? _self.filteredCalls : filteredCalls // ignore: cast_nullable_to_non_nullable
|
||||
as List<CallHistoryEntity>,filter: null == filter ? _self.filter : filter // ignore: cast_nullable_to_non_nullable
|
||||
as CallFilter,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [CallHistoryViewState].
|
||||
extension CallHistoryViewStatePatterns on CallHistoryViewState {
|
||||
/// A variant of `map` that fallback to returning `orElse`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _CallHistoryViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryViewState() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// Callbacks receives the raw object, upcasted.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case final Subclass2 value:
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _CallHistoryViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryViewState():
|
||||
return $default(_that);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `map` that fallback to returning `null`.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case final Subclass value:
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _CallHistoryViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryViewState() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, List<CallHistoryEntity> calls, List<CallHistoryEntity> filteredCalls, CallFilter filter, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.calls,_that.filteredCalls,_that.filter,_that.errorMessage);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, List<CallHistoryEntity> calls, List<CallHistoryEntity> filteredCalls, CallFilter filter, String errorMessage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryViewState():
|
||||
return $default(_that.isLoading,_that.calls,_that.filteredCalls,_that.filter,_that.errorMessage);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, List<CallHistoryEntity> calls, List<CallHistoryEntity> filteredCalls, CallFilter filter, String errorMessage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CallHistoryViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.calls,_that.filteredCalls,_that.filter,_that.errorMessage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _CallHistoryViewState implements CallHistoryViewState {
|
||||
const _CallHistoryViewState({this.isLoading = true, final List<CallHistoryEntity> calls = const [], final List<CallHistoryEntity> filteredCalls = const [], this.filter = CallFilter.all, this.errorMessage = ''}): _calls = calls,_filteredCalls = filteredCalls;
|
||||
|
||||
|
||||
@override@JsonKey() final bool isLoading;
|
||||
final List<CallHistoryEntity> _calls;
|
||||
@override@JsonKey() List<CallHistoryEntity> get calls {
|
||||
if (_calls is EqualUnmodifiableListView) return _calls;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_calls);
|
||||
}
|
||||
|
||||
final List<CallHistoryEntity> _filteredCalls;
|
||||
@override@JsonKey() List<CallHistoryEntity> get filteredCalls {
|
||||
if (_filteredCalls is EqualUnmodifiableListView) return _filteredCalls;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_filteredCalls);
|
||||
}
|
||||
|
||||
@override@JsonKey() final CallFilter filter;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
|
||||
/// Create a copy of CallHistoryViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$CallHistoryViewStateCopyWith<_CallHistoryViewState> get copyWith => __$CallHistoryViewStateCopyWithImpl<_CallHistoryViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallHistoryViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&const DeepCollectionEquality().equals(other._calls, _calls)&&const DeepCollectionEquality().equals(other._filteredCalls, _filteredCalls)&&(identical(other.filter, filter) || other.filter == filter)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,const DeepCollectionEquality().hash(_calls),const DeepCollectionEquality().hash(_filteredCalls),filter,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CallHistoryViewState(isLoading: $isLoading, calls: $calls, filteredCalls: $filteredCalls, filter: $filter, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$CallHistoryViewStateCopyWith<$Res> implements $CallHistoryViewStateCopyWith<$Res> {
|
||||
factory _$CallHistoryViewStateCopyWith(_CallHistoryViewState value, $Res Function(_CallHistoryViewState) _then) = __$CallHistoryViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isLoading, List<CallHistoryEntity> calls, List<CallHistoryEntity> filteredCalls, CallFilter filter, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$CallHistoryViewStateCopyWithImpl<$Res>
|
||||
implements _$CallHistoryViewStateCopyWith<$Res> {
|
||||
__$CallHistoryViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _CallHistoryViewState _self;
|
||||
final $Res Function(_CallHistoryViewState) _then;
|
||||
|
||||
/// Create a copy of CallHistoryViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? calls = null,Object? filteredCalls = null,Object? filter = null,Object? errorMessage = null,}) {
|
||||
return _then(_CallHistoryViewState(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,calls: null == calls ? _self._calls : calls // ignore: cast_nullable_to_non_nullable
|
||||
as List<CallHistoryEntity>,filteredCalls: null == filteredCalls ? _self._filteredCalls : filteredCalls // ignore: cast_nullable_to_non_nullable
|
||||
as List<CallHistoryEntity>,filter: null == filter ? _self.filter : filter // ignore: cast_nullable_to_non_nullable
|
||||
as CallFilter,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -25,7 +25,7 @@ class ContactsScreen extends ConsumerWidget {
|
||||
contactsViewModelProvider.select((s) => s.errorMessage),
|
||||
(previous, next) {
|
||||
if (next.isNotEmpty) {
|
||||
showTopSnackbar(context, message: next, type: MessageType.error);
|
||||
showTopSnackbar(context, message: context.translate(next), type: MessageType.error);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -58,14 +58,21 @@ class ContactsScreen extends ConsumerWidget {
|
||||
shape: const CircleBorder(),
|
||||
child: InkWell(
|
||||
customBorder: const CircleBorder(),
|
||||
onTap: () => showDialog(
|
||||
context: context,
|
||||
builder: (_) => const Dialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
child: NewContactDialog(),
|
||||
),
|
||||
),
|
||||
child: SizedBox(
|
||||
onTap: () {
|
||||
if (state.contacts.length == state.maxLimit) {
|
||||
showTopSnackbar(context, message: context.translate(I18n.errorContactsMax));
|
||||
return;
|
||||
}
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => const Dialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
child: NewContactDialog(),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: SizedBox(
|
||||
width: SizeUtils.getByScreen(small: 48, big: 46),
|
||||
height: SizeUtils.getByScreen(small: 48, big: 46),
|
||||
child: Icon(
|
||||
|
||||
@@ -104,18 +104,22 @@ class _EditContactScreenState extends ConsumerState<EditContactScreen> {
|
||||
height: SizeUtils.getByScreen(small: 28, big: 26),
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
initialSelection: state.dialCode,
|
||||
onChanged: (country) {
|
||||
final vm =
|
||||
ref.read(contactsViewModelProvider.notifier);
|
||||
vm.updateDialCode(
|
||||
country.dialCode ?? state.dialCode,
|
||||
);
|
||||
},
|
||||
width: 80,
|
||||
Align(
|
||||
alignment: Alignment.bottomLeft,
|
||||
child: CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
initialSelection: state.dialCode,
|
||||
onChanged: (country) {
|
||||
final vm =
|
||||
ref.read(contactsViewModelProvider.notifier);
|
||||
vm.updateDialCode(
|
||||
country.dialCode ?? state.dialCode,
|
||||
);
|
||||
},
|
||||
width: 80,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: SizeUtils.getByScreen(small: 10, big: 10, xl: 6),
|
||||
|
||||
@@ -134,6 +134,11 @@ class ContactsViewModel extends Notifier<ContactsViewState> {
|
||||
Future<bool> deleteContact(ContactEntity contact) async {
|
||||
if (state.isLoading) return false;
|
||||
|
||||
if (state.contacts.length == 1){
|
||||
state = state.copyWith(errorMessage: I18n.errorContactsMin);
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
state = state.copyWith(isLoading: true, errorMessage: '');
|
||||
|
||||
|
||||
@@ -8,9 +8,10 @@ part 'contacts_view_state.freezed.dart';
|
||||
abstract class ContactsViewState with _$ContactsViewState {
|
||||
const factory ContactsViewState({
|
||||
@Default([]) List<ContactEntity> contacts,
|
||||
@Default(10) int maxLimit,
|
||||
@Default('+34') String dialCode,
|
||||
@Default(true) bool isLoading,
|
||||
@Default(false) bool isEditing,
|
||||
@Default('') String errorMessage,
|
||||
@Default('') String errorMessage
|
||||
}) = _ContactsViewState;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$ContactsViewState {
|
||||
|
||||
List<ContactEntity> get contacts; String get dialCode; bool get isLoading; bool get isEditing; String get errorMessage;
|
||||
List<ContactEntity> get contacts; int get maxLimit; String get dialCode; bool get isLoading; bool get isEditing; String get errorMessage;
|
||||
/// Create a copy of ContactsViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -25,16 +25,16 @@ $ContactsViewStateCopyWith<ContactsViewState> get copyWith => _$ContactsViewStat
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactsViewState&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isEditing, isEditing) || other.isEditing == isEditing)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ContactsViewState&&const DeepCollectionEquality().equals(other.contacts, contacts)&&(identical(other.maxLimit, maxLimit) || other.maxLimit == maxLimit)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isEditing, isEditing) || other.isEditing == isEditing)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(contacts),dialCode,isLoading,isEditing,errorMessage);
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(contacts),maxLimit,dialCode,isLoading,isEditing,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ContactsViewState(contacts: $contacts, dialCode: $dialCode, isLoading: $isLoading, isEditing: $isEditing, errorMessage: $errorMessage)';
|
||||
return 'ContactsViewState(contacts: $contacts, maxLimit: $maxLimit, dialCode: $dialCode, isLoading: $isLoading, isEditing: $isEditing, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ abstract mixin class $ContactsViewStateCopyWith<$Res> {
|
||||
factory $ContactsViewStateCopyWith(ContactsViewState value, $Res Function(ContactsViewState) _then) = _$ContactsViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
List<ContactEntity> contacts, String dialCode, bool isLoading, bool isEditing, String errorMessage
|
||||
List<ContactEntity> contacts, int maxLimit, String dialCode, bool isLoading, bool isEditing, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
@@ -62,10 +62,11 @@ class _$ContactsViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of ContactsViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? contacts = null,Object? dialCode = null,Object? isLoading = null,Object? isEditing = null,Object? errorMessage = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? contacts = null,Object? maxLimit = null,Object? dialCode = null,Object? isLoading = null,Object? isEditing = null,Object? errorMessage = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
contacts: null == contacts ? _self.contacts : contacts // ignore: cast_nullable_to_non_nullable
|
||||
as List<ContactEntity>,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as List<ContactEntity>,maxLimit: null == maxLimit ? _self.maxLimit : maxLimit // ignore: cast_nullable_to_non_nullable
|
||||
as int,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isEditing: null == isEditing ? _self.isEditing : isEditing // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
@@ -154,10 +155,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<ContactEntity> contacts, String dialCode, bool isLoading, bool isEditing, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<ContactEntity> contacts, int maxLimit, String dialCode, bool isLoading, bool isEditing, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ContactsViewState() when $default != null:
|
||||
return $default(_that.contacts,_that.dialCode,_that.isLoading,_that.isEditing,_that.errorMessage);case _:
|
||||
return $default(_that.contacts,_that.maxLimit,_that.dialCode,_that.isLoading,_that.isEditing,_that.errorMessage);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -175,10 +176,10 @@ return $default(_that.contacts,_that.dialCode,_that.isLoading,_that.isEditing,_t
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<ContactEntity> contacts, String dialCode, bool isLoading, bool isEditing, String errorMessage) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<ContactEntity> contacts, int maxLimit, String dialCode, bool isLoading, bool isEditing, String errorMessage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ContactsViewState():
|
||||
return $default(_that.contacts,_that.dialCode,_that.isLoading,_that.isEditing,_that.errorMessage);case _:
|
||||
return $default(_that.contacts,_that.maxLimit,_that.dialCode,_that.isLoading,_that.isEditing,_that.errorMessage);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -195,10 +196,10 @@ return $default(_that.contacts,_that.dialCode,_that.isLoading,_that.isEditing,_t
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<ContactEntity> contacts, String dialCode, bool isLoading, bool isEditing, String errorMessage)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<ContactEntity> contacts, int maxLimit, String dialCode, bool isLoading, bool isEditing, String errorMessage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ContactsViewState() when $default != null:
|
||||
return $default(_that.contacts,_that.dialCode,_that.isLoading,_that.isEditing,_that.errorMessage);case _:
|
||||
return $default(_that.contacts,_that.maxLimit,_that.dialCode,_that.isLoading,_that.isEditing,_that.errorMessage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -210,7 +211,7 @@ return $default(_that.contacts,_that.dialCode,_that.isLoading,_that.isEditing,_t
|
||||
|
||||
|
||||
class _ContactsViewState implements ContactsViewState {
|
||||
const _ContactsViewState({final List<ContactEntity> contacts = const [], this.dialCode = '+34', this.isLoading = true, this.isEditing = false, this.errorMessage = ''}): _contacts = contacts;
|
||||
const _ContactsViewState({final List<ContactEntity> contacts = const [], this.maxLimit = 10, this.dialCode = '+34', this.isLoading = true, this.isEditing = false, this.errorMessage = ''}): _contacts = contacts;
|
||||
|
||||
|
||||
final List<ContactEntity> _contacts;
|
||||
@@ -220,6 +221,7 @@ class _ContactsViewState implements ContactsViewState {
|
||||
return EqualUnmodifiableListView(_contacts);
|
||||
}
|
||||
|
||||
@override@JsonKey() final int maxLimit;
|
||||
@override@JsonKey() final String dialCode;
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool isEditing;
|
||||
@@ -235,16 +237,16 @@ _$ContactsViewStateCopyWith<_ContactsViewState> get copyWith => __$ContactsViewS
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactsViewState&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isEditing, isEditing) || other.isEditing == isEditing)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ContactsViewState&&const DeepCollectionEquality().equals(other._contacts, _contacts)&&(identical(other.maxLimit, maxLimit) || other.maxLimit == maxLimit)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isEditing, isEditing) || other.isEditing == isEditing)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_contacts),dialCode,isLoading,isEditing,errorMessage);
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_contacts),maxLimit,dialCode,isLoading,isEditing,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ContactsViewState(contacts: $contacts, dialCode: $dialCode, isLoading: $isLoading, isEditing: $isEditing, errorMessage: $errorMessage)';
|
||||
return 'ContactsViewState(contacts: $contacts, maxLimit: $maxLimit, dialCode: $dialCode, isLoading: $isLoading, isEditing: $isEditing, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -255,7 +257,7 @@ abstract mixin class _$ContactsViewStateCopyWith<$Res> implements $ContactsViewS
|
||||
factory _$ContactsViewStateCopyWith(_ContactsViewState value, $Res Function(_ContactsViewState) _then) = __$ContactsViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
List<ContactEntity> contacts, String dialCode, bool isLoading, bool isEditing, String errorMessage
|
||||
List<ContactEntity> contacts, int maxLimit, String dialCode, bool isLoading, bool isEditing, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
@@ -272,10 +274,11 @@ class __$ContactsViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of ContactsViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? contacts = null,Object? dialCode = null,Object? isLoading = null,Object? isEditing = null,Object? errorMessage = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? contacts = null,Object? maxLimit = null,Object? dialCode = null,Object? isLoading = null,Object? isEditing = null,Object? errorMessage = null,}) {
|
||||
return _then(_ContactsViewState(
|
||||
contacts: null == contacts ? _self._contacts : contacts // ignore: cast_nullable_to_non_nullable
|
||||
as List<ContactEntity>,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as List<ContactEntity>,maxLimit: null == maxLimit ? _self.maxLimit : maxLimit // ignore: cast_nullable_to_non_nullable
|
||||
as int,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isEditing: null == isEditing ? _self.isEditing : isEditing // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
|
||||
@@ -24,7 +24,7 @@ class ContactCard extends ConsumerWidget {
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: SizeUtils.getByScreen(small: 22, big: 21),
|
||||
horizontal: SizeUtils.getByScreen(small: 22, big: 21, xl: 18),
|
||||
vertical: SizeUtils.getByScreen(small: 12, big: 8),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
@@ -71,11 +71,13 @@ class ContactCard extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
if (isEditing) ...[
|
||||
DecoratedBox(
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFF5D52),
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
height: SizeUtils.getByScreen(small: 48, big: 48, xl: 40),
|
||||
width: SizeUtils.getByScreen(small: 48, big: 48, xl: 40),
|
||||
child: IconButton(
|
||||
onPressed: () => showDialog(
|
||||
context: context,
|
||||
@@ -83,21 +85,30 @@ class ContactCard extends ConsumerWidget {
|
||||
child: ConfirmDeleteDialog(contact: contact),
|
||||
),
|
||||
),
|
||||
icon: const Icon(Icons.close, color: Colors.white),
|
||||
icon: Icon(
|
||||
Icons.close,
|
||||
color: Colors.white,
|
||||
size: SizeUtils.getByScreen(small: 28, big: 22),),
|
||||
),
|
||||
),
|
||||
SizedBox(width: SizeUtils.getByScreen(small: 16, big: 14)),
|
||||
DecoratedBox(
|
||||
SizedBox(width: SizeUtils.getByScreen(small: 16, big: 14, xl: 10)),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: theme.getColorFor(ThemeCode.legacyPrimary),
|
||||
borderRadius: BorderRadius.all(Radius.circular(12)),
|
||||
),
|
||||
height: SizeUtils.getByScreen(small: 48, big: 48, xl: 40),
|
||||
width: SizeUtils.getByScreen(small: 48, big: 48, xl: 40),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
final nav = GetIt.I<NavigationContract>();
|
||||
nav.pushTo(AppRoutes.editContactPath(contact.id));
|
||||
},
|
||||
icon: const Icon(Icons.edit_outlined, color: Colors.white),
|
||||
icon: Icon(
|
||||
Icons.edit_outlined,
|
||||
color: Colors.white,
|
||||
size: SizeUtils.getByScreen(small: 28, big: 22),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user