Compare commits
41 Commits
feature/re
...
set-reset-
| Author | SHA1 | Date | |
|---|---|---|---|
| c80b7a9a5f | |||
| db153bb38d | |||
| 50c4529cba | |||
| b6deb4b371 | |||
| 47c7821b0c | |||
| a07e9c23ca | |||
| 5111d5d65f | |||
| ced0895063 | |||
| 34e7a7c60f | |||
| c89f1c666e | |||
| 33c2403aef | |||
| 0088d146f0 | |||
| 94c042d403 | |||
| 48cb23379c | |||
| e526dce2c9 | |||
| cacc2460f1 | |||
| dd53db6795 | |||
| 435a9c04f9 | |||
| 8e3a27e0d3 | |||
| 48d2430c9c | |||
| cf0c55eafe | |||
| 03c6633504 | |||
| b8184f02ec | |||
| c12d1924c4 | |||
| 869f33f1f1 | |||
| a07246130e | |||
| 67aafafd1e | |||
| c929e1e2d7 | |||
| 990266ba95 | |||
| fa36037aac | |||
| c9e2adf692 | |||
| 995b69eb65 | |||
| 88269c40f8 | |||
| f1226b4c18 | |||
| b636550619 | |||
| 797d236547 | |||
| 90447ce9a0 | |||
| 22ef648b41 | |||
| 4eb4ac81ce | |||
| 904cfee2a9 | |||
| 69b3cf358a |
@@ -3,349 +3,349 @@
|
||||
"packages": [
|
||||
{
|
||||
"name": "ansi_styles",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/ansi_styles-0.3.2+1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ansi_styles-0.3.2+1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "args",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/args-2.7.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "async",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/async-2.13.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "characters",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "charcode",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/charcode-1.4.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/charcode-1.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "checked_yaml",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/checked_yaml-2.0.4",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/checked_yaml-2.0.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "cli_launcher",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cli_launcher-0.3.2+1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_launcher-0.3.2+1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "cli_util",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cli_util-0.4.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_util-0.4.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "collection",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "conventional_commit",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/conventional_commit-0.6.1+1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/conventional_commit-0.6.1+1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "ffi",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/ffi-2.1.4",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ffi-2.1.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "file",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/file-7.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "flutter",
|
||||
"rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter",
|
||||
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "flutter_secure_storage",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage-9.2.4",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage-9.2.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "flutter_secure_storage_linux",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_linux-1.2.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "flutter_secure_storage_macos",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_macos-3.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "flutter_secure_storage_platform_interface",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_platform_interface-1.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_platform_interface-1.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "flutter_secure_storage_web",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_web-1.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "flutter_secure_storage_windows",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_secure_storage_windows-3.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "flutter_web_plugins",
|
||||
"rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_web_plugins",
|
||||
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_web_plugins",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "glob",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/glob-2.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "graphs",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/graphs-2.3.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/graphs-2.3.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "http",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.5.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http-1.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "http_parser",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_parser-4.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "io",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/io-1.0.5",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/io-1.0.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "js",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.6.7",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/js-0.6.7",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.19"
|
||||
},
|
||||
{
|
||||
"name": "json_annotation",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/json_annotation-4.9.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/json_annotation-4.9.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "material_color_utilities",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "melos",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/melos-6.3.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/melos-6.3.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.16.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "mustache_template",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/mustache_template-2.0.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/mustache_template-2.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path-1.9.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "path_provider",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider-2.1.5",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider-2.1.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_android",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_android-2.2.20",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.20",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_foundation",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_foundation-2.4.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.4.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_linux",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.19"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_platform_interface",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_platform_interface-2.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_windows",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "platform",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.6",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/platform-3.1.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "plugin_platform_interface",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "pool",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pool-1.5.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pool-1.5.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "process",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/process-5.0.5",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/process-5.0.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "prompts",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/prompts-2.0.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/prompts-2.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "pub_semver",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_semver-2.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "pub_updater",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pub_updater-0.5.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_updater-0.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "pubspec_parse",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_parse-1.5.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "sky_engine",
|
||||
"rootUri": "file:///C:/Program%20Files/Flutter/bin/cache/pkg/sky_engine",
|
||||
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "source_span",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_span-1.10.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "stack_trace",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stack_trace-1.12.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "string_scanner",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/string_scanner-1.4.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "term_glyph",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/term_glyph-1.2.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "typed_data",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/typed_data-1.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "vector_math",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "web",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web-1.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "win32",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/win32-5.15.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/win32-5.15.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "xdg_directories",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/xdg_directories-1.1.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "yaml",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml-3.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "yaml_edit",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/yaml_edit-2.2.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml_edit-2.2.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
@@ -358,7 +358,7 @@
|
||||
],
|
||||
"generator": "pub",
|
||||
"generatorVersion": "3.9.2",
|
||||
"flutterRoot": "file:///C:/Program%20Files/Flutter",
|
||||
"flutterVersion": "3.35.6",
|
||||
"pubCache": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache"
|
||||
"flutterRoot": "file:///Users/juliandalcalaf/Development/flutter",
|
||||
"flutterVersion": "3.35.7",
|
||||
"pubCache": "file:///Users/juliandalcalaf/.pub-cache"
|
||||
}
|
||||
|
||||
Binary file not shown.
1
.idea/modules.xml
generated
1
.idea/modules.xml
generated
@@ -17,7 +17,6 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/modules/legacy/melos_legacy.iml" filepath="$PROJECT_DIR$/modules/legacy/melos_legacy.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/modules/legacy/modules/legacy_auth/melos_legacy_auth.iml" filepath="$PROJECT_DIR$/modules/legacy/modules/legacy_auth/melos_legacy_auth.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/modules/legacy/modules/legacy_dashboard_shell/melos_legacy_dashboard_shell.iml" filepath="$PROJECT_DIR$/modules/legacy/modules/legacy_dashboard_shell/melos_legacy_dashboard_shell.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/modules/legacy/packages/legacy_design_system/melos_legacy_design_system.iml" filepath="$PROJECT_DIR$/modules/legacy/packages/legacy_design_system/melos_legacy_design_system.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/modules/legacy/packages/legacy_shared/melos_legacy_shared.iml" filepath="$PROJECT_DIR$/modules/legacy/packages/legacy_shared/melos_legacy_shared.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/modules/legacy/modules/location/melos_location.iml" filepath="$PROJECT_DIR$/modules/legacy/modules/location/melos_location.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/packages/navigation/melos_navigation.iml" filepath="$PROJECT_DIR$/packages/navigation/melos_navigation.iml" />
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Flutter Run -> 'flutter_treezor_entrust_sdk_bridge_example'" type="FlutterRunConfigurationType" factoryName="Flutter">
|
||||
<option name="filePath" value="$PROJECT_DIR$/packages//flutter_treezor_entrust_sdk_bridge//example/lib/main.dart" />
|
||||
<option name="filePath" value="$PROJECT_DIR$/packages/flutter_treezor_entrust_sdk_bridge/example/lib/main.dart" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -1,6 +1,6 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Flutter Run -> 'sf_app_platform'" type="FlutterRunConfigurationType" factoryName="Flutter">
|
||||
<option name="filePath" value="$PROJECT_DIR$/apps//mobile_app/lib/main.dart" />
|
||||
<option name="filePath" value="$PROJECT_DIR$/apps/mobile_app/lib/main.dart" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- Generated by Melos -->
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Flutter Test -> 'design_system'" type="FlutterTestConfigType" factoryName="Flutter Test">
|
||||
<option name="testDir" value="$PROJECT_DIR$/packages\\design_system\test" />
|
||||
<option name="testDir" value="$PROJECT_DIR$/packages/design_system/test" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -1,7 +1,7 @@
|
||||
<!-- Generated by Melos -->
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Flutter Test -> 'flutter_treezor_entrust_sdk_bridge'" type="FlutterTestConfigType" factoryName="Flutter Test">
|
||||
<option name="testDir" value="$PROJECT_DIR$/packages\\flutter_treezor_entrust_sdk_bridge\test" />
|
||||
<option name="testDir" value="$PROJECT_DIR$/packages/flutter_treezor_entrust_sdk_bridge/test" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
@@ -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"
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
PODS:
|
||||
- Flutter (1.0.0)
|
||||
- flutter_contacts (0.0.1):
|
||||
- Flutter
|
||||
- flutter_native_splash (2.4.3):
|
||||
- Flutter
|
||||
- flutter_treezor_entrust_sdk_bridge (0.0.1):
|
||||
@@ -23,6 +25,7 @@ PODS:
|
||||
|
||||
DEPENDENCIES:
|
||||
- Flutter (from `Flutter`)
|
||||
- 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`)
|
||||
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
|
||||
@@ -35,6 +38,8 @@ DEPENDENCIES:
|
||||
EXTERNAL SOURCES:
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
flutter_contacts:
|
||||
:path: ".symlinks/plugins/flutter_contacts/ios"
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_treezor_entrust_sdk_bridge:
|
||||
@@ -54,6 +59,7 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_contacts: edb1c5ce76aa433e20e6cb14c615f4c0b66e0983
|
||||
flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29
|
||||
flutter_treezor_entrust_sdk_bridge: 4c2c94fb74ab57576e8d49f5f2a4b214e41141fe
|
||||
mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e
|
||||
|
||||
@@ -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)";
|
||||
|
||||
@@ -47,8 +47,14 @@
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>NSContactsUsageDescription</key>
|
||||
<string>Necesitamos acceso a tus contactos para seleccionar números de teléfono.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Necesitamos la cámara para escanear códigos QR</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Usamos tu ubicación para verificar la seguridad de las transacciones.</string>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>Usamos tu ubicación para verificar la seguridad de las transacciones.</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
|
||||
@@ -47,8 +47,14 @@
|
||||
<true/>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<true/>
|
||||
<key>NSContactsUsageDescription</key>
|
||||
<string>Necesitamos acceso a tus contactos para seleccionar números de teléfono.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Necesitamos la cámara para escanear códigos QR</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Usamos tu ubicación para verificar la seguridad de las transacciones.</string>
|
||||
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
|
||||
<string>Usamos tu ubicación para verificar la seguridad de las transacciones.</string>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<false/>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
|
||||
@@ -21,6 +21,25 @@ import 'package:splash/splash.dart';
|
||||
|
||||
final GlobalKey<NavigatorState> rootNavigatorKey = GlobalKey<NavigatorState>();
|
||||
|
||||
final _legacyControlPanelNavKey =
|
||||
GlobalKey<NavigatorState>(debugLabel: 'legacyControlPanel');
|
||||
final _legacyDeviceMgmtNavKey =
|
||||
GlobalKey<NavigatorState>(debugLabel: 'legacyDeviceMgmt');
|
||||
final _legacyLocationNavKey =
|
||||
GlobalKey<NavigatorState>(debugLabel: 'legacyLocation');
|
||||
final _legacyChatNavKey = GlobalKey<NavigatorState>(debugLabel: 'legacyChat');
|
||||
final _legacySettingsNavKey =
|
||||
GlobalKey<NavigatorState>(debugLabel: 'legacySettings');
|
||||
|
||||
final _dashboardHomeNavKey =
|
||||
GlobalKey<NavigatorState>(debugLabel: 'dashboardHome');
|
||||
final _dashboardActivityNavKey =
|
||||
GlobalKey<NavigatorState>(debugLabel: 'dashboardActivity');
|
||||
final _dashboardNotificationsNavKey =
|
||||
GlobalKey<NavigatorState>(debugLabel: 'dashboardNotifications');
|
||||
final _dashboardProfileNavKey =
|
||||
GlobalKey<NavigatorState>(debugLabel: 'dashboardProfile');
|
||||
|
||||
late final GoRouter appRouter;
|
||||
|
||||
void configureAppRouter() {
|
||||
@@ -40,6 +59,7 @@ void configureAppRouter() {
|
||||
},
|
||||
branches: [
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _legacyControlPanelNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.controlPanel,
|
||||
@@ -88,6 +108,7 @@ void configureAppRouter() {
|
||||
],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _legacyDeviceMgmtNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.deviceManagement,
|
||||
@@ -141,11 +162,22 @@ 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _legacyLocationNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.legacyLocation,
|
||||
@@ -156,6 +188,7 @@ void configureAppRouter() {
|
||||
),
|
||||
// TODO: Añadir branch para Chat (tab 4)
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _legacyChatNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: '${AppRoutes.legacyDashboard}/chat',
|
||||
@@ -170,6 +203,7 @@ void configureAppRouter() {
|
||||
],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _legacySettingsNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.settings,
|
||||
@@ -345,6 +379,7 @@ void configureAppRouter() {
|
||||
},
|
||||
branches: [
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _dashboardHomeNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.dashboardHome,
|
||||
@@ -386,6 +421,30 @@ void configureAppRouter() {
|
||||
name: 'home_extract',
|
||||
pageBuilder: const ExtractBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'edit',
|
||||
name: 'home_edit_child_profile',
|
||||
pageBuilder:
|
||||
const EditChildProfileBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'set-pin',
|
||||
name: 'home_set_card_pin',
|
||||
pageBuilder:
|
||||
const SetCardPinBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'change-pin',
|
||||
name: 'home_change_card_pin',
|
||||
pageBuilder:
|
||||
const ChangeCardPinBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'renew-card',
|
||||
name: 'home_renew_card',
|
||||
pageBuilder:
|
||||
const RenewCardBuilder().buildPage,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -393,6 +452,7 @@ void configureAppRouter() {
|
||||
],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _dashboardActivityNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.dashboardActivity,
|
||||
@@ -402,6 +462,7 @@ void configureAppRouter() {
|
||||
],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _dashboardNotificationsNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.dashboardNotifications,
|
||||
@@ -411,6 +472,7 @@ void configureAppRouter() {
|
||||
],
|
||||
),
|
||||
StatefulShellBranch(
|
||||
navigatorKey: _dashboardProfileNavKey,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: AppRoutes.dashboardProfile,
|
||||
@@ -427,6 +489,12 @@ void configureAppRouter() {
|
||||
name: 'profile_settings',
|
||||
pageBuilder: const ProfileSettingsBuilder().buildPage,
|
||||
routes: [
|
||||
GoRoute(
|
||||
path: 'edit-personal-data',
|
||||
name: 'profile_edit_personal_data',
|
||||
pageBuilder:
|
||||
const EditPersonalDataBuilder().buildPage,
|
||||
),
|
||||
GoRoute(
|
||||
path: 'payment-methods',
|
||||
name: 'profile_payment_methods',
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,19 +40,28 @@ class SaveFamilyAppState extends ConsumerState<SaveFamilyApp>
|
||||
repository: GetIt.I<QuestiaRepository>(),
|
||||
onUnauthorized: () {
|
||||
clearSessionData();
|
||||
appRouter.go(AppRoutes.legacyLogin);
|
||||
appRouter.go(AppRoutes.login);
|
||||
},
|
||||
);
|
||||
onBeforeSessionCleared = () {
|
||||
walletHeartbeat.stop();
|
||||
legacyHeartbeat.stop();
|
||||
};
|
||||
// walletHeartbeat.start();
|
||||
legacyHeartbeat.start();
|
||||
appRouter.routerDelegate.addListener(_onRouteChanged);
|
||||
}
|
||||
|
||||
void _onRouteChanged() {
|
||||
final location = appRouter.routerDelegate.currentConfiguration.uri.path;
|
||||
if (location.startsWith(AppRoutes.legacyDashboard)) {
|
||||
legacyHeartbeat.start();
|
||||
} else {
|
||||
legacyHeartbeat.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
appRouter.routerDelegate.removeListener(_onRouteChanged);
|
||||
walletHeartbeat.stop();
|
||||
legacyHeartbeat.stop();
|
||||
WidgetsBinding.instance.removeObserver(this);
|
||||
@@ -65,7 +74,7 @@ class SaveFamilyAppState extends ConsumerState<SaveFamilyApp>
|
||||
ref.read(appLifecycleStateProvider.notifier).setState(state);
|
||||
if (state == AppLifecycleState.resumed) {
|
||||
// walletHeartbeat.start();
|
||||
legacyHeartbeat.start();
|
||||
_onRouteChanged();
|
||||
ref.read(permissionsProvider.notifier).checkPermissions();
|
||||
} else if (state == AppLifecycleState.paused) {
|
||||
// walletHeartbeat.stop();
|
||||
|
||||
@@ -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/
|
||||
@@ -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:
|
||||
@@ -1117,6 +1125,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 +1584,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+1
|
||||
version: 1.0.0+5
|
||||
|
||||
environment:
|
||||
sdk: ^3.9.2
|
||||
|
||||
Binary file not shown.
File diff suppressed because one or more lines are too long
@@ -3,163 +3,163 @@
|
||||
"packages": [
|
||||
{
|
||||
"name": "_fe_analyzer_shared",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/_fe_analyzer_shared-85.0.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/_fe_analyzer_shared-85.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "analyzer",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/analyzer-7.7.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/analyzer-7.7.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "archive",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/archive-4.0.9",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/archive-4.0.9",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "args",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/args-2.7.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/args-2.7.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "async",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/async-2.13.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/async-2.13.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "boolean_selector",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/boolean_selector-2.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/boolean_selector-2.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "build",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build-3.1.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build-3.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "build_config",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_config-1.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_config-1.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "build_daemon",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_daemon-4.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_daemon-4.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "build_resolvers",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_resolvers-3.0.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_resolvers-3.0.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "build_runner",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_runner-2.7.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_runner-2.7.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "build_runner_core",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/build_runner_core-9.3.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/build_runner_core-9.3.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "built_collection",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/built_collection-5.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/built_collection-5.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "built_value",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/built_value-8.12.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/built_value-8.12.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "characters",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/characters-1.4.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/characters-1.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "checked_yaml",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/checked_yaml-2.0.4",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/checked_yaml-2.0.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "cli_config",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cli_config-0.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cli_config-0.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "clock",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/clock-1.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/clock-1.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "code_builder",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/code_builder-4.11.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/code_builder-4.11.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "collection",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/collection-1.19.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/collection-1.19.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "confetti",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/confetti-0.7.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/confetti-0.7.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "convert",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/convert-3.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/convert-3.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "cookie_jar",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/cookie_jar-4.0.8",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/cookie_jar-4.0.8",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.15"
|
||||
},
|
||||
{
|
||||
"name": "country_code_picker",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/country_code_picker-3.4.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/country_code_picker-3.4.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "coverage",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/coverage-1.15.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/coverage-1.15.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "crypto",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/crypto-3.0.7",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/crypto-3.0.7",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "dart_style",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dart_style-3.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dart_style-3.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
@@ -171,91 +171,91 @@
|
||||
},
|
||||
{
|
||||
"name": "diacritic",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/diacritic-0.1.6",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/diacritic-0.1.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "dio",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio-5.9.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio-5.9.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.18"
|
||||
},
|
||||
{
|
||||
"name": "dio_cookie_manager",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio_cookie_manager-3.3.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio_cookie_manager-3.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.18"
|
||||
},
|
||||
{
|
||||
"name": "dio_web_adapter",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/dio_web_adapter-2.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/dio_web_adapter-2.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "equatable",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/equatable-2.0.8",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/equatable-2.0.8",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "fake_async",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fake_async-1.3.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fake_async-1.3.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "ffi",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/ffi-2.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/ffi-2.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "file",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/file-7.0.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/file-7.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "fixnum",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fixnum-1.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fixnum-1.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "fl_chart",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/fl_chart-1.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/fl_chart-1.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "flutter",
|
||||
"rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter",
|
||||
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "flutter_lints",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_lints-5.0.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_lints-5.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "flutter_riverpod",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_riverpod-3.2.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_riverpod-3.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "flutter_svg",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/flutter_svg-2.2.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/flutter_svg-2.2.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "flutter_test",
|
||||
"rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_test",
|
||||
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_test",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
@@ -267,7 +267,7 @@
|
||||
},
|
||||
{
|
||||
"name": "flutter_web_plugins",
|
||||
"rootUri": "file:///C:/Program%20Files/Flutter/packages/flutter_web_plugins",
|
||||
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/packages/flutter_web_plugins",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
@@ -279,259 +279,259 @@
|
||||
},
|
||||
{
|
||||
"name": "freezed",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/freezed-3.2.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/freezed-3.2.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "freezed_annotation",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/freezed_annotation-3.1.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/freezed_annotation-3.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "frontend_server_client",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/frontend_server_client-4.0.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/frontend_server_client-4.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "get_it",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/get_it-9.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/get_it-9.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "glob",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/glob-2.1.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/glob-2.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "go_router",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/go_router-17.1.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/go_router-17.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "graphs",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/graphs-2.3.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/graphs-2.3.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "http",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http-1.6.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http-1.6.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "http_multi_server",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_multi_server-3.2.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_multi_server-3.2.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "http_parser",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/http_parser-4.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/http_parser-4.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "intl",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/intl-0.20.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/intl-0.20.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "io",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/io-1.0.5",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/io-1.0.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "js",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/js-0.7.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/js-0.7.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "json_annotation",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/json_annotation-4.9.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/json_annotation-4.9.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "json_serializable",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/json_serializable-6.11.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/json_serializable-6.11.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "leak_tracker",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker-11.0.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker-11.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "leak_tracker_flutter_testing",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker_flutter_testing-3.0.10",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "leak_tracker_testing",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/leak_tracker_testing-3.0.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/leak_tracker_testing-3.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "lints",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/lints-5.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/lints-5.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "logging",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/logging-1.3.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/logging-1.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "lottie",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/lottie-3.3.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/lottie-3.3.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "matcher",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/matcher-0.12.17",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/matcher-0.12.17",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "material_color_utilities",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/material_color_utilities-0.11.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/material_color_utilities-0.11.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "meta",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/meta-1.16.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/meta-1.16.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "mime",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/mime-2.0.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/mime-2.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "node_preamble",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/node_preamble-2.0.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/node_preamble-2.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "package_config",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/package_config-2.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/package_config-2.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path-1.9.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path-1.9.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "path_parsing",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_parsing-1.1.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_parsing-1.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "path_provider",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider-2.1.5",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider-2.1.5",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_android",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_android-2.2.22",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.22",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_foundation",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_foundation-2.5.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_foundation-2.5.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_linux",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_linux-2.2.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.19"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_platform_interface",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_platform_interface-2.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_platform_interface-2.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "path_provider_windows",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/path_provider_windows-2.3.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "petitparser",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/petitparser-7.0.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/petitparser-7.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "platform",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/platform-3.1.6",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/platform-3.1.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "plugin_platform_interface",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/plugin_platform_interface-2.1.8",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/plugin_platform_interface-2.1.8",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "pool",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pool-1.5.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pool-1.5.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "posix",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/posix-6.5.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/posix-6.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "pub_semver",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pub_semver-2.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pub_semver-2.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "pubspec_parse",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/pubspec_parse-1.5.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/pubspec_parse-1.5.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "riverpod",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/riverpod-3.2.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/riverpod-3.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
@@ -561,181 +561,181 @@
|
||||
},
|
||||
{
|
||||
"name": "shared_preferences",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences-2.5.4",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences-2.5.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "shared_preferences_android",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_android-2.4.20",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.20",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "shared_preferences_foundation",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_foundation-2.5.6",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_foundation-2.5.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "shared_preferences_linux",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_linux-2.4.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_linux-2.4.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "shared_preferences_platform_interface",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_platform_interface-2.4.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.2"
|
||||
},
|
||||
{
|
||||
"name": "shared_preferences_web",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_web-2.4.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_web-2.4.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "shared_preferences_windows",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shared_preferences_windows-2.4.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_windows-2.4.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "shelf",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf-1.4.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf-1.4.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "shelf_packages_handler",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_packages_handler-3.0.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_packages_handler-3.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.17"
|
||||
},
|
||||
{
|
||||
"name": "shelf_static",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_static-1.1.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_static-1.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "shelf_web_socket",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/shelf_web_socket-3.0.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shelf_web_socket-3.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "sky_engine",
|
||||
"rootUri": "file:///C:/Program%20Files/Flutter/bin/cache/pkg/sky_engine",
|
||||
"rootUri": "file:///Users/juliandalcalaf/Development/flutter/bin/cache/pkg/sky_engine",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "source_gen",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_gen-4.0.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_gen-4.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "source_helper",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_helper-1.3.8",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_helper-1.3.8",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.7"
|
||||
},
|
||||
{
|
||||
"name": "source_map_stack_trace",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_map_stack_trace-2.1.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_map_stack_trace-2.1.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "source_maps",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_maps-0.10.13",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_maps-0.10.13",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "source_span",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/source_span-1.10.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/source_span-1.10.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "stack_trace",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stack_trace-1.12.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stack_trace-1.12.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "state_notifier",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/state_notifier-1.0.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/state_notifier-1.0.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.12"
|
||||
},
|
||||
{
|
||||
"name": "stream_channel",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stream_channel-2.1.4",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stream_channel-2.1.4",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "stream_transform",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/stream_transform-2.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/stream_transform-2.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "string_scanner",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/string_scanner-1.4.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/string_scanner-1.4.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "term_glyph",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/term_glyph-1.2.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/term_glyph-1.2.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "test",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test-1.26.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test-1.26.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "test_api",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test_api-0.7.6",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test_api-0.7.6",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "test_core",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/test_core-0.6.11",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/test_core-0.6.11",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "timing",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/timing-1.0.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/timing-1.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "top_snackbar_flutter",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/top_snackbar_flutter-3.3.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/top_snackbar_flutter-3.3.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "2.15"
|
||||
},
|
||||
{
|
||||
"name": "typed_data",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/typed_data-1.4.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/typed_data-1.4.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "universal_io",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/universal_io-2.3.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/universal_io-2.3.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
@@ -747,79 +747,79 @@
|
||||
},
|
||||
{
|
||||
"name": "vector_graphics",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics-1.1.19",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_graphics-1.1.19",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.6"
|
||||
},
|
||||
{
|
||||
"name": "vector_graphics_codec",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics_codec-1.1.13",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_graphics_codec-1.1.13",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "vector_graphics_compiler",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_graphics_compiler-1.1.20",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_graphics_compiler-1.1.20",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.9"
|
||||
},
|
||||
{
|
||||
"name": "vector_math",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vector_math-2.2.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vector_math-2.2.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.1"
|
||||
},
|
||||
{
|
||||
"name": "vm_service",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/vm_service-15.0.2",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/vm_service-15.0.2",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.5"
|
||||
},
|
||||
{
|
||||
"name": "watcher",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/watcher-1.2.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/watcher-1.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "web",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web-1.1.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web-1.1.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "web_socket",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket-1.0.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web_socket-1.0.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
{
|
||||
"name": "web_socket_channel",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/web_socket_channel-3.0.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/web_socket_channel-3.0.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "webkit_inspection_protocol",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/webkit_inspection_protocol-1.2.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.0"
|
||||
},
|
||||
{
|
||||
"name": "xdg_directories",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/xdg_directories-1.1.0",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/xdg_directories-1.1.0",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.3"
|
||||
},
|
||||
{
|
||||
"name": "xml",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/xml-6.6.1",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/xml-6.6.1",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.8"
|
||||
},
|
||||
{
|
||||
"name": "yaml",
|
||||
"rootUri": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache/hosted/pub.dev/yaml-3.1.3",
|
||||
"rootUri": "file:///Users/juliandalcalaf/.pub-cache/hosted/pub.dev/yaml-3.1.3",
|
||||
"packageUri": "lib/",
|
||||
"languageVersion": "3.4"
|
||||
},
|
||||
@@ -832,7 +832,7 @@
|
||||
],
|
||||
"generator": "pub",
|
||||
"generatorVersion": "3.9.2",
|
||||
"flutterRoot": "file:///C:/Program%20Files/Flutter",
|
||||
"flutterVersion": "3.35.6",
|
||||
"pubCache": "file:///C:/Users/Aitor%20Arana/AppData/Local/Pub/Cache"
|
||||
"flutterRoot": "file:///Users/juliandalcalaf/Development/flutter",
|
||||
"flutterVersion": "3.35.7",
|
||||
"pubCache": "file:///Users/juliandalcalaf/.pub-cache"
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
3.35.6
|
||||
3.35.7
|
||||
@@ -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":"/Users/juliandalcalaf/Desktop/save-family-app/sf-app-platform/packages/flutter_treezor_entrust_sdk_bridge/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_foundation","path":"/Users/juliandalcalaf/.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":"/Users/juliandalcalaf/.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":"/Users/juliandalcalaf/Desktop/save-family-app/sf-app-platform/packages/flutter_treezor_entrust_sdk_bridge/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"path_provider_android","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_android-2.2.22/","native_build":true,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_android","path":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/shared_preferences_android-2.4.20/","native_build":true,"dependencies":[],"dev_dependency":false}],"macos":[{"name":"path_provider_foundation","path":"/Users/juliandalcalaf/.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":"/Users/juliandalcalaf/.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":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_linux","path":"/Users/juliandalcalaf/.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":"/Users/juliandalcalaf/.pub-cache/hosted/pub.dev/path_provider_windows-2.3.0/","native_build":false,"dependencies":[],"dev_dependency":false},{"name":"shared_preferences_windows","path":"/Users/juliandalcalaf/.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":"/Users/juliandalcalaf/.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-18 14:45:38.408085","version":"3.35.7","swift_package_manager_enabled":{"ios":false,"macos":false}}
|
||||
@@ -1,5 +1,6 @@
|
||||
export 'src/presentation/activity_screen.dart';
|
||||
export 'src/widgets/activity_list.dart';
|
||||
export 'src/widgets/pagination_bar.dart';
|
||||
export 'src/widgets/transaction_tile.dart';
|
||||
export 'src/activity_builder.dart';
|
||||
export 'src/providers/activity_providers.dart';
|
||||
|
||||
@@ -17,7 +17,7 @@ class GetWalletTransactionsUseCaseImpl implements GetWalletTransactionsUseCase {
|
||||
required String walletId,
|
||||
Map<String, dynamic>? queryParameters,
|
||||
}) {
|
||||
return _repository.getWalletTransactions(
|
||||
return _repository.getWalletOperations(
|
||||
walletId: walletId,
|
||||
queryParameters: queryParameters,
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:activity/src/presentation/state/activity_view_model.dart';
|
||||
import 'package:activity/src/presentation/state/activity_view_state.dart';
|
||||
import 'package:activity/src/widgets/pagination_bar.dart';
|
||||
import 'package:activity/src/widgets/transaction_tile.dart';
|
||||
|
||||
class ActivityScreen extends ConsumerStatefulWidget {
|
||||
@@ -173,7 +174,7 @@ class _ActivityScreenState extends ConsumerState<ActivityScreen> {
|
||||
return _buildError(context, theme, viewState.errorMessage);
|
||||
}
|
||||
|
||||
if (viewState.transactions.isEmpty) {
|
||||
if (viewState.transactionPages.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
context.translate(I18n.activityNoTransactions),
|
||||
@@ -185,38 +186,48 @@ class _ActivityScreenState extends ConsumerState<ActivityScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
final walletId = viewState.selectedTab!.walletId;
|
||||
final balanceAsync = ref.watch(walletBalanceProvider(walletId));
|
||||
final currentTransactions = viewState.transactionPages[viewState.currentPage];
|
||||
|
||||
return RefreshIndicator(
|
||||
onRefresh: () =>
|
||||
ref.read(activityViewModelProvider.notifier).loadTabs(),
|
||||
child: ListView.builder(
|
||||
child: ListView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24),
|
||||
itemCount: viewState.transactions.length + 1,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == 0) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
child: balanceAsync.when(
|
||||
loading: () =>
|
||||
const Center(child: AppLoadingIndicator(size: 48)),
|
||||
error: (_, __) => const SizedBox.shrink(),
|
||||
data: (balance) => WalletBalanceBlock(
|
||||
availableBalance: balance.availableBalance,
|
||||
allocatedBalance: balance.allocatedBalance,
|
||||
totalBalance: balance.totalBalance,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
final transaction = viewState.transactions[index - 1];
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: TransactionTile(transaction: transaction),
|
||||
);
|
||||
},
|
||||
children: [
|
||||
// TODO: WalletBalanceBlock temporarily hidden
|
||||
// final walletId = viewState.selectedTab!.walletId;
|
||||
// final balanceAsync = ref.watch(walletBalanceProvider(walletId));
|
||||
// Padding(
|
||||
// padding: const EdgeInsets.only(bottom: 16),
|
||||
// child: balanceAsync.when(
|
||||
// loading: () =>
|
||||
// const Center(child: AppLoadingIndicator(size: 48)),
|
||||
// error: (_, __) => const SizedBox.shrink(),
|
||||
// data: (balance) => WalletBalanceBlock(
|
||||
// availableBalance: balance.availableBalance,
|
||||
// allocatedBalance: balance.allocatedBalance,
|
||||
// totalBalance: balance.totalBalance,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
...currentTransactions.map(
|
||||
(tx) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: TransactionTile(transaction: tx),
|
||||
),
|
||||
),
|
||||
PaginationBar(
|
||||
currentPage: viewState.currentPage,
|
||||
totalPages: viewState.transactionPages.length,
|
||||
hasMore: viewState.nextCursor != null,
|
||||
isLoadingMore: viewState.isLoadingMore,
|
||||
onPageChanged: (page) =>
|
||||
ref.read(activityViewModelProvider.notifier).setPage(page),
|
||||
onLoadMore: () =>
|
||||
ref.read(activityViewModelProvider.notifier).loadMore(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -73,20 +73,27 @@ class ActivityViewModel extends Notifier<ActivityViewState> {
|
||||
final tab = state.selectedTab;
|
||||
if (tab == null) return;
|
||||
|
||||
state = state.copyWith(isLoadingTransactions: true, errorMessage: '');
|
||||
state = state.copyWith(
|
||||
isLoadingTransactions: true,
|
||||
errorMessage: '',
|
||||
transactionPages: [],
|
||||
nextCursor: null,
|
||||
currentPage: 0,
|
||||
);
|
||||
|
||||
try {
|
||||
final query = TransactionsQuery(
|
||||
walletId: tab.walletId,
|
||||
dateFilter: state.selectedDateFilter,
|
||||
);
|
||||
final transactions =
|
||||
final response =
|
||||
await ref.read(walletTransactionsProvider(query).future);
|
||||
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isLoadingTransactions: false,
|
||||
transactions: transactions,
|
||||
transactionPages: [response.items],
|
||||
nextCursor: response.nextCursor,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
@@ -97,6 +104,38 @@ class ActivityViewModel extends Notifier<ActivityViewState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> loadMore() async {
|
||||
final tab = state.selectedTab;
|
||||
if (tab == null || state.isLoadingMore || state.nextCursor == null) return;
|
||||
|
||||
state = state.copyWith(isLoadingMore: true);
|
||||
|
||||
try {
|
||||
final query = TransactionsQuery(
|
||||
walletId: tab.walletId,
|
||||
dateFilter: state.selectedDateFilter,
|
||||
cursor: state.nextCursor,
|
||||
);
|
||||
final response =
|
||||
await ref.read(walletTransactionsProvider(query).future);
|
||||
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isLoadingMore: false,
|
||||
transactionPages: [...state.transactionPages, response.items],
|
||||
nextCursor: response.nextCursor,
|
||||
currentPage: state.transactionPages.length,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isLoadingMore: false);
|
||||
}
|
||||
}
|
||||
|
||||
void setPage(int page) {
|
||||
state = state.copyWith(currentPage: page);
|
||||
}
|
||||
|
||||
void selectWallet(int index) {
|
||||
if (index == state.selectedWalletIndex) return;
|
||||
state = state.copyWith(selectedWalletIndex: index);
|
||||
|
||||
@@ -14,7 +14,10 @@ abstract class ActivityViewState with _$ActivityViewState {
|
||||
@Default([]) List<WalletTab> tabs,
|
||||
@Default(0) int selectedWalletIndex,
|
||||
@Default(DateFilter.today) DateFilter selectedDateFilter,
|
||||
@Default([]) List<WalletTransactionEntity> transactions,
|
||||
@Default([]) List<List<WalletTransactionEntity>> transactionPages,
|
||||
String? nextCursor,
|
||||
@Default(false) bool isLoadingMore,
|
||||
@Default(0) int currentPage,
|
||||
@Default('') String errorMessage,
|
||||
}) = _ActivityViewState;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$ActivityViewState {
|
||||
|
||||
bool get isLoading; bool get isLoadingTransactions; List<WalletTab> get tabs; int get selectedWalletIndex; DateFilter get selectedDateFilter; List<WalletTransactionEntity> get transactions; String get errorMessage;
|
||||
bool get isLoading; bool get isLoadingTransactions; List<WalletTab> get tabs; int get selectedWalletIndex; DateFilter get selectedDateFilter; List<List<WalletTransactionEntity>> get transactionPages; String? get nextCursor; bool get isLoadingMore; int get currentPage; String get errorMessage;
|
||||
/// Create a copy of ActivityViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -25,16 +25,16 @@ $ActivityViewStateCopyWith<ActivityViewState> get copyWith => _$ActivityViewStat
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ActivityViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingTransactions, isLoadingTransactions) || other.isLoadingTransactions == isLoadingTransactions)&&const DeepCollectionEquality().equals(other.tabs, tabs)&&(identical(other.selectedWalletIndex, selectedWalletIndex) || other.selectedWalletIndex == selectedWalletIndex)&&(identical(other.selectedDateFilter, selectedDateFilter) || other.selectedDateFilter == selectedDateFilter)&&const DeepCollectionEquality().equals(other.transactions, transactions)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ActivityViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingTransactions, isLoadingTransactions) || other.isLoadingTransactions == isLoadingTransactions)&&const DeepCollectionEquality().equals(other.tabs, tabs)&&(identical(other.selectedWalletIndex, selectedWalletIndex) || other.selectedWalletIndex == selectedWalletIndex)&&(identical(other.selectedDateFilter, selectedDateFilter) || other.selectedDateFilter == selectedDateFilter)&&const DeepCollectionEquality().equals(other.transactionPages, transactionPages)&&(identical(other.nextCursor, nextCursor) || other.nextCursor == nextCursor)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.currentPage, currentPage) || other.currentPage == currentPage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isLoadingTransactions,const DeepCollectionEquality().hash(tabs),selectedWalletIndex,selectedDateFilter,const DeepCollectionEquality().hash(transactions),errorMessage);
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isLoadingTransactions,const DeepCollectionEquality().hash(tabs),selectedWalletIndex,selectedDateFilter,const DeepCollectionEquality().hash(transactionPages),nextCursor,isLoadingMore,currentPage,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ActivityViewState(isLoading: $isLoading, isLoadingTransactions: $isLoadingTransactions, tabs: $tabs, selectedWalletIndex: $selectedWalletIndex, selectedDateFilter: $selectedDateFilter, transactions: $transactions, errorMessage: $errorMessage)';
|
||||
return 'ActivityViewState(isLoading: $isLoading, isLoadingTransactions: $isLoadingTransactions, tabs: $tabs, selectedWalletIndex: $selectedWalletIndex, selectedDateFilter: $selectedDateFilter, transactionPages: $transactionPages, nextCursor: $nextCursor, isLoadingMore: $isLoadingMore, currentPage: $currentPage, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ abstract mixin class $ActivityViewStateCopyWith<$Res> {
|
||||
factory $ActivityViewStateCopyWith(ActivityViewState value, $Res Function(ActivityViewState) _then) = _$ActivityViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<WalletTransactionEntity> transactions, String errorMessage
|
||||
bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
@@ -62,15 +62,18 @@ class _$ActivityViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of ActivityViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? isLoadingTransactions = null,Object? tabs = null,Object? selectedWalletIndex = null,Object? selectedDateFilter = null,Object? transactions = null,Object? errorMessage = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? isLoadingTransactions = null,Object? tabs = null,Object? selectedWalletIndex = null,Object? selectedDateFilter = null,Object? transactionPages = null,Object? nextCursor = freezed,Object? isLoadingMore = null,Object? currentPage = null,Object? errorMessage = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isLoadingTransactions: null == isLoadingTransactions ? _self.isLoadingTransactions : isLoadingTransactions // ignore: cast_nullable_to_non_nullable
|
||||
as bool,tabs: null == tabs ? _self.tabs : tabs // ignore: cast_nullable_to_non_nullable
|
||||
as List<WalletTab>,selectedWalletIndex: null == selectedWalletIndex ? _self.selectedWalletIndex : selectedWalletIndex // ignore: cast_nullable_to_non_nullable
|
||||
as int,selectedDateFilter: null == selectedDateFilter ? _self.selectedDateFilter : selectedDateFilter // ignore: cast_nullable_to_non_nullable
|
||||
as DateFilter,transactions: null == transactions ? _self.transactions : transactions // ignore: cast_nullable_to_non_nullable
|
||||
as List<WalletTransactionEntity>,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as DateFilter,transactionPages: null == transactionPages ? _self.transactionPages : transactionPages // ignore: cast_nullable_to_non_nullable
|
||||
as List<List<WalletTransactionEntity>>,nextCursor: freezed == nextCursor ? _self.nextCursor : nextCursor // ignore: cast_nullable_to_non_nullable
|
||||
as String?,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable
|
||||
as bool,currentPage: null == currentPage ? _self.currentPage : currentPage // ignore: cast_nullable_to_non_nullable
|
||||
as int,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
@@ -156,10 +159,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<WalletTransactionEntity> transactions, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ActivityViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.selectedWalletIndex,_that.selectedDateFilter,_that.transactions,_that.errorMessage);case _:
|
||||
return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.selectedWalletIndex,_that.selectedDateFilter,_that.transactionPages,_that.nextCursor,_that.isLoadingMore,_that.currentPage,_that.errorMessage);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -177,10 +180,10 @@ return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.sel
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<WalletTransactionEntity> transactions, String errorMessage) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage, String errorMessage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ActivityViewState():
|
||||
return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.selectedWalletIndex,_that.selectedDateFilter,_that.transactions,_that.errorMessage);case _:
|
||||
return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.selectedWalletIndex,_that.selectedDateFilter,_that.transactionPages,_that.nextCursor,_that.isLoadingMore,_that.currentPage,_that.errorMessage);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -197,10 +200,10 @@ return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.sel
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<WalletTransactionEntity> transactions, String errorMessage)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage, String errorMessage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ActivityViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.selectedWalletIndex,_that.selectedDateFilter,_that.transactions,_that.errorMessage);case _:
|
||||
return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.selectedWalletIndex,_that.selectedDateFilter,_that.transactionPages,_that.nextCursor,_that.isLoadingMore,_that.currentPage,_that.errorMessage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -212,7 +215,7 @@ return $default(_that.isLoading,_that.isLoadingTransactions,_that.tabs,_that.sel
|
||||
|
||||
|
||||
class _ActivityViewState extends ActivityViewState {
|
||||
const _ActivityViewState({this.isLoading = false, this.isLoadingTransactions = false, final List<WalletTab> tabs = const [], this.selectedWalletIndex = 0, this.selectedDateFilter = DateFilter.today, final List<WalletTransactionEntity> transactions = const [], this.errorMessage = ''}): _tabs = tabs,_transactions = transactions,super._();
|
||||
const _ActivityViewState({this.isLoading = false, this.isLoadingTransactions = false, final List<WalletTab> tabs = const [], this.selectedWalletIndex = 0, this.selectedDateFilter = DateFilter.today, final List<List<WalletTransactionEntity>> transactionPages = const [], this.nextCursor, this.isLoadingMore = false, this.currentPage = 0, this.errorMessage = ''}): _tabs = tabs,_transactionPages = transactionPages,super._();
|
||||
|
||||
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@@ -226,13 +229,16 @@ class _ActivityViewState extends ActivityViewState {
|
||||
|
||||
@override@JsonKey() final int selectedWalletIndex;
|
||||
@override@JsonKey() final DateFilter selectedDateFilter;
|
||||
final List<WalletTransactionEntity> _transactions;
|
||||
@override@JsonKey() List<WalletTransactionEntity> get transactions {
|
||||
if (_transactions is EqualUnmodifiableListView) return _transactions;
|
||||
final List<List<WalletTransactionEntity>> _transactionPages;
|
||||
@override@JsonKey() List<List<WalletTransactionEntity>> get transactionPages {
|
||||
if (_transactionPages is EqualUnmodifiableListView) return _transactionPages;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_transactions);
|
||||
return EqualUnmodifiableListView(_transactionPages);
|
||||
}
|
||||
|
||||
@override final String? nextCursor;
|
||||
@override@JsonKey() final bool isLoadingMore;
|
||||
@override@JsonKey() final int currentPage;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
|
||||
/// Create a copy of ActivityViewState
|
||||
@@ -245,16 +251,16 @@ _$ActivityViewStateCopyWith<_ActivityViewState> get copyWith => __$ActivityViewS
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActivityViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingTransactions, isLoadingTransactions) || other.isLoadingTransactions == isLoadingTransactions)&&const DeepCollectionEquality().equals(other._tabs, _tabs)&&(identical(other.selectedWalletIndex, selectedWalletIndex) || other.selectedWalletIndex == selectedWalletIndex)&&(identical(other.selectedDateFilter, selectedDateFilter) || other.selectedDateFilter == selectedDateFilter)&&const DeepCollectionEquality().equals(other._transactions, _transactions)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ActivityViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isLoadingTransactions, isLoadingTransactions) || other.isLoadingTransactions == isLoadingTransactions)&&const DeepCollectionEquality().equals(other._tabs, _tabs)&&(identical(other.selectedWalletIndex, selectedWalletIndex) || other.selectedWalletIndex == selectedWalletIndex)&&(identical(other.selectedDateFilter, selectedDateFilter) || other.selectedDateFilter == selectedDateFilter)&&const DeepCollectionEquality().equals(other._transactionPages, _transactionPages)&&(identical(other.nextCursor, nextCursor) || other.nextCursor == nextCursor)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.currentPage, currentPage) || other.currentPage == currentPage)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isLoadingTransactions,const DeepCollectionEquality().hash(_tabs),selectedWalletIndex,selectedDateFilter,const DeepCollectionEquality().hash(_transactions),errorMessage);
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isLoadingTransactions,const DeepCollectionEquality().hash(_tabs),selectedWalletIndex,selectedDateFilter,const DeepCollectionEquality().hash(_transactionPages),nextCursor,isLoadingMore,currentPage,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ActivityViewState(isLoading: $isLoading, isLoadingTransactions: $isLoadingTransactions, tabs: $tabs, selectedWalletIndex: $selectedWalletIndex, selectedDateFilter: $selectedDateFilter, transactions: $transactions, errorMessage: $errorMessage)';
|
||||
return 'ActivityViewState(isLoading: $isLoading, isLoadingTransactions: $isLoadingTransactions, tabs: $tabs, selectedWalletIndex: $selectedWalletIndex, selectedDateFilter: $selectedDateFilter, transactionPages: $transactionPages, nextCursor: $nextCursor, isLoadingMore: $isLoadingMore, currentPage: $currentPage, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -265,7 +271,7 @@ abstract mixin class _$ActivityViewStateCopyWith<$Res> implements $ActivityViewS
|
||||
factory _$ActivityViewStateCopyWith(_ActivityViewState value, $Res Function(_ActivityViewState) _then) = __$ActivityViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<WalletTransactionEntity> transactions, String errorMessage
|
||||
bool isLoading, bool isLoadingTransactions, List<WalletTab> tabs, int selectedWalletIndex, DateFilter selectedDateFilter, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
@@ -282,15 +288,18 @@ class __$ActivityViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of ActivityViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? isLoadingTransactions = null,Object? tabs = null,Object? selectedWalletIndex = null,Object? selectedDateFilter = null,Object? transactions = null,Object? errorMessage = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? isLoadingTransactions = null,Object? tabs = null,Object? selectedWalletIndex = null,Object? selectedDateFilter = null,Object? transactionPages = null,Object? nextCursor = freezed,Object? isLoadingMore = null,Object? currentPage = null,Object? errorMessage = null,}) {
|
||||
return _then(_ActivityViewState(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isLoadingTransactions: null == isLoadingTransactions ? _self.isLoadingTransactions : isLoadingTransactions // ignore: cast_nullable_to_non_nullable
|
||||
as bool,tabs: null == tabs ? _self._tabs : tabs // ignore: cast_nullable_to_non_nullable
|
||||
as List<WalletTab>,selectedWalletIndex: null == selectedWalletIndex ? _self.selectedWalletIndex : selectedWalletIndex // ignore: cast_nullable_to_non_nullable
|
||||
as int,selectedDateFilter: null == selectedDateFilter ? _self.selectedDateFilter : selectedDateFilter // ignore: cast_nullable_to_non_nullable
|
||||
as DateFilter,transactions: null == transactions ? _self._transactions : transactions // ignore: cast_nullable_to_non_nullable
|
||||
as List<WalletTransactionEntity>,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as DateFilter,transactionPages: null == transactionPages ? _self._transactionPages : transactionPages // ignore: cast_nullable_to_non_nullable
|
||||
as List<List<WalletTransactionEntity>>,nextCursor: freezed == nextCursor ? _self.nextCursor : nextCursor // ignore: cast_nullable_to_non_nullable
|
||||
as String?,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable
|
||||
as bool,currentPage: null == currentPage ? _self.currentPage : currentPage // ignore: cast_nullable_to_non_nullable
|
||||
as int,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
103
modules/activity/lib/src/widgets/pagination_bar.dart
Normal file
103
modules/activity/lib/src/widgets/pagination_bar.dart
Normal file
@@ -0,0 +1,103 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
class PaginationBar extends ConsumerWidget {
|
||||
final int currentPage;
|
||||
final int totalPages;
|
||||
final bool hasMore;
|
||||
final bool isLoadingMore;
|
||||
final ValueChanged<int> onPageChanged;
|
||||
final VoidCallback onLoadMore;
|
||||
|
||||
const PaginationBar({
|
||||
super.key,
|
||||
required this.currentPage,
|
||||
required this.totalPages,
|
||||
required this.hasMore,
|
||||
required this.isLoadingMore,
|
||||
required this.onPageChanged,
|
||||
required this.onLoadMore,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final textColor = theme.getColorFor(ThemeCode.textPrimary);
|
||||
final primaryColor = theme.getColorFor(ThemeCode.buttonPrimary);
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: currentPage > 0
|
||||
? () => onPageChanged(currentPage - 1)
|
||||
: null,
|
||||
icon: Icon(Icons.chevron_left, color: currentPage > 0 ? primaryColor : Colors.grey),
|
||||
iconSize: 28,
|
||||
constraints: const BoxConstraints(minWidth: 36, minHeight: 36),
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
Flexible(
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: List.generate(totalPages, (index) {
|
||||
final isSelected = index == currentPage;
|
||||
return GestureDetector(
|
||||
onTap: () => onPageChanged(index),
|
||||
child: Container(
|
||||
width: 32,
|
||||
height: 32,
|
||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? primaryColor : Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: isSelected ? null : Border.all(color: Colors.grey.shade300),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
'${index + 1}',
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: isSelected ? Colors.white : textColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (hasMore)
|
||||
isLoadingMore
|
||||
? const Padding(
|
||||
padding: EdgeInsets.only(left: 8),
|
||||
child: AppLoadingIndicator(size: 20),
|
||||
)
|
||||
: IconButton(
|
||||
onPressed: onLoadMore,
|
||||
icon: Icon(Icons.add_circle_outline, color: primaryColor),
|
||||
iconSize: 28,
|
||||
constraints: const BoxConstraints(minWidth: 36, minHeight: 36),
|
||||
padding: EdgeInsets.zero,
|
||||
tooltip: 'Load more',
|
||||
),
|
||||
IconButton(
|
||||
onPressed: currentPage < totalPages - 1
|
||||
? () => onPageChanged(currentPage + 1)
|
||||
: null,
|
||||
icon: Icon(Icons.chevron_right, color: currentPage < totalPages - 1 ? primaryColor : Colors.grey),
|
||||
iconSize: 28,
|
||||
constraints: const BoxConstraints(minWidth: 36, minHeight: 36),
|
||||
padding: EdgeInsets.zero,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:design_system/design_system.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
|
||||
@@ -12,9 +13,18 @@ class TransactionTile extends ConsumerWidget {
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final color = _color(transaction.transactionType);
|
||||
final icon = _icon(transaction.transactionType);
|
||||
final label = context.translate(_i18nKey(transaction.transactionType));
|
||||
final isDeclined = transaction.status == 'DECLINED';
|
||||
final isCredit = transaction.direction == 'CREDIT';
|
||||
final color = isDeclined ? Colors.grey : _color(transaction.operationType);
|
||||
final icon = _icon(transaction.operationType);
|
||||
final label = transaction.merchantName ??
|
||||
context.translate(_i18nKey(transaction.operationType));
|
||||
final amountPrefix = isCredit ? '+' : '-';
|
||||
final amountColor = isDeclined
|
||||
? Colors.grey
|
||||
: isCredit
|
||||
? Colors.green
|
||||
: Colors.red;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -41,19 +51,27 @@ class TransactionTile extends ConsumerWidget {
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'${transaction.amount} ${transaction.currency}',
|
||||
'$amountPrefix${transaction.amount.toStringAsFixed(2)} ${transaction.currency}',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
color: amountColor,
|
||||
decoration: isDeclined ? TextDecoration.lineThrough : null,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (transaction.name.isNotEmpty) ...[
|
||||
if (transaction.messageToUser != null &&
|
||||
transaction.messageToUser!.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
transaction.name,
|
||||
transaction.messageToUser!,
|
||||
style: const TextStyle(fontSize: 13, color: Colors.red),
|
||||
),
|
||||
] else if (transaction.label.isNotEmpty) ...[
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
transaction.label,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
@@ -61,12 +79,65 @@ class TransactionTile extends ConsumerWidget {
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
transaction.executionDate,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 4,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
children: [
|
||||
Text(
|
||||
_formatDate(transaction.createdDate, context),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
),
|
||||
if (transaction.merchantCity != null &&
|
||||
transaction.merchantCity!.isNotEmpty)
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.location_on, size: 12,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
const SizedBox(width: 2),
|
||||
Text(
|
||||
transaction.merchantCity!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (transaction.maskedPan != null &&
|
||||
transaction.maskedPan!.isNotEmpty)
|
||||
Text(
|
||||
transaction.maskedPan!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
),
|
||||
if (isDeclined)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 6,
|
||||
vertical: 2,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red.withAlpha(0x1A),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
),
|
||||
child: Text(
|
||||
transaction.status,
|
||||
style: const TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -74,82 +145,51 @@ class TransactionTile extends ConsumerWidget {
|
||||
}
|
||||
|
||||
static IconData _icon(TransactionType type) => switch (type) {
|
||||
TransactionType.payin ||
|
||||
TransactionType.payinAcquiring ||
|
||||
TransactionType.checkPayin => Icons.arrow_downward,
|
||||
TransactionType.payout ||
|
||||
TransactionType.payoutSctInstantEmit => Icons.arrow_upward,
|
||||
TransactionType.payinRefund ||
|
||||
TransactionType.payoutRefund ||
|
||||
TransactionType.payinRefundAcquiring ||
|
||||
TransactionType.checkRefund => Icons.replay,
|
||||
TransactionType.transfer ||
|
||||
TransactionType.sctr ||
|
||||
TransactionType.sctrInst ||
|
||||
TransactionType.creditInternationalTransfer => Icons.swap_horiz,
|
||||
TransactionType.cardTopup => Icons.arrow_downward,
|
||||
TransactionType.cardTransaction => Icons.credit_card,
|
||||
TransactionType.sdde || TransactionType.sddr => Icons.account_balance,
|
||||
TransactionType.creditTransferReturned ||
|
||||
TransactionType.payinSctInstantRecall ||
|
||||
TransactionType.payinSctInstantEmitRecall ||
|
||||
TransactionType.sctrRecall ||
|
||||
TransactionType.sddrReversal => Icons.undo,
|
||||
TransactionType.bankTransfer ||
|
||||
TransactionType.instantBankTransfer => Icons.account_balance,
|
||||
TransactionType.walletTransfer => Icons.swap_horiz,
|
||||
TransactionType.bankDirectDebit => Icons.account_balance_wallet,
|
||||
TransactionType.check => Icons.receipt_long,
|
||||
TransactionType.creditNote => Icons.replay,
|
||||
TransactionType.fees => Icons.monetization_on,
|
||||
TransactionType.unknown => Icons.help_outline,
|
||||
};
|
||||
|
||||
static Color _color(TransactionType type) => switch (type) {
|
||||
TransactionType.payin ||
|
||||
TransactionType.payinAcquiring ||
|
||||
TransactionType.checkPayin => Colors.green,
|
||||
TransactionType.payout ||
|
||||
TransactionType.payoutSctInstantEmit => Colors.red,
|
||||
TransactionType.payinRefund ||
|
||||
TransactionType.payoutRefund ||
|
||||
TransactionType.payinRefundAcquiring ||
|
||||
TransactionType.checkRefund ||
|
||||
TransactionType.creditTransferReturned ||
|
||||
TransactionType.payinSctInstantRecall ||
|
||||
TransactionType.payinSctInstantEmitRecall ||
|
||||
TransactionType.sctrRecall ||
|
||||
TransactionType.sddrReversal => Colors.orange,
|
||||
TransactionType.transfer ||
|
||||
TransactionType.sctr ||
|
||||
TransactionType.sctrInst ||
|
||||
TransactionType.creditInternationalTransfer ||
|
||||
TransactionType.sdde ||
|
||||
TransactionType.sddr => Colors.blue,
|
||||
TransactionType.cardTopup => Colors.green,
|
||||
TransactionType.cardTransaction => Colors.purple,
|
||||
TransactionType.bankTransfer ||
|
||||
TransactionType.instantBankTransfer ||
|
||||
TransactionType.walletTransfer => Colors.blue,
|
||||
TransactionType.bankDirectDebit => Colors.red,
|
||||
TransactionType.check => Colors.teal,
|
||||
TransactionType.creditNote => Colors.orange,
|
||||
TransactionType.fees => Colors.red,
|
||||
TransactionType.unknown => Colors.grey,
|
||||
};
|
||||
|
||||
static String _i18nKey(TransactionType type) => switch (type) {
|
||||
TransactionType.payin => I18n.transactionPayin,
|
||||
TransactionType.payout => I18n.transactionPayout,
|
||||
TransactionType.transfer => I18n.transactionTransfer,
|
||||
TransactionType.payinRefund => I18n.transactionPayinRefund,
|
||||
TransactionType.payoutRefund => I18n.transactionPayoutRefund,
|
||||
TransactionType.bankDirectDebit => I18n.transactionBankDirectDebit,
|
||||
TransactionType.bankTransfer => I18n.transactionBankTransfer,
|
||||
TransactionType.cardTopup => I18n.transactionCardTopup,
|
||||
TransactionType.cardTransaction => I18n.transactionCardPayment,
|
||||
TransactionType.payinAcquiring => I18n.transactionPayinAcquiring,
|
||||
TransactionType.payinRefundAcquiring =>
|
||||
I18n.transactionPayinRefundAcquiring,
|
||||
TransactionType.sctrInst => I18n.transactionSctrInst,
|
||||
TransactionType.payinSctInstantRecall =>
|
||||
I18n.transactionPayinSctInstantRecall,
|
||||
TransactionType.payoutSctInstantEmit =>
|
||||
I18n.transactionPayoutSctInstantEmit,
|
||||
TransactionType.payinSctInstantEmitRecall =>
|
||||
I18n.transactionPayinSctInstantEmitRecall,
|
||||
TransactionType.creditTransferReturned =>
|
||||
I18n.transactionCreditTransferReturned,
|
||||
TransactionType.checkPayin => I18n.transactionCheckPayin,
|
||||
TransactionType.sdde => I18n.transactionSdde,
|
||||
TransactionType.sddr => I18n.transactionSddr,
|
||||
TransactionType.sddrReversal => I18n.transactionSddrReversal,
|
||||
TransactionType.sctrRecall => I18n.transactionSctrRecall,
|
||||
TransactionType.checkRefund => I18n.transactionCheckRefund,
|
||||
TransactionType.sctr => I18n.transactionSctr,
|
||||
TransactionType.creditInternationalTransfer =>
|
||||
I18n.transactionCreditInternationalTransfer,
|
||||
TransactionType.check => I18n.transactionCheck,
|
||||
TransactionType.creditNote => I18n.transactionCreditNote,
|
||||
TransactionType.fees => I18n.transactionFees,
|
||||
TransactionType.instantBankTransfer => I18n.transactionInstantBankTransfer,
|
||||
TransactionType.walletTransfer => I18n.transactionWalletTransfer,
|
||||
TransactionType.unknown => I18n.transactionUnknown,
|
||||
};
|
||||
|
||||
static String _formatDate(String raw, BuildContext context) {
|
||||
try {
|
||||
final date = DateTime.parse(raw).toLocal();
|
||||
final locale = Localizations.localeOf(context).languageCode;
|
||||
return DateFormat('d MMM yyyy · HH:mm', locale).format(date);
|
||||
} catch (_) {
|
||||
return raw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class OnboardingScreen extends ConsumerWidget {
|
||||
|
||||
void goToNext() {
|
||||
if (isLast) {
|
||||
navigationContract.goTo(AppRoutes.legacyLogin);
|
||||
navigationContract.goTo(AppRoutes.login);
|
||||
} else {
|
||||
pageController.nextPage(
|
||||
duration: const Duration(milliseconds: 400),
|
||||
@@ -111,7 +111,7 @@ class OnboardingScreen extends ConsumerWidget {
|
||||
? const SizedBox.shrink()
|
||||
: TextButton(
|
||||
onPressed: () =>
|
||||
navigationContract.goTo(AppRoutes.legacyLogin),
|
||||
navigationContract.goTo(AppRoutes.login),
|
||||
child: Text(
|
||||
context.translate(I18n.skip),
|
||||
style: AppFonts.stolzlStyle(
|
||||
|
||||
@@ -15,6 +15,7 @@ class ScaPinView extends StatelessWidget {
|
||||
final VoidCallback onSubmit;
|
||||
final String clearPinText;
|
||||
final String? errorMessage;
|
||||
final int pinLength;
|
||||
|
||||
const ScaPinView({
|
||||
super.key,
|
||||
@@ -30,6 +31,7 @@ class ScaPinView extends StatelessWidget {
|
||||
required this.onSubmit,
|
||||
required this.clearPinText,
|
||||
this.errorMessage,
|
||||
this.pinLength = 6,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -49,7 +51,7 @@ class ScaPinView extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const SizedBox(width: 44),
|
||||
_PinDots(length: pin.length, max: 6),
|
||||
_PinDots(length: pin.length, max: pinLength),
|
||||
const SizedBox(width: 12),
|
||||
SizedBox(
|
||||
width: 44,
|
||||
|
||||
@@ -495,7 +495,6 @@ class SignUpViewModel extends Notifier<SignUpViewState> {
|
||||
String _emailErrorFor(String value) {
|
||||
final email = value.trim();
|
||||
if (email.isEmpty) return I18n.errorEmailRequired;
|
||||
if (email.contains('+')) return I18n.errorEmailPlusNotAllowed;
|
||||
if (!_isValidEmail(email)) return I18n.errorEmailInvalid;
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -7,3 +7,7 @@ export 'src/features/lock_card/lock_card_builder.dart';
|
||||
export 'src/features/limits/limits_builder.dart';
|
||||
export 'src/features/goals/goals_builder.dart';
|
||||
export 'src/features/extract/extract_builder.dart';
|
||||
export 'src/features/edit_child_profile/edit_child_profile_builder.dart';
|
||||
export 'src/features/card_pin/card_pin_builder.dart';
|
||||
export 'src/features/card_pin/card_pin_view_state.dart';
|
||||
export 'src/features/renew_card/renew_card_builder.dart';
|
||||
|
||||
41
modules/home/lib/src/features/card_pin/card_pin_builder.dart
Normal file
41
modules/home/lib/src/features/card_pin/card_pin_builder.dart
Normal file
@@ -0,0 +1,41 @@
|
||||
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 'card_pin_screen.dart';
|
||||
import 'card_pin_view_state.dart';
|
||||
|
||||
class SetCardPinBuilder {
|
||||
const SetCardPinBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final childWalletId = state.pathParameters['childWalletId'] ?? '';
|
||||
final navigationContract = GetIt.I<NavigationContract>();
|
||||
return MaterialPage(
|
||||
key: state.pageKey,
|
||||
child: CardPinScreen(
|
||||
childId: childWalletId,
|
||||
navigation: navigationContract,
|
||||
mode: CardPinMode.set,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ChangeCardPinBuilder {
|
||||
const ChangeCardPinBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final childWalletId = state.pathParameters['childWalletId'] ?? '';
|
||||
final navigationContract = GetIt.I<NavigationContract>();
|
||||
return MaterialPage(
|
||||
key: state.pageKey,
|
||||
child: CardPinScreen(
|
||||
childId: childWalletId,
|
||||
navigation: navigationContract,
|
||||
mode: CardPinMode.change,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
136
modules/home/lib/src/features/card_pin/card_pin_screen.dart
Normal file
136
modules/home/lib/src/features/card_pin/card_pin_screen.dart
Normal file
@@ -0,0 +1,136 @@
|
||||
import 'package:auth/auth.dart';
|
||||
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 'card_pin_view_model.dart';
|
||||
import 'card_pin_view_state.dart';
|
||||
|
||||
class CardPinScreen extends ConsumerWidget {
|
||||
final String childId;
|
||||
final NavigationContract navigation;
|
||||
final CardPinMode mode;
|
||||
|
||||
const CardPinScreen({
|
||||
super.key,
|
||||
required this.childId,
|
||||
required this.navigation,
|
||||
required this.mode,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final arg = (childId, mode);
|
||||
final viewState = ref.watch(cardPinViewModelProvider(arg));
|
||||
final viewModel = ref.read(cardPinViewModelProvider(arg).notifier);
|
||||
|
||||
ref.listen(cardPinViewModelProvider(arg), (prev, next) {
|
||||
if (next.success && !(prev?.success ?? false)) {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: context.translate(I18n.cardPinSuccess),
|
||||
type: MessageType.success,
|
||||
);
|
||||
navigation.goBack();
|
||||
return;
|
||||
}
|
||||
if (next.errorMessage.isNotEmpty &&
|
||||
next.errorMessage != (prev?.errorMessage ?? '')) {
|
||||
if (next.errorMessage == 'cardPinMismatch') {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: context.translate(I18n.cardPinMismatch),
|
||||
type: MessageType.error,
|
||||
);
|
||||
} else {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: context.translate(I18n.cardPinError),
|
||||
type: MessageType.error,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (viewState.isLoading) {
|
||||
return const Scaffold(body: Center(child: AppLoadingIndicator()));
|
||||
}
|
||||
|
||||
if (viewState.errorMessage.isNotEmpty && viewState.childProfile == null) {
|
||||
return Scaffold(
|
||||
body: Center(child: Text('Error: ${viewState.errorMessage}')),
|
||||
);
|
||||
}
|
||||
|
||||
final pinLength = viewState.step == CardPinStep.scaPin ? 6 : 4;
|
||||
final stepTitle = _stepTitle(context, viewState.step);
|
||||
final currentPin = switch (viewState.step) {
|
||||
CardPinStep.currentPin => viewState.currentPin,
|
||||
CardPinStep.newPin => viewState.newPin,
|
||||
CardPinStep.confirmPin => viewState.confirmPin,
|
||||
CardPinStep.scaPin => viewState.scaPin,
|
||||
};
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
onPressed: () {
|
||||
if (viewModel.isFirstStep) {
|
||||
navigation.goBack();
|
||||
} else {
|
||||
viewModel.goBack();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: ScaPinView(
|
||||
title: stepTitle,
|
||||
pin: currentPin,
|
||||
pinLength: pinLength,
|
||||
isProcessing: viewState.isSigning || viewState.isSubmitting,
|
||||
processingText: context.translate(I18n.scaSigning),
|
||||
canSubmit: viewModel.canSubmitStep,
|
||||
submitText: viewState.step == CardPinStep.scaPin
|
||||
? context.translate(I18n.scaConnect)
|
||||
: context.translate(I18n.cardPinNext),
|
||||
clearPinText: context.translate(I18n.scaClearPin),
|
||||
onDigitPressed: viewModel.onDigitPressed,
|
||||
onBackspacePressed: viewModel.onBackspacePressed,
|
||||
onClearPin: viewModel.onClearPin,
|
||||
onSubmit: viewModel.onStepSubmit,
|
||||
),
|
||||
),
|
||||
),
|
||||
SafeArea(
|
||||
child: TextButton(
|
||||
onPressed: () => navigation.goBack(),
|
||||
child: Text(context.translate(I18n.cancel)),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _stepTitle(BuildContext context, CardPinStep step) {
|
||||
return switch (step) {
|
||||
CardPinStep.currentPin => context.translate(I18n.cardPinCurrentStep),
|
||||
CardPinStep.newPin => context.translate(I18n.cardPinNewStep),
|
||||
CardPinStep.confirmPin => context.translate(I18n.cardPinConfirmStep),
|
||||
CardPinStep.scaPin => context.translate(I18n.cardPinScaStep),
|
||||
};
|
||||
}
|
||||
}
|
||||
257
modules/home/lib/src/features/card_pin/card_pin_view_model.dart
Normal file
257
modules/home/lib/src/features/card_pin/card_pin_view_model.dart
Normal file
@@ -0,0 +1,257 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:sca_treezor/sca_treezor.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
import '../child_wallet/child_data_provider.dart';
|
||||
import 'card_pin_view_state.dart';
|
||||
|
||||
final cardPinViewModelProvider = NotifierProvider.autoDispose
|
||||
.family<CardPinViewModel, CardPinViewState, (String, CardPinMode)>(
|
||||
CardPinViewModel.new,
|
||||
);
|
||||
|
||||
class CardPinViewModel extends Notifier<CardPinViewState> {
|
||||
final (String, CardPinMode) arg;
|
||||
CardPinViewModel(this.arg);
|
||||
|
||||
String get childId => arg.$1;
|
||||
CardPinMode get mode => arg.$2;
|
||||
|
||||
late final TreezorWalletConnectionService _connectionService;
|
||||
late final TreezorWalletSignatureService _signatureService;
|
||||
|
||||
@override
|
||||
CardPinViewState build() {
|
||||
debugPrint('[CardPIN] build() mode=$mode childId=$childId');
|
||||
_connectionService = GetIt.I<TreezorWalletConnectionService>();
|
||||
_signatureService = GetIt.I<TreezorWalletSignatureService>();
|
||||
|
||||
ref.listen(childDataProvider(childId), (prev, next) {
|
||||
state = state.copyWith(
|
||||
isLoading: next.isLoading,
|
||||
childProfile: next.childProfile,
|
||||
childWallet: next.childWallet,
|
||||
device: next.device,
|
||||
errorMessage: next.errorMessage,
|
||||
);
|
||||
if (next.childProfile != null &&
|
||||
prev?.childProfile == null &&
|
||||
state.cardId.isEmpty) {
|
||||
_loadCard(next.childProfile!.walletId);
|
||||
}
|
||||
});
|
||||
|
||||
final data = ref.read(childDataProvider(childId));
|
||||
final initialStep =
|
||||
mode == CardPinMode.change ? CardPinStep.currentPin : CardPinStep.newPin;
|
||||
|
||||
final initialState = CardPinViewState(
|
||||
isLoading: data.isLoading,
|
||||
childProfile: data.childProfile,
|
||||
childWallet: data.childWallet,
|
||||
device: data.device,
|
||||
errorMessage: data.errorMessage,
|
||||
step: initialStep,
|
||||
);
|
||||
|
||||
if (data.childProfile != null) {
|
||||
Future.microtask(() => _loadCard(data.childProfile!.walletId));
|
||||
}
|
||||
|
||||
return initialState;
|
||||
}
|
||||
|
||||
Future<void> _loadCard(String walletId) async {
|
||||
debugPrint('[CardPIN] _loadCard walletId=$walletId');
|
||||
try {
|
||||
final card =
|
||||
await ref.read(treezorRepositoryProvider).getCard(walletId: walletId);
|
||||
if (!ref.mounted) return;
|
||||
debugPrint('[CardPIN] _loadCard cardId=${card.cardId} status=${card.status}');
|
||||
state = state.copyWith(cardId: card.cardId.toString());
|
||||
} catch (e) {
|
||||
debugPrint('[CardPIN] _loadCard error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
String _currentStepPin() => switch (state.step) {
|
||||
CardPinStep.currentPin => state.currentPin,
|
||||
CardPinStep.newPin => state.newPin,
|
||||
CardPinStep.confirmPin => state.confirmPin,
|
||||
CardPinStep.scaPin => state.scaPin,
|
||||
};
|
||||
|
||||
int get _currentStepMaxLength =>
|
||||
state.step == CardPinStep.scaPin ? 6 : 4;
|
||||
|
||||
void onDigitPressed(String digit) {
|
||||
final current = _currentStepPin();
|
||||
if (current.length >= _currentStepMaxLength) return;
|
||||
final updated = current + digit;
|
||||
state = _updateStepPin(updated).copyWith(errorMessage: '');
|
||||
}
|
||||
|
||||
void onBackspacePressed() {
|
||||
final current = _currentStepPin();
|
||||
if (current.isEmpty) return;
|
||||
state = _updateStepPin(current.substring(0, current.length - 1));
|
||||
}
|
||||
|
||||
void onClearPin() {
|
||||
state = _updateStepPin('');
|
||||
}
|
||||
|
||||
CardPinViewState _updateStepPin(String value) => switch (state.step) {
|
||||
CardPinStep.currentPin => state.copyWith(currentPin: value),
|
||||
CardPinStep.newPin => state.copyWith(newPin: value),
|
||||
CardPinStep.confirmPin => state.copyWith(confirmPin: value),
|
||||
CardPinStep.scaPin => state.copyWith(scaPin: value),
|
||||
};
|
||||
|
||||
bool get canSubmitStep => _currentStepPin().length == _currentStepMaxLength;
|
||||
|
||||
void onStepSubmit() {
|
||||
debugPrint('[CardPIN] onStepSubmit step=${state.step}');
|
||||
switch (state.step) {
|
||||
case CardPinStep.currentPin:
|
||||
debugPrint('[CardPIN] currentPin entered, advancing to newPin');
|
||||
state = state.copyWith(step: CardPinStep.newPin, errorMessage: '');
|
||||
case CardPinStep.newPin:
|
||||
debugPrint('[CardPIN] newPin entered, advancing to confirmPin');
|
||||
state = state.copyWith(step: CardPinStep.confirmPin, errorMessage: '');
|
||||
case CardPinStep.confirmPin:
|
||||
if (state.confirmPin != state.newPin) {
|
||||
debugPrint('[CardPIN] confirmPin MISMATCH');
|
||||
state = state.copyWith(
|
||||
confirmPin: '',
|
||||
errorMessage: 'cardPinMismatch',
|
||||
);
|
||||
return;
|
||||
}
|
||||
debugPrint('[CardPIN] confirmPin matches, advancing to scaPin');
|
||||
state = state.copyWith(step: CardPinStep.scaPin, errorMessage: '');
|
||||
case CardPinStep.scaPin:
|
||||
debugPrint('[CardPIN] scaPin entered, submitting...');
|
||||
_submit();
|
||||
}
|
||||
}
|
||||
|
||||
void goBack() {
|
||||
switch (state.step) {
|
||||
case CardPinStep.currentPin:
|
||||
break;
|
||||
case CardPinStep.newPin:
|
||||
if (mode == CardPinMode.change) {
|
||||
state = state.copyWith(step: CardPinStep.currentPin, newPin: '');
|
||||
}
|
||||
case CardPinStep.confirmPin:
|
||||
state = state.copyWith(step: CardPinStep.newPin, confirmPin: '');
|
||||
case CardPinStep.scaPin:
|
||||
state = state.copyWith(step: CardPinStep.confirmPin, scaPin: '');
|
||||
}
|
||||
}
|
||||
|
||||
bool get isFirstStep =>
|
||||
(mode == CardPinMode.set && state.step == CardPinStep.newPin) ||
|
||||
(mode == CardPinMode.change && state.step == CardPinStep.currentPin);
|
||||
|
||||
Future<void> _submit() async {
|
||||
final cardId = state.cardId;
|
||||
final walletId = state.childProfile?.walletId;
|
||||
final userId = state.childProfile?.treezorUserId;
|
||||
debugPrint('[CardPIN] _submit mode=$mode cardId=$cardId walletId=$walletId userId=$userId');
|
||||
if (cardId.isEmpty || walletId == null) {
|
||||
debugPrint('[CardPIN] _submit aborted: cardId or walletId missing');
|
||||
return;
|
||||
}
|
||||
|
||||
state = state.copyWith(isSigning: true, errorMessage: '');
|
||||
|
||||
try {
|
||||
debugPrint('[CardPIN] connecting with SCA PIN...');
|
||||
await _connectionService.connectWithPin(loginPin: state.scaPin);
|
||||
if (!ref.mounted) return;
|
||||
debugPrint('[CardPIN] SCA connection successful');
|
||||
|
||||
final String scaProof;
|
||||
if (mode == CardPinMode.set) {
|
||||
final url =
|
||||
'https://savefamily.preprod.secure.treezor.co/cards/$cardId/setPIN';
|
||||
final scaInput = jsonEncode({
|
||||
'url': url,
|
||||
'body': {
|
||||
'newPIN': state.newPin,
|
||||
'confirmPIN': state.confirmPin,
|
||||
'userId': userId,
|
||||
},
|
||||
});
|
||||
debugPrint('[CardPIN] setPIN scaInput: $scaInput');
|
||||
scaProof = await _signatureService.generateJwsWithPin(
|
||||
message: '',
|
||||
input: scaInput,
|
||||
pin: state.scaPin,
|
||||
);
|
||||
debugPrint('[CardPIN] setPIN scaProof: $scaProof');
|
||||
} else {
|
||||
final url =
|
||||
'https://savefamily.preprod.secure.treezor.co/cards/$cardId/ChangePIN';
|
||||
final scaInput = jsonEncode({
|
||||
'url': url,
|
||||
'body': {
|
||||
'currentPIN': state.currentPin,
|
||||
'newPIN': state.newPin,
|
||||
'confirmPIN': state.confirmPin,
|
||||
'userId': userId,
|
||||
},
|
||||
});
|
||||
debugPrint('[CardPIN] changePIN scaInput: $scaInput');
|
||||
scaProof = await _signatureService.generateJwsWithPin(
|
||||
message: '',
|
||||
input: scaInput,
|
||||
pin: state.scaPin,
|
||||
);
|
||||
debugPrint('[CardPIN] changePIN scaProof: $scaProof');
|
||||
}
|
||||
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isSigning: false, isSubmitting: true, scaPin: '');
|
||||
|
||||
if (mode == CardPinMode.set) {
|
||||
debugPrint('[CardPIN] calling backend setCardPin walletId=$walletId');
|
||||
await ref.read(treezorRepositoryProvider).setCardPin(
|
||||
walletId: walletId,
|
||||
newPin: state.newPin,
|
||||
confirmPin: state.confirmPin,
|
||||
scaProof: scaProof,
|
||||
);
|
||||
debugPrint('[CardPIN] setCardPin SUCCESS');
|
||||
} else {
|
||||
debugPrint('[CardPIN] calling backend changeCardPin walletId=$walletId');
|
||||
await ref.read(treezorRepositoryProvider).changeCardPin(
|
||||
walletId: walletId,
|
||||
currentPin: state.currentPin,
|
||||
newPin: state.newPin,
|
||||
confirmPin: state.confirmPin,
|
||||
scaProof: scaProof,
|
||||
);
|
||||
debugPrint('[CardPIN] changeCardPin SUCCESS');
|
||||
}
|
||||
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isSubmitting: false, success: true);
|
||||
} catch (e) {
|
||||
debugPrint('[CardPIN] _submit ERROR: $e');
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isSigning: false,
|
||||
isSubmitting: false,
|
||||
scaPin: '',
|
||||
errorMessage: e.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
part 'card_pin_view_state.freezed.dart';
|
||||
|
||||
enum CardPinMode { set, change }
|
||||
|
||||
enum CardPinStep { currentPin, newPin, confirmPin, scaPin }
|
||||
|
||||
@freezed
|
||||
abstract class CardPinViewState with _$CardPinViewState {
|
||||
const factory CardPinViewState({
|
||||
@Default(true) bool isLoading,
|
||||
ChildProfileEntity? childProfile,
|
||||
ChildWalletEntity? childWallet,
|
||||
DeviceEntity? device,
|
||||
@Default('') String cardId,
|
||||
@Default('') String currentPin,
|
||||
@Default('') String newPin,
|
||||
@Default('') String confirmPin,
|
||||
@Default('') String scaPin,
|
||||
@Default(CardPinStep.newPin) CardPinStep step,
|
||||
@Default(false) bool isSigning,
|
||||
@Default(false) bool isSubmitting,
|
||||
@Default(false) bool success,
|
||||
@Default('') String errorMessage,
|
||||
}) = _CardPinViewState;
|
||||
}
|
||||
@@ -0,0 +1,382 @@
|
||||
// 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 'card_pin_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$CardPinViewState {
|
||||
|
||||
bool get isLoading; ChildProfileEntity? get childProfile; ChildWalletEntity? get childWallet; DeviceEntity? get device; String get cardId; String get currentPin; String get newPin; String get confirmPin; String get scaPin; CardPinStep get step; bool get isSigning; bool get isSubmitting; bool get success; String get errorMessage;
|
||||
/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$CardPinViewStateCopyWith<CardPinViewState> get copyWith => _$CardPinViewStateCopyWithImpl<CardPinViewState>(this as CardPinViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is CardPinViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.childProfile, childProfile) || other.childProfile == childProfile)&&(identical(other.childWallet, childWallet) || other.childWallet == childWallet)&&(identical(other.device, device) || other.device == device)&&(identical(other.cardId, cardId) || other.cardId == cardId)&&(identical(other.currentPin, currentPin) || other.currentPin == currentPin)&&(identical(other.newPin, newPin) || other.newPin == newPin)&&(identical(other.confirmPin, confirmPin) || other.confirmPin == confirmPin)&&(identical(other.scaPin, scaPin) || other.scaPin == scaPin)&&(identical(other.step, step) || other.step == step)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.isSubmitting, isSubmitting) || other.isSubmitting == isSubmitting)&&(identical(other.success, success) || other.success == success)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,childProfile,childWallet,device,cardId,currentPin,newPin,confirmPin,scaPin,step,isSigning,isSubmitting,success,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CardPinViewState(isLoading: $isLoading, childProfile: $childProfile, childWallet: $childWallet, device: $device, cardId: $cardId, currentPin: $currentPin, newPin: $newPin, confirmPin: $confirmPin, scaPin: $scaPin, step: $step, isSigning: $isSigning, isSubmitting: $isSubmitting, success: $success, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $CardPinViewStateCopyWith<$Res> {
|
||||
factory $CardPinViewStateCopyWith(CardPinViewState value, $Res Function(CardPinViewState) _then) = _$CardPinViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String currentPin, String newPin, String confirmPin, String scaPin, CardPinStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
$ChildProfileEntityCopyWith<$Res>? get childProfile;$ChildWalletEntityCopyWith<$Res>? get childWallet;$DeviceEntityCopyWith<$Res>? get device;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$CardPinViewStateCopyWithImpl<$Res>
|
||||
implements $CardPinViewStateCopyWith<$Res> {
|
||||
_$CardPinViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final CardPinViewState _self;
|
||||
final $Res Function(CardPinViewState) _then;
|
||||
|
||||
/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? childProfile = freezed,Object? childWallet = freezed,Object? device = freezed,Object? cardId = null,Object? currentPin = null,Object? newPin = null,Object? confirmPin = null,Object? scaPin = null,Object? step = null,Object? isSigning = null,Object? isSubmitting = null,Object? success = null,Object? errorMessage = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,childProfile: freezed == childProfile ? _self.childProfile : childProfile // ignore: cast_nullable_to_non_nullable
|
||||
as ChildProfileEntity?,childWallet: freezed == childWallet ? _self.childWallet : childWallet // ignore: cast_nullable_to_non_nullable
|
||||
as ChildWalletEntity?,device: freezed == device ? _self.device : device // ignore: cast_nullable_to_non_nullable
|
||||
as DeviceEntity?,cardId: null == cardId ? _self.cardId : cardId // ignore: cast_nullable_to_non_nullable
|
||||
as String,currentPin: null == currentPin ? _self.currentPin : currentPin // ignore: cast_nullable_to_non_nullable
|
||||
as String,newPin: null == newPin ? _self.newPin : newPin // ignore: cast_nullable_to_non_nullable
|
||||
as String,confirmPin: null == confirmPin ? _self.confirmPin : confirmPin // ignore: cast_nullable_to_non_nullable
|
||||
as String,scaPin: null == scaPin ? _self.scaPin : scaPin // ignore: cast_nullable_to_non_nullable
|
||||
as String,step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable
|
||||
as CardPinStep,isSigning: null == isSigning ? _self.isSigning : isSigning // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||
as bool,success: null == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChildProfileEntityCopyWith<$Res>? get childProfile {
|
||||
if (_self.childProfile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChildProfileEntityCopyWith<$Res>(_self.childProfile!, (value) {
|
||||
return _then(_self.copyWith(childProfile: value));
|
||||
});
|
||||
}/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChildWalletEntityCopyWith<$Res>? get childWallet {
|
||||
if (_self.childWallet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChildWalletEntityCopyWith<$Res>(_self.childWallet!, (value) {
|
||||
return _then(_self.copyWith(childWallet: value));
|
||||
});
|
||||
}/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$DeviceEntityCopyWith<$Res>? get device {
|
||||
if (_self.device == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $DeviceEntityCopyWith<$Res>(_self.device!, (value) {
|
||||
return _then(_self.copyWith(device: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [CardPinViewState].
|
||||
extension CardPinViewStatePatterns on CardPinViewState {
|
||||
/// 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( _CardPinViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CardPinViewState() 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( _CardPinViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CardPinViewState():
|
||||
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( _CardPinViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CardPinViewState() 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, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String currentPin, String newPin, String confirmPin, String scaPin, CardPinStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CardPinViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.currentPin,_that.newPin,_that.confirmPin,_that.scaPin,_that.step,_that.isSigning,_that.isSubmitting,_that.success,_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, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String currentPin, String newPin, String confirmPin, String scaPin, CardPinStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CardPinViewState():
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.currentPin,_that.newPin,_that.confirmPin,_that.scaPin,_that.step,_that.isSigning,_that.isSubmitting,_that.success,_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, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String currentPin, String newPin, String confirmPin, String scaPin, CardPinStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CardPinViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.currentPin,_that.newPin,_that.confirmPin,_that.scaPin,_that.step,_that.isSigning,_that.isSubmitting,_that.success,_that.errorMessage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _CardPinViewState implements CardPinViewState {
|
||||
const _CardPinViewState({this.isLoading = true, this.childProfile, this.childWallet, this.device, this.cardId = '', this.currentPin = '', this.newPin = '', this.confirmPin = '', this.scaPin = '', this.step = CardPinStep.newPin, this.isSigning = false, this.isSubmitting = false, this.success = false, this.errorMessage = ''});
|
||||
|
||||
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override final ChildProfileEntity? childProfile;
|
||||
@override final ChildWalletEntity? childWallet;
|
||||
@override final DeviceEntity? device;
|
||||
@override@JsonKey() final String cardId;
|
||||
@override@JsonKey() final String currentPin;
|
||||
@override@JsonKey() final String newPin;
|
||||
@override@JsonKey() final String confirmPin;
|
||||
@override@JsonKey() final String scaPin;
|
||||
@override@JsonKey() final CardPinStep step;
|
||||
@override@JsonKey() final bool isSigning;
|
||||
@override@JsonKey() final bool isSubmitting;
|
||||
@override@JsonKey() final bool success;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
|
||||
/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$CardPinViewStateCopyWith<_CardPinViewState> get copyWith => __$CardPinViewStateCopyWithImpl<_CardPinViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CardPinViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.childProfile, childProfile) || other.childProfile == childProfile)&&(identical(other.childWallet, childWallet) || other.childWallet == childWallet)&&(identical(other.device, device) || other.device == device)&&(identical(other.cardId, cardId) || other.cardId == cardId)&&(identical(other.currentPin, currentPin) || other.currentPin == currentPin)&&(identical(other.newPin, newPin) || other.newPin == newPin)&&(identical(other.confirmPin, confirmPin) || other.confirmPin == confirmPin)&&(identical(other.scaPin, scaPin) || other.scaPin == scaPin)&&(identical(other.step, step) || other.step == step)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.isSubmitting, isSubmitting) || other.isSubmitting == isSubmitting)&&(identical(other.success, success) || other.success == success)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,childProfile,childWallet,device,cardId,currentPin,newPin,confirmPin,scaPin,step,isSigning,isSubmitting,success,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CardPinViewState(isLoading: $isLoading, childProfile: $childProfile, childWallet: $childWallet, device: $device, cardId: $cardId, currentPin: $currentPin, newPin: $newPin, confirmPin: $confirmPin, scaPin: $scaPin, step: $step, isSigning: $isSigning, isSubmitting: $isSubmitting, success: $success, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$CardPinViewStateCopyWith<$Res> implements $CardPinViewStateCopyWith<$Res> {
|
||||
factory _$CardPinViewStateCopyWith(_CardPinViewState value, $Res Function(_CardPinViewState) _then) = __$CardPinViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String currentPin, String newPin, String confirmPin, String scaPin, CardPinStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
@override $ChildProfileEntityCopyWith<$Res>? get childProfile;@override $ChildWalletEntityCopyWith<$Res>? get childWallet;@override $DeviceEntityCopyWith<$Res>? get device;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$CardPinViewStateCopyWithImpl<$Res>
|
||||
implements _$CardPinViewStateCopyWith<$Res> {
|
||||
__$CardPinViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _CardPinViewState _self;
|
||||
final $Res Function(_CardPinViewState) _then;
|
||||
|
||||
/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? childProfile = freezed,Object? childWallet = freezed,Object? device = freezed,Object? cardId = null,Object? currentPin = null,Object? newPin = null,Object? confirmPin = null,Object? scaPin = null,Object? step = null,Object? isSigning = null,Object? isSubmitting = null,Object? success = null,Object? errorMessage = null,}) {
|
||||
return _then(_CardPinViewState(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,childProfile: freezed == childProfile ? _self.childProfile : childProfile // ignore: cast_nullable_to_non_nullable
|
||||
as ChildProfileEntity?,childWallet: freezed == childWallet ? _self.childWallet : childWallet // ignore: cast_nullable_to_non_nullable
|
||||
as ChildWalletEntity?,device: freezed == device ? _self.device : device // ignore: cast_nullable_to_non_nullable
|
||||
as DeviceEntity?,cardId: null == cardId ? _self.cardId : cardId // ignore: cast_nullable_to_non_nullable
|
||||
as String,currentPin: null == currentPin ? _self.currentPin : currentPin // ignore: cast_nullable_to_non_nullable
|
||||
as String,newPin: null == newPin ? _self.newPin : newPin // ignore: cast_nullable_to_non_nullable
|
||||
as String,confirmPin: null == confirmPin ? _self.confirmPin : confirmPin // ignore: cast_nullable_to_non_nullable
|
||||
as String,scaPin: null == scaPin ? _self.scaPin : scaPin // ignore: cast_nullable_to_non_nullable
|
||||
as String,step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable
|
||||
as CardPinStep,isSigning: null == isSigning ? _self.isSigning : isSigning // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||
as bool,success: null == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChildProfileEntityCopyWith<$Res>? get childProfile {
|
||||
if (_self.childProfile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChildProfileEntityCopyWith<$Res>(_self.childProfile!, (value) {
|
||||
return _then(_self.copyWith(childProfile: value));
|
||||
});
|
||||
}/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChildWalletEntityCopyWith<$Res>? get childWallet {
|
||||
if (_self.childWallet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChildWalletEntityCopyWith<$Res>(_self.childWallet!, (value) {
|
||||
return _then(_self.copyWith(childWallet: value));
|
||||
});
|
||||
}/// Create a copy of CardPinViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$DeviceEntityCopyWith<$Res>? get device {
|
||||
if (_self.device == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $DeviceEntityCopyWith<$Res>(_self.device!, (value) {
|
||||
return _then(_self.copyWith(device: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -1,6 +1,5 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
@@ -15,11 +14,12 @@ class ChildDataNotifier extends Notifier<ChildDataState> {
|
||||
final String childId;
|
||||
ChildDataNotifier(this.childId);
|
||||
|
||||
late final TreezorRepository _treezorRepository;
|
||||
late final UserRepository _userRepository;
|
||||
late TreezorRepository _treezorRepository;
|
||||
late UserRepository _userRepository;
|
||||
|
||||
@override
|
||||
ChildDataState build() {
|
||||
ref.watch(walletRefreshProvider);
|
||||
final link = ref.keepAlive();
|
||||
final timer = Timer(const Duration(minutes: 5), link.close);
|
||||
ref.onDispose(timer.cancel);
|
||||
@@ -56,9 +56,7 @@ class ChildDataNotifier extends Notifier<ChildDataState> {
|
||||
device = await _userRepository.getDeviceByIdentificator(
|
||||
identificator: childProfile.deviceIdentificator,
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('Error fetching device for child $childId: $e');
|
||||
}
|
||||
} catch (_) {}
|
||||
|
||||
if (!ref.mounted) return;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:navigation/navigation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_localizations/sf_localizations.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
import '../../card_colors.dart';
|
||||
import '../../presentation/state/home_view_model.dart';
|
||||
@@ -162,14 +163,119 @@ class _ChildWalletScreenState extends ConsumerState<ChildWalletScreen> {
|
||||
),
|
||||
),
|
||||
_buildGenderAvatar(device?.carrierGenre, 50),
|
||||
Text(
|
||||
childName,
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
Expanded(
|
||||
child: Text(
|
||||
childName,
|
||||
style: TextStyle(
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.backgroundPrimary,
|
||||
),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () => widget.navigation.pushTo(
|
||||
AppRoutes.renewCard(widget.childId),
|
||||
),
|
||||
icon: Icon(
|
||||
Icons.credit_card_outlined,
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
PopupMenuButton<String>(
|
||||
icon: Icon(
|
||||
Icons.more_vert,
|
||||
color: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
),
|
||||
onSelected: (value) {
|
||||
if (value == 'edit') {
|
||||
widget.navigation.pushTo(
|
||||
AppRoutes.editChildProfile(widget.childId),
|
||||
);
|
||||
} else if (value == 'delete') {
|
||||
_showDeleteConfirmation();
|
||||
} else if (value == 'set_pin') {
|
||||
widget.navigation.pushTo(
|
||||
AppRoutes.setCardPin(widget.childId),
|
||||
);
|
||||
} else if (value == 'change_pin') {
|
||||
widget.navigation.pushTo(
|
||||
AppRoutes.changeCardPin(widget.childId),
|
||||
);
|
||||
} else if (value == 'unblock_pin') {
|
||||
_showUnblockPinConfirmation();
|
||||
}
|
||||
},
|
||||
itemBuilder: (_) => [
|
||||
PopupMenuItem(
|
||||
value: 'edit',
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(Icons.edit_outlined),
|
||||
Text(
|
||||
context.translate(I18n.editChildProfile),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!viewState.isPinBlocked && !(viewState.childProfile?.hasCardPin ?? false))
|
||||
PopupMenuItem(
|
||||
value: 'set_pin',
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(Icons.pin_outlined),
|
||||
Text(
|
||||
context.translate(I18n.cardPinSet),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (!viewState.isPinBlocked && (viewState.childProfile?.hasCardPin ?? false))
|
||||
PopupMenuItem(
|
||||
value: 'change_pin',
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(Icons.lock_reset_outlined),
|
||||
Text(
|
||||
context.translate(I18n.cardPinChange),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (viewState.isPinBlocked)
|
||||
PopupMenuItem(
|
||||
value: 'unblock_pin',
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(Icons.lock_open_outlined),
|
||||
Text(
|
||||
context.translate(I18n.cardPinUnblock),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(Icons.delete_outline, color: Colors.red),
|
||||
Text(
|
||||
context.translate(I18n.deleteDevice),
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
@@ -196,76 +302,37 @@ class _ChildWalletScreenState extends ConsumerState<ChildWalletScreen> {
|
||||
minHeight: 10,
|
||||
borderRadius: BorderRadius.all(Radius.circular(5)),
|
||||
),
|
||||
if (CardStatus.fromString(viewState.cardStatus) ==
|
||||
CardStatus.lost ||
|
||||
CardStatus.fromString(viewState.cardStatus) ==
|
||||
CardStatus.stolen)
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.all(0)),
|
||||
),
|
||||
onPressed: viewState.isUpdatingCard
|
||||
? null
|
||||
: () => _showDeleteConfirmation(context, ref),
|
||||
child: Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.delete_outline,
|
||||
size: 24,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textSecondary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
context.translate(I18n.deleteDevice),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
else
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.all(0)),
|
||||
),
|
||||
onPressed: () =>
|
||||
_showCardStatusSheet(context, ref, theme),
|
||||
child: Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.lock_outline,
|
||||
size: 24,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textSecondary,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
locked
|
||||
? context.translate(
|
||||
I18n.childWalletUnlockCard,
|
||||
)
|
||||
: context.translate(
|
||||
I18n.childWalletLockCard,
|
||||
),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
TextButton(
|
||||
style: ButtonStyle(
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.all(0)),
|
||||
),
|
||||
onPressed: () =>
|
||||
_showCardStatusSheet(context, ref, theme),
|
||||
child: Row(
|
||||
spacing: 10,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.lock_outline,
|
||||
size: 24,
|
||||
color: theme.getColorFor(ThemeCode.textSecondary),
|
||||
),
|
||||
Text(
|
||||
locked
|
||||
? context.translate(
|
||||
I18n.childWalletUnlockCard,
|
||||
)
|
||||
: context.translate(I18n.childWalletLockCard),
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16,
|
||||
color: theme.getColorFor(
|
||||
ThemeCode.textSecondary,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
@@ -302,7 +369,7 @@ class _ChildWalletScreenState extends ConsumerState<ChildWalletScreen> {
|
||||
child: AppLoadingIndicator(size: 48),
|
||||
),
|
||||
)
|
||||
else if (viewState.transactions.isEmpty)
|
||||
else if (viewState.transactionPages.isEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(24),
|
||||
child: Center(
|
||||
@@ -319,13 +386,34 @@ class _ChildWalletScreenState extends ConsumerState<ChildWalletScreen> {
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
...viewState.transactions.map(
|
||||
else ...[
|
||||
...viewState.transactionPages[viewState.currentPage].map(
|
||||
(tx) => Padding(
|
||||
padding: const EdgeInsets.only(bottom: 12),
|
||||
child: TransactionTile(transaction: tx),
|
||||
),
|
||||
),
|
||||
PaginationBar(
|
||||
currentPage: viewState.currentPage,
|
||||
totalPages: viewState.transactionPages.length,
|
||||
hasMore: viewState.nextCursor != null,
|
||||
isLoadingMore: viewState.isLoadingMore,
|
||||
onPageChanged: (page) => ref
|
||||
.read(
|
||||
childWalletViewModelProvider(
|
||||
widget.childId,
|
||||
).notifier,
|
||||
)
|
||||
.setPage(page),
|
||||
onLoadMore: () => ref
|
||||
.read(
|
||||
childWalletViewModelProvider(
|
||||
widget.childId,
|
||||
).notifier,
|
||||
)
|
||||
.loadMore(),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -342,17 +430,13 @@ class _ChildWalletScreenState extends ConsumerState<ChildWalletScreen> {
|
||||
|
||||
Widget _buildGenderAvatar(String? carrierGenre, double size) {
|
||||
final IconData icon;
|
||||
final Color color;
|
||||
switch (carrierGenre) {
|
||||
case 'M':
|
||||
icon = Icons.face;
|
||||
color = const Color(0xFF64B5F6);
|
||||
case 'F':
|
||||
icon = Icons.face_3;
|
||||
color = const Color(0xFFF48FB1);
|
||||
default:
|
||||
icon = Icons.face_2;
|
||||
color = const Color(0xFF90A4AE);
|
||||
}
|
||||
return CircleAvatar(
|
||||
radius: size / 2,
|
||||
@@ -376,43 +460,150 @@ class _ChildWalletScreenState extends ConsumerState<ChildWalletScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
void _showDeleteConfirmation(BuildContext context, WidgetRef ref) {
|
||||
Future<void> _showDeleteConfirmation() async {
|
||||
final theme = ref.read(themePortProvider);
|
||||
final userRepo = ref.read(userRepositoryProvider);
|
||||
final navigator = Navigator.of(context, rootNavigator: true);
|
||||
final checkingText = context.translate(I18n.deleteDeviceChecking);
|
||||
final notAllowedTitle = context.translate(I18n.deleteDeviceNotAllowedTitle);
|
||||
final nonZeroText = context.translate(
|
||||
I18n.deleteDeviceWalletNonZeroBalance,
|
||||
);
|
||||
final acceptText = context.translate(I18n.accept);
|
||||
final confirmTitle = context.translate(I18n.deleteDeviceConfirmTitle);
|
||||
final confirmMessage = context.translate(I18n.deleteDeviceConfirmMessage);
|
||||
final cancelText = context.translate(I18n.cancel);
|
||||
final deleteText = context.translate(I18n.deleteDevice);
|
||||
final successText = context.translate(I18n.deleteDeviceSuccess);
|
||||
final bgColor = theme.getColorFor(ThemeCode.backgroundPrimary);
|
||||
final shape = RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (_) => AlertDialog(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundPrimary),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
title: Text(context.translate(I18n.deleteDeviceConfirmTitle)),
|
||||
content: Text(context.translate(I18n.deleteDeviceConfirmMessage)),
|
||||
backgroundColor: bgColor,
|
||||
shape: shape,
|
||||
content: Row(
|
||||
spacing: 16,
|
||||
children: [const AppLoadingIndicator(size: 24), Text(checkingText)],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
try {
|
||||
final deletability = await userRepo.checkChildProfileDeletability(
|
||||
childProfileId: widget.childId,
|
||||
);
|
||||
if (!mounted) return;
|
||||
navigator.pop();
|
||||
|
||||
if (!deletability.isDeletable) {
|
||||
if (!mounted) return;
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
backgroundColor: bgColor,
|
||||
shape: shape,
|
||||
title: Text(notAllowedTitle),
|
||||
content: Text(nonZeroText),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
child: Text(acceptText),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mounted) return;
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
backgroundColor: bgColor,
|
||||
shape: shape,
|
||||
title: Text(confirmTitle),
|
||||
content: Text(confirmMessage),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
child: Text(cancelText),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(ctx).pop();
|
||||
final viewModel = ref.read(
|
||||
childWalletViewModelProvider(widget.childId).notifier,
|
||||
);
|
||||
final success = await viewModel.deleteDevice();
|
||||
if (success && mounted) {
|
||||
ref
|
||||
.read(homeViewModelProvider.notifier)
|
||||
.removeChild(widget.childId);
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: successText,
|
||||
type: MessageType.success,
|
||||
);
|
||||
widget.navigation.goBack();
|
||||
}
|
||||
},
|
||||
child: Text(deleteText, style: TextStyle(color: Colors.red)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
navigator.pop();
|
||||
showTopSnackbar(context, message: e.toString(), type: MessageType.error);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _showUnblockPinConfirmation() async {
|
||||
final theme = ref.read(themePortProvider);
|
||||
final confirmTitle = context.translate(I18n.cardPinUnblock);
|
||||
final confirmMessage = context.translate(I18n.cardPinUnblockConfirm);
|
||||
final cancelText = context.translate(I18n.cancel);
|
||||
final confirmText = context.translate(I18n.accept);
|
||||
final successText = context.translate(I18n.cardPinUnblockSuccess);
|
||||
final bgColor = theme.getColorFor(ThemeCode.backgroundPrimary);
|
||||
final shape = RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
);
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
backgroundColor: bgColor,
|
||||
shape: shape,
|
||||
title: Text(confirmTitle),
|
||||
content: Text(confirmMessage),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(context.translate(I18n.cancel)),
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
child: Text(cancelText),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () async {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(ctx).pop();
|
||||
final viewModel = ref.read(
|
||||
childWalletViewModelProvider(widget.childId).notifier,
|
||||
);
|
||||
final success = await viewModel.deleteDevice();
|
||||
if (success && context.mounted) {
|
||||
ref
|
||||
.read(homeViewModelProvider.notifier)
|
||||
.removeChild(widget.childId);
|
||||
final success = await viewModel.unblockCardPin();
|
||||
if (success && mounted) {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: context.translate(I18n.deleteDeviceSuccess),
|
||||
message: successText,
|
||||
type: MessageType.success,
|
||||
);
|
||||
widget.navigation.goBack();
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
context.translate(I18n.deleteDevice),
|
||||
style: TextStyle(color: Colors.red),
|
||||
),
|
||||
child: Text(confirmText),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -463,13 +654,19 @@ class _CardStatusSheetState extends ConsumerState<_CardStatusSheet> {
|
||||
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
...statuses.map(
|
||||
(status) => RadioListTile<String>(
|
||||
title: Text(context.translate(_labelKey(status))),
|
||||
value: status,
|
||||
groupValue: _selected,
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
onChanged: (v) => setState(() => _selected = v!),
|
||||
RadioGroup<String>(
|
||||
groupValue: _selected!,
|
||||
onChanged: (v) => setState(() => _selected = v),
|
||||
child: Column(
|
||||
children: statuses
|
||||
.map(
|
||||
(status) => RadioListTile<String>(
|
||||
title: Text(context.translate(_labelKey(status))),
|
||||
value: status,
|
||||
activeColor: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
@@ -5,7 +5,6 @@ import 'package:get_it/get_it.dart';
|
||||
import 'package:sca_treezor/sca_treezor.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
|
||||
import '../../card_colors.dart';
|
||||
import 'child_data_provider.dart';
|
||||
import 'child_wallet_view_state.dart';
|
||||
@@ -19,8 +18,8 @@ class ChildWalletViewModel extends Notifier<ChildWalletViewState> {
|
||||
final String childId;
|
||||
ChildWalletViewModel(this.childId);
|
||||
|
||||
late final TreezorWalletConnectionService _connectionService;
|
||||
late final TreezorWalletSignatureService _signatureService;
|
||||
late TreezorWalletConnectionService _connectionService;
|
||||
late TreezorWalletSignatureService _signatureService;
|
||||
|
||||
@override
|
||||
ChildWalletViewState build() {
|
||||
@@ -43,6 +42,8 @@ class ChildWalletViewModel extends Notifier<ChildWalletViewState> {
|
||||
}
|
||||
});
|
||||
|
||||
ref.watch(walletRefreshProvider);
|
||||
|
||||
final data = ref.read(childDataProvider(childId));
|
||||
final initialState = ChildWalletViewState(
|
||||
isLoading: data.isLoading,
|
||||
@@ -66,19 +67,53 @@ class ChildWalletViewModel extends Notifier<ChildWalletViewState> {
|
||||
state = state.copyWith(isLoadingTransactions: true);
|
||||
try {
|
||||
final query = TransactionsQuery(walletId: walletId);
|
||||
final transactions =
|
||||
await ref.read(walletTransactionsProvider(query).future);
|
||||
final response = await ref.read(
|
||||
walletTransactionsProvider(query).future,
|
||||
);
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isLoadingTransactions: false,
|
||||
transactions: transactions,
|
||||
transactionPages: [response.items],
|
||||
nextCursor: response.nextCursor,
|
||||
currentPage: 0,
|
||||
);
|
||||
} catch (_) {
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isLoadingTransactions: false);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> loadMore() async {
|
||||
final walletId = state.childProfile?.walletId;
|
||||
if (walletId == null || state.isLoadingMore || state.nextCursor == null) return;
|
||||
|
||||
state = state.copyWith(isLoadingMore: true);
|
||||
|
||||
try {
|
||||
final query = TransactionsQuery(
|
||||
walletId: walletId,
|
||||
cursor: state.nextCursor,
|
||||
);
|
||||
final response = await ref.read(
|
||||
walletTransactionsProvider(query).future,
|
||||
);
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isLoadingMore: false,
|
||||
transactionPages: [...state.transactionPages, response.items],
|
||||
nextCursor: response.nextCursor,
|
||||
currentPage: state.transactionPages.length,
|
||||
);
|
||||
} catch (_) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isLoadingMore: false);
|
||||
}
|
||||
}
|
||||
|
||||
void setPage(int page) {
|
||||
state = state.copyWith(currentPage: page);
|
||||
}
|
||||
|
||||
Future<void> _loadCard(String walletId) async {
|
||||
try {
|
||||
final card = await ref
|
||||
@@ -89,6 +124,7 @@ class ChildWalletViewModel extends Notifier<ChildWalletViewState> {
|
||||
cardId: card.cardId.toString(),
|
||||
cardStatus: card.status,
|
||||
locked: CardStatus.fromString(card.status).isLocked,
|
||||
isPinBlocked: card.isPinBlocked,
|
||||
);
|
||||
} catch (_) {}
|
||||
}
|
||||
@@ -181,6 +217,12 @@ class ChildWalletViewModel extends Notifier<ChildWalletViewState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<ChildProfileDeletabilityEntity> checkDeletability() async {
|
||||
return ref
|
||||
.read(userRepositoryProvider)
|
||||
.checkChildProfileDeletability(childProfileId: childId);
|
||||
}
|
||||
|
||||
Future<bool> deleteDevice() async {
|
||||
final deviceId = state.device?.id;
|
||||
if (deviceId == null || deviceId.isEmpty) return false;
|
||||
@@ -195,7 +237,33 @@ class ChildWalletViewModel extends Notifier<ChildWalletViewState> {
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return false;
|
||||
state = state.copyWith(isUpdatingCard: false, cardStatusError: e.toString());
|
||||
state = state.copyWith(
|
||||
isUpdatingCard: false,
|
||||
cardStatusError: e.toString(),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> unblockCardPin() async {
|
||||
final walletId = state.childProfile?.walletId;
|
||||
if (walletId == null) return false;
|
||||
|
||||
state = state.copyWith(isUpdatingCard: true, cardStatusError: '');
|
||||
|
||||
try {
|
||||
await ref.read(treezorRepositoryProvider).unblockCardPin(
|
||||
walletId: walletId,
|
||||
);
|
||||
if (!ref.mounted) return false;
|
||||
state = state.copyWith(isUpdatingCard: false);
|
||||
return true;
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return false;
|
||||
state = state.copyWith(
|
||||
isUpdatingCard: false,
|
||||
cardStatusError: e.toString(),
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ abstract class ChildWalletViewState with _$ChildWalletViewState {
|
||||
@Default('') String cardId,
|
||||
@Default('') String cardStatus,
|
||||
@Default(false) bool locked,
|
||||
@Default(false) bool isPinBlocked,
|
||||
@Default('') String errorMessage,
|
||||
@Default(false) bool isUpdatingCard,
|
||||
@Default('') String cardStatusError,
|
||||
@@ -22,6 +23,9 @@ abstract class ChildWalletViewState with _$ChildWalletViewState {
|
||||
@Default('') String pin,
|
||||
@Default(false) bool isSigning,
|
||||
@Default(false) bool isLoadingTransactions,
|
||||
@Default([]) List<WalletTransactionEntity> transactions,
|
||||
@Default([]) List<List<WalletTransactionEntity>> transactionPages,
|
||||
String? nextCursor,
|
||||
@Default(false) bool isLoadingMore,
|
||||
@Default(0) int currentPage,
|
||||
}) = _ChildWalletViewState;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$ChildWalletViewState {
|
||||
|
||||
bool get isLoading; ChildProfileEntity? get childProfile; ChildWalletEntity? get childWallet; DeviceEntity? get device; String get cardId; String get cardStatus; bool get locked; String get errorMessage; bool get isUpdatingCard; String get cardStatusError; bool get cardStatusSuccess; bool get showPin; String get selectedStatus; String get pin; bool get isSigning; bool get isLoadingTransactions; List<WalletTransactionEntity> get transactions;
|
||||
bool get isLoading; ChildProfileEntity? get childProfile; ChildWalletEntity? get childWallet; DeviceEntity? get device; String get cardId; String get cardStatus; bool get locked; bool get isPinBlocked; String get errorMessage; bool get isUpdatingCard; String get cardStatusError; bool get cardStatusSuccess; bool get showPin; String get selectedStatus; String get pin; bool get isSigning; bool get isLoadingTransactions; List<List<WalletTransactionEntity>> get transactionPages; String? get nextCursor; bool get isLoadingMore; int get currentPage;
|
||||
/// Create a copy of ChildWalletViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -25,16 +25,16 @@ $ChildWalletViewStateCopyWith<ChildWalletViewState> get copyWith => _$ChildWalle
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChildWalletViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.childProfile, childProfile) || other.childProfile == childProfile)&&(identical(other.childWallet, childWallet) || other.childWallet == childWallet)&&(identical(other.device, device) || other.device == device)&&(identical(other.cardId, cardId) || other.cardId == cardId)&&(identical(other.cardStatus, cardStatus) || other.cardStatus == cardStatus)&&(identical(other.locked, locked) || other.locked == locked)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isUpdatingCard, isUpdatingCard) || other.isUpdatingCard == isUpdatingCard)&&(identical(other.cardStatusError, cardStatusError) || other.cardStatusError == cardStatusError)&&(identical(other.cardStatusSuccess, cardStatusSuccess) || other.cardStatusSuccess == cardStatusSuccess)&&(identical(other.showPin, showPin) || other.showPin == showPin)&&(identical(other.selectedStatus, selectedStatus) || other.selectedStatus == selectedStatus)&&(identical(other.pin, pin) || other.pin == pin)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.isLoadingTransactions, isLoadingTransactions) || other.isLoadingTransactions == isLoadingTransactions)&&const DeepCollectionEquality().equals(other.transactions, transactions));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChildWalletViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.childProfile, childProfile) || other.childProfile == childProfile)&&(identical(other.childWallet, childWallet) || other.childWallet == childWallet)&&(identical(other.device, device) || other.device == device)&&(identical(other.cardId, cardId) || other.cardId == cardId)&&(identical(other.cardStatus, cardStatus) || other.cardStatus == cardStatus)&&(identical(other.locked, locked) || other.locked == locked)&&(identical(other.isPinBlocked, isPinBlocked) || other.isPinBlocked == isPinBlocked)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isUpdatingCard, isUpdatingCard) || other.isUpdatingCard == isUpdatingCard)&&(identical(other.cardStatusError, cardStatusError) || other.cardStatusError == cardStatusError)&&(identical(other.cardStatusSuccess, cardStatusSuccess) || other.cardStatusSuccess == cardStatusSuccess)&&(identical(other.showPin, showPin) || other.showPin == showPin)&&(identical(other.selectedStatus, selectedStatus) || other.selectedStatus == selectedStatus)&&(identical(other.pin, pin) || other.pin == pin)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.isLoadingTransactions, isLoadingTransactions) || other.isLoadingTransactions == isLoadingTransactions)&&const DeepCollectionEquality().equals(other.transactionPages, transactionPages)&&(identical(other.nextCursor, nextCursor) || other.nextCursor == nextCursor)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.currentPage, currentPage) || other.currentPage == currentPage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,childProfile,childWallet,device,cardId,cardStatus,locked,errorMessage,isUpdatingCard,cardStatusError,cardStatusSuccess,showPin,selectedStatus,pin,isSigning,isLoadingTransactions,const DeepCollectionEquality().hash(transactions));
|
||||
int get hashCode => Object.hashAll([runtimeType,isLoading,childProfile,childWallet,device,cardId,cardStatus,locked,isPinBlocked,errorMessage,isUpdatingCard,cardStatusError,cardStatusSuccess,showPin,selectedStatus,pin,isSigning,isLoadingTransactions,const DeepCollectionEquality().hash(transactionPages),nextCursor,isLoadingMore,currentPage]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChildWalletViewState(isLoading: $isLoading, childProfile: $childProfile, childWallet: $childWallet, device: $device, cardId: $cardId, cardStatus: $cardStatus, locked: $locked, errorMessage: $errorMessage, isUpdatingCard: $isUpdatingCard, cardStatusError: $cardStatusError, cardStatusSuccess: $cardStatusSuccess, showPin: $showPin, selectedStatus: $selectedStatus, pin: $pin, isSigning: $isSigning, isLoadingTransactions: $isLoadingTransactions, transactions: $transactions)';
|
||||
return 'ChildWalletViewState(isLoading: $isLoading, childProfile: $childProfile, childWallet: $childWallet, device: $device, cardId: $cardId, cardStatus: $cardStatus, locked: $locked, isPinBlocked: $isPinBlocked, errorMessage: $errorMessage, isUpdatingCard: $isUpdatingCard, cardStatusError: $cardStatusError, cardStatusSuccess: $cardStatusSuccess, showPin: $showPin, selectedStatus: $selectedStatus, pin: $pin, isSigning: $isSigning, isLoadingTransactions: $isLoadingTransactions, transactionPages: $transactionPages, nextCursor: $nextCursor, isLoadingMore: $isLoadingMore, currentPage: $currentPage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ abstract mixin class $ChildWalletViewStateCopyWith<$Res> {
|
||||
factory $ChildWalletViewStateCopyWith(ChildWalletViewState value, $Res Function(ChildWalletViewState) _then) = _$ChildWalletViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<WalletTransactionEntity> transactions
|
||||
bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, bool isPinBlocked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage
|
||||
});
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class _$ChildWalletViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of ChildWalletViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? childProfile = freezed,Object? childWallet = freezed,Object? device = freezed,Object? cardId = null,Object? cardStatus = null,Object? locked = null,Object? errorMessage = null,Object? isUpdatingCard = null,Object? cardStatusError = null,Object? cardStatusSuccess = null,Object? showPin = null,Object? selectedStatus = null,Object? pin = null,Object? isSigning = null,Object? isLoadingTransactions = null,Object? transactions = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? childProfile = freezed,Object? childWallet = freezed,Object? device = freezed,Object? cardId = null,Object? cardStatus = null,Object? locked = null,Object? isPinBlocked = null,Object? errorMessage = null,Object? isUpdatingCard = null,Object? cardStatusError = null,Object? cardStatusSuccess = null,Object? showPin = null,Object? selectedStatus = null,Object? pin = null,Object? isSigning = null,Object? isLoadingTransactions = null,Object? transactionPages = null,Object? nextCursor = freezed,Object? isLoadingMore = null,Object? currentPage = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,childProfile: freezed == childProfile ? _self.childProfile : childProfile // ignore: cast_nullable_to_non_nullable
|
||||
@@ -71,6 +71,7 @@ as ChildWalletEntity?,device: freezed == device ? _self.device : device // ignor
|
||||
as DeviceEntity?,cardId: null == cardId ? _self.cardId : cardId // ignore: cast_nullable_to_non_nullable
|
||||
as String,cardStatus: null == cardStatus ? _self.cardStatus : cardStatus // ignore: cast_nullable_to_non_nullable
|
||||
as String,locked: null == locked ? _self.locked : locked // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isPinBlocked: null == isPinBlocked ? _self.isPinBlocked : isPinBlocked // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,isUpdatingCard: null == isUpdatingCard ? _self.isUpdatingCard : isUpdatingCard // ignore: cast_nullable_to_non_nullable
|
||||
as bool,cardStatusError: null == cardStatusError ? _self.cardStatusError : cardStatusError // ignore: cast_nullable_to_non_nullable
|
||||
@@ -80,8 +81,11 @@ as bool,selectedStatus: null == selectedStatus ? _self.selectedStatus : selected
|
||||
as String,pin: null == pin ? _self.pin : pin // ignore: cast_nullable_to_non_nullable
|
||||
as String,isSigning: null == isSigning ? _self.isSigning : isSigning // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isLoadingTransactions: null == isLoadingTransactions ? _self.isLoadingTransactions : isLoadingTransactions // ignore: cast_nullable_to_non_nullable
|
||||
as bool,transactions: null == transactions ? _self.transactions : transactions // ignore: cast_nullable_to_non_nullable
|
||||
as List<WalletTransactionEntity>,
|
||||
as bool,transactionPages: null == transactionPages ? _self.transactionPages : transactionPages // ignore: cast_nullable_to_non_nullable
|
||||
as List<List<WalletTransactionEntity>>,nextCursor: freezed == nextCursor ? _self.nextCursor : nextCursor // ignore: cast_nullable_to_non_nullable
|
||||
as String?,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable
|
||||
as bool,currentPage: null == currentPage ? _self.currentPage : currentPage // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
/// Create a copy of ChildWalletViewState
|
||||
@@ -202,10 +206,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<WalletTransactionEntity> transactions)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, bool isPinBlocked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChildWalletViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.cardStatus,_that.locked,_that.errorMessage,_that.isUpdatingCard,_that.cardStatusError,_that.cardStatusSuccess,_that.showPin,_that.selectedStatus,_that.pin,_that.isSigning,_that.isLoadingTransactions,_that.transactions);case _:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.cardStatus,_that.locked,_that.isPinBlocked,_that.errorMessage,_that.isUpdatingCard,_that.cardStatusError,_that.cardStatusSuccess,_that.showPin,_that.selectedStatus,_that.pin,_that.isSigning,_that.isLoadingTransactions,_that.transactionPages,_that.nextCursor,_that.isLoadingMore,_that.currentPage);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -223,10 +227,10 @@ return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.devic
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<WalletTransactionEntity> transactions) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, bool isPinBlocked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChildWalletViewState():
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.cardStatus,_that.locked,_that.errorMessage,_that.isUpdatingCard,_that.cardStatusError,_that.cardStatusSuccess,_that.showPin,_that.selectedStatus,_that.pin,_that.isSigning,_that.isLoadingTransactions,_that.transactions);case _:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.cardStatus,_that.locked,_that.isPinBlocked,_that.errorMessage,_that.isUpdatingCard,_that.cardStatusError,_that.cardStatusSuccess,_that.showPin,_that.selectedStatus,_that.pin,_that.isSigning,_that.isLoadingTransactions,_that.transactionPages,_that.nextCursor,_that.isLoadingMore,_that.currentPage);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -243,10 +247,10 @@ return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.devic
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<WalletTransactionEntity> transactions)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, bool isPinBlocked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _ChildWalletViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.cardStatus,_that.locked,_that.errorMessage,_that.isUpdatingCard,_that.cardStatusError,_that.cardStatusSuccess,_that.showPin,_that.selectedStatus,_that.pin,_that.isSigning,_that.isLoadingTransactions,_that.transactions);case _:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardId,_that.cardStatus,_that.locked,_that.isPinBlocked,_that.errorMessage,_that.isUpdatingCard,_that.cardStatusError,_that.cardStatusSuccess,_that.showPin,_that.selectedStatus,_that.pin,_that.isSigning,_that.isLoadingTransactions,_that.transactionPages,_that.nextCursor,_that.isLoadingMore,_that.currentPage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -258,7 +262,7 @@ return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.devic
|
||||
|
||||
|
||||
class _ChildWalletViewState implements ChildWalletViewState {
|
||||
const _ChildWalletViewState({this.isLoading = true, this.childProfile, this.childWallet, this.device, this.cardId = '', this.cardStatus = '', this.locked = false, this.errorMessage = '', this.isUpdatingCard = false, this.cardStatusError = '', this.cardStatusSuccess = false, this.showPin = false, this.selectedStatus = '', this.pin = '', this.isSigning = false, this.isLoadingTransactions = false, final List<WalletTransactionEntity> transactions = const []}): _transactions = transactions;
|
||||
const _ChildWalletViewState({this.isLoading = true, this.childProfile, this.childWallet, this.device, this.cardId = '', this.cardStatus = '', this.locked = false, this.isPinBlocked = false, this.errorMessage = '', this.isUpdatingCard = false, this.cardStatusError = '', this.cardStatusSuccess = false, this.showPin = false, this.selectedStatus = '', this.pin = '', this.isSigning = false, this.isLoadingTransactions = false, final List<List<WalletTransactionEntity>> transactionPages = const [], this.nextCursor, this.isLoadingMore = false, this.currentPage = 0}): _transactionPages = transactionPages;
|
||||
|
||||
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@@ -268,6 +272,7 @@ class _ChildWalletViewState implements ChildWalletViewState {
|
||||
@override@JsonKey() final String cardId;
|
||||
@override@JsonKey() final String cardStatus;
|
||||
@override@JsonKey() final bool locked;
|
||||
@override@JsonKey() final bool isPinBlocked;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override@JsonKey() final bool isUpdatingCard;
|
||||
@override@JsonKey() final String cardStatusError;
|
||||
@@ -277,13 +282,16 @@ class _ChildWalletViewState implements ChildWalletViewState {
|
||||
@override@JsonKey() final String pin;
|
||||
@override@JsonKey() final bool isSigning;
|
||||
@override@JsonKey() final bool isLoadingTransactions;
|
||||
final List<WalletTransactionEntity> _transactions;
|
||||
@override@JsonKey() List<WalletTransactionEntity> get transactions {
|
||||
if (_transactions is EqualUnmodifiableListView) return _transactions;
|
||||
final List<List<WalletTransactionEntity>> _transactionPages;
|
||||
@override@JsonKey() List<List<WalletTransactionEntity>> get transactionPages {
|
||||
if (_transactionPages is EqualUnmodifiableListView) return _transactionPages;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_transactions);
|
||||
return EqualUnmodifiableListView(_transactionPages);
|
||||
}
|
||||
|
||||
@override final String? nextCursor;
|
||||
@override@JsonKey() final bool isLoadingMore;
|
||||
@override@JsonKey() final int currentPage;
|
||||
|
||||
/// Create a copy of ChildWalletViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -295,16 +303,16 @@ _$ChildWalletViewStateCopyWith<_ChildWalletViewState> get copyWith => __$ChildWa
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ChildWalletViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.childProfile, childProfile) || other.childProfile == childProfile)&&(identical(other.childWallet, childWallet) || other.childWallet == childWallet)&&(identical(other.device, device) || other.device == device)&&(identical(other.cardId, cardId) || other.cardId == cardId)&&(identical(other.cardStatus, cardStatus) || other.cardStatus == cardStatus)&&(identical(other.locked, locked) || other.locked == locked)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isUpdatingCard, isUpdatingCard) || other.isUpdatingCard == isUpdatingCard)&&(identical(other.cardStatusError, cardStatusError) || other.cardStatusError == cardStatusError)&&(identical(other.cardStatusSuccess, cardStatusSuccess) || other.cardStatusSuccess == cardStatusSuccess)&&(identical(other.showPin, showPin) || other.showPin == showPin)&&(identical(other.selectedStatus, selectedStatus) || other.selectedStatus == selectedStatus)&&(identical(other.pin, pin) || other.pin == pin)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.isLoadingTransactions, isLoadingTransactions) || other.isLoadingTransactions == isLoadingTransactions)&&const DeepCollectionEquality().equals(other._transactions, _transactions));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ChildWalletViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.childProfile, childProfile) || other.childProfile == childProfile)&&(identical(other.childWallet, childWallet) || other.childWallet == childWallet)&&(identical(other.device, device) || other.device == device)&&(identical(other.cardId, cardId) || other.cardId == cardId)&&(identical(other.cardStatus, cardStatus) || other.cardStatus == cardStatus)&&(identical(other.locked, locked) || other.locked == locked)&&(identical(other.isPinBlocked, isPinBlocked) || other.isPinBlocked == isPinBlocked)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.isUpdatingCard, isUpdatingCard) || other.isUpdatingCard == isUpdatingCard)&&(identical(other.cardStatusError, cardStatusError) || other.cardStatusError == cardStatusError)&&(identical(other.cardStatusSuccess, cardStatusSuccess) || other.cardStatusSuccess == cardStatusSuccess)&&(identical(other.showPin, showPin) || other.showPin == showPin)&&(identical(other.selectedStatus, selectedStatus) || other.selectedStatus == selectedStatus)&&(identical(other.pin, pin) || other.pin == pin)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.isLoadingTransactions, isLoadingTransactions) || other.isLoadingTransactions == isLoadingTransactions)&&const DeepCollectionEquality().equals(other._transactionPages, _transactionPages)&&(identical(other.nextCursor, nextCursor) || other.nextCursor == nextCursor)&&(identical(other.isLoadingMore, isLoadingMore) || other.isLoadingMore == isLoadingMore)&&(identical(other.currentPage, currentPage) || other.currentPage == currentPage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,childProfile,childWallet,device,cardId,cardStatus,locked,errorMessage,isUpdatingCard,cardStatusError,cardStatusSuccess,showPin,selectedStatus,pin,isSigning,isLoadingTransactions,const DeepCollectionEquality().hash(_transactions));
|
||||
int get hashCode => Object.hashAll([runtimeType,isLoading,childProfile,childWallet,device,cardId,cardStatus,locked,isPinBlocked,errorMessage,isUpdatingCard,cardStatusError,cardStatusSuccess,showPin,selectedStatus,pin,isSigning,isLoadingTransactions,const DeepCollectionEquality().hash(_transactionPages),nextCursor,isLoadingMore,currentPage]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ChildWalletViewState(isLoading: $isLoading, childProfile: $childProfile, childWallet: $childWallet, device: $device, cardId: $cardId, cardStatus: $cardStatus, locked: $locked, errorMessage: $errorMessage, isUpdatingCard: $isUpdatingCard, cardStatusError: $cardStatusError, cardStatusSuccess: $cardStatusSuccess, showPin: $showPin, selectedStatus: $selectedStatus, pin: $pin, isSigning: $isSigning, isLoadingTransactions: $isLoadingTransactions, transactions: $transactions)';
|
||||
return 'ChildWalletViewState(isLoading: $isLoading, childProfile: $childProfile, childWallet: $childWallet, device: $device, cardId: $cardId, cardStatus: $cardStatus, locked: $locked, isPinBlocked: $isPinBlocked, errorMessage: $errorMessage, isUpdatingCard: $isUpdatingCard, cardStatusError: $cardStatusError, cardStatusSuccess: $cardStatusSuccess, showPin: $showPin, selectedStatus: $selectedStatus, pin: $pin, isSigning: $isSigning, isLoadingTransactions: $isLoadingTransactions, transactionPages: $transactionPages, nextCursor: $nextCursor, isLoadingMore: $isLoadingMore, currentPage: $currentPage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -315,7 +323,7 @@ abstract mixin class _$ChildWalletViewStateCopyWith<$Res> implements $ChildWalle
|
||||
factory _$ChildWalletViewStateCopyWith(_ChildWalletViewState value, $Res Function(_ChildWalletViewState) _then) = __$ChildWalletViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<WalletTransactionEntity> transactions
|
||||
bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardId, String cardStatus, bool locked, bool isPinBlocked, String errorMessage, bool isUpdatingCard, String cardStatusError, bool cardStatusSuccess, bool showPin, String selectedStatus, String pin, bool isSigning, bool isLoadingTransactions, List<List<WalletTransactionEntity>> transactionPages, String? nextCursor, bool isLoadingMore, int currentPage
|
||||
});
|
||||
|
||||
|
||||
@@ -332,7 +340,7 @@ class __$ChildWalletViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of ChildWalletViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? childProfile = freezed,Object? childWallet = freezed,Object? device = freezed,Object? cardId = null,Object? cardStatus = null,Object? locked = null,Object? errorMessage = null,Object? isUpdatingCard = null,Object? cardStatusError = null,Object? cardStatusSuccess = null,Object? showPin = null,Object? selectedStatus = null,Object? pin = null,Object? isSigning = null,Object? isLoadingTransactions = null,Object? transactions = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? childProfile = freezed,Object? childWallet = freezed,Object? device = freezed,Object? cardId = null,Object? cardStatus = null,Object? locked = null,Object? isPinBlocked = null,Object? errorMessage = null,Object? isUpdatingCard = null,Object? cardStatusError = null,Object? cardStatusSuccess = null,Object? showPin = null,Object? selectedStatus = null,Object? pin = null,Object? isSigning = null,Object? isLoadingTransactions = null,Object? transactionPages = null,Object? nextCursor = freezed,Object? isLoadingMore = null,Object? currentPage = null,}) {
|
||||
return _then(_ChildWalletViewState(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,childProfile: freezed == childProfile ? _self.childProfile : childProfile // ignore: cast_nullable_to_non_nullable
|
||||
@@ -341,6 +349,7 @@ as ChildWalletEntity?,device: freezed == device ? _self.device : device // ignor
|
||||
as DeviceEntity?,cardId: null == cardId ? _self.cardId : cardId // ignore: cast_nullable_to_non_nullable
|
||||
as String,cardStatus: null == cardStatus ? _self.cardStatus : cardStatus // ignore: cast_nullable_to_non_nullable
|
||||
as String,locked: null == locked ? _self.locked : locked // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isPinBlocked: null == isPinBlocked ? _self.isPinBlocked : isPinBlocked // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,isUpdatingCard: null == isUpdatingCard ? _self.isUpdatingCard : isUpdatingCard // ignore: cast_nullable_to_non_nullable
|
||||
as bool,cardStatusError: null == cardStatusError ? _self.cardStatusError : cardStatusError // ignore: cast_nullable_to_non_nullable
|
||||
@@ -350,8 +359,11 @@ as bool,selectedStatus: null == selectedStatus ? _self.selectedStatus : selected
|
||||
as String,pin: null == pin ? _self.pin : pin // ignore: cast_nullable_to_non_nullable
|
||||
as String,isSigning: null == isSigning ? _self.isSigning : isSigning // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isLoadingTransactions: null == isLoadingTransactions ? _self.isLoadingTransactions : isLoadingTransactions // ignore: cast_nullable_to_non_nullable
|
||||
as bool,transactions: null == transactions ? _self._transactions : transactions // ignore: cast_nullable_to_non_nullable
|
||||
as List<WalletTransactionEntity>,
|
||||
as bool,transactionPages: null == transactionPages ? _self._transactionPages : transactionPages // ignore: cast_nullable_to_non_nullable
|
||||
as List<List<WalletTransactionEntity>>,nextCursor: freezed == nextCursor ? _self.nextCursor : nextCursor // ignore: cast_nullable_to_non_nullable
|
||||
as String?,isLoadingMore: null == isLoadingMore ? _self.isLoadingMore : isLoadingMore // ignore: cast_nullable_to_non_nullable
|
||||
as bool,currentPage: null == currentPage ? _self.currentPage : currentPage // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
import '../../presentation/state/home_view_model.dart';
|
||||
import '../child_wallet/child_data_provider.dart';
|
||||
import 'deposit_view_state.dart';
|
||||
|
||||
@@ -100,8 +99,7 @@ class DepositViewModel extends Notifier<DepositViewState> {
|
||||
);
|
||||
|
||||
if (!ref.mounted) return;
|
||||
ref.read(childDataProvider(childId).notifier).load();
|
||||
ref.read(homeViewModelProvider.notifier).refreshChildWallet(childId);
|
||||
ref.read(walletRefreshProvider.notifier).refresh();
|
||||
await ref.read(parentWalletBalanceProvider.notifier).refresh();
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isSubmitting: false, success: true);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
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/edit_child_profile_screen.dart';
|
||||
|
||||
class EditChildProfileBuilder {
|
||||
const EditChildProfileBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final childWalletId = state.pathParameters['childWalletId'] ?? '';
|
||||
final navigationContract = GetIt.I<NavigationContract>();
|
||||
return MaterialPage(
|
||||
key: state.pageKey,
|
||||
child: EditChildProfileScreen(
|
||||
childId: childWalletId,
|
||||
navigation: navigationContract,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
import 'package:auth/auth.dart';
|
||||
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 'edit_child_profile_view_model.dart';
|
||||
|
||||
class EditChildProfileScreen extends ConsumerWidget {
|
||||
final String childId;
|
||||
final NavigationContract navigation;
|
||||
|
||||
const EditChildProfileScreen({
|
||||
super.key,
|
||||
required this.childId,
|
||||
required this.navigation,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final viewState = ref.watch(editChildProfileViewModelProvider(childId));
|
||||
final viewModel =
|
||||
ref.read(editChildProfileViewModelProvider(childId).notifier);
|
||||
|
||||
ref.listen(editChildProfileViewModelProvider(childId), (prev, next) {
|
||||
if (next.saveSuccess && !(prev?.saveSuccess ?? false)) {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: context.translate(I18n.editChildProfileSaveSuccess),
|
||||
type: MessageType.success,
|
||||
);
|
||||
navigation.goBack();
|
||||
}
|
||||
if (next.errorMessage.isNotEmpty &&
|
||||
!next.showPin &&
|
||||
next.errorMessage != (prev?.errorMessage ?? '')) {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: next.errorMessage,
|
||||
type: MessageType.error,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (viewState.isLoading) {
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
body: const Center(child: AppLoadingIndicator()),
|
||||
);
|
||||
}
|
||||
|
||||
if (viewState.showPin) {
|
||||
return _buildPinScaffold(context, theme, viewState, viewModel);
|
||||
}
|
||||
|
||||
return _buildFormScaffold(context, theme, viewState, viewModel);
|
||||
}
|
||||
|
||||
Widget _buildPinScaffold(
|
||||
BuildContext context,
|
||||
ThemePort theme,
|
||||
EditChildProfileViewState viewState,
|
||||
EditChildProfileViewModel viewModel,
|
||||
) {
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
onPressed: viewModel.cancelPin,
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: ScaPinView(
|
||||
title: context.translate(I18n.scaPinEnter),
|
||||
pin: viewState.pin,
|
||||
isProcessing: viewState.isSigning || viewState.isSaving,
|
||||
processingText: context.translate(I18n.scaSigning),
|
||||
canSubmit: viewModel.canSubmitPin,
|
||||
submitText: context.translate(I18n.scaConnect),
|
||||
clearPinText: context.translate(I18n.scaClearPin),
|
||||
onDigitPressed: viewModel.onDigitPressed,
|
||||
onBackspacePressed: viewModel.onBackspacePressed,
|
||||
onClearPin: viewModel.onClearPin,
|
||||
onSubmit: () => viewModel.onPinSubmit(),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (viewState.errorMessage.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Text(
|
||||
viewState.errorMessage,
|
||||
style: const TextStyle(color: Colors.red),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: viewModel.cancelPin,
|
||||
child: Text(context.translate(I18n.cancel)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFormScaffold(
|
||||
BuildContext context,
|
||||
ThemePort theme,
|
||||
EditChildProfileViewState viewState,
|
||||
EditChildProfileViewModel viewModel,
|
||||
) {
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
onPressed: () => navigation.goBack(),
|
||||
),
|
||||
title: Text(
|
||||
context.translate(I18n.editChildProfileTitle),
|
||||
style: TextStyle(color: theme.getColorFor(ThemeCode.textPrimary)),
|
||||
),
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
TextFormField(
|
||||
initialValue: viewState.firstName,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.translate(I18n.firstNameLabel),
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
onChanged: viewModel.setFirstName,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
initialValue: viewState.lastName,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.translate(I18n.lastNameLabel),
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
onChanged: viewModel.setLastName,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
initialValue: viewState.address,
|
||||
decoration: InputDecoration(
|
||||
labelText: context.translate(I18n.streetLabel),
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
onChanged: viewModel.setAddress,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
PrimaryButton(
|
||||
onPressed: () => viewModel.requestPin(),
|
||||
text: context.translate(I18n.profileSettingsSave),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => navigation.goBack(),
|
||||
child: Text(context.translate(I18n.cancel)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:sca_treezor/sca_treezor.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
import '../../child_wallet/child_data_provider.dart';
|
||||
|
||||
export 'edit_child_profile_view_state.dart';
|
||||
import 'edit_child_profile_view_state.dart';
|
||||
|
||||
final editChildProfileViewModelProvider = NotifierProvider.autoDispose
|
||||
.family<EditChildProfileViewModel, EditChildProfileViewState, String>(
|
||||
EditChildProfileViewModel.new,
|
||||
);
|
||||
|
||||
class EditChildProfileViewModel extends Notifier<EditChildProfileViewState> {
|
||||
final String childId;
|
||||
EditChildProfileViewModel(this.childId);
|
||||
|
||||
late TreezorWalletConnectionService _connectionService;
|
||||
late TreezorWalletSignatureService _signatureService;
|
||||
|
||||
@override
|
||||
EditChildProfileViewState build() {
|
||||
_connectionService = GetIt.I<TreezorWalletConnectionService>();
|
||||
_signatureService = GetIt.I<TreezorWalletSignatureService>();
|
||||
|
||||
Future.microtask(() => _loadChildProfile());
|
||||
return const EditChildProfileViewState();
|
||||
}
|
||||
|
||||
Future<void> _loadChildProfile() async {
|
||||
state = state.copyWith(isLoading: true, errorMessage: '');
|
||||
|
||||
try {
|
||||
final childData = ref.read(childDataProvider(childId));
|
||||
var childProfile = childData.childProfile;
|
||||
|
||||
if (childProfile == null) {
|
||||
final profiles =
|
||||
await ref.read(userRepositoryProvider).getChildProfiles();
|
||||
childProfile = profiles.where((p) => p.id == childId).firstOrNull;
|
||||
if (childProfile == null) {
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
errorMessage: 'Child profile not found',
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (!ref.mounted) return;
|
||||
}
|
||||
|
||||
state = state.copyWith(
|
||||
isLoading: false,
|
||||
firstName: childProfile.firstName,
|
||||
lastName: childProfile.lastName,
|
||||
address: childProfile.address,
|
||||
childProfileId: childProfile.id,
|
||||
treezorUserId: childProfile.treezorUserId,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isLoading: false, errorMessage: e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
void setFirstName(String value) =>
|
||||
state = state.copyWith(firstName: value, saveSuccess: false);
|
||||
|
||||
void setLastName(String value) =>
|
||||
state = state.copyWith(lastName: value, saveSuccess: false);
|
||||
|
||||
void setAddress(String value) =>
|
||||
state = state.copyWith(address: value, saveSuccess: false);
|
||||
|
||||
void requestPin() {
|
||||
state = state.copyWith(showPin: true, pin: '', errorMessage: '');
|
||||
}
|
||||
|
||||
void cancelPin() {
|
||||
state = state.copyWith(showPin: false, pin: '');
|
||||
}
|
||||
|
||||
void onDigitPressed(String digit) {
|
||||
if (state.pin.length >= 6) return;
|
||||
state = state.copyWith(pin: state.pin + digit, errorMessage: '');
|
||||
}
|
||||
|
||||
void onBackspacePressed() {
|
||||
if (state.pin.isEmpty) return;
|
||||
state = state.copyWith(pin: state.pin.substring(0, state.pin.length - 1));
|
||||
}
|
||||
|
||||
void onClearPin() {
|
||||
state = state.copyWith(pin: '');
|
||||
}
|
||||
|
||||
bool get canSubmitPin => state.pin.length == 6;
|
||||
|
||||
Future<void> onPinSubmit() async {
|
||||
state = state.copyWith(isSigning: true, errorMessage: '');
|
||||
|
||||
try {
|
||||
await _connectionService.connectWithPin(loginPin: state.pin);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
final scaProof = await _generateScaProof();
|
||||
if (!ref.mounted) return;
|
||||
|
||||
state = state.copyWith(isSigning: false, isSaving: true, pin: '');
|
||||
|
||||
await ref.read(userRepositoryProvider).updateChildProfile(
|
||||
childProfileId: state.childProfileId,
|
||||
scaProof: scaProof,
|
||||
firstName: state.firstName,
|
||||
lastName: state.lastName,
|
||||
address: state.address,
|
||||
);
|
||||
if (!ref.mounted) return;
|
||||
|
||||
ref.read(walletRefreshProvider.notifier).refresh();
|
||||
|
||||
state = state.copyWith(
|
||||
isSaving: false,
|
||||
saveSuccess: true,
|
||||
showPin: false,
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isSigning: false,
|
||||
isSaving: false,
|
||||
pin: '',
|
||||
errorMessage: e.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> _generateScaProof() async {
|
||||
final url =
|
||||
'https://savefamily.sandbox.treezor.co/v1/users/${state.treezorUserId}';
|
||||
final scaBody = <String, dynamic>{
|
||||
'firstName': state.firstName,
|
||||
'lastName': state.lastName,
|
||||
};
|
||||
|
||||
return _signatureService.generateJwsWithPin(
|
||||
message: '',
|
||||
input: jsonEncode({'url': url, 'body': scaBody}),
|
||||
pin: state.pin,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'edit_child_profile_view_state.freezed.dart';
|
||||
|
||||
@freezed
|
||||
abstract class EditChildProfileViewState with _$EditChildProfileViewState {
|
||||
const factory EditChildProfileViewState({
|
||||
@Default(true) bool isLoading,
|
||||
@Default(false) bool isSaving,
|
||||
@Default(false) bool isSigning,
|
||||
@Default(false) bool showPin,
|
||||
@Default('') String pin,
|
||||
@Default('') String firstName,
|
||||
@Default('') String lastName,
|
||||
@Default('') String address,
|
||||
@Default('') String childProfileId,
|
||||
@Default('') String treezorUserId,
|
||||
@Default('') String errorMessage,
|
||||
@Default(false) bool saveSuccess,
|
||||
}) = _EditChildProfileViewState;
|
||||
}
|
||||
@@ -0,0 +1,304 @@
|
||||
// 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 'edit_child_profile_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$EditChildProfileViewState {
|
||||
|
||||
bool get isLoading; bool get isSaving; bool get isSigning; bool get showPin; String get pin; String get firstName; String get lastName; String get address; String get childProfileId; String get treezorUserId; String get errorMessage; bool get saveSuccess;
|
||||
/// Create a copy of EditChildProfileViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$EditChildProfileViewStateCopyWith<EditChildProfileViewState> get copyWith => _$EditChildProfileViewStateCopyWithImpl<EditChildProfileViewState>(this as EditChildProfileViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is EditChildProfileViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.showPin, showPin) || other.showPin == showPin)&&(identical(other.pin, pin) || other.pin == pin)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.address, address) || other.address == address)&&(identical(other.childProfileId, childProfileId) || other.childProfileId == childProfileId)&&(identical(other.treezorUserId, treezorUserId) || other.treezorUserId == treezorUserId)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.saveSuccess, saveSuccess) || other.saveSuccess == saveSuccess));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isSaving,isSigning,showPin,pin,firstName,lastName,address,childProfileId,treezorUserId,errorMessage,saveSuccess);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'EditChildProfileViewState(isLoading: $isLoading, isSaving: $isSaving, isSigning: $isSigning, showPin: $showPin, pin: $pin, firstName: $firstName, lastName: $lastName, address: $address, childProfileId: $childProfileId, treezorUserId: $treezorUserId, errorMessage: $errorMessage, saveSuccess: $saveSuccess)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $EditChildProfileViewStateCopyWith<$Res> {
|
||||
factory $EditChildProfileViewStateCopyWith(EditChildProfileViewState value, $Res Function(EditChildProfileViewState) _then) = _$EditChildProfileViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isLoading, bool isSaving, bool isSigning, bool showPin, String pin, String firstName, String lastName, String address, String childProfileId, String treezorUserId, String errorMessage, bool saveSuccess
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$EditChildProfileViewStateCopyWithImpl<$Res>
|
||||
implements $EditChildProfileViewStateCopyWith<$Res> {
|
||||
_$EditChildProfileViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final EditChildProfileViewState _self;
|
||||
final $Res Function(EditChildProfileViewState) _then;
|
||||
|
||||
/// Create a copy of EditChildProfileViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? isSaving = null,Object? isSigning = null,Object? showPin = null,Object? pin = null,Object? firstName = null,Object? lastName = null,Object? address = null,Object? childProfileId = null,Object? treezorUserId = null,Object? errorMessage = null,Object? saveSuccess = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
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,isSigning: null == isSigning ? _self.isSigning : isSigning // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showPin: null == showPin ? _self.showPin : showPin // ignore: cast_nullable_to_non_nullable
|
||||
as bool,pin: null == pin ? _self.pin : pin // ignore: cast_nullable_to_non_nullable
|
||||
as String,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable
|
||||
as String,childProfileId: null == childProfileId ? _self.childProfileId : childProfileId // ignore: cast_nullable_to_non_nullable
|
||||
as String,treezorUserId: null == treezorUserId ? _self.treezorUserId : treezorUserId // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,saveSuccess: null == saveSuccess ? _self.saveSuccess : saveSuccess // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [EditChildProfileViewState].
|
||||
extension EditChildProfileViewStatePatterns on EditChildProfileViewState {
|
||||
/// 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( _EditChildProfileViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _EditChildProfileViewState() 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( _EditChildProfileViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _EditChildProfileViewState():
|
||||
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( _EditChildProfileViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _EditChildProfileViewState() 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, bool isSaving, bool isSigning, bool showPin, String pin, String firstName, String lastName, String address, String childProfileId, String treezorUserId, String errorMessage, bool saveSuccess)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _EditChildProfileViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.isSaving,_that.isSigning,_that.showPin,_that.pin,_that.firstName,_that.lastName,_that.address,_that.childProfileId,_that.treezorUserId,_that.errorMessage,_that.saveSuccess);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, bool isSaving, bool isSigning, bool showPin, String pin, String firstName, String lastName, String address, String childProfileId, String treezorUserId, String errorMessage, bool saveSuccess) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _EditChildProfileViewState():
|
||||
return $default(_that.isLoading,_that.isSaving,_that.isSigning,_that.showPin,_that.pin,_that.firstName,_that.lastName,_that.address,_that.childProfileId,_that.treezorUserId,_that.errorMessage,_that.saveSuccess);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, bool isSaving, bool isSigning, bool showPin, String pin, String firstName, String lastName, String address, String childProfileId, String treezorUserId, String errorMessage, bool saveSuccess)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _EditChildProfileViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.isSaving,_that.isSigning,_that.showPin,_that.pin,_that.firstName,_that.lastName,_that.address,_that.childProfileId,_that.treezorUserId,_that.errorMessage,_that.saveSuccess);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _EditChildProfileViewState implements EditChildProfileViewState {
|
||||
const _EditChildProfileViewState({this.isLoading = true, this.isSaving = false, this.isSigning = false, this.showPin = false, this.pin = '', this.firstName = '', this.lastName = '', this.address = '', this.childProfileId = '', this.treezorUserId = '', this.errorMessage = '', this.saveSuccess = false});
|
||||
|
||||
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool isSaving;
|
||||
@override@JsonKey() final bool isSigning;
|
||||
@override@JsonKey() final bool showPin;
|
||||
@override@JsonKey() final String pin;
|
||||
@override@JsonKey() final String firstName;
|
||||
@override@JsonKey() final String lastName;
|
||||
@override@JsonKey() final String address;
|
||||
@override@JsonKey() final String childProfileId;
|
||||
@override@JsonKey() final String treezorUserId;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
@override@JsonKey() final bool saveSuccess;
|
||||
|
||||
/// Create a copy of EditChildProfileViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$EditChildProfileViewStateCopyWith<_EditChildProfileViewState> get copyWith => __$EditChildProfileViewStateCopyWithImpl<_EditChildProfileViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _EditChildProfileViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isSaving, isSaving) || other.isSaving == isSaving)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.showPin, showPin) || other.showPin == showPin)&&(identical(other.pin, pin) || other.pin == pin)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.address, address) || other.address == address)&&(identical(other.childProfileId, childProfileId) || other.childProfileId == childProfileId)&&(identical(other.treezorUserId, treezorUserId) || other.treezorUserId == treezorUserId)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage)&&(identical(other.saveSuccess, saveSuccess) || other.saveSuccess == saveSuccess));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isSaving,isSigning,showPin,pin,firstName,lastName,address,childProfileId,treezorUserId,errorMessage,saveSuccess);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'EditChildProfileViewState(isLoading: $isLoading, isSaving: $isSaving, isSigning: $isSigning, showPin: $showPin, pin: $pin, firstName: $firstName, lastName: $lastName, address: $address, childProfileId: $childProfileId, treezorUserId: $treezorUserId, errorMessage: $errorMessage, saveSuccess: $saveSuccess)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$EditChildProfileViewStateCopyWith<$Res> implements $EditChildProfileViewStateCopyWith<$Res> {
|
||||
factory _$EditChildProfileViewStateCopyWith(_EditChildProfileViewState value, $Res Function(_EditChildProfileViewState) _then) = __$EditChildProfileViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isLoading, bool isSaving, bool isSigning, bool showPin, String pin, String firstName, String lastName, String address, String childProfileId, String treezorUserId, String errorMessage, bool saveSuccess
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$EditChildProfileViewStateCopyWithImpl<$Res>
|
||||
implements _$EditChildProfileViewStateCopyWith<$Res> {
|
||||
__$EditChildProfileViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _EditChildProfileViewState _self;
|
||||
final $Res Function(_EditChildProfileViewState) _then;
|
||||
|
||||
/// Create a copy of EditChildProfileViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? isSaving = null,Object? isSigning = null,Object? showPin = null,Object? pin = null,Object? firstName = null,Object? lastName = null,Object? address = null,Object? childProfileId = null,Object? treezorUserId = null,Object? errorMessage = null,Object? saveSuccess = null,}) {
|
||||
return _then(_EditChildProfileViewState(
|
||||
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,isSigning: null == isSigning ? _self.isSigning : isSigning // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showPin: null == showPin ? _self.showPin : showPin // ignore: cast_nullable_to_non_nullable
|
||||
as bool,pin: null == pin ? _self.pin : pin // ignore: cast_nullable_to_non_nullable
|
||||
as String,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||
as String,lastName: null == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||
as String,address: null == address ? _self.address : address // ignore: cast_nullable_to_non_nullable
|
||||
as String,childProfileId: null == childProfileId ? _self.childProfileId : childProfileId // ignore: cast_nullable_to_non_nullable
|
||||
as String,treezorUserId: null == treezorUserId ? _self.treezorUserId : treezorUserId // ignore: cast_nullable_to_non_nullable
|
||||
as String,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,saveSuccess: null == saveSuccess ? _self.saveSuccess : saveSuccess // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
import '../../presentation/state/home_view_model.dart';
|
||||
import '../child_wallet/child_data_provider.dart';
|
||||
import 'extract_view_state.dart';
|
||||
|
||||
@@ -92,8 +91,7 @@ class ExtractViewModel extends Notifier<ExtractViewState> {
|
||||
);
|
||||
|
||||
if (!ref.mounted) return;
|
||||
ref.read(childDataProvider(childId).notifier).load();
|
||||
ref.read(homeViewModelProvider.notifier).refreshChildWallet(childId);
|
||||
ref.read(walletRefreshProvider.notifier).refresh();
|
||||
ref.read(parentWalletBalanceProvider.notifier).applyOptimisticPayin(amount);
|
||||
state = state.copyWith(isSubmitting: false, success: true);
|
||||
} catch (e) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
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 'renew_card_screen.dart';
|
||||
|
||||
class RenewCardBuilder {
|
||||
const RenewCardBuilder();
|
||||
|
||||
Page<void> buildPage(BuildContext context, GoRouterState state) {
|
||||
final childWalletId = state.pathParameters['childWalletId'] ?? '';
|
||||
final navigationContract = GetIt.I<NavigationContract>();
|
||||
return MaterialPage(
|
||||
key: state.pageKey,
|
||||
child: RenewCardScreen(
|
||||
childId: childWalletId,
|
||||
navigation: navigationContract,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
162
modules/home/lib/src/features/renew_card/renew_card_screen.dart
Normal file
162
modules/home/lib/src/features/renew_card/renew_card_screen.dart
Normal file
@@ -0,0 +1,162 @@
|
||||
import 'package:auth/auth.dart';
|
||||
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 'renew_card_view_model.dart';
|
||||
import 'renew_card_view_state.dart';
|
||||
|
||||
class RenewCardScreen extends ConsumerWidget {
|
||||
final String childId;
|
||||
final NavigationContract navigation;
|
||||
|
||||
const RenewCardScreen({
|
||||
super.key,
|
||||
required this.childId,
|
||||
required this.navigation,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final viewState = ref.watch(renewCardViewModelProvider(childId));
|
||||
final viewModel = ref.read(renewCardViewModelProvider(childId).notifier);
|
||||
|
||||
ref.listen(renewCardViewModelProvider(childId), (prev, next) {
|
||||
if (next.success && !(prev?.success ?? false)) {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: context.translate(I18n.renewCardSuccess),
|
||||
type: MessageType.success,
|
||||
);
|
||||
navigation.goBack();
|
||||
return;
|
||||
}
|
||||
if (next.errorMessage.isNotEmpty &&
|
||||
next.errorMessage != (prev?.errorMessage ?? '')) {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: context.translate(I18n.renewCardError),
|
||||
type: MessageType.error,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (viewState.isLoading) {
|
||||
return const Scaffold(body: Center(child: AppLoadingIndicator()));
|
||||
}
|
||||
|
||||
if (viewState.errorMessage.isNotEmpty && viewState.childProfile == null) {
|
||||
return Scaffold(
|
||||
body: Center(child: Text('Error: ${viewState.errorMessage}')),
|
||||
);
|
||||
}
|
||||
|
||||
if (viewState.step == RenewCardStep.scaPin) {
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
onPressed: viewModel.goBackToToken,
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: ScaPinView(
|
||||
title: context.translate(I18n.renewCardPinTitle),
|
||||
pin: viewState.pin,
|
||||
isProcessing:
|
||||
viewState.isSigning || viewState.isSubmitting,
|
||||
processingText: context.translate(I18n.scaSigning),
|
||||
canSubmit: viewModel.canSubmitPin,
|
||||
submitText: context.translate(I18n.scaConnect),
|
||||
clearPinText: context.translate(I18n.scaClearPin),
|
||||
onDigitPressed: viewModel.onDigitPressed,
|
||||
onBackspacePressed: viewModel.onBackspacePressed,
|
||||
onClearPin: viewModel.onClearPin,
|
||||
onSubmit: () => viewModel.onPinSubmit(),
|
||||
),
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => navigation.goBack(),
|
||||
child: Text(context.translate(I18n.cancel)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
appBar: AppBar(
|
||||
backgroundColor: theme.getColorFor(ThemeCode.backgroundSecondary),
|
||||
leading: IconButton(
|
||||
icon: Icon(
|
||||
Icons.arrow_back,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
onPressed: () => navigation.goBack(),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
context.translate(I18n.renewCardTitle),
|
||||
style: const TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text(
|
||||
context.translate(I18n.renewCardTokenHint),
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
CustomTextField(
|
||||
controller: viewModel.cardTokenController,
|
||||
hint: 'XXXXXXXXXX',
|
||||
),
|
||||
const Spacer(),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
child: PrimaryButton(
|
||||
onPressed: viewState.cardToken.isEmpty
|
||||
? null
|
||||
: viewModel.onCardTokenSubmit,
|
||||
text: context.translate(I18n.cardPinNext),
|
||||
color: theme.getColorFor(ThemeCode.buttonPrimary),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Center(
|
||||
child: TextButton(
|
||||
onPressed: () => navigation.goBack(),
|
||||
child: Text(context.translate(I18n.cancel)),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:sca_treezor/sca_treezor.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
import '../child_wallet/child_data_provider.dart';
|
||||
import 'renew_card_view_state.dart';
|
||||
|
||||
final renewCardViewModelProvider = NotifierProvider.autoDispose
|
||||
.family<RenewCardViewModel, RenewCardViewState, String>(
|
||||
RenewCardViewModel.new,
|
||||
);
|
||||
|
||||
class RenewCardViewModel extends Notifier<RenewCardViewState> {
|
||||
final String childId;
|
||||
RenewCardViewModel(this.childId);
|
||||
|
||||
late final TextEditingController cardTokenController;
|
||||
late final TreezorWalletConnectionService _connectionService;
|
||||
late final TreezorWalletSignatureService _signatureService;
|
||||
|
||||
@override
|
||||
RenewCardViewState build() {
|
||||
_connectionService = GetIt.I<TreezorWalletConnectionService>();
|
||||
_signatureService = GetIt.I<TreezorWalletSignatureService>();
|
||||
|
||||
cardTokenController = TextEditingController();
|
||||
cardTokenController.addListener(_onTokenChanged);
|
||||
ref.onDispose(_disposeControllers);
|
||||
|
||||
ref.listen(childDataProvider(childId), (prev, next) {
|
||||
state = state.copyWith(
|
||||
isLoading: next.isLoading,
|
||||
childProfile: next.childProfile,
|
||||
childWallet: next.childWallet,
|
||||
device: next.device,
|
||||
errorMessage: next.errorMessage,
|
||||
);
|
||||
});
|
||||
|
||||
final data = ref.read(childDataProvider(childId));
|
||||
return RenewCardViewState(
|
||||
isLoading: data.isLoading,
|
||||
childProfile: data.childProfile,
|
||||
childWallet: data.childWallet,
|
||||
device: data.device,
|
||||
errorMessage: data.errorMessage,
|
||||
);
|
||||
}
|
||||
|
||||
void _disposeControllers() {
|
||||
cardTokenController.removeListener(_onTokenChanged);
|
||||
cardTokenController.dispose();
|
||||
}
|
||||
|
||||
void _onTokenChanged() {
|
||||
state = state.copyWith(cardToken: cardTokenController.text.trim());
|
||||
}
|
||||
|
||||
void onCardTokenSubmit() {
|
||||
if (state.cardToken.isEmpty) return;
|
||||
state = state.copyWith(step: RenewCardStep.scaPin, pin: '', errorMessage: '');
|
||||
}
|
||||
|
||||
void goBackToToken() {
|
||||
state = state.copyWith(step: RenewCardStep.cardToken, pin: '');
|
||||
}
|
||||
|
||||
void onDigitPressed(String digit) {
|
||||
if (state.pin.length >= 6) return;
|
||||
state = state.copyWith(pin: state.pin + digit, errorMessage: '');
|
||||
}
|
||||
|
||||
void onBackspacePressed() {
|
||||
if (state.pin.isEmpty) return;
|
||||
state = state.copyWith(pin: state.pin.substring(0, state.pin.length - 1));
|
||||
}
|
||||
|
||||
void onClearPin() {
|
||||
state = state.copyWith(pin: '');
|
||||
}
|
||||
|
||||
bool get canSubmitPin => state.pin.length == 6;
|
||||
|
||||
Future<void> onPinSubmit() async {
|
||||
final childProfile = state.childProfile;
|
||||
final cardToken = state.cardToken;
|
||||
if (childProfile == null || cardToken.isEmpty) return;
|
||||
|
||||
state = state.copyWith(isSigning: true, errorMessage: '');
|
||||
|
||||
try {
|
||||
debugPrint('[RenewCard] connecting with SCA PIN...');
|
||||
await _connectionService.connectWithPin(loginPin: state.pin);
|
||||
if (!ref.mounted) return;
|
||||
debugPrint('[RenewCard] SCA connection successful');
|
||||
|
||||
final url =
|
||||
'https://savefamily.sandbox.treezor.co/v1/cards/$cardToken/public-token-activation';
|
||||
final scaInput = jsonEncode({
|
||||
'url': url,
|
||||
'body': <String, dynamic>{},
|
||||
});
|
||||
debugPrint('[RenewCard] scaInput: $scaInput');
|
||||
|
||||
final scaProof = await _signatureService.generateJwsWithPin(
|
||||
message: '',
|
||||
input: scaInput,
|
||||
pin: state.pin,
|
||||
);
|
||||
debugPrint('[RenewCard] scaProof: $scaProof');
|
||||
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(isSigning: false, isSubmitting: true, pin: '');
|
||||
|
||||
debugPrint('[RenewCard] calling backend renewCard childProfileId=${childProfile.id} publicToken=$cardToken');
|
||||
await ref.read(treezorRepositoryProvider).renewCard(
|
||||
childProfileId: childProfile.id,
|
||||
publicToken: cardToken,
|
||||
scaProof: scaProof,
|
||||
);
|
||||
debugPrint('[RenewCard] renewCard SUCCESS');
|
||||
|
||||
if (!ref.mounted) return;
|
||||
ref.read(walletRefreshProvider.notifier).refresh();
|
||||
state = state.copyWith(isSubmitting: false, success: true);
|
||||
} catch (e) {
|
||||
debugPrint('[RenewCard] ERROR: $e');
|
||||
if (!ref.mounted) return;
|
||||
state = state.copyWith(
|
||||
isSigning: false,
|
||||
isSubmitting: false,
|
||||
pin: '',
|
||||
errorMessage: e.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:sf_shared/sf_shared.dart';
|
||||
|
||||
part 'renew_card_view_state.freezed.dart';
|
||||
|
||||
enum RenewCardStep { cardToken, scaPin }
|
||||
|
||||
@freezed
|
||||
abstract class RenewCardViewState with _$RenewCardViewState {
|
||||
const factory RenewCardViewState({
|
||||
@Default(true) bool isLoading,
|
||||
ChildProfileEntity? childProfile,
|
||||
ChildWalletEntity? childWallet,
|
||||
DeviceEntity? device,
|
||||
@Default('') String cardToken,
|
||||
@Default('') String pin,
|
||||
@Default(RenewCardStep.cardToken) RenewCardStep step,
|
||||
@Default(false) bool isSigning,
|
||||
@Default(false) bool isSubmitting,
|
||||
@Default(false) bool success,
|
||||
@Default('') String errorMessage,
|
||||
}) = _RenewCardViewState;
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
// 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 'renew_card_view_state.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$RenewCardViewState {
|
||||
|
||||
bool get isLoading; ChildProfileEntity? get childProfile; ChildWalletEntity? get childWallet; DeviceEntity? get device; String get cardToken; String get pin; RenewCardStep get step; bool get isSigning; bool get isSubmitting; bool get success; String get errorMessage;
|
||||
/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$RenewCardViewStateCopyWith<RenewCardViewState> get copyWith => _$RenewCardViewStateCopyWithImpl<RenewCardViewState>(this as RenewCardViewState, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is RenewCardViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.childProfile, childProfile) || other.childProfile == childProfile)&&(identical(other.childWallet, childWallet) || other.childWallet == childWallet)&&(identical(other.device, device) || other.device == device)&&(identical(other.cardToken, cardToken) || other.cardToken == cardToken)&&(identical(other.pin, pin) || other.pin == pin)&&(identical(other.step, step) || other.step == step)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.isSubmitting, isSubmitting) || other.isSubmitting == isSubmitting)&&(identical(other.success, success) || other.success == success)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,childProfile,childWallet,device,cardToken,pin,step,isSigning,isSubmitting,success,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RenewCardViewState(isLoading: $isLoading, childProfile: $childProfile, childWallet: $childWallet, device: $device, cardToken: $cardToken, pin: $pin, step: $step, isSigning: $isSigning, isSubmitting: $isSubmitting, success: $success, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $RenewCardViewStateCopyWith<$Res> {
|
||||
factory $RenewCardViewStateCopyWith(RenewCardViewState value, $Res Function(RenewCardViewState) _then) = _$RenewCardViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardToken, String pin, RenewCardStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
$ChildProfileEntityCopyWith<$Res>? get childProfile;$ChildWalletEntityCopyWith<$Res>? get childWallet;$DeviceEntityCopyWith<$Res>? get device;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$RenewCardViewStateCopyWithImpl<$Res>
|
||||
implements $RenewCardViewStateCopyWith<$Res> {
|
||||
_$RenewCardViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final RenewCardViewState _self;
|
||||
final $Res Function(RenewCardViewState) _then;
|
||||
|
||||
/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? childProfile = freezed,Object? childWallet = freezed,Object? device = freezed,Object? cardToken = null,Object? pin = null,Object? step = null,Object? isSigning = null,Object? isSubmitting = null,Object? success = null,Object? errorMessage = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,childProfile: freezed == childProfile ? _self.childProfile : childProfile // ignore: cast_nullable_to_non_nullable
|
||||
as ChildProfileEntity?,childWallet: freezed == childWallet ? _self.childWallet : childWallet // ignore: cast_nullable_to_non_nullable
|
||||
as ChildWalletEntity?,device: freezed == device ? _self.device : device // ignore: cast_nullable_to_non_nullable
|
||||
as DeviceEntity?,cardToken: null == cardToken ? _self.cardToken : cardToken // ignore: cast_nullable_to_non_nullable
|
||||
as String,pin: null == pin ? _self.pin : pin // ignore: cast_nullable_to_non_nullable
|
||||
as String,step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable
|
||||
as RenewCardStep,isSigning: null == isSigning ? _self.isSigning : isSigning // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||
as bool,success: null == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChildProfileEntityCopyWith<$Res>? get childProfile {
|
||||
if (_self.childProfile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChildProfileEntityCopyWith<$Res>(_self.childProfile!, (value) {
|
||||
return _then(_self.copyWith(childProfile: value));
|
||||
});
|
||||
}/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChildWalletEntityCopyWith<$Res>? get childWallet {
|
||||
if (_self.childWallet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChildWalletEntityCopyWith<$Res>(_self.childWallet!, (value) {
|
||||
return _then(_self.copyWith(childWallet: value));
|
||||
});
|
||||
}/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$DeviceEntityCopyWith<$Res>? get device {
|
||||
if (_self.device == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $DeviceEntityCopyWith<$Res>(_self.device!, (value) {
|
||||
return _then(_self.copyWith(device: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [RenewCardViewState].
|
||||
extension RenewCardViewStatePatterns on RenewCardViewState {
|
||||
/// 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( _RenewCardViewState value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RenewCardViewState() 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( _RenewCardViewState value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RenewCardViewState():
|
||||
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( _RenewCardViewState value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _RenewCardViewState() 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, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardToken, String pin, RenewCardStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RenewCardViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardToken,_that.pin,_that.step,_that.isSigning,_that.isSubmitting,_that.success,_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, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardToken, String pin, RenewCardStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RenewCardViewState():
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardToken,_that.pin,_that.step,_that.isSigning,_that.isSubmitting,_that.success,_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, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardToken, String pin, RenewCardStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _RenewCardViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.childProfile,_that.childWallet,_that.device,_that.cardToken,_that.pin,_that.step,_that.isSigning,_that.isSubmitting,_that.success,_that.errorMessage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
|
||||
class _RenewCardViewState implements RenewCardViewState {
|
||||
const _RenewCardViewState({this.isLoading = true, this.childProfile, this.childWallet, this.device, this.cardToken = '', this.pin = '', this.step = RenewCardStep.cardToken, this.isSigning = false, this.isSubmitting = false, this.success = false, this.errorMessage = ''});
|
||||
|
||||
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override final ChildProfileEntity? childProfile;
|
||||
@override final ChildWalletEntity? childWallet;
|
||||
@override final DeviceEntity? device;
|
||||
@override@JsonKey() final String cardToken;
|
||||
@override@JsonKey() final String pin;
|
||||
@override@JsonKey() final RenewCardStep step;
|
||||
@override@JsonKey() final bool isSigning;
|
||||
@override@JsonKey() final bool isSubmitting;
|
||||
@override@JsonKey() final bool success;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
|
||||
/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$RenewCardViewStateCopyWith<_RenewCardViewState> get copyWith => __$RenewCardViewStateCopyWithImpl<_RenewCardViewState>(this, _$identity);
|
||||
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _RenewCardViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.childProfile, childProfile) || other.childProfile == childProfile)&&(identical(other.childWallet, childWallet) || other.childWallet == childWallet)&&(identical(other.device, device) || other.device == device)&&(identical(other.cardToken, cardToken) || other.cardToken == cardToken)&&(identical(other.pin, pin) || other.pin == pin)&&(identical(other.step, step) || other.step == step)&&(identical(other.isSigning, isSigning) || other.isSigning == isSigning)&&(identical(other.isSubmitting, isSubmitting) || other.isSubmitting == isSubmitting)&&(identical(other.success, success) || other.success == success)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,childProfile,childWallet,device,cardToken,pin,step,isSigning,isSubmitting,success,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'RenewCardViewState(isLoading: $isLoading, childProfile: $childProfile, childWallet: $childWallet, device: $device, cardToken: $cardToken, pin: $pin, step: $step, isSigning: $isSigning, isSubmitting: $isSubmitting, success: $success, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$RenewCardViewStateCopyWith<$Res> implements $RenewCardViewStateCopyWith<$Res> {
|
||||
factory _$RenewCardViewStateCopyWith(_RenewCardViewState value, $Res Function(_RenewCardViewState) _then) = __$RenewCardViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isLoading, ChildProfileEntity? childProfile, ChildWalletEntity? childWallet, DeviceEntity? device, String cardToken, String pin, RenewCardStep step, bool isSigning, bool isSubmitting, bool success, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
@override $ChildProfileEntityCopyWith<$Res>? get childProfile;@override $ChildWalletEntityCopyWith<$Res>? get childWallet;@override $DeviceEntityCopyWith<$Res>? get device;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$RenewCardViewStateCopyWithImpl<$Res>
|
||||
implements _$RenewCardViewStateCopyWith<$Res> {
|
||||
__$RenewCardViewStateCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _RenewCardViewState _self;
|
||||
final $Res Function(_RenewCardViewState) _then;
|
||||
|
||||
/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? childProfile = freezed,Object? childWallet = freezed,Object? device = freezed,Object? cardToken = null,Object? pin = null,Object? step = null,Object? isSigning = null,Object? isSubmitting = null,Object? success = null,Object? errorMessage = null,}) {
|
||||
return _then(_RenewCardViewState(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,childProfile: freezed == childProfile ? _self.childProfile : childProfile // ignore: cast_nullable_to_non_nullable
|
||||
as ChildProfileEntity?,childWallet: freezed == childWallet ? _self.childWallet : childWallet // ignore: cast_nullable_to_non_nullable
|
||||
as ChildWalletEntity?,device: freezed == device ? _self.device : device // ignore: cast_nullable_to_non_nullable
|
||||
as DeviceEntity?,cardToken: null == cardToken ? _self.cardToken : cardToken // ignore: cast_nullable_to_non_nullable
|
||||
as String,pin: null == pin ? _self.pin : pin // ignore: cast_nullable_to_non_nullable
|
||||
as String,step: null == step ? _self.step : step // ignore: cast_nullable_to_non_nullable
|
||||
as RenewCardStep,isSigning: null == isSigning ? _self.isSigning : isSigning // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isSubmitting: null == isSubmitting ? _self.isSubmitting : isSubmitting // ignore: cast_nullable_to_non_nullable
|
||||
as bool,success: null == success ? _self.success : success // ignore: cast_nullable_to_non_nullable
|
||||
as bool,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChildProfileEntityCopyWith<$Res>? get childProfile {
|
||||
if (_self.childProfile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChildProfileEntityCopyWith<$Res>(_self.childProfile!, (value) {
|
||||
return _then(_self.copyWith(childProfile: value));
|
||||
});
|
||||
}/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$ChildWalletEntityCopyWith<$Res>? get childWallet {
|
||||
if (_self.childWallet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $ChildWalletEntityCopyWith<$Res>(_self.childWallet!, (value) {
|
||||
return _then(_self.copyWith(childWallet: value));
|
||||
});
|
||||
}/// Create a copy of RenewCardViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$DeviceEntityCopyWith<$Res>? get device {
|
||||
if (_self.device == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $DeviceEntityCopyWith<$Res>(_self.device!, (value) {
|
||||
return _then(_self.copyWith(device: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -37,32 +37,20 @@ class HomeScreen extends ConsumerWidget {
|
||||
margin: EdgeInsets.all(30),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text.rich(
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text.rich(
|
||||
TextSpan(
|
||||
text: context.translate(I18n.homeGreeting),
|
||||
style: TextStyle(fontSize: 25),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: context.translate(I18n.homeGreeting),
|
||||
style: TextStyle(fontSize: 25),
|
||||
children: <TextSpan>[
|
||||
TextSpan(
|
||||
text: viewState.userName,
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
text: viewState.userName,
|
||||
style: TextStyle(fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () =>
|
||||
navigationContract.pushTo(AppRoutes.deviceSetup),
|
||||
icon: Icon(
|
||||
Icons.person_add_outlined,
|
||||
color: theme.getColorFor(ThemeCode.textPrimary),
|
||||
),
|
||||
tooltip: context.translate(I18n.homeAddAnotherKid),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const ChildWalletsSlider(),
|
||||
Align(
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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,15 @@ 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)
|
||||
),
|
||||
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 +51,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),
|
||||
|
||||
@@ -77,7 +77,7 @@ class PersonalDataScreen extends ConsumerWidget {
|
||||
child: Column(
|
||||
children: [
|
||||
Text(context.translate(I18n.personalDataMessage)),
|
||||
const SizedBox(height: 14),
|
||||
const SizedBox(height: 4),
|
||||
const _SaveButton(),
|
||||
],
|
||||
),
|
||||
@@ -169,12 +169,33 @@ class _PhoneField extends ConsumerWidget {
|
||||
final hint = ref.watch(
|
||||
personalDataViewModelProvider.select((s) => s.user?.phone ?? ''),
|
||||
);
|
||||
final dialCode = ref.read(
|
||||
personalDataViewModelProvider.select((s)=>s.dialCode)
|
||||
);
|
||||
|
||||
return CustomTextField(
|
||||
controller: vm.phoneController,
|
||||
hint: hint,
|
||||
label: context.translate(I18n.phoneLabel),
|
||||
keyboardType: TextInputType.phone,
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
CountryPrefixPicker(
|
||||
headerText: context.translate(I18n.selectYourCountry),
|
||||
initialSelection: dialCode,
|
||||
onChanged: (country) {
|
||||
vm.updateDialCode(
|
||||
country.dialCode ?? dialCode,
|
||||
);
|
||||
},
|
||||
width: 80,
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: CustomTextField(
|
||||
controller: vm.phoneController,
|
||||
hint: hint,
|
||||
label: context.translate(I18n.phoneLabel),
|
||||
keyboardType: TextInputType.phone,
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,12 +39,26 @@ class PersonalDataViewModel extends Notifier<PersonalDataViewState> {
|
||||
state = state.copyWith(user: user, isLoading: false);
|
||||
}
|
||||
|
||||
void updateDialCode(String value) {
|
||||
if (value == state.dialCode) return;
|
||||
|
||||
state = state.copyWith(
|
||||
dialCode: value,
|
||||
errorMessage: '',
|
||||
);
|
||||
}
|
||||
|
||||
bool get _hasChanges =>
|
||||
firstNameController.text.trim().isNotEmpty ||
|
||||
lastNameController.text.trim().isNotEmpty ||
|
||||
phoneController.text.trim().isNotEmpty;
|
||||
|
||||
UpdateUserRequestEntity _toRequest() {
|
||||
final dialCode = state.dialCode;
|
||||
final fullPhone = phoneController.text.trim().isNotEmpty
|
||||
? dialCode+phoneController.text.trim()
|
||||
: null;
|
||||
|
||||
return UpdateUserRequestEntity(
|
||||
firstName: firstNameController.text.trim().isNotEmpty
|
||||
? firstNameController.text.trim()
|
||||
@@ -52,9 +66,7 @@ class PersonalDataViewModel extends Notifier<PersonalDataViewState> {
|
||||
lastName: lastNameController.text.trim().isNotEmpty
|
||||
? lastNameController.text.trim()
|
||||
: null,
|
||||
phone: phoneController.text.trim().isNotEmpty
|
||||
? phoneController.text.trim()
|
||||
: null,
|
||||
phone: fullPhone,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ abstract class PersonalDataViewState with _$PersonalDataViewState {
|
||||
const factory PersonalDataViewState({
|
||||
@Default(true) bool isLoading,
|
||||
@Default(false) bool isComplete,
|
||||
@Default('+34') String dialCode,
|
||||
UserEntity? user,
|
||||
@Default('') String errorMessage,
|
||||
}) = _PersonalDataViewState;
|
||||
|
||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$PersonalDataViewState {
|
||||
|
||||
bool get isLoading; bool get isComplete; UserEntity? get user; String get errorMessage;
|
||||
bool get isLoading; bool get isComplete; String get dialCode; UserEntity? get user; String get errorMessage;
|
||||
/// Create a copy of PersonalDataViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -25,16 +25,16 @@ $PersonalDataViewStateCopyWith<PersonalDataViewState> get copyWith => _$Personal
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is PersonalDataViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.user, user) || other.user == user)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is PersonalDataViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.user, user) || other.user == user)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isComplete,user,errorMessage);
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isComplete,dialCode,user,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PersonalDataViewState(isLoading: $isLoading, isComplete: $isComplete, user: $user, errorMessage: $errorMessage)';
|
||||
return 'PersonalDataViewState(isLoading: $isLoading, isComplete: $isComplete, dialCode: $dialCode, user: $user, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ abstract mixin class $PersonalDataViewStateCopyWith<$Res> {
|
||||
factory $PersonalDataViewStateCopyWith(PersonalDataViewState value, $Res Function(PersonalDataViewState) _then) = _$PersonalDataViewStateCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool isLoading, bool isComplete, UserEntity? user, String errorMessage
|
||||
bool isLoading, bool isComplete, String dialCode, UserEntity? user, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
@@ -62,11 +62,12 @@ class _$PersonalDataViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of PersonalDataViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? isComplete = null,Object? user = freezed,Object? errorMessage = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? isLoading = null,Object? isComplete = null,Object? dialCode = null,Object? user = freezed,Object? errorMessage = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable
|
||||
as bool,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||
as bool,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||
as UserEntity?,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
@@ -165,10 +166,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, bool isComplete, UserEntity? user, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool isLoading, bool isComplete, String dialCode, UserEntity? user, String errorMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _PersonalDataViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);case _:
|
||||
return $default(_that.isLoading,_that.isComplete,_that.dialCode,_that.user,_that.errorMessage);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -186,10 +187,10 @@ return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, bool isComplete, UserEntity? user, String errorMessage) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool isLoading, bool isComplete, String dialCode, UserEntity? user, String errorMessage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _PersonalDataViewState():
|
||||
return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);case _:
|
||||
return $default(_that.isLoading,_that.isComplete,_that.dialCode,_that.user,_that.errorMessage);case _:
|
||||
throw StateError('Unexpected subclass');
|
||||
|
||||
}
|
||||
@@ -206,10 +207,10 @@ return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, bool isComplete, UserEntity? user, String errorMessage)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool isLoading, bool isComplete, String dialCode, UserEntity? user, String errorMessage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _PersonalDataViewState() when $default != null:
|
||||
return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);case _:
|
||||
return $default(_that.isLoading,_that.isComplete,_that.dialCode,_that.user,_that.errorMessage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -221,11 +222,12 @@ return $default(_that.isLoading,_that.isComplete,_that.user,_that.errorMessage);
|
||||
|
||||
|
||||
class _PersonalDataViewState implements PersonalDataViewState {
|
||||
const _PersonalDataViewState({this.isLoading = true, this.isComplete = false, this.user, this.errorMessage = ''});
|
||||
const _PersonalDataViewState({this.isLoading = true, this.isComplete = false, this.dialCode = '+34', this.user, this.errorMessage = ''});
|
||||
|
||||
|
||||
@override@JsonKey() final bool isLoading;
|
||||
@override@JsonKey() final bool isComplete;
|
||||
@override@JsonKey() final String dialCode;
|
||||
@override final UserEntity? user;
|
||||
@override@JsonKey() final String errorMessage;
|
||||
|
||||
@@ -239,16 +241,16 @@ _$PersonalDataViewStateCopyWith<_PersonalDataViewState> get copyWith => __$Perso
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PersonalDataViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.user, user) || other.user == user)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PersonalDataViewState&&(identical(other.isLoading, isLoading) || other.isLoading == isLoading)&&(identical(other.isComplete, isComplete) || other.isComplete == isComplete)&&(identical(other.dialCode, dialCode) || other.dialCode == dialCode)&&(identical(other.user, user) || other.user == user)&&(identical(other.errorMessage, errorMessage) || other.errorMessage == errorMessage));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isComplete,user,errorMessage);
|
||||
int get hashCode => Object.hash(runtimeType,isLoading,isComplete,dialCode,user,errorMessage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'PersonalDataViewState(isLoading: $isLoading, isComplete: $isComplete, user: $user, errorMessage: $errorMessage)';
|
||||
return 'PersonalDataViewState(isLoading: $isLoading, isComplete: $isComplete, dialCode: $dialCode, user: $user, errorMessage: $errorMessage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -259,7 +261,7 @@ abstract mixin class _$PersonalDataViewStateCopyWith<$Res> implements $PersonalD
|
||||
factory _$PersonalDataViewStateCopyWith(_PersonalDataViewState value, $Res Function(_PersonalDataViewState) _then) = __$PersonalDataViewStateCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool isLoading, bool isComplete, UserEntity? user, String errorMessage
|
||||
bool isLoading, bool isComplete, String dialCode, UserEntity? user, String errorMessage
|
||||
});
|
||||
|
||||
|
||||
@@ -276,11 +278,12 @@ class __$PersonalDataViewStateCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of PersonalDataViewState
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? isComplete = null,Object? user = freezed,Object? errorMessage = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? isLoading = null,Object? isComplete = null,Object? dialCode = null,Object? user = freezed,Object? errorMessage = null,}) {
|
||||
return _then(_PersonalDataViewState(
|
||||
isLoading: null == isLoading ? _self.isLoading : isLoading // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isComplete: null == isComplete ? _self.isComplete : isComplete // ignore: cast_nullable_to_non_nullable
|
||||
as bool,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||
as bool,dialCode: null == dialCode ? _self.dialCode : dialCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,user: freezed == user ? _self.user : user // ignore: cast_nullable_to_non_nullable
|
||||
as UserEntity?,errorMessage: null == errorMessage ? _self.errorMessage : errorMessage // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
|
||||
@@ -96,7 +96,7 @@ packages:
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
build_runner:
|
||||
dependency: transitive
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: build_runner
|
||||
sha256: b24597fceb695969d47025c958f3837f9f0122e237c6a22cb082a5ac66c3ca30
|
||||
@@ -338,10 +338,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: fl_chart
|
||||
sha256: "7ca9a40f4eb85949190e54087be8b4d6ac09dc4c54238d782a34cf1f7c011de9"
|
||||
sha256: b938f77d042cbcd822936a7a359a7235bad8bd72070de1f827efc2cc297ac888
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.1"
|
||||
version: "1.2.0"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -367,18 +367,18 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_riverpod
|
||||
sha256: e2026c72738a925a60db30258ff1f29974e40716749f3c9850aabf34ffc1a14c
|
||||
sha256: "4e166be88e1dbbaa34a280bdb744aeae73b7ef25fdf8db7a3bb776760a3648e2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
version: "3.3.1"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_svg
|
||||
sha256: "87fbd7c534435b6c5d9d98b01e1fd527812b82e68ddd8bd35fc45ed0fa8f0a95"
|
||||
sha256: "1ded017b39c8e15c8948ea855070a5ff8ff8b3d5e83f3446e02d6bb12add7ad9"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.3"
|
||||
version: "2.2.4"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@@ -620,10 +620,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: logger
|
||||
sha256: a7967e31b703831a893bbc3c3dd11db08126fe5f369b5c648a36f821979f5be3
|
||||
sha256: "25aee487596a6257655a1e091ec2ae66bc30e7af663592cc3a27e6591e05035c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.2"
|
||||
version: "2.7.0"
|
||||
logging:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1257,10 +1257,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: a4f059dc26fc8295b5921376600a194c4ec7d55e72f2fe4c7d2831e103d461e6
|
||||
sha256: "7076216a10d5c390315fbe536a30f1254c341e7543e6c4c8a815e591307772b1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.19"
|
||||
version: "1.1.20"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1361,10 +1361,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: webview_flutter_wkwebview
|
||||
sha256: fc0af89d403e1c053f03d023d97550412fa79f35332e2939514c82e6fe633198
|
||||
sha256: "2df8fd9ada04d699b9db8e79aa783a16e5d89b69e5b74009b87e16b59912cf98"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.23.8"
|
||||
version: "3.24.0"
|
||||
wkt_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -56,6 +56,7 @@ dependencies:
|
||||
uuid: ^4.5.2
|
||||
qr_flutter: ^4.1.0
|
||||
url_launcher: ^6.3.2
|
||||
build_runner: ^2.7.1
|
||||
|
||||
# The following adds the Cupertino Icons font to your application.
|
||||
# Use with the CupertinoIcons class for iOS style icons.
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -13,28 +13,21 @@ import 'package:utils/utils.dart';
|
||||
class ControlPanelScreen extends ConsumerWidget {
|
||||
final NavigationContract navigationContract;
|
||||
|
||||
const ControlPanelScreen({
|
||||
super.key,
|
||||
required this.navigationContract,
|
||||
});
|
||||
const ControlPanelScreen({super.key, required this.navigationContract});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = ref.watch(themePortProvider);
|
||||
final state = ref.watch(controlPanelViewModelProvider);
|
||||
|
||||
ref.listen(
|
||||
controlPanelViewModelProvider.select((s) => s.errorMessage),
|
||||
(previous, next) {
|
||||
if (next.isNotEmpty) {
|
||||
showTopSnackbar(
|
||||
context,
|
||||
message: next,
|
||||
type: MessageType.error,
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
ref.listen(controlPanelViewModelProvider.select((s) => s.errorMessage), (
|
||||
previous,
|
||||
next,
|
||||
) {
|
||||
if (next.isNotEmpty) {
|
||||
showTopSnackbar(context, message: next, type: MessageType.error);
|
||||
}
|
||||
});
|
||||
|
||||
if (state.isLoading) {
|
||||
return Scaffold(
|
||||
@@ -90,7 +83,9 @@ class _Header extends ConsumerWidget {
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: SizeUtils.getByScreen(small: 14, big: 14)),
|
||||
padding: EdgeInsets.only(
|
||||
top: SizeUtils.getByScreen(small: 14, big: 14),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Image.asset(
|
||||
@@ -102,17 +97,13 @@ class _Header extends ConsumerWidget {
|
||||
width: SizeUtils.getByScreen(small: 130, big: 140),
|
||||
height: 32,
|
||||
child: CustomDropdown(
|
||||
items: state.devices
|
||||
.map(
|
||||
(DeviceEntity device) {
|
||||
final name = device.carrierName ?? '';
|
||||
return Text(
|
||||
name.length > 10 ? '${name.substring(0, 10)}...' : name,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
},
|
||||
)
|
||||
.toList(),
|
||||
items: state.devices.map((DeviceEntity device) {
|
||||
final name = device.carrierName ?? '';
|
||||
return Text(
|
||||
name.length > 10 ? '${name.substring(0, 10)}...' : name,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
}).toList(),
|
||||
values: state.devices,
|
||||
value: state.selectedDevice,
|
||||
onChanged: (device) {
|
||||
@@ -153,13 +144,13 @@ class _MenuSection extends ConsumerWidget {
|
||||
text: I18n.customerService,
|
||||
),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)),
|
||||
_SectionButton(
|
||||
onPressed: () {
|
||||
navigationContract.pushTo(AppRoutes.dashboardHome);
|
||||
},
|
||||
icon: SFIcons.payments,
|
||||
text: I18n.sfPay,
|
||||
),
|
||||
// _SectionButton(
|
||||
// onPressed: () {
|
||||
// navigationContract.pushTo(AppRoutes.dashboardHome);
|
||||
// },
|
||||
// icon: SFIcons.payments,
|
||||
// text: I18n.sfPay,
|
||||
// ),
|
||||
SizedBox(height: SizeUtils.getByScreen(small: 8, big: 7)),
|
||||
_SectionButton(
|
||||
onPressed: () {
|
||||
@@ -267,7 +258,6 @@ class _MapSection extends ConsumerWidget {
|
||||
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();
|
||||
|
||||
|
||||
@@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,4 +9,6 @@ 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';
|
||||
@@ -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',
|
||||
);
|
||||
|
||||
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,50 @@
|
||||
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,
|
||||
required String deviceIdentificator,
|
||||
String? imgType,
|
||||
String? timestamp,
|
||||
required String fileId,
|
||||
String? fileName,
|
||||
String? contentType,
|
||||
required int createdAt,
|
||||
}) = _GetPicturesItemResponseModel;
|
||||
|
||||
factory GetPicturesItemResponseModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$GetPicturesItemResponseModelFromJson(json);
|
||||
}
|
||||
|
||||
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,
|
||||
))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,567 @@
|
||||
// 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;
|
||||
/// 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));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,imgType,timestamp,fileId,fileName,contentType,createdAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GetPicturesItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, imgType: $imgType, timestamp: $timestamp, fileId: $fileId, fileName: $fileName, contentType: $contentType, createdAt: $createdAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @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
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @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,}) {
|
||||
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,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// 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)? $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);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) $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);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)? $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);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _GetPicturesItemResponseModel implements GetPicturesItemResponseModel {
|
||||
const _GetPicturesItemResponseModel({required this.id, required this.deviceIdentificator, this.imgType, this.timestamp, required this.fileId, this.fileName, this.contentType, required this.createdAt});
|
||||
factory _GetPicturesItemResponseModel.fromJson(Map<String, dynamic> json) => _$GetPicturesItemResponseModelFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String deviceIdentificator;
|
||||
@override final String? imgType;
|
||||
@override final String? timestamp;
|
||||
@override final String fileId;
|
||||
@override final String? fileName;
|
||||
@override final String? contentType;
|
||||
@override final int createdAt;
|
||||
|
||||
/// 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));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,deviceIdentificator,imgType,timestamp,fileId,fileName,contentType,createdAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GetPicturesItemResponseModel(id: $id, deviceIdentificator: $deviceIdentificator, imgType: $imgType, timestamp: $timestamp, fileId: $fileId, fileName: $fileName, contentType: $contentType, createdAt: $createdAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @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
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @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,}) {
|
||||
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,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
@@ -0,0 +1,47 @@
|
||||
// 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(),
|
||||
);
|
||||
|
||||
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,
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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});
|
||||
}
|
||||
@@ -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);
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user