From 0bc65b6e84b43bae7f2c42bb10eb8541be3b3319 Mon Sep 17 00:00:00 2001 From: Komek Hayytnazarov Date: Mon, 27 Feb 2023 12:23:37 +0500 Subject: [PATCH] first commit --- .gitignore | 46 + .metadata | 10 + .vscode/settings.json | 8 + README.md | 17 + analysis_options.yaml | 276 ++++++ android/.gitignore | 12 + android/app/build.gradle | 71 ++ android/app/src/debug/AndroidManifest.xml | 7 + android/app/src/main/AndroidManifest.xml | 57 ++ .../digital/birzha/MainActivity.kt | 6 + .../app/src/main/res/drawable-hdpi/splash.png | Bin 0 -> 35126 bytes .../app/src/main/res/drawable-mdpi/splash.png | Bin 0 -> 15208 bytes .../src/main/res/drawable-v21/background.png | Bin 0 -> 70 bytes .../res/drawable-v21/launch_background.xml | 9 + .../src/main/res/drawable-xhdpi/splash.png | Bin 0 -> 25844 bytes .../src/main/res/drawable-xxhdpi/splash.png | Bin 0 -> 96362 bytes .../src/main/res/drawable-xxxhdpi/splash.png | Bin 0 -> 65978 bytes .../app/src/main/res/drawable/background.png | Bin 0 -> 70 bytes .../main/res/drawable/launch_background.xml | 9 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 544 bytes .../main/res/mipmap-hdpi/launcher_icon.png | Bin 0 -> 2237 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 442 bytes .../main/res/mipmap-mdpi/launcher_icon.png | Bin 0 -> 1374 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 721 bytes .../main/res/mipmap-xhdpi/launcher_icon.png | Bin 0 -> 2978 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 1031 bytes .../main/res/mipmap-xxhdpi/launcher_icon.png | Bin 0 -> 5686 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 1443 bytes .../main/res/mipmap-xxxhdpi/launcher_icon.png | Bin 0 -> 6454 bytes .../app/src/main/res/values-night/styles.xml | 19 + android/app/src/main/res/values/styles.xml | 19 + android/app/src/profile/AndroidManifest.xml | 7 + android/app/upload-keystore.jks | Bin 0 -> 2257 bytes android/build.gradle | 29 + android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 6 + android/settings.gradle | 11 + android/settings_aar.gradle | 1 + assets/fonts/AppBarIcons.ttf | Bin 0 -> 2268 bytes assets/fonts/Settings_Icons.ttf | Bin 0 -> 3408 bytes assets/fonts/TabNavIcons.ttf | Bin 0 -> 2708 bytes assets/fonts/svgs.ttf | Bin 0 -> 2704 bytes assets/icon.jpg | Bin 0 -> 28016 bytes assets/icons/home_screen/build.svg | 18 + assets/icons/home_screen/chemical.svg | 31 + assets/icons/home_screen/machine.svg | 42 + assets/icons/home_screen/shirt.svg | 12 + assets/icons/profile_screen/cart.svg | 16 + assets/icons/profile_screen/exit.svg | 16 + assets/icons/profile_screen/message.svg | 26 + .../profile_screen/phone_not_verified.svg | 3 + .../icons/profile_screen/phone_verified.svg | 3 + assets/icons/profile_screen/popup_history.svg | 16 + assets/icons/profile_screen/profile.svg | 7 + .../icons/settings_screen/confidentials.svg | 17 + assets/icons/settings_screen/contact.svg | 11 + assets/icons/settings_screen/feedback.svg | 5 + assets/icons/settings_screen/lang.svg | 9 + assets/images/appBarIcon.svg | 11 + assets/images/map.jpg | Bin 0 -> 41006 bytes assets/images/product1.jpg | Bin 0 -> 7733 bytes assets/images/unauth.svg | 1 + ios/.gitignore | 34 + ios/Flutter/AppFrameworkInfo.plist | 26 + ios/Flutter/Debug.xcconfig | 2 + ios/Flutter/Release.xcconfig | 2 + ios/Podfile | 41 + ios/Podfile.lock | 117 +++ ios/Runner.xcodeproj/project.pbxproj | 556 +++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 87 ++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 122 +++ .../Icon-App-1024x1024@1x.png | Bin 0 -> 114755 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 600 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1159 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1685 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 916 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1822 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 3002 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1159 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 2525 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 4451 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 4451 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 8508 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 2435 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 6423 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 7497 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + ios/Runner/Base.lproj/LaunchScreen.storyboard | 37 + ios/Runner/Base.lproj/Main.storyboard | 26 + ios/Runner/Info.plist | 49 + ios/Runner/Runner-Bridging-Header.h | 1 + ios/Runner/Runner.entitlements | 8 + l10n.yaml | 3 + lib/components/TextInputCustom.dart | 127 +++ lib/components/abstractForm.dart | 216 +++++ lib/components/actionIcons/searchicon.dart | 22 + lib/components/appBarIcons.dart | 26 + lib/components/askQuantity.dart | 73 ++ lib/components/baseWidget.dart | 202 ++++ lib/components/button.dart | 90 ++ lib/components/categoryBuilder.dart | 104 +++ lib/components/categoryNameWidget.dart | 36 + lib/components/contactInfo.dart | 59 ++ lib/components/customCardWidget.dart | 78 ++ lib/components/dialog.dart | 73 ++ lib/components/fakeSearchBar.dart | 90 ++ lib/components/icon.dart | 36 + lib/components/imagePlaceHolder.dart | 19 + lib/components/indicator.dart | 19 + lib/components/localizationOverride.dart | 44 + lib/components/postBuilderFactory.dart | 33 + lib/components/postlist.dart | 79 ++ lib/components/productBuilder.dart | 166 ++++ lib/components/radio.dart | 95 ++ lib/components/refreshButton.dart | 20 + lib/components/searchBar.dart | 161 ++++ lib/components/settingsIcons.dart | 29 + lib/components/slider.dart | 96 ++ lib/components/tab_nav_icons.dart | 28 + lib/components/tabview.dart | 218 +++++ lib/components/unauthenticatedWidget.dart | 51 + lib/components/verifyPhoneDialog.dart | 143 +++ lib/constants.dart | 86 ++ lib/core/adaptix/adaptix.dart | 48 + lib/core/adaptix/models/resizer.dart | 41 + lib/core/adaptix/models/sizing.dart | 37 + lib/core/adaptix/widgets/initializer.dart | 23 + lib/core/lazyload/lazyload.dart | 7 + lib/core/lazyload/streamControl.dart | 41 + lib/core/lazyload/widget.dart | 308 +++++++ lib/core/manager/manager.dart | 19 + lib/core/manager/models/manager_model.dart | 127 +++ .../models/manager_observer_mixin.dart | 37 + lib/core/manager/models/manager_state.dart | 10 + .../manager/models/paginated_manager.dart | 51 + lib/core/manager/models/task.dart | 88 ++ lib/core/manager/widgets/manager_builder.dart | 23 + .../manager/widgets/manager_selector.dart | 39 + .../widgets/paginated_collection_builder.dart | 204 ++++ lib/core/orm/models/dao.dart | 10 + lib/core/orm/models/database/database.dart | 96 ++ lib/core/orm/models/database/mobile.dart | 11 + lib/core/orm/models/database/stub.dart | 10 + lib/core/orm/models/database/web.dart | 11 + lib/core/orm/orm.dart | 34 + lib/countryCodes.dart | 244 +++++ lib/l10n/app_en.arb | 191 ++++ lib/l10n/app_ru.arb | 191 ++++ lib/l10n/app_tk.arb | 191 ++++ lib/main.dart | 73 ++ lib/models/attributes/attribute.dart | 72 ++ lib/models/attributes/category.dart | 52 ++ lib/models/attributes/market_type.dart | 66 ++ lib/models/attributes/miscelaneous.dart | 94 ++ lib/models/attributes/packaging.dart | 66 ++ lib/models/categories/category.dart | 35 + lib/models/categories/home.dart | 44 + lib/models/categories/interfaces.dart | 57 ++ .../categories/products/my_products.dart | 59 ++ lib/models/categories/products/pure.dart | 20 + lib/models/categories/products/remote.dart | 101 ++ lib/models/categories/products/search.dart | 38 + lib/models/categories/pureCategory.dart | 21 + lib/models/categories/relatedProducts.dart | 65 ++ lib/models/categories/remoteCategory.dart | 13 + lib/models/chatroom/chatroom.dart | 303 ++++++ lib/models/chatroom/message.dart | 79 ++ lib/models/exceptions/exception.dart | 55 ++ lib/models/products/composable.dart | 25 + lib/models/products/composableProduct.dart | 126 +++ lib/models/products/my_product.dart | 70 ++ lib/models/products/post.dart | 31 + lib/models/products/product.dart | 137 +++ lib/models/queries/query.dart | 46 + lib/models/queries/subCategoryQuery.dart | 11 + lib/models/settings/settingsModel.dart | 246 +++++ lib/models/settings/theme.dart | 143 +++ lib/models/tk_intl.dart | 577 ++++++++++++ lib/models/transactions/serializer.dart | 55 ++ lib/models/transactions/transaction.dart | 23 + lib/models/translationModel.dart | 16 + lib/models/user/simpleUser.dart | 10 + lib/models/user/user.dart | 408 ++++++++ lib/models/user/userManager.dart | 629 +++++++++++++ lib/new/api/a.rest | 10 + lib/new/api/bank.dart | 60 ++ lib/new/api/news.dart | 36 + lib/new/api/sort.dart | 124 +++ lib/new/global/form_field_decoration.dart | 87 ++ lib/new/global/full_width_button.dart | 48 + lib/new/models/bank.dart | 16 + lib/new/models/bank_info.dart | 23 + lib/new/models/category_filter.dart | 16 + lib/new/models/export.dart | 55 ++ lib/new/models/filter.dart | 0 lib/new/models/import.dart | 43 + lib/new/models/news.dart | 51 + lib/new/models/sort_group.dart | 28 + lib/new/screens/news/binding.dart | 9 + lib/new/screens/news/controller.dart | 50 + lib/new/screens/news/details_screen.dart | 108 +++ lib/new/screens/news/screen.dart | 181 ++++ lib/new/screens/quotes/controller.dart | 29 + .../screens/quotes/exports/controller.dart | 222 +++++ lib/new/screens/quotes/exports/screen.dart | 104 +++ lib/new/screens/quotes/exports/state.dart | 46 + .../exports/widgets/expandable_card.dart | 177 ++++ .../quotes/exports/widgets/filter_dialog.dart | 235 +++++ .../quotes/exports/widgets/filter_widget.dart | 90 ++ .../screens/quotes/imports/controller.dart | 176 ++++ lib/new/screens/quotes/imports/screen.dart | 101 ++ lib/new/screens/quotes/imports/state.dart | 34 + .../imports/widgets/expandable_card.dart | 177 ++++ .../quotes/imports/widgets/filter_dialog.dart | 173 ++++ .../quotes/imports/widgets/filter_widget.dart | 89 ++ lib/new/screens/quotes/screen.dart | 48 + lib/new/screens/quotes/state.dart | 29 + lib/new/screens/quotes/widgets/custom_dd.dart | 96 ++ .../top_up_balance/bank_top_up_screen.dart | 338 +++++++ .../screens/top_up_balance/controller.dart | 93 ++ .../top_up_balance/online_top_up_screen.dart | 239 +++++ lib/new/screens/top_up_balance/state.dart | 31 + lib/new/themes/colors.dart | 15 + lib/new/utils/capitalize.dart | 5 + lib/new/utils/constants.dart | 3 + lib/new/utils/http_util.dart | 328 +++++++ lib/new/utils/locale.dart | 9 + lib/screens/auth/login.dart | 158 ++++ lib/screens/auth/logout.dart | 85 ++ lib/screens/auth/register.dart | 109 +++ lib/screens/auth/smsVerification.dart | 99 ++ lib/screens/auth/update.dart | 142 +++ lib/screens/details.dart | 409 ++++++++ lib/screens/first_page.dart | 18 + lib/screens/home/homeScreen.dart | 124 +++ lib/screens/masterCategoryScreen.dart | 85 ++ .../personalCabinet/addPost/step1.dart | 205 +++++ .../personalCabinet/addPost/step2.dart | 358 +++++++ .../personalCabinet/messages/messages.dart | 97 ++ .../messages/personalChat.dart | 244 +++++ lib/screens/personalCabinet/my_products.dart | 32 + .../personalCabinet/personalCabinet.dart | 245 +++++ .../personalCabinet/topUp/topUpHistory.dart | 162 ++++ lib/screens/photo.dart | 95 ++ lib/screens/primal.dart | 53 ++ lib/screens/productsScreen.dart | 71 ++ lib/screens/settings/contact.dart | 137 +++ lib/screens/settings/feedback.dart | 59 ++ lib/screens/settings/settingsScreen.dart | 109 +++ lib/services/helpers.dart | 45 + lib/services/imageUpload.dart | 67 ++ lib/services/modals.dart | 353 +++++++ lib/services/requests.dart | 38 + lib/services/streamFetchService.dart | 38 + lib/services/textMetaData.dart | 41 + lib/services/translationServices.dart | 24 + lib/services/validator.dart | 20 + pubspec.lock | 871 ++++++++++++++++++ pubspec.yaml | 120 +++ test/widget_test.dart | 14 + web/favicon.png | Bin 0 -> 917 bytes web/icons/Icon-192.png | Bin 0 -> 5292 bytes web/icons/Icon-512.png | Bin 0 -> 8252 bytes web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes web/index.html | 109 +++ web/manifest.json | 23 + web/splash/img/dark-1x.png | Bin 0 -> 23588 bytes web/splash/img/dark-2x.png | Bin 0 -> 72511 bytes web/splash/img/dark-3x.png | Bin 0 -> 65978 bytes web/splash/img/light-1x.png | Bin 0 -> 23588 bytes web/splash/img/light-2x.png | Bin 0 -> 72511 bytes web/splash/img/light-3x.png | Bin 0 -> 65978 bytes web/splash/style.css | 43 + windows/.gitignore | 17 + windows/CMakeLists.txt | 95 ++ windows/flutter/CMakeLists.txt | 103 +++ .../flutter/generated_plugin_registrant.cc | 14 + windows/flutter/generated_plugin_registrant.h | 15 + windows/flutter/generated_plugins.cmake | 24 + windows/runner/CMakeLists.txt | 17 + windows/runner/Runner.rc | 121 +++ windows/runner/flutter_window.cpp | 61 ++ windows/runner/flutter_window.h | 33 + windows/runner/main.cpp | 43 + windows/runner/resource.h | 16 + windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes windows/runner/runner.exe.manifest | 20 + windows/runner/utils.cpp | 64 ++ windows/runner/utils.h | 19 + windows/runner/win32_window.cpp | 245 +++++ windows/runner/win32_window.h | 98 ++ 303 files changed, 20284 insertions(+) create mode 100644 .gitignore create mode 100644 .metadata create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100644 analysis_options.yaml create mode 100644 android/.gitignore create mode 100644 android/app/build.gradle create mode 100644 android/app/src/debug/AndroidManifest.xml create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/kotlin/com/tpsadvertising/digital/birzha/MainActivity.kt create mode 100644 android/app/src/main/res/drawable-hdpi/splash.png create mode 100644 android/app/src/main/res/drawable-mdpi/splash.png create mode 100644 android/app/src/main/res/drawable-v21/background.png create mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 android/app/src/main/res/drawable-xhdpi/splash.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/splash.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/splash.png create mode 100644 android/app/src/main/res/drawable/background.png create mode 100644 android/app/src/main/res/drawable/launch_background.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-hdpi/launcher_icon.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/launcher_icon.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/launcher_icon.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png create mode 100644 android/app/src/main/res/values-night/styles.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/profile/AndroidManifest.xml create mode 100644 android/app/upload-keystore.jks create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100644 android/settings.gradle create mode 100644 android/settings_aar.gradle create mode 100644 assets/fonts/AppBarIcons.ttf create mode 100644 assets/fonts/Settings_Icons.ttf create mode 100644 assets/fonts/TabNavIcons.ttf create mode 100644 assets/fonts/svgs.ttf create mode 100644 assets/icon.jpg create mode 100644 assets/icons/home_screen/build.svg create mode 100644 assets/icons/home_screen/chemical.svg create mode 100644 assets/icons/home_screen/machine.svg create mode 100644 assets/icons/home_screen/shirt.svg create mode 100644 assets/icons/profile_screen/cart.svg create mode 100644 assets/icons/profile_screen/exit.svg create mode 100644 assets/icons/profile_screen/message.svg create mode 100644 assets/icons/profile_screen/phone_not_verified.svg create mode 100644 assets/icons/profile_screen/phone_verified.svg create mode 100644 assets/icons/profile_screen/popup_history.svg create mode 100644 assets/icons/profile_screen/profile.svg create mode 100644 assets/icons/settings_screen/confidentials.svg create mode 100644 assets/icons/settings_screen/contact.svg create mode 100644 assets/icons/settings_screen/feedback.svg create mode 100644 assets/icons/settings_screen/lang.svg create mode 100644 assets/images/appBarIcon.svg create mode 100644 assets/images/map.jpg create mode 100644 assets/images/product1.jpg create mode 100644 assets/images/unauth.svg create mode 100644 ios/.gitignore create mode 100644 ios/Flutter/AppFrameworkInfo.plist create mode 100644 ios/Flutter/Debug.xcconfig create mode 100644 ios/Flutter/Release.xcconfig create mode 100644 ios/Podfile create mode 100644 ios/Podfile.lock create mode 100644 ios/Runner.xcodeproj/project.pbxproj create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner/AppDelegate.swift create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 ios/Runner/Base.lproj/Main.storyboard create mode 100644 ios/Runner/Info.plist create mode 100644 ios/Runner/Runner-Bridging-Header.h create mode 100644 ios/Runner/Runner.entitlements create mode 100644 l10n.yaml create mode 100644 lib/components/TextInputCustom.dart create mode 100644 lib/components/abstractForm.dart create mode 100644 lib/components/actionIcons/searchicon.dart create mode 100644 lib/components/appBarIcons.dart create mode 100644 lib/components/askQuantity.dart create mode 100644 lib/components/baseWidget.dart create mode 100644 lib/components/button.dart create mode 100644 lib/components/categoryBuilder.dart create mode 100644 lib/components/categoryNameWidget.dart create mode 100644 lib/components/contactInfo.dart create mode 100644 lib/components/customCardWidget.dart create mode 100644 lib/components/dialog.dart create mode 100644 lib/components/fakeSearchBar.dart create mode 100644 lib/components/icon.dart create mode 100644 lib/components/imagePlaceHolder.dart create mode 100644 lib/components/indicator.dart create mode 100644 lib/components/localizationOverride.dart create mode 100644 lib/components/postBuilderFactory.dart create mode 100644 lib/components/postlist.dart create mode 100644 lib/components/productBuilder.dart create mode 100644 lib/components/radio.dart create mode 100644 lib/components/refreshButton.dart create mode 100644 lib/components/searchBar.dart create mode 100644 lib/components/settingsIcons.dart create mode 100644 lib/components/slider.dart create mode 100644 lib/components/tab_nav_icons.dart create mode 100644 lib/components/tabview.dart create mode 100644 lib/components/unauthenticatedWidget.dart create mode 100644 lib/components/verifyPhoneDialog.dart create mode 100644 lib/constants.dart create mode 100644 lib/core/adaptix/adaptix.dart create mode 100644 lib/core/adaptix/models/resizer.dart create mode 100644 lib/core/adaptix/models/sizing.dart create mode 100644 lib/core/adaptix/widgets/initializer.dart create mode 100644 lib/core/lazyload/lazyload.dart create mode 100644 lib/core/lazyload/streamControl.dart create mode 100644 lib/core/lazyload/widget.dart create mode 100644 lib/core/manager/manager.dart create mode 100644 lib/core/manager/models/manager_model.dart create mode 100644 lib/core/manager/models/manager_observer_mixin.dart create mode 100644 lib/core/manager/models/manager_state.dart create mode 100644 lib/core/manager/models/paginated_manager.dart create mode 100644 lib/core/manager/models/task.dart create mode 100644 lib/core/manager/widgets/manager_builder.dart create mode 100644 lib/core/manager/widgets/manager_selector.dart create mode 100644 lib/core/manager/widgets/paginated_collection_builder.dart create mode 100644 lib/core/orm/models/dao.dart create mode 100644 lib/core/orm/models/database/database.dart create mode 100644 lib/core/orm/models/database/mobile.dart create mode 100644 lib/core/orm/models/database/stub.dart create mode 100644 lib/core/orm/models/database/web.dart create mode 100644 lib/core/orm/orm.dart create mode 100644 lib/countryCodes.dart create mode 100644 lib/l10n/app_en.arb create mode 100644 lib/l10n/app_ru.arb create mode 100644 lib/l10n/app_tk.arb create mode 100644 lib/main.dart create mode 100644 lib/models/attributes/attribute.dart create mode 100644 lib/models/attributes/category.dart create mode 100644 lib/models/attributes/market_type.dart create mode 100644 lib/models/attributes/miscelaneous.dart create mode 100644 lib/models/attributes/packaging.dart create mode 100644 lib/models/categories/category.dart create mode 100644 lib/models/categories/home.dart create mode 100644 lib/models/categories/interfaces.dart create mode 100644 lib/models/categories/products/my_products.dart create mode 100644 lib/models/categories/products/pure.dart create mode 100644 lib/models/categories/products/remote.dart create mode 100644 lib/models/categories/products/search.dart create mode 100644 lib/models/categories/pureCategory.dart create mode 100644 lib/models/categories/relatedProducts.dart create mode 100644 lib/models/categories/remoteCategory.dart create mode 100644 lib/models/chatroom/chatroom.dart create mode 100644 lib/models/chatroom/message.dart create mode 100644 lib/models/exceptions/exception.dart create mode 100644 lib/models/products/composable.dart create mode 100644 lib/models/products/composableProduct.dart create mode 100644 lib/models/products/my_product.dart create mode 100644 lib/models/products/post.dart create mode 100644 lib/models/products/product.dart create mode 100644 lib/models/queries/query.dart create mode 100644 lib/models/queries/subCategoryQuery.dart create mode 100644 lib/models/settings/settingsModel.dart create mode 100644 lib/models/settings/theme.dart create mode 100644 lib/models/tk_intl.dart create mode 100644 lib/models/transactions/serializer.dart create mode 100644 lib/models/transactions/transaction.dart create mode 100644 lib/models/translationModel.dart create mode 100644 lib/models/user/simpleUser.dart create mode 100644 lib/models/user/user.dart create mode 100644 lib/models/user/userManager.dart create mode 100644 lib/new/api/a.rest create mode 100644 lib/new/api/bank.dart create mode 100644 lib/new/api/news.dart create mode 100644 lib/new/api/sort.dart create mode 100644 lib/new/global/form_field_decoration.dart create mode 100644 lib/new/global/full_width_button.dart create mode 100644 lib/new/models/bank.dart create mode 100644 lib/new/models/bank_info.dart create mode 100644 lib/new/models/category_filter.dart create mode 100644 lib/new/models/export.dart create mode 100644 lib/new/models/filter.dart create mode 100644 lib/new/models/import.dart create mode 100644 lib/new/models/news.dart create mode 100644 lib/new/models/sort_group.dart create mode 100644 lib/new/screens/news/binding.dart create mode 100644 lib/new/screens/news/controller.dart create mode 100644 lib/new/screens/news/details_screen.dart create mode 100644 lib/new/screens/news/screen.dart create mode 100644 lib/new/screens/quotes/controller.dart create mode 100644 lib/new/screens/quotes/exports/controller.dart create mode 100644 lib/new/screens/quotes/exports/screen.dart create mode 100644 lib/new/screens/quotes/exports/state.dart create mode 100644 lib/new/screens/quotes/exports/widgets/expandable_card.dart create mode 100644 lib/new/screens/quotes/exports/widgets/filter_dialog.dart create mode 100644 lib/new/screens/quotes/exports/widgets/filter_widget.dart create mode 100644 lib/new/screens/quotes/imports/controller.dart create mode 100644 lib/new/screens/quotes/imports/screen.dart create mode 100644 lib/new/screens/quotes/imports/state.dart create mode 100644 lib/new/screens/quotes/imports/widgets/expandable_card.dart create mode 100644 lib/new/screens/quotes/imports/widgets/filter_dialog.dart create mode 100644 lib/new/screens/quotes/imports/widgets/filter_widget.dart create mode 100644 lib/new/screens/quotes/screen.dart create mode 100644 lib/new/screens/quotes/state.dart create mode 100644 lib/new/screens/quotes/widgets/custom_dd.dart create mode 100644 lib/new/screens/top_up_balance/bank_top_up_screen.dart create mode 100644 lib/new/screens/top_up_balance/controller.dart create mode 100644 lib/new/screens/top_up_balance/online_top_up_screen.dart create mode 100644 lib/new/screens/top_up_balance/state.dart create mode 100644 lib/new/themes/colors.dart create mode 100644 lib/new/utils/capitalize.dart create mode 100644 lib/new/utils/constants.dart create mode 100644 lib/new/utils/http_util.dart create mode 100644 lib/new/utils/locale.dart create mode 100644 lib/screens/auth/login.dart create mode 100644 lib/screens/auth/logout.dart create mode 100644 lib/screens/auth/register.dart create mode 100644 lib/screens/auth/smsVerification.dart create mode 100644 lib/screens/auth/update.dart create mode 100644 lib/screens/details.dart create mode 100644 lib/screens/first_page.dart create mode 100644 lib/screens/home/homeScreen.dart create mode 100644 lib/screens/masterCategoryScreen.dart create mode 100644 lib/screens/personalCabinet/addPost/step1.dart create mode 100644 lib/screens/personalCabinet/addPost/step2.dart create mode 100644 lib/screens/personalCabinet/messages/messages.dart create mode 100644 lib/screens/personalCabinet/messages/personalChat.dart create mode 100644 lib/screens/personalCabinet/my_products.dart create mode 100644 lib/screens/personalCabinet/personalCabinet.dart create mode 100644 lib/screens/personalCabinet/topUp/topUpHistory.dart create mode 100644 lib/screens/photo.dart create mode 100644 lib/screens/primal.dart create mode 100644 lib/screens/productsScreen.dart create mode 100644 lib/screens/settings/contact.dart create mode 100644 lib/screens/settings/feedback.dart create mode 100644 lib/screens/settings/settingsScreen.dart create mode 100644 lib/services/helpers.dart create mode 100644 lib/services/imageUpload.dart create mode 100644 lib/services/modals.dart create mode 100644 lib/services/requests.dart create mode 100644 lib/services/streamFetchService.dart create mode 100644 lib/services/textMetaData.dart create mode 100644 lib/services/translationServices.dart create mode 100644 lib/services/validator.dart create mode 100644 pubspec.lock create mode 100644 pubspec.yaml create mode 100644 test/widget_test.dart create mode 100644 web/favicon.png create mode 100644 web/icons/Icon-192.png create mode 100644 web/icons/Icon-512.png create mode 100644 web/icons/Icon-maskable-192.png create mode 100644 web/icons/Icon-maskable-512.png create mode 100644 web/index.html create mode 100644 web/manifest.json create mode 100644 web/splash/img/dark-1x.png create mode 100644 web/splash/img/dark-2x.png create mode 100644 web/splash/img/dark-3x.png create mode 100644 web/splash/img/light-1x.png create mode 100644 web/splash/img/light-2x.png create mode 100644 web/splash/img/light-3x.png create mode 100644 web/splash/style.css create mode 100644 windows/.gitignore create mode 100644 windows/CMakeLists.txt create mode 100644 windows/flutter/CMakeLists.txt create mode 100644 windows/flutter/generated_plugin_registrant.cc create mode 100644 windows/flutter/generated_plugin_registrant.h create mode 100644 windows/flutter/generated_plugins.cmake create mode 100644 windows/runner/CMakeLists.txt create mode 100644 windows/runner/Runner.rc create mode 100644 windows/runner/flutter_window.cpp create mode 100644 windows/runner/flutter_window.h create mode 100644 windows/runner/main.cpp create mode 100644 windows/runner/resource.h create mode 100644 windows/runner/resources/app_icon.ico create mode 100644 windows/runner/runner.exe.manifest create mode 100644 windows/runner/utils.cpp create mode 100644 windows/runner/utils.h create mode 100644 windows/runner/win32_window.cpp create mode 100644 windows/runner/win32_window.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0fa6b67 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.packages +.pub-cache/ +.pub/ +/build/ + +# Web related +lib/generated_plugin_registrant.dart + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..ec98142 --- /dev/null +++ b/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: d79295af24c3ed621c33713ecda14ad196fd9c31 + channel: stable + +project_type: app diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..1ccf579 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "cSpell.words": [ + "adaptix", + "birzha", + "prefs", + "Resizer" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..1fb0aeb --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# birzha + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) + +For help getting started with Flutter, view our +[online documentation](https://flutter.dev/docs), which offers tutorials, +samples, guidance on mobile development, and a full API reference. +# birzha diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..c374854 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,276 @@ +# include: package:lint/analysis_options.yaml +analyzer: + # strong-mode: + # Will become the default once non-nullable types land + # https://github.com/dart-lang/sdk/issues/31410#issuecomment-510683629 + # implicit-casts: false + errors: + # treat missing required parameters as a warning (not a hint) + missing_required_param: warning + # treat missing returns as a warning (not a hint) + missing_return: warning + todo: ignore +# Rules are in the same order (alphabetically) as documented at http://dart-lang.github.io/linter/lints +# and https://github.com/dart-lang/linter/blob/master/example/all.yaml +linter: + rules: + # Prevents accidental return type changes which results in a breaking API change. + # Enforcing return type makes API changes visible in a diff + # pedantic: enabled + # http://dart-lang.github.io/linter/lints/always_declare_return_types.html + - always_declare_return_types + + # Single line `if`s are fine as recommended in Effective Dart "DO format your code using dartfmt" + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/always_put_control_body_on_new_line.html + # - always_put_control_body_on_new_line + + # Flutter widgets always put a Key as first optional parameter which breaks this rule. + # Also violates other orderings like matching the class fields or alphabetically. + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/always_declare_return_types.html + # - always_put_required_named_parameters_first + + # All non nullable named parameters should be and annotated with @required. + # This allows API consumers to get warnings via lint rather than a crash a runtime. + # Might become obsolete with Non-Nullable types + # pedantic: enabled + # http://dart-lang.github.io/linter/lints/always_require_non_null_named_parameters.html + - always_require_non_null_named_parameters + + # Since dart 2.0 dart is a sound language, specifying types is not required anymore. + # `var foo = 10;` is enough information for the compiler to make foo a int. + # Violates Effective Dart "AVOID type annotating initialized local variables". + # Makes code unnecessarily complex https://github.com/dart-lang/linter/issues/1620 + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/always_specify_types.html + # - always_specify_types + + # Protect against unintentionally overriding superclass members + # pedantic: enabled + # http://dart-lang.github.io/linter/lints/annotate_overrides.html + - annotate_overrides + + # All methods should define a return type. dynamic is no exception. + # Violates Effective Dart "PREFER annotating with dynamic instead of letting inference fail" + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_annotating_with_dynamic.html + # - avoid_annotating_with_dynamic + + # A leftover from dart1, should be deprecated + # pedantic: disabled + # - https://github.com/dart-lang/linter/issues/1401 + # http://dart-lang.github.io/linter/lints/avoid_as.html + # - avoid_as + + # Highlights boolean expressions which can be simplified + # http://dart-lang.github.io/linter/lints/avoid_bool_literals_in_conditional_expressions.html + - avoid_bool_literals_in_conditional_expressions + + # There are no strong arguments to enable this rule because it is very strict. Catching anything is useful + # and common even if not always the most correct thing to do. + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_catches_without_on_clauses.html + # - avoid_catches_without_on_clauses + + # Errors aren't for catching but to prevent prior to runtime + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_catching_errors.html + - avoid_catching_errors + + # Can usually be replaced with an extension + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_classes_with_only_static_members.html + # - avoid_classes_with_only_static_members + + # Never accidentally use dynamic invocations + # Dart SDK: unreleased • (Linter vnull) + # https://dart-lang.github.io/linter/lints/avoid_dynamic_calls.html + # avoid_dynamic_calls + + # Only useful when targeting JS + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_double_and_int_checks.html + # - avoid_double_and_int_checks + + # Prevents accidental empty else cases. See samples in documentation + # pedantic: enabled + # http://dart-lang.github.io/linter/lints/avoid_empty_else.html + - avoid_empty_else + + # It is expected that mutable objects which override hash & equals shouldn't be used as keys for hashmaps. + # This one use case doesn't make all hash & equals implementations for mutable classes bad. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_equals_and_hash_code_on_mutable_classes.html + # - avoid_equals_and_hash_code_on_mutable_classes + + # Use different quotes instead of escaping + # Dart SDK: >= 2.8.0-dev.11.0 • (Linter v0.1.111) + # https://dart-lang.github.io/linter/lints/avoid_escaping_inner_quotes.html + - avoid_escaping_inner_quotes + + # Prevents unnecessary allocation of a field + # pedantic: disabled + # http://dart-lang.github.io/linter/lints/avoid_field_initializers_in_const_classes.html + - avoid_field_initializers_in_const_classes + + # Prevents allocating a lambda and allows return/break/continue control flow statements inside the loop + # http://dart-lang.github.io/linter/lints/avoid_function_literals_in_foreach_calls.html + - avoid_function_literals_in_foreach_calls + + # Don't break value types by implementing them + # http://dart-lang.github.io/linter/lints/avoid_implementing_value_types.html + - avoid_implementing_value_types + + # Removes redundant `= null;` + # https://dart-lang.github.io/linter/lints/avoid_init_to_null.html + - avoid_init_to_null + + # Only useful when targeting JS + # Warns about too large integers when compiling to JS + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_js_rounded_ints.html + # - avoid_js_rounded_ints + + # Null checks aren't required in ==() operators + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_null_checks_in_equality_operators.html + - avoid_null_checks_in_equality_operators + + # Good APIs don't use ambiguous boolean parameters. Instead use named parameters + # https://dart-lang.github.io/linter/lints/avoid_positional_boolean_parameters.html + - avoid_positional_boolean_parameters + + # Don't call print in production code + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_print.html + - avoid_print + + # Always prefer function references over typedefs. + # Jumping twice in code to see the signature of a lambda sucks. This is different from the flutter analysis_options + # https://dart-lang.github.io/linter/lints/avoid_private_typedef_functions.html + - avoid_private_typedef_functions + + # Don't explicitly set defaults + # Dart SDK: >= 2.8.0-dev.1.0 • (Linter v0.1.107) + # https://dart-lang.github.io/linter/lints/avoid_redundant_argument_values.html + - avoid_redundant_argument_values + + # package or relative? Let's end the discussion and use package everywhere. + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_relative_lib_imports.html + - avoid_relative_lib_imports + + # Not recommended to break dartdoc but besides that there is no reason to continue with bad naming + # https://dart-lang.github.io/linter/lints/avoid_renaming_method_parameters.html + # - avoid_renaming_method_parameters + + # Setters always return void, therefore defining void is redundant + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_return_types_on_setters.html + - avoid_return_types_on_setters + + # Especially with Non-Nullable types on the horizon, `int?` is fine. + # There are plenty of valid reasons to return null. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_returning_null.html + # - avoid_returning_null + + # Don't use `Future?`, therefore never return null instead of a Future. + # Will become obsolete one Non-Nullable types land + # https://dart-lang.github.io/linter/lints/avoid_returning_null_for_future.html + - avoid_returning_null_for_future + + # Use empty returns, don't show off with you knowledge about dart internals. + # https://dart-lang.github.io/linter/lints/avoid_returning_null_for_void.html + - avoid_returning_null_for_void + + # Hinting you forgot about the cascade operator. But too often you did this on purpose. + # There are plenty of valid reasons to return this. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_returning_this.html + # - avoid_returning_this + + # Prevents logical inconsistencies. It's good practice to define getters for all existing setters. + # https://dart-lang.github.io/linter/lints/avoid_setters_without_getters.html + - avoid_setters_without_getters + + # Don't reuse a type parameter when on with the same name already exists in the same scope + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_shadowing_type_parameters.html + - avoid_shadowing_type_parameters + + # A single cascade operator can be replaced with a normal method call + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_single_cascade_in_expression_statements.html + - avoid_single_cascade_in_expression_statements + + # Might cause frame drops because of synchronous file access on mobile, especially on older phones with slow storage. + # There are no known measurements sync access does *not* drop frames. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_slow_async_io.html + # - avoid_slow_async_io + + # Don't use .toString() in production code which might be minified + # Dart SDK: >= 2.10.0-144.0.dev • (Linter v0.1.119) + # https://dart-lang.github.io/linter/lints/avoid_type_to_string.html + - avoid_type_to_string + + # Don't use a parameter names which can be confused with a types (i.e. int, bool, num, ...) + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/avoid_types_as_parameter_names.html + - avoid_types_as_parameter_names + + # Adding the type is not required, but sometimes improves readability. Therefore removing it doesn't always help + # https://dart-lang.github.io/linter/lints/avoid_types_on_closure_parameters.html + # - avoid_types_on_closure_parameters + + # Containers without parameters have no effect and can be removed + # https://dart-lang.github.io/linter/lints/avoid_unnecessary_containers.html + - avoid_unnecessary_containers + + # Unused parameters should be removed + # https://dart-lang.github.io/linter/lints/avoid_unused_constructor_parameters.html + - avoid_unused_constructor_parameters + + # TODO double check + # For async functions use `Future` as return value, not `void` + # This allows usage of the await keyword and prevents operations from running in parallel. + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/avoid_void_async.html + - avoid_void_async + + # Flutter mobile only: Web packages aren't available in mobile flutter apps + # https://dart-lang.github.io/linter/lints/avoid_web_libraries_in_flutter.html + - avoid_web_libraries_in_flutter + + # Use the await keyword only for futures. There is nothing to await in synchronous code + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/await_only_futures.html + - await_only_futures + + # Follow the style guide and use UpperCamelCase for extensions + # pedantic: enabled + # https://dart-lang.github.io/linter/lints/camel_case_extensions.html + - camel_case_extensions + + # Follow the style guide and use UpperCamelCase for class names and typedefs + # https://dart-lang.github.io/linter/lints/camel_case_types.html + - camel_case_types + + # Prevents leaks and code executing after their lifecycle. + # Discussion https://github.com/passsy/dart-lint/issues/4 + # + # pedantic: disabled + # https://dart-lang.github.io/linter/lints/cancel_subscriptions.html + - cancel_subscriptions + + # The cascade syntax is weird and you shouldn't be forced to use it. + # False positives: + # https://github.com/dart-lang/linter/issues/1589 + # + # https://dart-lang.github.io/linter/lints/cascade_invocations.html + # - cascade_invocations + + # Don't cast T? to T. Use ! instead + # Dart SDK: >= 2.11.0-182.0.dev • (Linter v0.1.120 \ No newline at end of file diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..0e64246 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,12 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +/gradle/wrapper/gradle-6.7-all.zip +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..9b3aa2b --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,71 @@ +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterRoot = localProperties.getProperty('flutter.sdk') +if (flutterRoot == null) { + throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +def keystoreProperties = new Properties() +def keystorePropertiesFile = rootProject.file('key.properties') +if (keystorePropertiesFile.exists()) { + keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) +} + +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" + +android { + compileSdkVersion 31 + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.tpsadvertising.digital.birzha" + minSdkVersion 20 + targetSdkVersion 31 + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + signingConfigs { + release { + keyAlias keystoreProperties['keyAlias'] + keyPassword keystoreProperties['keyPassword'] + storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null + storePassword keystoreProperties['storePassword'] + } + } + buildTypes { + release { + signingConfig signingConfigs.release + } + } +} + +flutter { + source '../..' +} + +dependencies { + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..80766fb --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..096d4f5 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/tpsadvertising/digital/birzha/MainActivity.kt b/android/app/src/main/kotlin/com/tpsadvertising/digital/birzha/MainActivity.kt new file mode 100644 index 0000000..f86abd3 --- /dev/null +++ b/android/app/src/main/kotlin/com/tpsadvertising/digital/birzha/MainActivity.kt @@ -0,0 +1,6 @@ +package com.tpsadvertising.digital.birzha + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() { +} diff --git a/android/app/src/main/res/drawable-hdpi/splash.png b/android/app/src/main/res/drawable-hdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..fe755b9aff703d9da84886504057d3d966a0bb4a GIT binary patch literal 35126 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 K4=YulhW{T+!{#Lb literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-v21/background.png b/android/app/src/main/res/drawable-v21/background.png new file mode 100644 index 0000000000000000000000000000000000000000..ffa595e074b5137e11a4c6de04f22c42732f9004 GIT binary patch literal 70 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}1TpU9x7?TU5etorPVExJTU{BBs Q37`anr>mdKI;Vst0K@JOQvd(} literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..3fe6b2e --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..6119b8f1ca0f00c4360ceb41e204be322d00b9e7 GIT binary patch literal 25844 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png new file mode 100644 index 0000000000000000000000000000000000000000..c3502e239ffc4080058d5d0f328b160a35c15549 GIT binary patch literal 65978 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable/background.png b/android/app/src/main/res/drawable/background.png new file mode 100644 index 0000000000000000000000000000000000000000..ffa595e074b5137e11a4c6de04f22c42732f9004 GIT binary patch literal 70 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx1|;Q0k92}1TpU9x7?TU5etorPVExJTU{BBs Q37`anr>mdKI;Vst0K@JOQvd(} literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..3fe6b2e --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..db77bb4b7b0906d62b1847e87f15cdcacf6a4f29 GIT binary patch literal 544 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAj~WQl7;NpOBzNqJ&XDuZK6ep0G} zXKrG8YEWuoN@d~6R2!h8bpbvhu0Wd6uZuB!w&u2PAxD2eNXD>P5D~Wn-+_Wa#27Xc zC?Zj|6r#X(-D3u$NCt}(Ms06KgJ4FxJVv{GM)!I~&n8Bnc94O7-Hd)cjDZswgC;Qs zO=b+9!WcT8F?0rF7!Uys2bs@gozCP?z~o%U|N3vA*22NaGQG zlg@K`O_XuxvZ&Ks^m&R!`&1=spLvfx7oGDKDwpwW`#iqdw@AL`7MR}m`rwr|mZgU`8P7SBkL78fFf!WnuYWm$5Z0 zNXhDbCv&49sM544K|?c)WrFfiZvCi9h0O)B3Pgg&ebxsLQ05GG~ AQ2+n{ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7b136a26bcf9b106f42b3353f74acac3951498ee GIT binary patch literal 2237 zcmV;u2txOXP)o!_MuHkHf;0eBvln@(^|45T?h%QGO4MwWh7d_ zYqJmChe=5x+LmnXr&g*ajaQpwV3TL5`7;||U~yYfRI%8KOJJyg z-!o{ry0`jhrcA+;Px1m5r~2n$0;;%ZHur$#${zjUOc^ihjXM~o{t_*Z`HdaS(l&MH zCQ!{q(b_Yn*u1U*%T+2)%9Ke4M4Z_C zU#ffNDa{_kk)dnv%(@@(Gge~pS9uUNXV7r6`+A3Q!ERS(U3N?)Ocm=dUTZ~)O*bD) zRJ*DUK_%s%b)|=m@9LiNNqtkNrQKLwO8F$j5^ii55dz^FB>|Jtu^$tQgaRQoEvO9l z7>*A2|8>@rG>mmgOwo-pnncj+VW}1&aB9WjU3GBO^Ed zMutO+U-5eE5i+>4BaB31DLAlFU68^wxPd`+>u~udtR99o-`TGG@Q*JptAH^5T9QO6 zd;SM6ExHz5`{*CW5-O$J>U%laK6AZnq?05H0Mq2eP8VL}{U{y`_>P7~1*W8kcj5 z3+%QY0t&F;%y4nMD%P4 z0&)QCqeCIDQeET=hF>_dD{FT zC)VzoBNJKPuKzZRb+ugF_G8fXk88B>=5uSP?hW+6M+vCL9-@P9%`HwmQ#^O!WmKpV zFE(&{gQtIg!$qyDxbV$SnKsk~xpIhsTz3@QpWS1y5?R$sJaCB4R($7%{@2A?ELP1QhPM;>Ywlf7warcpmD3D+7z~&BMVew$4qE)+Rw2_ zPDQDJ1xNvxc|r8YV^&H1n_=@=a>uunkcf0m-Bu^lHvH==gc8ZK>wgy9X2I5}-mHsZc6;j2b%0Fr{0?{Vk-< z6#3FF!fUZn#WDWfOOaQqB#7}G2UlCg#mgFleE_goTF9z4a?&AAz_vj3+CDL-pBmVU zuiydGE!!&YI}@pXBQoI-eZ?mis7~(_@kE7qjfyborwc^a&PE_>-M25WE!m1kD#UlV zr|l+!I>TTJ-?K}pPbex9JW#+V6-q-Mi~FP*Vo7Uw!YRJ+6Y?}~>uR~uk)R>s0bB2x z@W6PuQ78T89Ck)Do3==*ElSU5ls3=ZZ!~R!Z8U9yZ8U9yZ8ZHKoS~$z&@6V|00000 LNkvXXu0mjf-vU3Q literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..17987b79bb8a35cc66c3c1fd44f5a5526c1b78be GIT binary patch literal 442 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sk|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5Xx&nMcT!A!W`0S9QKQy;}1Cl^CgaH=;G9cpY;r$Q>i*pfB zP2drbID<_#qf;rPZx^FqH)F_D#*k@@q03KywUtLX8Ua?`H+NMzkczFPK3lFz@i_kW%1NOn0|D2I9n9wzH8m|-tHjsw|9>@K=iMBhxvkv6m8Y-l zytQ?X=U+MF$@3 zt`~i=@j|6y)RWMK--}M|=T`o&^Ni>IoWKHEbBXz7?A@mgWoL>!*SXo`SZH-*HSdS+ yn*9;$7;m`l>wYBC5bq;=U}IMqLzqbYCidGC!)_gkIk_C@UVt}F6F_bLZA4|3fjs=uI zX0jy<&begoT`3f#3Kvb&GEE_7H-+qe zuCIK0bGSK>i<`H*m#?)z4Xwk+KX0Gka_XzARVNcf+x9hI_;PHd&#VWX-Sy5U^HR_H zN7w+!To0xUNitPcc|!EI%qI2O@zH+N+$c+B;TU=_sZTnrl9$Dc10t{mgd5_u{*aHyAsC* z?p}V@0#Qbpw~M#9Z4Gs&`wKAHzF-u^2*M#cF6%~@X4+tY_CLl3{tc0$X(D4Yg&TdK z8u$9d1q7WtejEMl`!4fSv0_J$XAU|kQ~?W%IM8rXQ5A8VO>?zpt5ObnxgVEf*%eDylL$k*_l^;_nwaR zJR!iiIUqzx3d3=r*&y`UQ&3y28G>er|4>N__>-3&#Of0Z5YSw`F)GPdEk+X==yoVG zkQ?YJ-|#!X_deqv=`4J5Pl2ksc?g-kJ;Q`7!o&gu-bnIm#wWB0%N(X@logWoP7d5a z1YsYu^EEB0ODi;bv+&07A9%2&1;fzXw4fyb^^E-qle&P4_T(gVHosXsrV-FWUv)a9qQ61Mn&5<-j*y3b@p3*j<7` zQghF&xsIHWPt*PJ=>u`7(;7NH7&oWC?b7OK^BUWR%?rMs;ah? zaVDubsXGaEr}2nF6_<62V-!4n_Pgq@)qSi^Q^9r{BW^<{z-9&yA6O6Ly5#t(?-~$q(_j_V&tzWmI?`5FapQK zpy!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ac7977644956a36198a2739fb1dec22489f142f8 GIT binary patch literal 2978 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 Yzr2hwim+c+fdBvi07*qoM6N<$f<~0L-~a#s literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..d5f1c8d34e7a88e3f88bea192c3a370d44689c3c GIT binary patch literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..850deff1c251167df56e7d07c7072a2f55e2f41c GIT binary patch literal 5686 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 B5bXc} literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4d6372eebdb28e45604e46eeda8dd24651419bc0 GIT binary patch literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..089ae5415f2237642d17416e734d1688544a9977 GIT binary patch literal 6454 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 YvG7`}$&C}re+b~do~drNw$sc11NmHjO8@`> literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..411ccd3 --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..a937a0b --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,19 @@ + + + + + + + \ No newline at end of file diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..80766fb --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/upload-keystore.jks b/android/app/upload-keystore.jks new file mode 100644 index 0000000000000000000000000000000000000000..f409c5517b41955494fb1989b981da81c84ba955 GIT binary patch literal 2257 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 literal 0 HcmV?d00001 diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..7603b16 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,29 @@ +buildscript { + ext.kotlin_version = '1.6.10' + repositories { + google() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:4.1.0' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" + project.evaluationDependsOn(':app') +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..94adc3a --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..bc6a58a --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..44e62bc --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,11 @@ +include ':app' + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/android/settings_aar.gradle b/android/settings_aar.gradle new file mode 100644 index 0000000..e7b4def --- /dev/null +++ b/android/settings_aar.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/assets/fonts/AppBarIcons.ttf b/assets/fonts/AppBarIcons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..21ae244b424cceacdb15aa866f3e9fa206de6cd4 GIT binary patch literal 2268 zcmd^A&u<$=6n?Y6oY=12q>UYw#@QyV-86}RHL_bbBxzDy2&7Hz-~=vcyYbqNY_G95 zB`FAT;83YOv)+~zHGcuK8qfE> z_sz_E&$F|{h{!|lkx22g`B!Jvt4A&qu@hjI&gWyvsY5S)0{a^5f?m@aSLXis4ECSs z@0O~Y#+Khm5Q!VGAC`;SYN*c@g!T@4stm&Qv3LvkEA+$Vnzi8_Xg`4VE^Ker)HS+J zk1)RhyQ`*cG*}O@ zZQJhn-4v%O63%2_St4Imv+8uf(RcivxgE@^m6C?_9Sb_{WndU7k6Fphwn!!tE(^S3 z*E%D+LkWfm1d>It&uELr3#&AH+gp#2Y{J z(vwr?p$NT5Wk@HcSV-`(;i2$8B|Ob0(y6H6XTfwT;Acvo5)!6ahx^2u~c?jBDHvx#)(`({mFIRQdWrB5#FwfqN(*tjH(#}XgpXW!Ni z`VSo&={w#ld2EWGf{pwgDfy5uv>4H^vvYsDZO;xSj|j6pIJ3Fw51ENL?V7+>DzpcgIu0{bI%nF_Q+lC zd)`o=Am+I4{!=p_{$kJgcj|?B;{D&dyX2l=&~>j%=nLTl^wQ7vyT(sL7QOSPGV;Re zV1ZnebFc{hH3v(;MF-2cx!-iK0{$HbyJ?iJIM_q`=nMX4OWoM#8hz(rM*S@3V1ayW z&A}r04F^lWTMm{fz-~BL0spmw-Be&dIM_pBVQkK9Y&I*UvZWrK8&Q+-WJ0~TshXfF zb*-vu>sHxpw$vHbsIFU9v02g0dQ>-SW2#}+tzxxma%*8T+i{<6G;+n#dR1%gq;}#$ zvDvDabu|%<@1)Nb>&2#K6<7K8txKh(Wf`i`G;3k(j)EP*n8dxGqy*4KC{!prstVOfqbe8;Uoi`_xTghs2Hk*%vljk8 zuGitMQ`8=7xOKULGu&UrV?OaMV3+Juvri+o2F^zjv8}_SVa454yYU4(jus-}yQ;`1 zioAAHpM|<^&(Q1$S23fLeTyz3ilm*HVQ10AiZ!6@fAUcgGxx1w9Uc0pT~`ZihGKYj f%m4Ac$-lqPY9bSu$nZt2)D2T<6}6_0>y-Wh<*I6~ literal 0 HcmV?d00001 diff --git a/assets/fonts/Settings_Icons.ttf b/assets/fonts/Settings_Icons.ttf new file mode 100644 index 0000000000000000000000000000000000000000..65867f4fc9d7357381d5d2c95663b270aac6b4f0 GIT binary patch literal 3408 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 Tth-8Pwb)U>)-Rd$HT3%((|Mwc literal 0 HcmV?d00001 diff --git a/assets/fonts/svgs.ttf b/assets/fonts/svgs.ttf new file mode 100644 index 0000000000000000000000000000000000000000..8ba7b797ea48f53facfd2e94f16ba5495f09d026 GIT binary patch literal 2704 zcmd^BOKcn06}@+ce^Qi&KSi=74n=Y3#1j9a93`S<$(7yOLJLcE;}7DDDN3ZkU&v8l zr7qxQff|NU^ap2=6lt7ny6VOSjCSL;=%QV=tNeg21f*!QDNwW!ne&DdLkVmk`@G?s zcka3OzIX3^Z)QkLL|(c@GG)%Je|K5^QQ~zXJ^^;)+w19EY3iFb$hRS1EI0J_u~+~3 zd&vJqzqeiA+j{iDiGLHxZ=v6)R`kt@Ki^-3?MLXvDhTJB@^673qEA;F#*Lu8|3CQt z19GU|D(ielGT{3Y$i9Ytqs?L3g#H=GYEy4i-h1Qj1d$W6oN2eZMsD%=0+Ht|^k)dM z%NP1PM7Hz&gZ_bSO)y_*c9Q{n&&WNxHvHm$$Sdy)i}y3xZ+$+(w`yCHuR?Z_Bv>>t zlbv27hbalxgNvwd$^*TJGE^ez^y>Ky^4E2vN#kTYq(6+gUfb3&|G<-BC$tQP%{9b& zEdPb?VpWn}mqf*G4@UlovWy5Mvddtf(7vXrVj-bTfeI^=(hIEQm3*$m^GYFUTX;87NZeG{*VW#& zK%x-jUwS9J{8q4#IQY~(?(W@jb2J})@Ye^pvzza{{ct>y7(cZ)846AIYJvQ8fPe1s z08QuLce{J{+`iubqxlIA^!_yg54+Ee6V&hZtMUd;oOr1ou8x zmr5tnz9DINeApFrB#VXQe2LSX;$gVYNG0#~|6Z&_cKQ8p)u+YxPJ}-(W??UB(#%S$z1OL2R}J;p%Cl-Nlgp~t_tX}sT2rs9`mRxJb-L=3x>esbj7q0g zZZ%WoR%1rpYBh~Yz1|Yi+TQ9weX8BQP}$zC>z%{YVSKUD>DF3JHJi#Drq5KGm5y#y zHpTMY*S2$pv88TxS`Bs8T1RbnT051pk*XR-dm)`Zygsc^i`ukD9jehbRmmU~U#b;) z7Gn&P130jMyFkPR8376@)G(MG=ep-f5N^DZIe>w*uWQ2SO`Yw z>$qBvb!%8<^$Xso5L+APqk`CWq0uqp)2yDxUo_+BA`-ExihNSY>uJ_!VBIu5bTh(D zcnq@d(rbt!XJ)o#X3@cn4WQL8<)b2Iq1(YcW!R_8x*A{?D2?lB`Quw=Ht`?nNzKj@ h%WPvi{v+5LdaY^O?N&OrGESnaTQQ7UbGr+_&j4NCuz~;p literal 0 HcmV?d00001 diff --git a/assets/icon.jpg b/assets/icon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9ff36027bd5f601f6d08ab83ad0eef1b1e7f9f36 GIT binary patch literal 28016 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 b>Z|%-pPu{rlm4gi9|` + + + + + + + + + + + + + + + + + diff --git a/assets/icons/home_screen/chemical.svg b/assets/icons/home_screen/chemical.svg new file mode 100644 index 0000000..3c48bb7 --- /dev/null +++ b/assets/icons/home_screen/chemical.svg @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/home_screen/machine.svg b/assets/icons/home_screen/machine.svg new file mode 100644 index 0000000..f4bb36d --- /dev/null +++ b/assets/icons/home_screen/machine.svg @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/home_screen/shirt.svg b/assets/icons/home_screen/shirt.svg new file mode 100644 index 0000000..4a015e4 --- /dev/null +++ b/assets/icons/home_screen/shirt.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/icons/profile_screen/cart.svg b/assets/icons/profile_screen/cart.svg new file mode 100644 index 0000000..0c97ce1 --- /dev/null +++ b/assets/icons/profile_screen/cart.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/icons/profile_screen/exit.svg b/assets/icons/profile_screen/exit.svg new file mode 100644 index 0000000..5c4078f --- /dev/null +++ b/assets/icons/profile_screen/exit.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/icons/profile_screen/message.svg b/assets/icons/profile_screen/message.svg new file mode 100644 index 0000000..17e5611 --- /dev/null +++ b/assets/icons/profile_screen/message.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/profile_screen/phone_not_verified.svg b/assets/icons/profile_screen/phone_not_verified.svg new file mode 100644 index 0000000..f6b30ec --- /dev/null +++ b/assets/icons/profile_screen/phone_not_verified.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/profile_screen/phone_verified.svg b/assets/icons/profile_screen/phone_verified.svg new file mode 100644 index 0000000..58f6de6 --- /dev/null +++ b/assets/icons/profile_screen/phone_verified.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/profile_screen/popup_history.svg b/assets/icons/profile_screen/popup_history.svg new file mode 100644 index 0000000..ccf424e --- /dev/null +++ b/assets/icons/profile_screen/popup_history.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/assets/icons/profile_screen/profile.svg b/assets/icons/profile_screen/profile.svg new file mode 100644 index 0000000..5267e70 --- /dev/null +++ b/assets/icons/profile_screen/profile.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/icons/settings_screen/confidentials.svg b/assets/icons/settings_screen/confidentials.svg new file mode 100644 index 0000000..df6d8e0 --- /dev/null +++ b/assets/icons/settings_screen/confidentials.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/icons/settings_screen/contact.svg b/assets/icons/settings_screen/contact.svg new file mode 100644 index 0000000..d53ab5c --- /dev/null +++ b/assets/icons/settings_screen/contact.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/icons/settings_screen/feedback.svg b/assets/icons/settings_screen/feedback.svg new file mode 100644 index 0000000..b8544d0 --- /dev/null +++ b/assets/icons/settings_screen/feedback.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/icons/settings_screen/lang.svg b/assets/icons/settings_screen/lang.svg new file mode 100644 index 0000000..c5be39d --- /dev/null +++ b/assets/icons/settings_screen/lang.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/images/appBarIcon.svg b/assets/images/appBarIcon.svg new file mode 100644 index 0000000..4c3a2c2 --- /dev/null +++ b/assets/images/appBarIcon.svg @@ -0,0 +1,11 @@ + + + + + + diff --git a/assets/images/map.jpg b/assets/images/map.jpg new file mode 100644 index 0000000000000000000000000000000000000000..64288cfa4df6a3523f00b86f1038dd6c6b536121 GIT binary patch literal 41006 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 #5mehncTRL~)q6 zXhvd6=PA`3Z+|gTiOev=p*HmDN6W9eykp)W?Zyt)yIt)E`~b7PJw6H zpfj}?XSkaPZZ8l!XP!=8r~c{flYLE{8689*3Oeb7iV`>=P!$7Mh>kdLkx3@$`}Htr z^~YvvWc8xLVQ5gQ7je#+-b>=LDtF7TW^~WW6)}_JHJR-1@Js`{JdqLIFZ3zwU8j-- zmhX+iH{^Z4@2>-08bqzhVp+_CAF8henO*=$qQ5=wTan@p?;Qo=Er|HE_2M1ni!W;S z_rH-gYVtpPYt@LLnsafkYY)5mZHAVbZvwB!tVX+W*)LuvdPr1H4yj&tkM7ge8mp83 zUAdJ1)7+Y2S10Z&F561aPNMFTF7s~TkF*2grk`gi8Ih)Ag%G;{S^2Ft55s&wc}RSs z{`^0n#E$tFwcU|=a74TT?K0Aw)L#VbwZVba%gG|pKal5-d^5TXa#m&9MqA;3`Wy$4 zriI+QDw}Ne3t55d+qKUqHoX~7W`z9RgPA$zMHGGf{>HXu^$QCu0TWBl{?n zx7~0**M2VXKda1rem<{DGi9*q8HTJvGGu(2&BWR-aJM;PH%&Chg#tA4D_9&MnU7$8 z<9deUy1ME$Ou`yT{gqg=92Ye!xAMVxf8pX7s%jp1su5>-@o@>w`^taVcRS%?0_92J zRAR*W_%&Qf;rW~7$G-P@kQsUle3r>0R0#5GRQkGL;{01e63c9|^!#ja#y{Fp|$3T_nPrP)8!3*5;Yf^8wzdbX>Ro|YqfRj#+Kbc zN8lD{knjc2S!!c?rKAt2lt066*LB-*APGh0<_ims6kuj52S>o2>z zH!%ZeGLZDYddHv0GM{)jdM3znugl#qkGbagk8&Km1&}LuWDlX6khsayIqcF`L#BM_ z8_3;O=(N6jH=F1sA5Kx-(9hC8I2?Z+4HX@X9aDT7AR}v&;#%~j6j1=?2Ns&u% zsZk24UJVy!c@fXi@)!RtuBn$WXoP_X0Rz;4qs%Hy=sJ;P6T zPx#!h%~qv^LEY5(R&8U84*#g$N}vZvlo=znIZ6=y*>3b~wCK6S=HxPg95nC}MRpcg z>%zi+to_AW+b5U#52Jp!3d*pgmlq8&fQsuS>j-YUUaqM_iw-h`J z9gRZQ*QS`QCTqR@=3$zD6W=dX3p{#@N7&y$La-d5zKWWyPc9?*r%nOewc zbdJm23jj)^|GP}boA=UYY~A>vN&DBE{&x@Fb5Xy>@@J6|vcFT8@Kit9`V6RV5I);& zt(nMBn0B?ahmUHx{Isn<+;{Yd=OJ+zHtelpI+%O|<@*Np+QI;Sovy?g{WhDcS-B;C zuQ7K|lNk@9NzijC>*-Zk>J90givoGhOLgEW>q-}V(oNU?obx99|1!p^>dGZ|FZrw| zrM9M;+6I;DRmCmpAZe8`cSOqDoRR?*D|U^a4a#e};P|!O9#QS&?(=>pA5`eSEnpa* zqt1corx_QWR08kVmDO@Vw)@6?8n0-kqF9tKSW=rY238nMMn}^rv=+^ybuFx=Hg^^` zqq=8TRGg&b1)p`{#n&Z2LMB$`I7!P(dq3TAH(_2MeA?Jg0sY4Hbu6}c-H`nLOwMFV zedZ*6^vj}PQ;Ad{zM_vbg4|R3ay%%rL^l3;2;KPEC>%x&XpOPww<~!r?KrFvPR2=N z$^0Ta`dVG2@#&tt6Os-nFR^sZ`ZPPnhb`fRlz$c%cOsojo{tjU&~KgfrsHDB@~8Kj z)DYG!{a$n6f$wh4-B#<>VE7Hk9r%Y`3NiSJqD;{@!6!<2#I!EMY|KYBA;`95f2k{X zuhUC-EAyi@nudC|EDP}qfM@5-ZPST((fmwAu<8Y{5C=I$60C3>x40~be^YC#a5*MT zn1rQE>e7pDFJ7cGPM6IdVS+L4Z^xX`MDb|$>39LA6T3>v<)9z-Dh$o1KW|t@r4PIS zB3GqQCXnrE47N#O(#A}o^UUVc(n~xM7JZJ!pXm5>ba(7IeGaLiIw-T$>Ce(4Te`05 z4`qYt+1D&7RcAn<{#((}w`o)TO#MrDz6;MdOag)H5u@*R>f2&C>PmXi&3EEJN&*j> zq_}a>4GU1O?SQsHyYf7(i5;p{R-Z{OFlbeDOlHR@Y`Zz*_#IWk7_wGCReziT0ecDj z!+2lV!cGGJa1W_!aCw9l#>7(P^=`+IN)6%~t@<9_j+suh6ybuXe71>Wi_;dZyY2Sf zZNtqA01s?ne3?qjUpT7lwf6W*KlfiZ)jJB`<9_2~pAWd}vc5%Q&g0*M(Wi4P_74E* zqDX#*=sWBHzfoOV|LP-h48)V&s)}GPb0)|rBHW{8$G6pyzk5ks_Rkp2s&4^;9mnkmAJ8!^e6mo#PXLMmrK$hS+imv)F7s^o48Q8AwXs=XRn zpFD$=)NvsQ*0{twUtE)8(Ps|U%!2KBg$WPSAn+m7eJ=Vnw59!Zznl5b~8flA5{Xferm$b9N5tJF_`n34H1Pw zi^OPZ9OqAPUFD^uOcIWOCC^S@?Fa1_o6xN7H?EF9!B(>lynHjm0bqP$g(nDJxN(}# zjm?}_jPeZB93wTJ|RsU4R$3kN$^aX*q};oJ8N0(JGMB ze-`Fp-%DT0_@ci65Z`)I0JnR{FZ?ltLqv4i}>=iyS8O2rzFJEQDZIz0LG z`juDH6|#T2KJEs$s=^ErDz?KYLT1y{eoT?qw2Hg$cldnz7KE@~q4eF!;sogGnPYMUnqmy*3A3zQ?1*YkXAoU@Ex@DtJr=m})Vr#Joi6W0_nR-x zwnv_{-R7R=1%PxE%j)*+(x zPh7tH#DdgOQ7l$oID_A7jD%$)Q_V&-drFgK{tiz@FZBk1o;}l2{r1^t+S{BhfplR0 zq!EW`VwPUmMg(iNy1`+iUZd|D)(M)%Fu&IzO0|I61YP z1m@~Zv2)-#$uo;W8!+mA2vvC^*30b*g;^hZ?uha~lg;=Dcnfq+H5fIRO3-$6KixTf z7NRk5$of5qH+_CFZv;Y2Q|Vi14Y&JlJ#e%-^3;456M2&zq>lx4Z8Z<`p>V%A_F=90 z=qOQOYrrd?($*9ftY#Ej5&tG%U`T+P=Y9nNsxh?jC*~yX1%TQW;R3>eW+4eiM|iOm zr6FSuEh#Rvs19s8e#fe#kTB4l5zX(bm`J9kAQfRe>#FNGl3SRckIpE$vD0ZJ#X>(y zqsHu$K6}D@tyTh?Tya;dWQexUF|LH-Qn{}|4YFuW_B z-9EVcolGl6Tnu%76f6)e^=2JmZvy6rw262m0}N5jDLUM1*(t5Z!+EzGrU{xNP%CnAYhI|Mdc(>$xwhChM%U zx|AnYAi=1WWb}zF@D)soi+5nQogM>5fs_xV9ZsxdS-0j^(RQC$7Tz~;JeRFrygR+I z6*)40%ipY^$5G0C7LBU|wQ4r7ruE4IRb`U4&7J8;JA~I_A|%JRK8sX z)U5t>po+Yil+p){h?CyDeqv|TCrYkbwoc7-Z}!~A_T+L-q0oVq-)&ySTNw7w?FAru zaE-)isq(gu_bKdsP-sJ9CPm!DH~K34uy32lWEEi_&u%{0vhbiu#L94h2xxp5WsXPw zz%R-@*Hb*Uf*DHlI@-Luen$B^KD7yEo&a@Yq;|fOM6rzqAz9HiMx<_8^0o{6juN3T ztn3O%L>ii=Kj-60RgpK<_Vv%EKlqRo!**^@?nTRRBe%v0UT0hN(Z1H!MwsKGG^yaw zTTE=WJcFcRVIl%3aGipUbi0ko>sM2p(t zrxiPKZj)kz&Vte&;qNd4<<^VUjGI!(hatCy_7G=W^LR1RTmgE=3#WJt@SVgUG?H4= zd)TSBAgQJDL6-F?3sdM*@%PqLUst_W-)?xlP}c`{&i{j}vy5sh>biAWN~r(=3I&Q5 zcP~x?rC2EhcXui78l0lRDPA0k6?ZG{5Zv7f?g4u9zTcHG?vFF_Gj`72Yp*ruGqH@$ z>c(M=%N8n~IF7(2h|dz3BW^V@&qgwO8uwB=)~Ey!cA%nt+O zBxm@A(H$L`W`kRNEH}*0Ij-vmxvt@{4VaruQrIH11(Kp=jYgUqCNApg=o%dTl#w`6 z4lu1pH}t5kjiORXlqt?f{mNdS@4L4K5b1h|J!ndJRF8Z0^azW#1C=(k? z{-1~uHKcAaFITtz^B}G zD4}?f9Q#~G85`m{t%M|j;q2Yx79w*rulPvLmA)(`fk}74YIrKDyZ=p$*q+#-ToOTs z{Q;3zbRtvV%Q9x4^azsGmI;nQ*^@qu1A(i{qR0XP@5Y!eK82tyjw_7pC*NtwI#M&U zh`~n5=6Z~6o4Hg9`(?;(RvC?&`nz99lKdq|M@&rFduW@`nky0LZ{ilN$#HO+ofIBEz8b*p)%Qm}h zGECc|)wl7{H(|i$rsKJxa2=*!q zQ=`l7&rZU9F7n{{HDK2KB>ZO+OHhvXv3>cwOE0Xsd8oIvg2y@G>i&JY3PbFCC#;#& zIu2rZ_~f$(h@B@^*||AKS8i{f+7p=*Vsj16Qhk0) z5dHntkyC6T7&cX2uCoP9wt_l4!Md*=ii%8$RTKp9)k2Kv{Nw_Y)Ws8A_)S5*KXMr~ zQx;@Mx0hioQj=(xg%hF^-R}PYy{Xf%9w4T>osy;k>OKtKOC*>%zQikf!l= z+qk0}>G%B+!>onA&jCBqtMaobhkw!}B>w0uXnH67p855A923l6I&vR&bi>8pqbJjN zVx0tCK1y{bX|>F(*J240|Ef>(Li-@MeHRE=+Z}`zZCdm=#yt%`VPzs!8*I2Xho^^X z{HzE+vg++$s3gsiX34n(8~)-&jA9B!6w6G-<2Ol4=?^@MEAMpBEFes7gfT#TT8)u?*kV1EDee4v*b9lI5A`72wJ$xm*<|r z;Y;4X3?yH5vd9yKPvn!d<;{+8k+R@d@)R5+ju)?9`*OKk_btrBU8tQG_FCd55p^>f zZ>g**_nXbOKGJE5V->nbKKDI8zFf3}=@H%PIHM#dUNcV<&GGW#kR>)#?F%E#m_f2Y zxq-Q|T8($niIDZxqxSVj^-eeTGRvwi-f9}^0P zuZI<(MZcgg`D4rj**Zdrq|`m+KwJByUX-mx9Lj-BPxz+F_UGL}{7K@M#nbbC$+x5< zZ|wE{0n~&E*vP6%i$}mhx+gP_N1C_GXLjnhjB6-$v$dPz-igibqUIhWZKt1{lYn%B zPP2D0QQ~|`-*S}3b&r`vd+k&3## ztuFp5pQC=`nQt%ePy$od{nhq&7NVy+5t&b;48Jy z=*K>a?IfnAqF6MRC#P>oIv!X*jne^Tn0lTGB&#&Z{>c8x<|_4}d(@paW!mlebB;o9 z)%IJN4J@F_bc^`Q5@Q3}D7#~-x~ZBoO3rVQBm1Y@3gdhP-)Vg?pbnRe3x*sp-ChW%4<+lY0|G4$VppIK|R~G#x*N{@>aR}e6qP} zwc_EWn5+o`)%qnich6w(#5*DNXeZlnxk@Yxzl2DJ?}-XNcZ(ABAr(ty-k+HH~cE!wnG`!{TkM9~+EA(bW*nE3ezW=W5yACl3+x5sbaaT2%Csmfw*eOX~-}NR?#n888<^ww)14Y9Yn;UQtHw7K!XT zNm>wT>&g{408ebjUJ?V}fagWpLaFy<(IeHv<Bwd2`N$`%Vn zVBWKD%iZl1Pk%1+^EE-y5S)c$6pzkglXV)HhpN= zB5OchXlaT)UKPv9S^KNwV<~ah8tV-|Iyt(}(CGO5BV|Yfi?+N6#fXV}>?|m7DtNH| z95CHSRi*nB@SsMn5I0qnOHTD!!`@QrZqkTpHQ4N&t~R!%%ZA!_E9>MVY4_6OR$qga ztaS<+0fg5eTo>^ZSo=A*Sb;x96385aY*dnS_fRv9=$N^_eO=2|dGP4E^FUz|{UHA# z(ZW$JI%{^s`|?7>Sa!Os){E$v)jWLT^-DGBIf75h-I;i`XH32DyFbg?AxM#7tnIPy z8U~4Wz6XwF{xMPnyIQJCb&ikCUz;`PoI;r|#5gf_utOuSN5!#I`UvK4%{L_4O1KvE z=;zqega{TnA!E--*WOKT^V^9^eL@1U&qjfqwWO-qivIv>T+n4`ZZ*Q^KW0EixX#op z4;Y^pilggpK-41kK}RDS-9^Y*$OvH0{cDFh{b7@F>1bb9q@bvtSIqYL>f9h&UU7&4 zQ1Z?*dOehWB`Pf%{B_q>_#?>Qc~%QER@=@9zJCt9lo=JE1YXHQ+j3uAsnJs(f1g>T z09$sAknsp|m}&<7J?~K;dFJau!`!bgN&Mj6qh6PW$Sx-eNit4iawMF90?$g@v2Hur zT?AOCWb>`g*vzXNDZCvnBFU=g!9KuB$^ho?L@pkGz~k(T#AA%S;7j(2V5K;#y&3Mv z=?&gA7DhpvSaHS!ptxL|vbDq3XpVpf8df4S`zZ)bNfpyt4w+3h*g7ne5y$3z3#>eV zj=hYklEQ0>_dXM-FtaBA(}0G5_mxBq$%+2Nf6%efb)PML@e_`YGDkMI$7 zNxMQi)y$3E_C&)zv)7r%-W5+eA?3gvl`7N zEP-UPxN)+oU+Au~`q1*eezu<7iKi~s%1v>xAKs>W_FO8&NTy>z#Cl#>pumHHjg&Oz zi`B9sM9F8&bEn5}`NL%1(~$MCtDt>DuvUUqpC!%Ef_ys9qC$qoIpT5WM1os(DmvH6 zUj6YafeLu#F#ZySJ77-O=gj#dTgzoR68qo^_iod?J_e(X!CGPT%ZyQpxhaz0+Jj+Z1GOz-{s?<=;L`iZb5SXmal zXa0m48GC(~6fbz|e~f`~0A@153mYfsLfe0+{3c$6@-3j7x`%cOqI}39vPkLOxaF?i zZtpJAwam?hT8limS3HB{SGf8chMW{Vf1Qdb(5qYJ4T^?)U2n*HVYwC5%-3Jx#1kHOa>2)7{&&002m{j*Lf4ea&`ibu@J*em znAtPLvTEeoUGpEHiQ9j5AsvE0r~3u2)Bif4`*=Zcfc>=S-r;r=9y@TL;q$@$QvFNU z(pYUdK3ORW4FgREJ=JP4&M1kZ>-wG(EGQp<`wOJrmabZ`47hz{firGVKt5vt%;BZ7 zK3HpSi$1FBz2D*V1Af1u7>vQniCEOEnX9iPd_UKp!8th{3h8z@V#L7jSZlY0ERcM8 z{OL=edt0JSyXikeqHSV8+nP~bMKk96n!c)p+#&F8y$srE=}W(K>%Ud?=QJ@YqV4v3 z=7J2F`gr@#eAu^ihHHY8_ET*zQ2zi55dP$2XD2)(=vw>qb0Xl2*t(14cW3lAo%^cj ztJ~%?_O+~VVZ}2W7a?M5Bu~|s)1|xL1;YR?K)*1#B!=h1W;l1cE{omt{#YENzI@>o zEZ~WJOXDGU=jQ=atIR;}=+lNS9>guT?b`eVc4Ut9ve2)&>C)9!o_ZQsAJOi@c^hTL zSoqckQ%sg5G4}L@h8n%Y9p`|+3nab2F9T{Pi2iY(9O5mJ?H&OMSALPKrTd_6-$&VL zVjdM9^30!F0B~6`gqokxhIX+UZ^+l4X{~;XBKrhH)3)?|qhupTg>! zX*+%_24UYWZm2#syK7y08Sz+`=z=yx#1N99zgxzCej=2h)M2rz@($wMwC&Z@f#t71 z4B>`%NVclF)mNn45r%owCz_HAFl76xP4o3aSi12&5l@;<)q3Pc@64>qWWrah zgQIm1;`C7a>_Kz5%)95L8?7EjCW-05s1T{IIwMBZrqGPi`vHr|$@1uZ4dio%?5S-h zD=qjM>3|*O-#YhE49M^Mb8ba(&V-;i-f-RKI{pI@m?Q;6Q6Hz`=;q8+SZRT({l`X< zE}vFfm)q(h<{x)oOIkQ+=u?LjXZ4qjvl-IAy<;TE>^j^^5HW9$j_PoPHp;H`JNv1FUCvE3U#>365n013E4O%aOAbJ}+(6CKc+vglcKwyx(!_b9>h= zW+{vN$M}WSV{faka z?*09-`~!Bv{k$H#-ZDku2={8|biO3hyY61ayJgGi<$LWjDN{GheXlmP*t|88{@mdf z2jt%E1%|vjHfM)Gp~w`U+F-re(xOgAtb8){usf@Ith)q^ z!9yq*Gi#GM`pTrfCS#+q?yV!7w`+%KctsPI%uk7<+BfJ93jtT7*p5dna;GQSGv4CX zzoAC7HG)fg>f9@7aZR75OV>DEG^wo{Kl;Q;wdQHkuun+!>m&oJO6EdmB%huIDsy<2~NeY-LmSI25YHsvRgZSt+G<;--> zKBQ)O15Upnj)$K6efVQC^T?@3BD+msBJ$FD+WFCwf;ejEU_9eDGkAErW(;$`euYv0 z-NLerH~X(>x+F$Cm4+bawOv-xD`slYJJRjlaS?eFdx0`q2WqR)ldeeqPc( za3cSjL}bT+4GVUZ?!SA}o_8RNaOQ8V*7_=VN9LMZxt!FTurWHhGeETR5AbNWs~GCl zxUi!b8t>PBG2+F3`)E}W+@ep>ZTEIj1m2eBMEz%hNZ8lJw!ee#3~SJx@|{{ao{gYf zJ<~gStNxbWRhaP+RIs+V#U!sWscS#}8|wy(Q=h0{{2oK*I%@)}F zyhtBN$MDin5_#0uNZuA$!87_5QF*oM=-dRa}sut>h|O-3L~ zSKP1{a9qWgd@?U{?|@LI&ZBK3(>wnN6zicIqCs#VM==pnqDJ{#PPa*i&pm*M>wO1wqNi#d8Ph@Iy`=d99V5K{&I< zM+@8)%@a1(^+>{oU_$mJHUPnadK7tJ0h45-U4vg%8+44W#dy>12wCE-b5;#R%u_GZ0RTV=BJicG{AIrS&*ZGC+_aec@RpHzL4MqboLW7srY@&!ju z$~?TMwC#4!Uz7@o1k*?g*W^us)3+UkXZn{S_9 zz;{IiJ>d&_kODTGyHjV5eox>v#4fx4UOA^K0Fj0i>E>n_S{UTO_ww|SRA2BTk&uk{ zz3o0Y8*ZuMTS1#0hdC&@{vQbmLKK~Vv|i?!P4~l37S}jJP~oo!EBV|920%`@_?_1{ zni-3z^r=}4LPBKVL{di-s6rF@>xlI-n(E;TeFtuZ(rI+rQ?P%yI7_XOCmkl4cNH8+5IncPv3Yp zI`Aw{S8Oe)$FbmkqTyp>EcCY27pf)B@$~T)h zX#n;s!+uKg`HH>@SbL@Zk0)H;$#HLis;DbQm&Wluw-+{qF+w=y%l7Ioz=pLjG~&n9 z$lh7JS6VWZL>3F8j;}{W$LI+LZsXS=p%3b3%3sbBx3CvZLY2N${uFwK6N7I1tdswR zmo2EE1@q=({?8%-ONQ2mrmXy1rwvK=;NLR}H^oyCH_*1^X4*wv3YWcTscY!tPei-v z*!<6n3J^bS2;!o)!BGX{GNLEp52!9BJ;sPP}*gU%^!9|x}Uv<$_i8@Ia>;hGhjs^|$#_2zz= z#@Pmcc8X}rzb?+Zkl!0wYBztgmvXWBte*KLQpf>~n1BD?sCfULwjkNZ$HC49^PLrU z+4S&_2J5gO#lK`QSKJ=FM;w($wS2_rXkx}XX)rj|55rjNfhKK;c>dXa8(xCk$s zDB746;%~3{GnSkTBxpiDs;$(Yg9K4sAiH)_J?|HC9?lsU-)3wcXk2VQp9v2w(<2Jr zdOZIF(hUD%9zPODn}GjZQoyiv9l8kYsat(VIay)jEmCHQI)mH1%(pl(ajCp+$bP3K zj+{=3k)dij(RoajK|}v2H3_0Qoeqt-Bq`%ot_eXxTE$7P&x=eFgP9?@AeKwGnT!po>$U#APNk?+ak4A_r$>jl@IMA_2(nXHHk0u*gaYMt zE>8zM!OX58^INC04+nObBv3MKx!i+-a|`3T_8Mt&4Y;(TW)h;ytI*x$wSntG?t zESRkfQBGXYR)0RexI_)C{SsO@Jg*s#aXb*eD$r4(-B?{ab9obBvEEpl?tRvP3A@5r zX=rs?9~lkOvSHP`o-#?3g04!6P&@h>J`Iun1Jo|Gb8Yxyb{ncx3V1rf7QzuvWT_8c zWDPp!Npw23>eTz?S@ii8Hy-Km75vHWWGwWNw1 z_R~zz-&Lzh(lmkeHB9IbZ{N@*vi*1~H5-k#XDWW-+f03B7M+@6?JNdJ=SNp&yG!Vq zi858Ii3 zk<7gPzxG?dD<}@{n4G@!f{Oi#FU^P*pdT9OFoTM*_5-jy%7Zt; zE?Fg#=#mDn2~h8si-~_Zc*$gMFNH$yx1x2m@lLi#FqK{6ig}C+kb)!e}IErWmzg%n2RDNt8Lz~=`uCrHlaxC*w-{scw3KMYcE|4ChVADFQ;UG z;ftGF`*&?vjTo~>5$ANP%<)V9P1xVMXTQwZeH_?|i=OA+#Kq&k@uVb80%t!23nIUJ zIp4}y*uYMHUb!9yc-?0e73?cL#`WGK=6M_6FP_;_6-EY+e+b@ywMklkGs^$XU;y=INdQ=q zW0$}DIS@_MzjBl5`gmmvQafyb9?VR1Dyt8o=R`Dg z{J*$};iU7sKk2-@Rj~;%PMs8CTTU|g){b*E-Q3TTYMg@Yl!-4NMMMiHY3nsRmNT)% zFwlKEe?1py8Si*bCQnRcV+sm#{nc~57;BU9E8x6xjmEef(heEE&iD9o6y{3Sh}+{t z{vskBKzkKbUR#i*G|P(IiO1rG7Yx8&~BC_KH#1)Pv*r5{=jyB`V|V^7vsZyI3kFe*5~-WF$}9H zS6bi_ml?vHe%E+^O}-PhtL>h$m;)P|Q#q>0o3j~RJp2bpK`j_83D6Kx@*O{755Z;K zQU^nu(&)JkVeaVHH)y|ZMx+Q+jM$AkNl$#$AhxHTs9mpIk`dBxjjY{qNZ)!q&jMduj#+*-r^&=j8n7tG7a@zWQ>B!|U`-iz!F7BuWA(<+3n&=rUxZ z?3np1a+R^ybW+9PbTTh_m$3e^32t4;wmWOc>Fj{Bo6WBJWPL>oudwAImRm_W;~KeW zZBFk5c?CRUfc!o?DASz{@%Av@K)09^DLWE(T9ozc_N*`?KTLN>Cubfd;k7l1&8|+2 z)^gvZf-7d-SrhHhQBw$dH*P0m5R_S3I>u=0x90X#$(;%;Qk7swMsnqm_ceSv*dmpK z4bfUb78DPfJzXNseGm72M!$DGlfr2|arL2qvVVF6_5Ina0~^+Ph5ey*$olyYP@Hno*pL%_c1|w@dANX_KwDM|*Q^u3@7dU%hHM;6Or?C{2HqNzaeU2MA9V_x zvv=xqD`fEm{hXBE>j}A|QJftIZh`Nwkb0__hTKE~>!z;t+C1K_%otih305V*Y4%>2 zN$lcpk06^c$g+Y^<}Cpz!gnDlv#RNZku)V~G&VTjP^flfNRIO3(&OX<+8>m(tClWy zqg6=C1}xv$6fLy;Rr6`&9Yv~cc~9l7dfDJT=`5~u$&VJW4;m$Q+})Xt05GZ)torE# ze=HjN#}Em&*m51M?&g-Exj82aP38RqP{aK!=!wM(Lfn=@p61@A|{UmAw?yW6~bImg1`hF1=0EMMP`wc z5!x_dxY9YDiW&vI)o>cLVkZz0B`Al!vP>RnTVXFR0-Kg0;hyL5%_M13n6_*r?XW&IbpDp*Mul3tU<& z-H0XVc4;ed*h#e1RMuCY_e3bglWhr!&VJSV4)tx)OSCxk{Qw|1n9J3RBo?c8Zp#)2 zB@=Hye)19g2N2Yx!Yjt)0xCj6o;GHdJ{yN$fBYMkhKW&N?{s@{RcMBG#MWL_Ggjvz zsd>DO`x`BifgX*1j`KeCW!m-dSRuZ}Hcbm#&$sU$^lbvdu)&O?C7){1%FMTpl_hp2 zQEnc_){I1G`~ye)m%r&4jzhL=bCbgc`F1$0L@T{MXwMg9Mw3g?o)9~X$pZ`A0Vw^D zlpQ3WmniAgb)d)!Q@bCp5W&KB5qghz>D7#wk?H z1ee_TV2n5nWE_kthOo;nDNuT3B*Tn#t`pyowVBMo-ZA%L+mf&QCC>!)^0ynjfC|nR zC{sj|^#c<)YZf$ZlI zJCHgMfa@9a)hmJiT=AUO6T|B9- zP4I1P<`AL0ALRyVPtQU7H~QV5e6>?gC7IC#jLv0FTF9@@?KV&`Di4snE^{7hsd*IP z>8XyZg?%j|%39p(N8yE;BzW(_=3{?p zE2)j`?N~O^Cq1G4%T^f#4fmYhZ-er$NiQ%HM2J0lr6|OEluV@aMkdoVe+GRBa@Y}g zX%Ctp+HAk?=@V-xB7Gp~{%yq(l^aY&*?$vl~XSXx&1Wl>Z8?UoZOYA^=ub#@_t;pp2N zg01=vjF45O5E?$=?!84sxl}1+{IZ`2lQSKgIrmg5((Xa1bg|EYv2}8k$}F+n2hc~s zC)6S0bb;+5!hGULfn!eWqs%KOYim+Edz*V-(QtY;PgP&nWwZDYz2T)_JwjXalbOW3 zWP&$SlCV%bP&#aDm?m=FZ!yNBuTVVp$o;b99$tDX<@H)!@w`zvM&V|x^2w~&n5tbh zFfy6P6=d{vw0AVv)2?O4S&ZRtHAAQ2DEI7L?AXij(7*ox4C%%V0#^gz-BWypn-6m% zIpIwG|E-5mH4#S}o%=TEgZn$BS<`y!hReB@nP81#hZz2k8aGGS)=^cDMVGE{R+qOW z+H<8Y{B{*bG$GtVLxuA#jGv}{1J0qdjOPPvFS*c;B`zs&Zym>anrM47iX?XDml-sT zm(=b1Q4p*mg09<=YwPg`#Z74!UQ0yjNI|}hmm%hPo}1ZSnefb={+1GJo2ddCPd;o| z6Q)OTuvGWEmg=kejhyb=&D~&OIXh?PN41%!gTW^`-i^W6o7P2ivLSUOxmby6F6(K4 zVobpq*L7oAw}}dqOm%=hfHA2Gi0$_6I+SF-tS#G+`3w3%V)(gx zeg0OCbpovpSp_AQpL+)y8fC;m{rp^-%AVXBEHV|`O@X7Yv0t#hGBl!0{p(BeV9Kv} zTlr%er92KLhhFQ{_Q#S3=0ZW~xP#a3vu5K=e}5c!r_iByH9Y(JW!IYQu45rD93d=n zx+-y6m+RnWZ1Scx`9M94Rfrc!IG z2`0|$z2`Ue$AzTas4?d0xQ)tdps50jo0o;0DOe?{*_XY2CfEucd@G(>Y^o&Mv9=V{N0WpGm;xBE zxCThD{P32HKUV9~j{Ws{xhshT&ZV&SlqLRpE$pAjvdy(KX4J$vid> z?d0pFPx}(S;l4xoQuCP3HA#`Rd&QV+lg*?lBkWkmAy|P_4XEcl*eVy#U=6O73Tok8 zKTLz)qvpj6&E0BCiH#ZGpJr@g!=4qK`+g_I+}#;$BcVqq{<7dzr#OxI%Cop9Jd-r~ zsxV2TPNeG2-F*|v{YXdG+ris*lt>bd>bqCN0zP%JmaU}Fwr7^2S1%9FtQc$iB<6`V z7%9J0b^``TZzTzM7Iva=wp!L)dWZVPHezj)mY)#4rHIyD>D*)oHcrNHh8R3Fs?$Q^ zk-mc{?WAv^W7DZ0+7T4%?Z5-KKL;o({LBm=-TcY1qEQV?b*Jr?fGvSZ1B|5u(|mj; zs;~D1Q{2bg?tPi5{k?z9`!YMO;baQS#Lcjn0Jrij0p=Ktb=B2%NZ=JK%Wo;$WG&~h zBKfgm`RF)VC$i0<7MVsjIZRukbVCl1VmJ>hWCe5TsI#s%U<1rWTxCc8d611hk=cMho*vyX?+r!mKLElG#fZ|92!|TiWp9+}NxoMbAEl1+>)>j3VU7d5Fo~Zs zs5*lAWdbVUwv-L3nKKqDGS_8V>gY7})?W;WuPcsIHYEWRDRt?UW5Li)MG&_B!3S6< z=%c2%gPTn@qH0?85F%pwYG(NGByZJCfN`fQO#}kR4y#5ywW6z4K&ZueTd(MDKm*!Q0cXVq>Y}UdX*1fyX?E*^nx^Fi(bnx zUK7q3B^6}<9Hz))UqfC)@*pgDW%%>&-IMqZg0+k@v=h`GkjwQjXq+i=GWSx6cTT9&!@ znxtv8k>6YTLy22Q=|!(UdK+_N`zeF33lt-yNmg`aV+6}T=zxi5UAtgL(g8qz57a0M^6if(z5 zUi|~`_u%ww6>w?9Y5u%2l9zcH0f53cd}+L8X1oP9A;3Msmr?l#vkTj;+XFV@s&RiA z@a8&5Fq1B-Igy{&Y=}As3Rb+KtUAkLW+Mdo`s9e!M}!d zEl_FcX)^QWB)s$ZLBi1ZWv-328~%;btBh0K!XVDz{p$jM#^Jq(ZAGj78`tUI~LlS(MA-JL$ci^EVjVX(nG{C5G zKA-OI7zB6;(fv(43ErshLx`{2wyq(Iwv>pJek&0pA3S+kX8)`w>TZo=o9-#J&>L4#rVXx$_4m7@ec^9u=sc*cFZCR0 z7qLPy-eQ06ws_V0d2U{gCVCv=hBX}Vf=@GAl*Gvck8vT8f}^9Kf8i8}VE*NPqf!em zeWy5+(^?;A)|30rqF5NEZOXd0#0+c~iwtzZ7R1SiY9k{Kqn>01kZt$LPTW24PIEQ_YnFQQnx7i-vn_w%5ikqY46mMld6Kzkm&>~|WB$y%tKx;ZLv zQEv3r5@>&v-}V7BebyDy-58=N*TU19PkXI*c6HP;>2T2&Le$a}O{L$WQ+56*^aQ*R zY3`B=`)?-PR@)1jnbQM~w3O|-AD=11#hd$)cW)pg_5ObHFZnw*!XFE1MyOK^vZEqB zJSqyUd9yZPu|4aVWRCht<|bjtG%1(nRGx>hTT_nWp-!-Wi8A>v1# z;qi#Au5G<;cAF}WMW}n>l>h7jhfj%Jg?eqdR5i@FXYpF5En+=)pI2)nsl?8{uFbi6 z5t;{N>Op9IvUjWuFm@J21JHi%mbRW~0k88T+6d;|eNTp_H)|)UCv9Jp1UE0@^&7P-*YQfE3Da)-L*+{0pw#O;8#ub=N#Au{liX{{Ga%vq_Lu^q_N|&TL&%~)BZhbr*T&HRHpn~Buh5B>s5b~Hj^dl8B74tIwOOH9BnmBu^H9` zd~95idIJ~*7a>-PWH(>inrqZNvfW<{*I&Th^r==K6IlKMcp+8k#;KVmUw(fUsnyGlh-tk0{X<0fb5nJ3(|^ma9Qj_Lx6$76^@0fy zN$6(;t3P;ztV`TKh`fJf8Rkx0@*SUet3+1Do15}HNm7+2UWNS$*K&pZOC2w>;dP2_ z`HJ?)7dh`_r4-Ic}P1bk45}OTGjqRt1x-_~JD>d0i z!7qH#`JXv;`w+MZlqj#Cuhb0?5$KMx){1x?{x-B=_(~1-C_Cq5hjwSp!xawB~P6A3qA$RZTX#f7p_XmdVzlC z)N@q#!c#AXV``Iq)}ECTR(lq>)|PQ5s}H{t z-*{U_x%fTqWFV2ijx~v-Xx13#o2lGZdkf?QcVIy(ZT_j}10w1;-qG7;dvX7LDkx3( zoRTYNv8Pyqg||o5_2fg4H8Ev_P$T{G`nFfTgH8{u4e(^uKonc4zOK49>ex2dgUv<_ zOMqo0?_)B#tYFQ&S?_+q?!(~IVKj;h^WzEKU0I=el2y&r+N*g#0nx-ZTw!_b zQ>239O7ngX?Ky9^xH(M*>f5!y78W{fJ3djVOc}m8OU$%1BY86*oQz&qj_W4N6J!H$ z@}DHwUg3F6sHi!lcu^a*8gf+X{mwl9?xGZIZep$ZE!no&h<3)J6JYzzaL8`C*Y1Ji zy4`%uhgvpS@6T+~&^LI^-R9JUDs&vdUbZ?A-*3mtw@l5Zm}ON}T`rF9W8+|zx1bBl z4`{(d>HOo_9bbxjahyCkg#Q#4tQp#YRqDqE$9l*>Z!5C5oM6f+>mqDE@BXHmMoqQ( zj3nl%U3`80xS4})wwozUpJ{bDUe;}@D_-KFMvQTqH=1`G^i$T5FVQ|*23gLf1j#)*fdSmM|ID`yBsq>)lPRNQ(3pU-k>!1A&r1DtL7id%J zW#WQ59~b+#HOM)Sq!e{-!a=0khj_AXsDbbNLS#_$x8HBRIYjoS+wKYU+X`;9Gmo`^ z6DVe?lFc95A0k$_o}NM{*PNzlijAKB0WRoopHr$#d;er(xr?lA2B*BiGZ6^8M}U{X zZbSe~MYT4}xt0BTtrotSUSgcC5alLDsZqzM&WBeoJPiWABC&CTHB9ky^@OW*P$_|n z$>M_}>3U4^Y=@A64=752kIeS}?Xmx#Ui<&|iuL1DUatnlpl@Mh2`cNg@zE0%sT)63 zH%qb8lYxvhh?*Ed?4f#{)RT~w>0P?W#0L{ke~kyo^yIYxvMYd zoDVZTzYo{^HHQpt$zoVWWNl$H@tSikqo4(wDSMIOw;X3;u(*mR#(k0EQ zULX!!=ybU@j`m4_oJ?;G)%?yIqx+}~7n=~hA{#4^6H+mm+z9D&y+w#7xsoRPc9G|0 z%w6kirOC`HakN{4oUNSjw;hcUA(vo;uX{1;r2yS@H(Z!|A;~f*++G8xqYf)dtJEtqUqz!0ww@!fTUN?^|6SYmtcK!lkqREBeFW zGH+QpO-nP!*!9U#=zD~v;X7T(yZHK_n=b-01<(L^_E@$fI~Mm}T$yego0iUP_TStr z?#}@oA!QPFZx$r+KE3+Q0U$+14vxqkrEnc+jT}{w6=aa5Ypdk<9HsdiM?M|!4s@_i zC&ysOTM1RXS~{52Az8Llw6LYpXdAJtgY!#wvPEaLElE?Sa6F?XJN%BR1h2jMsQhH^ z7?QZIDE!ImypV67Hz8=_Ul_kyPu!om8wQN?u4TY!LHSm5pQajAh}DoS>1x4qU#iNEky?} z-tr*Xa=M=(%Qi&Q0~2ZZw*u=^FAh)qGX>!6rKX|Ual2ot;0T_>4BjEFmKwe&!nx-O z3(o@W;@xF?=Uoz23RyD@nM;UEM3k6hPcb$y!dOaAY(I5bo0@Jz+zKES%U^%WZnxkj zsTj8s7>n6gz3d~Agpc@cuBk_SBC`^>0=|=gTHDxR%wJwjvy*+0KF-b>^d(z042#k6 zxt6-i#Vm!>|AhsCzzyT&R5NxJxlPDVIXa!-Ft!_gn~*X4Rq}O!diWM$WKvB3q94}i zNf#=bo}78yMfW9YMd{&li!vrmakQ~bg$oVz+i}U*Tyx3o#I-YX-FbyHYSJ` z1kp{j2+?Z@hD<`#V00k{iJo8tqj$sTqC}4}dN+CulYKwWexK)k_j~O9ef!V%_xPuJbz2hXsajY{80bQlm&Wm|!A@K59zveg&3?c?8CZ#24;{dAbE6SF{FH zR-YueI3@Y?V3ybVfQ_>Re3zMYJHwARkwhFT0I8L|ct)|IlXD@Xq5|^=9_C-0E}kNE zOJ48!&4zcHK;~CAGXwE`Xqf% z=H~NV`yZFP+F5?JKl9aj%<}jv>OnH`ArJ5;RA=KLsdUc$6e_=tugGroiPEz4*&Lam zk&=N5xb>yt@69ah(+86sDwc^?b%X#KFkcAP=fASVA{<$P3)R%-@skqKK{qva@g7gY3s^6 zkk(9`e`ag?W9|Q95dSoerXaj4yFX8_A?7zVLciFzfV!aalO_K2)U#^gn+xKI2++m=z0y+blAy`iW* zy}my5bn1rlm)Ku1@9)R!QgEMtxa($gT$1Y9lg{RURD@u8HaXO>G_x#Rw$6a@GdHRD zdW}X@G_(F!1BHa>LnSSTYxI$?ug>=AM$^A8x2^P4LQ z7F!5?L=VS773?K}zSNXVz9xQM$0C(%Se|4{UB8>meIlWP)Pv~H+5KKLTIX+K;)J%# z4R&044^9t1f7&+iR<-@#ZcD%tK0L}I*XrBLu@WyUH5obP1tk*i=U>#Ah_rj(r(4rt+-I z{zxAZdi$Q(8oXWNm)H^^Gbob*P0P7amF%DVDHo~#rWZ*Z*60L;kb8)L4s#H_@?6_wUh3}(i;kaLS!iod)q0DwL z7B_t&1>G&^HEva#WD~SJw$H~BsIPL-NQpDkXcal7BpkWoqr=_~w;YXKD~bE8@zs$f z;52ZgHsE0&Ak1c4X|Qkl!=}1A@k@D3T#mzO7pO1wLCp_@>pAZCdG6`(R8;ldIf%#J z?tueDzEPFE0-zYsR8S*&iO74Rh9_(DXQ;x-^r6>%>+_G0m5622b;*9=1*hklAt}cn zZ~7IVVfM=Cq1)+*Jevv^qfIEBiZ$2zjB4!=43W(+hxH469+f#*Iv>|N&SdZK_ZV{5lz36zatScSuOC#M?DCPTAbUI^t>)^4sptDgw4 z-Am02_jBT|%-WBROTLz@LbmqJdikMkY08#vaPW=$GZ}62#LK@%bRU&{wFyO#{0L>% zsor#KMDx#dxN&`6=w1?T0$?g{yk^T0VFCK{gh0T^p$ByYP1A<@=Zx{>Q1y7{uIkXs z_i8{S!PWb9L3RJ+7O!#C=r(?V3e74QGQjP)E(4y0R_UK8#y^mZ|A*GcEtxr)@{IP^ z^DJ@fdHVS*7SSd?k-vAl(|l9i@Nvjg>Dl9Znw|ZbcH#%l1Je6K&pET5aJr-AWW%F9lCxJvPCsS?*aN5PQhK`!pasByy8P#l4aJFE=+GE7kzc6_R*kA#IrOFY6j(y=TAJz#f;Fx2;!x|&AE(~b{1~;X|upunTt44 zc{!T5ZKR49>BqggJ2pkXV2sOCY*KCRis$yD_vL_6a6B!Rlj_9SxU_UcVuKpmXM}@7 z)sYbnOA)vj6(#_2F8&BcI_HgxUs*r}Z(00e#h969Ii#*2kt)a8MW1V=PS)n|cgpg^555M&T&sL$Uwj-OJXFyP)lQv$#4r1{ z%aE7pLO4JlG0E7Hmax_exoS%CRlvo5k0P39pAE~{+YP!dJ^3!Kp_Gw(_(&hd!)e}D zye{0pj->Bhn`N%&|GGYCGUasYe4JqZo@qYDs(0^0Zi+qDGM=j6|20lAy^!9Bc9N{+ z70ZR%&nGFGvH{Yv1g~8a_4QCj!zRdjYokVtVylxToJHK+ zhuczB8Y@r3i36k}`$A?KHbD~F7@CUmhr!%5o%KJ=#TKN(yoIkg$YwkGR92?_Tpf0f z8osq(QdMsU>g)|U?$~&PP2#HVIr5rmIsC#lUB6D)`Q9)uH|nBeRwk-6`@E4`z@ef8 z#qx**kPeWNKio(g&#>f^Ww2>2Snu_x?Wk^$!y!TuF=$(a`JlqXm>Gi`cavPXKD69x zDl|%-k@qxA7rqer&4r-oD>Ound}MjuzC(^ryTZ}c;C}2U=fkdxhT&Es^rq!+JVf&4 z%sRyJiFD4(wTEgpo?+VMgzKdQ?Xex9=bWwiF_74!uDpBU9dsZN$m(SY6u6!+yex)y z?As64Nt}Jg*{1Y`*^b2ys!3w5GkdUhbIHY8p}@LThRW}uNb#>qMSg{KpE6V@FyG2m z?lR3F)epEnadhOS?XfE=%^=GA6->4l=3a9joU#>5#%8(JBOa-SHomn5zwa;G^p^8c z58H|HkHO->_67C)jIrfk%KiK<>O<~%_fxnnsVGmQzadp5WsIKFL^10q(VBUi{+SH< zD=G5d^$(aof4JqMv?Zv2LUdsAez^S_(3Z@61d4A}36&bLy@-o)dF$JogO590g>Z}) z%ts`6sVnz!F~%;`V9CaNl=D})+21|wz4NT! zAScvi;y_vkGS@=6V1wiKk5rY6guJ%p>29VZqnoiH?yGX~S4i49%Xfg_G-{ICctpHT z8hx1&!(yb}pHQfJyGF(6QZI=2mdP76y|`FW{*~ED7)EE8>!=#gmPUUp6et3&_Tvf4 z)q6|EV%gAa6}Cdw3STPz`()dlS4KPOGRswKUxQzd5gG78VcvI^fE^Jm>g4rdiN-E= z`d&LXiiKG^{(8+KT5$M2@u=v zni`q-mAVwk8RF>D+Q?}Fk?veQhh;m_P!JG9rRk7Tq`P#(n&qg6HmxADt9leQu!C_RV-C=!vLr;t3pgE@l}I6XeHK z8NcVUXE9$qP5kP5wCf<&wxUyMeVfWn0WP60eNDtlhkl?1#is09YyBP*uPxY^FBC0& zG>oZzSR_7pVYp1oU^8Ls3RiFb#pVkP#VDzx!ImBsc&~V!o6tws#+|(%{@7O3#IkVk z@!d(gI{1-ko@U+2QYeFLQs*1R<>YZmJ`$50tAI|C2h+uxX6K0qNFN?}*6R;6CTz(3?Xzkbi7@Y7Ib%EnvbY825^!wHXtzR8Ih+Wx%&Zj4RwMnk z*Nk?_-}a`YPcjU(j3APnES&}7G@EEGrzaG_=pV(&Zl+f;M|#*xq5GQK*D?1A6;n0o za#uV!<|ROxgg_uSMwg2WZb0Xe=x4m1jD3_ngfn{%APxdVq(W`R@{d0Kugc$G127OP75s$ebDoJa{_R(Ms8K-rV4LA zZ*$RG*Jm7##)_RJMj)Ve*Q*!|J;g zZm|5dT86J4UrhtUbF>|}^ER^()bIAv7C&?{>$AQ1R>G)#o+0l61Uvgt;BAzjP|?w( zGlPJHM!-l_%+_LU8EtjIj^mT5tqa@FwCDaEyxRFXL<^zkkg^<@oq$w3~Xzy9B__LsSlm$ z%}Wq6wuH1ywLD`a-Lq3pYXI`@^xBrP5Y1WeIYh4H0(DB&$XZTU_pLuMIZ75m&=w0UKVm`mM2kzlF0Tkzle+%M&*Co4?uE;9(QV-z9DZGas0JtHue@2U9xE>#Sv6)RAtP#3oJr3k)z1I1{cRa)fgdUb< zsJ@=tYzo`&0}0sQRxub?XLq zKMFue?#9y8gf568i=7{}fhM93AG>)TSEVi}a5T#g5UhtSW>eyi)?nx7!c)qf^2)m# z?Ft-?bsyU*eYR7Ks|3DrwXr_1?A{Y%>ZIi7=n8G=62;HDz^QyWaklCHUh6D9dR^BSD(UR{bB4TQDRjqE3O_yI&I!Ti1@M1LQDYp*F#yqrc7$G#PLZCt> za8z^+JaI1GeR`v8Fwf6mt#E|Mw$NlTDtl`l5v}WJ!Eo&)xv$8G)zrIOBD!L~p~a+r zF^cSZ5t;K@^iC?>mr5$roZY7OK&knqFG63&WcQ%0can(Rd-BojAGN+FMN6g{ZN8AF zxmJHMYU0NMB$9(^7&VCnVz(N6PPvsD9Z0q~yl?Vm4!6^fE$+bC{oc92MVW-v-ylY` zxxXs9Y4kwTaHN^zrL5s;J#~_*%9W_wUNwssetnS-(Td~CNw3S+Q01#wc=8*x3l8Xp z(8&wpOXLKf%(kSxixa#2%p|uVW7MspOQhOKJA`PTECq8WEuxCidZ$ZM>%S60_rVcTnUa1)@hP^s#VR2Hf8-L3G z{$bF#IJGPNr+D>Oo0m%DR~KSD*#h$B6Wz0DA9M03?NV_sG>w)ey`G{XmvbiO%4DKXIi+ykX^6Q4p}@=0d2(;_uD2LA>{!vLy-YWh!kzL9dR zg*><8YAiqU^M3ygQa(K_zNt)ecwE$=(-yQ?-WL8d##H?m=eiuH$LaUC(`bbcEXo3c zi#_WUmx;SOXXhKD#15Hl(VinYz{?h-xZiWQ3FrLaQ&8;fguJIm6TYOBuvGI4keH5w z^s7A@i^N?vn_A+(y+T8~o2ewn@_2qZfEACzDVx0>Q;-@u)5hO}P_CuDJPq&}eI+~d z$*!#V$i0r*+NHoOBo3M1i(qTJrFhTh>$x!D?nV`n=RBp6-H`>2Irc9;4z1YuShM1} zH^4vH(YuX}Z;#;4@ax*J_*hBXe4^KeL{CDc)ojHtUnNp1tw~+^9s6Jwlo>r(WQi^XUI71|m zax<`S@mYPs=wC4Rzk4VC0T1?iHRqvpQkiiIqccbbUq`%LgtKe?iBio3dax;4ksAc# zc%2A3SAFRBr2ncy&x^e(f*U~mu^u>p7V*%5N~0P4oUe3wS~xjekpZh8C@kDOF3A1} zOS(7M+2k+DWDAJDz+(77r+2Y*`v2V}pXnbVG|C6}HC5;?wWtp)70QsYcdb2=5r;yB zJ_Vw~2@*{^Jltpb)t2jl-!>j#&B`5;$u~IHUS)D$YTM@3%WM;Xljxc?A5jEcr%U;I zqq`fn%}#6xT-$pJ5Cd6Aw2@wo{zi7jKXwSo<7>vf;Zk3yO$?Wu0QA$XYzV1MKf#D$ zJbAK=2fy0w3NK*;*CxGnaJxWkQ5QN=qYlN>;lo|GY}j*+uOldNMmA%}GzzrCxak6Vkst z1c&Z?#LJxDEr2Cga^~5WIXod@?*crs{jLOQ009KZoa^M;531aXwJ=eGb4-w{deV9; zWc{E#6ZziLAe3tEt2)sSrj>@QFcmxAC5ipYZ6!zUx+p|)CZ?74U7axU%k$+l1XZl9 z0(!Boz=_ax6H_qkxWAm$0@2G*`&OXec1PFFUB{EF`K;V*M8A$cs_8`aH)ySj2-GQ# zWfQM8odST{82I7FlSrY~P5>|P&W-pHzL0tD519v6d*18`Anaj*zWaGo;Q!gHohhwB zMn?M+<_a5M<`Y)EjCj7cAAZRl7AV6W+p3KBY|B9Aw~SZ+7{Z4D(avfZaz!5CNQdn| z{+Hp7e12bACJICY|2b;Jzf86G(cL;~E&z@6*MxxsVJ8ad-km8sUel zh&DS`%|z4A_|>zai%Z5?WEmo2C-F{y8e4v@gXP4dZYI%K5Q#?>8$5*GGg2Ayd*VL; De#Q-4 literal 0 HcmV?d00001 diff --git a/assets/images/product1.jpg b/assets/images/product1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..f092d14a68dc1a9625fa155808946db0d3a384e2 GIT binary patch literal 7733 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 literal 0 HcmV?d00001 diff --git a/assets/images/unauth.svg b/assets/images/unauth.svg new file mode 100644 index 0000000..7cafd60 --- /dev/null +++ b/assets/images/unauth.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..8d4492f --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 9.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..ec97fc6 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..c4855bf --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..1e8c3c9 --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,41 @@ +# Uncomment this line to define a global platform for your project +# platform :ios, '9.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..567473e --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,117 @@ +PODS: + - DKImagePickerController/Core (4.3.3): + - DKImagePickerController/ImageDataManager + - DKImagePickerController/Resource + - DKImagePickerController/ImageDataManager (4.3.3) + - DKImagePickerController/PhotoGallery (4.3.3): + - DKImagePickerController/Core + - DKPhotoGallery + - DKImagePickerController/Resource (4.3.3) + - DKPhotoGallery (0.0.17): + - DKPhotoGallery/Core (= 0.0.17) + - DKPhotoGallery/Model (= 0.0.17) + - DKPhotoGallery/Preview (= 0.0.17) + - DKPhotoGallery/Resource (= 0.0.17) + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Core (0.0.17): + - DKPhotoGallery/Model + - DKPhotoGallery/Preview + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Model (0.0.17): + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Preview (0.0.17): + - DKPhotoGallery/Model + - DKPhotoGallery/Resource + - SDWebImage + - SwiftyGif + - DKPhotoGallery/Resource (0.0.17): + - SDWebImage + - SwiftyGif + - file_picker (0.0.1): + - DKImagePickerController/PhotoGallery + - Flutter + - Flutter (1.0.0) + - FMDB (2.7.5): + - FMDB/standard (= 2.7.5) + - FMDB/standard (2.7.5) + - path_provider_ios (0.0.1): + - Flutter + - SDWebImage (5.12.5): + - SDWebImage/Core (= 5.12.5) + - SDWebImage/Core (5.12.5) + - shared_preferences_ios (0.0.1): + - Flutter + - sqflite (0.0.2): + - Flutter + - FMDB (>= 2.7.5) + - SwiftyGif (5.4.3) + - url_launcher_ios (0.0.1): + - Flutter + - video_player_avfoundation (0.0.1): + - Flutter + - wakelock (0.0.1): + - Flutter + - webview_flutter_wkwebview (0.0.1): + - Flutter + +DEPENDENCIES: + - file_picker (from `.symlinks/plugins/file_picker/ios`) + - Flutter (from `Flutter`) + - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) + - shared_preferences_ios (from `.symlinks/plugins/shared_preferences_ios/ios`) + - sqflite (from `.symlinks/plugins/sqflite/ios`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + - video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`) + - wakelock (from `.symlinks/plugins/wakelock/ios`) + - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`) + +SPEC REPOS: + trunk: + - DKImagePickerController + - DKPhotoGallery + - FMDB + - SDWebImage + - SwiftyGif + +EXTERNAL SOURCES: + file_picker: + :path: ".symlinks/plugins/file_picker/ios" + Flutter: + :path: Flutter + path_provider_ios: + :path: ".symlinks/plugins/path_provider_ios/ios" + shared_preferences_ios: + :path: ".symlinks/plugins/shared_preferences_ios/ios" + sqflite: + :path: ".symlinks/plugins/sqflite/ios" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + video_player_avfoundation: + :path: ".symlinks/plugins/video_player_avfoundation/ios" + wakelock: + :path: ".symlinks/plugins/wakelock/ios" + webview_flutter_wkwebview: + :path: ".symlinks/plugins/webview_flutter_wkwebview/ios" + +SPEC CHECKSUMS: + DKImagePickerController: 72fd378f244cef3d27288e0aebf217a4467e4012 + DKPhotoGallery: fdfad5125a9fdda9cc57df834d49df790dbb4179 + file_picker: 3e6c3790de664ccf9b882732d9db5eaf6b8d4eb1 + Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a + path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 + SDWebImage: 0905f1b7760fc8ac4198cae0036600d67478751e + shared_preferences_ios: 548a61f8053b9b8a49ac19c1ffbc8b92c50d68ad + sqflite: 6d358c025f5b867b29ed92fc697fd34924e11904 + SwiftyGif: 6c3eafd0ce693cad58bb63d2b2fb9bacb8552780 + url_launcher_ios: 839c58cdb4279282219f5e248c3321761ff3c4de + video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff + wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f + webview_flutter_wkwebview: b7e70ef1ddded7e69c796c7390ee74180182971f + +PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c + +COCOAPODS: 1.11.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..d1d56e4 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,556 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 51; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; + F4E55937107BA5306BB95CAA /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 505142890B9BAEB822322951 /* Pods_Runner.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 2324F60B1D9EECDFBF46B475 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 4D2B1C1844A116A91D1F2ADC /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 505142890B9BAEB822322951 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 5280C790285D926E005DF18B /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + 6F1D9381F9FE45A06B6099F8 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + F4E55937107BA5306BB95CAA /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 88445B605A3ADB0F86AB262B /* Frameworks */ = { + isa = PBXGroup; + children = ( + 505142890B9BAEB822322951 /* Pods_Runner.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + E24870FF2A93B633776EC7B4 /* Pods */, + 88445B605A3ADB0F86AB262B /* Frameworks */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 5280C790285D926E005DF18B /* Runner.entitlements */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; + E24870FF2A93B633776EC7B4 /* Pods */ = { + isa = PBXGroup; + children = ( + 6F1D9381F9FE45A06B6099F8 /* Pods-Runner.debug.xcconfig */, + 2324F60B1D9EECDFBF46B475 /* Pods-Runner.release.xcconfig */, + 4D2B1C1844A116A91D1F2ADC /* Pods-Runner.profile.xcconfig */, + ); + path = Pods; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 5D77B75D4239A29236376CB3 /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + E7953A05086AEC43D00BCA7C /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 1300; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 5D77B75D4239A29236376CB3 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; + E7953A05086AEC43D00BCA7C /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = QQPXL8D953; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.tpsadvertising.digital.birzha; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = QQPXL8D953; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.tpsadvertising.digital.birzha; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = QQPXL8D953; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.tpsadvertising.digital.birzha; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..c87d15a --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..70693e4 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import UIKit +import Flutter + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..3faacd1b43d448b269dd51d4e040744eac9609a4 GIT binary patch literal 114755 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 z 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
-;Gy-Q#!^seFJ;e|RUVTd!yhc8-*?2~2Osk}#> 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 Z@-KzMy^*yz7b5@w002ovPDHLkV1m(gL1q8| literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..92a0f1e07fe6ca117ee02aee45783d6562d00c71 GIT binary patch literal 1685 zcmV;G25R|B1T=d z51K%yn+U$K#4k=!XaS=*$Q<~xIUyU0Q^yb#5TwvvdwuqQ?qDf!Z4dVxiwXY^w7t7L z_v@ek^W6V>DvU9D(L(iq1D+=)(GwMu=!uF+v{$&@tWp`oFpM07%Yt^foIlna*Bhe} zQ!?am(?^52{^E(Qjt5hlLH87t(SrE#qx*=@@15p)_)FbQ6Aj`zUOZe8 z@Pdh(L5a!f6zhZLhs?t$fo#^Wu|_JMN2RQ*hV8yTs%)D)}A<+H(3< z-Ob0NHqMF+-T6t1$HQ@)i@^wqlZd;esjjc5L!${3JtD#w85_TVKDz#w&XW}_V>aW~ zw%*d+=F}x?uGAdw?tF+D%!t@YhCAEu`WoErcFKbG5lor26>?lsV1CQI`by0S-)?F_ zrKXuvwpJ*O(us1@T0NLDTPqlc^9^x_UAnfms`P2kqrhc?aag!P`Z=hf z88mcPA3IZ*yD9d71QcNkwDq>Fsy;+FO3WJUco< zcpqsBiP~}v7iAlL=i4Wmh>tYn7hU(8U>rA7SA8f;7p{?lR;X04 zo;2UOoG^DO%VEedFZL?)VRyRUe2b$&ywh@Z_jfn_ixXlDl|>nmrYRD;WSEz*p1|F% zebBjbi_LbmZCEFZo6u7W8Db`@KWSSzx`(vMh zQU8E5JMY5f8y!9~0!<@ENpS{km|AqdI65puZ7s@%IRW1ojc)B>L?$UtZ?$CVbs=A# zaeQP}8K$AIrUEO^?Tdw&DQzeR} zq9OF!5YEHpiisgh3wEgft<;p+Y(>7p5Kcz653)I%DlT0cYEAt-lA3A=l_(wu8e;z$ zx0sl8$k=OcHQWo%*uz%lbNX=Q!BfA27}LI690$7jZ-t~fW*Bhi>}St!$6MFVy>+Mi zd$@O`>Xzq6b%v>H3C`K)Jo}mQSb-UCYRYW)D7s~Pe8Diazk{1SyG>bIumqu+GJ5%z z^O*~{{~&ep!!}iEff+W?a?ARli1@(0V!x1YYHqooZjqaGaA)p?d=s}OSb4O(iJbXSkvQ`^ih)nj`-vW3jc^aA!mzVh2$izBCo{dTu^)KRa;n`A+6&QfpA z65j>aovp_l2P)JUD@5F+Nn{3GN;ij;3gw>MdD2fR8g$A7C|`XD4ZHI|g$Co1Kgf`e zI6lfWcrnikv`ISzWeWe_8}6A|2BlY9@m`34-sRaC`@`sy*ljZl0v5l2xK zBRQ5l!OglImu{=7K37l|BbnA|a35T!eroraw6csZ*Tn^zW0RKZt&R8KGL0*1Orj?$ fCeafWFC_XO*fY5#V;${o00000NkvXXu0mjfDNRa` literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..13b542495e9cd3373cf6d7e3ba39b1f64544fa98 GIT binary patch literal 916 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..ea39d6a51734f3bc5552fc00af74c3214a885247 GIT binary patch literal 1159 zcmV;21bF+2P)118^LeM$Z>&x|e{;n-eduwm>z!4Lk^pES) zyXVvIJ+CCove^A7e!2bgnhU6c8-_MxDjr~E9^;kw`t{AwZd!*rrBl=Y)#lNuV%k?`tY#)2Q?$~re zCh%jgo%i^Pl{%3yuXz2zP3G2<&3cXD`Oem39?z7R(JTTE+qI3Yq1<&BY#;f()GWav zn}OV?Ah)g#a(jJL(%gc(kBE7UAos4Oj$gmrrg{2>PTMiBcWU}gI8F$3un-J0$LA05 zDr>ciG%Iu9V(n_>Loz8Q%LaSQH2^g?Z(Mf{UW=#*e^RqmCRaiu$>vyM7#_HI*>&*4 zA9(c@#S3?v)Uh@4`H#W}E(n6)U>36CCFNV(Z1$SkPaAfq>rJYJb^;jGt}8BM{nwKe zKkx4$5DNJAMxR<{WquhDw`osvmG@SE>R>?!)4Ir*1iO)C!*diQVGh> zmGf@q!!K`D1sE3oBX7yrq)n(Mh9mZ~>g|=wdj2G9ERdB5tB&8;Inp3p zJXIJh488M#p$YqUF1YCI9pN?7Sf{SmB;BNwu3YfIFC!9o!ycN5R-SN3PK5T!1@fSM zKfN>?Rlahz&v`3h3v*=>fun)YT778%#j3Go^dCb14r6>RTKhsx+AVc>G-!qDB^*yc;czRLqW7UqT7E(agIp1B%dhBkE?;@ zzN~<*Im}W%BC=L+4!frkQ_LeOigV#3(BPfI(+f-wy-M$R{uT=}J689Jm+Xi)-K|S-G_ZYtW@&KN- Z@-KzMy^*yz7b5@w002ovPDHLkV1m(gL1q8| literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e393ff9f8c38280659f84a2f371bd6c96f8294a7 GIT binary patch literal 2525 zcmV<32_p81P)O%S7#C}>LM4|5c%-SHGGSg537-D<7{>rCi zCtS6nsQYefdC7ar%o}-ikOFb`J21)QhU*u~KN_*|MpW0`J7qA!QagO1$Mer zW!bU8nLJE{@E$OiNb6bSUuGYHrEp>ATwQ(+AA#E2EpP`C1!2U2147{2WkpApnhCR< zIrw&6e2y@FD*f*bcY0lZrVnO6dc!y)HcY3BFiiV?&5cVVUz!0qJ*?;-f8toRhmj1k z@|j=CIp=Ws42&9Edh46JTz*z>q0CzgPUok^Muq(F$yCANsJrzAk~cqxy$}AmA4Ai$ z&q?o}HH>ggWAF0k3W^RTO^?yfd+KRHa5UCdVdX2yVe*q{k#N>Dbr~}YOY>5u#ps@l z|LH}BssH9nEHlu4lV4pL)irk~WEPaaQiac(kr z*xUuF@TZ!avOLUBQlQd8wU(Y0+X_zSr5V7(7Nj~H_WGL3fl6&fYH5UTHS~Mfv>5&T zMbAJT(pXo8sQ~1*GR*@C=dGr$1ma=IzziOC;Vgao)>poInC}-#$$pruXJgjM@^@1W zlXdeK|AbMowbh?{$1K(39ItUx<++#AJ03rn6&ewyrAYC>%w3QM0JUF#=GEjiLBa9H z^*#sLkH8FrCWo?vXZEAn6FwGW2^GLarU2GR8VMXQF4C@swGXlok&tsEb;*tj-0 zBpf{Na`l}jW=0@H4;|)7UIRO66Stjg?d)@(SJK)9aR?#-iB@9bW@Hu*7cnY{ysuCSxCcjfkzpH{UhR6ICcO0A7I5?T?9zsfoD_KB-- zSu%E=fg9Vpf`dy zCKniD3$(_qAAf$eQ@I)mGFh!zVq7~x7b%MN9s4T#X`PaoGhQu+W^qlD+&IeuChNAd zH|hCPvS~>o&Yd0ZZc}7rh3F$YS{va=j#tMgtP9pn0@_z|Fa6=@SHspf5(H}FD;0u> z(^F)vXV1VAZO_W>r^vdMO}lE@)c0RE`jQKXf_hsN9nB5Zi;d~JuqY7=JNBLX~5YOfZIBVOG&hHop9B%Sc#UGIo_pc zTJ^mNVS?y*A*bTtiEG&7wMIyabGe3Rer}F)GtdKY#TN~qU2UT4F#) z!^oPbD-oAEbcw86*+)c$YyWj9>5*u?`*9wCVLcG{qo_@Ud8BLI?@}LRCjf0zhhxQF zylAHF?adm7_E2fLI2V|t8YHU1?wiY&)Fg!%D_G-m2`6tsGiR#Y`fxl|xI(yblxRWN-qUvAaST z`pg8c>i1;6zQvmO8llCAoVMso+Nbgpm0fI-yKXTx-JmTxm@+j=FLP^9Zlwjx=_!w^ zXtd##3cK)NKG^9}9LoT0!XB#H!cpFLFg^-XhDjQreIz zo-$EeoSQU@tXuCcvDf`DVNQ&T4i8#5ClWH5c=8^gWic9d6C$=VbD9%t-?xF~*@3|Tyz{`h zPc9DZZvg9+ntSdiKqGqA)Nn-~mqH`n*k&{Sj=IszkCe$afjj@uUKMrzCbHVB?`&Zi zhLqW&DC|5?`TM_Img~v?3;75P6a3kmKX^!&6@?NlT69 z`EWx!lHXC>KM0AK&MV<5Y~7!MLPIoA9vL$W>%Z+*%-$7$^-yBYE!Fhc`tmYW(+&EP zyd+arVV$KH?sE!Y2jb;Y1Z3#16^5g)$z6! zbJ*CZkQ*PbcJpc@^3-6ABwv9^~wrY#3c51LNrYSLdjbM6$m(K70 zUAyna_~726C`w(xLz zSh3_`)fOITf1T=gml`6aE3N)Gzhp11vaVmMRx-9u1)#Jf9u~oGj8OiYiM|W9w4xdZ n9_tzh9_tzh9_tzh9_#uq=Q#S*k*rH`00000NkvXXu0mjfObqBs literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..eb4439ea340f4ed657e9e6e97a24087d4a554cb2 GIT binary patch literal 4451 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
Z!ufQ?I={>h}K<#z8>VKbq%M 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 ZaCB5-z1pS~|L2MTD9WjUs%1=r{|A8vkh1^) literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..8a6cab69fc35be8d949353a141e4f9447d788c66 GIT binary patch literal 2435 zcmV-}34Hd6P)6N_#7B~= zXoy-ql8Ol`8W8UkK0l3MMmA2FAkBp3r*fMf+!s!uscWr8#s^%Z9hG&ePv z?X<4;99V2{=*zM&$^vOH=*v&x#XtgK%8HXW8`=jw z7(dl#N*CYs0;L zgTkk!RGrV~h#fU@FxE4?z* zu6P5l&vn#4p9ezu^(oUVgmPk(l@{Ks&%>hpQ)E#j4sL%Hp2JL)*`U?S`h%d}wxDnAQmERr$eOk`JmVW~p zgS~$KQ(lZn5SN1-hoo_Xvllz?viX6LAzqg4vF^?>VLq0s&CD4S_vg-zR?9hUzcgL1 zJ^MJPnJ{2-SVTPC;^?-c^{Zo$d|>3hD6FghHrBw$)KH(4*Z><%!9YDceG&Zj z%7exquft5b|M>Y!>E}Or5)fjh?4NhnY_BT(B+lK{*&$9xHOcKhd@XHLIY%U)&htW^ z0V|CJLVTv`cGB{aj!tf-_IUC31P?c7;jK6TNjTHzN3Nu8s^nzJbC?i6|FE#A1bF}L zEDJ6`Y4R6j=0byyo z&cx3>X*jFC**Yt&=){f$ft>as&3?G&h?$TRKu8#j$GB^Rbl+dpYG=%_eEuZk{lg|j z&4H%MF5jE`c4>#s*w-)3N9a=h&!Ep!yXLsNYV7)_9Y{0bu7a!D&HvyC7DA|C@t)Pu z(_i!!$YzmIuAY%GuU4J^X52HOybjT6UWbnmnuX`Ax!F3C>NDQMUL3LoNmn`eNTc0c zA;=F2Vi~+=P4t4q0E}4yA9zF{!NB};#>_=-ZewAC_rt*md(NhRm+BwJzFt(iJJG|Y zK5c4}a69v_rhiz$39B@f3bbp@^aY85A_&a_1ATI|H<-`q3w$gEKeTN-7}tE?GBfSi zxzFc5;jFfHmMuu5iR2dD5afo4uowg3!o=YJ@m>xPp1ahLwESd87ZI{Z38%zNddk_! z7KqJbEc>^dc(4b!TKp=E)qz2z+4kPlg^3ek`hU0C__T-0_L7vU?TZGdf_0Q0wLPA@})PDgCV=*oaoLx#O{An zpEz0NsL_HB%d79reyg;-%h;1GY@QB(+SH&=S4J}oW4q9|6J3E5YN)^ONQhm0wE9LX zdi>&2!X58UUz8FAS3aj$myt^yW8N07Y@I3G-!aHrcYdCgezLvGAVh(f;3cU6IV+>F zJwhZTPf~rlIhX8AjMpB&SohGpz-#V_TIst}7bOQlr#Z#?6}c)p_dtx^gnw!_hWiVH z>y`V>ogJM<`+mrm=-O8Uwyppj3c8L$D;}sVPHd0={o-T)y3sRl0K)C>O$93@JYhyI z%gHl4#bilpAP};w(C!=CV}+(u*!$Yf-RhcP3;D@Iwx)6m%#PAwuc%fZ#%dsUvA#?nCzmCthh)uJ;hUfYTeF6-gE+t{A?W(iL? zpz@YLL_!|;jwKG|dW<`|6{(+~e5y|;pD`}4CkJfWdj)hV-3?}oh=dfgHh^)L3G_+w z-qOvQq|Q!{gngU$*2=KVAopWu9R}sREok3T-P~}e?4=gY|Jw&61``U?Wm5j}GiIMw zmlUa9&vS0tTWdKgg$&69gjjE6=Wkc#vHIClK%Y?nw~=y6wR$u}Pf23nWd4w&%+>0X zBh^{ppBQiYvW7^*IdqSLVn%Pof7*r^M)yjDX1z8X@%QnTjjdQfE(K1NS)WPas`cqnP}O|#*PDaJ+c9n$ zVrAxTTf{-)(oCgoqk_WigM58)m_$?xCMzu>D=pGmtKuwK)N?%c z*Cs%i4^q`I{_H|Et>CSdHT>qp+KdnbH6N002ovPDHLkV1lw9 B$EN@Q literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..679e660101a987953a778038d695d5dd660b1834 GIT binary patch literal 6423 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ffccfb89965f580fe31a9a9dc5edb926c55ce823 GIT binary patch literal 7497 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 Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..d48df87 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Birzha + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + birzha + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + NSPhotoLibraryUsageDescription + User can upload product images. + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIViewControllerBasedStatusBarAppearance + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..903def2 --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/l10n.yaml b/l10n.yaml new file mode 100644 index 0000000..4e6692e --- /dev/null +++ b/l10n.yaml @@ -0,0 +1,3 @@ +arb-dir: lib/l10n +template-arb-file: app_en.arb +output-localization-file: app_localizations.dart \ No newline at end of file diff --git a/lib/components/TextInputCustom.dart b/lib/components/TextInputCustom.dart new file mode 100644 index 0000000..ec40840 --- /dev/null +++ b/lib/components/TextInputCustom.dart @@ -0,0 +1,127 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/services/textMetaData.dart'; + +class TextInputCustom extends StatefulWidget { + final double? fontSize; + final EdgeInsets? padding; + final EdgeInsets? margin; + final TextEditingController controller; + final TextInputMetaData fieldStandard; + final bool? showPassword; + final void Function(String?)? onChanged; + final Widget? suffix; + final Widget? prefix; + + TextInputCustom({ + Key? key, + this.showPassword, + this.fontSize, + this.padding, + this.suffix, + this.prefix, + this.margin, + required this.fieldStandard, + this.onChanged, + required this.controller, + }) : super(key: key); + + @override + _TextInputCustomState createState() => _TextInputCustomState(); +} + +class _TextInputCustomState extends State { + late FocusNode _focusNode; + bool hasFocus = false; + + @override + void initState() { + super.initState(); + _focusNode = FocusNode() + ..addListener(() { + setState(() { + hasFocus = _focusNode.hasFocus; + }); + }); + } + + Widget? suffix() { + return widget.suffix ?? (widget.fieldStandard.pickerMode != null ? Icon(Icons.arrow_drop_down) : null); + } + + @override + Widget build(BuildContext context) { + final double textSize = 14.adaptedPx(); + final border = OutlineInputBorder( + borderSide: BorderSide( + color: Colors.grey.shade300, + width: 0.9.adaptedPx(), + ), + ); + + return Container( + margin: widget.margin ?? EdgeInsets.symmetric(vertical: 12.adaptedPx()), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: widget.fieldStandard.pickerMode == null + ? null + : () async { + var extracted = await widget.fieldStandard.pickerMode!(context); + if (extracted != null) widget.controller.text = extracted.toString(); + }, + child: Row( + children: [ + Expanded( + child: TextFormField( + readOnly: widget.fieldStandard.readOnly, + cursorColor: Theme.of(context).accentColor, + keyboardType: widget.fieldStandard.type, + focusNode: _focusNode, + controller: widget.controller, + autofocus: widget.fieldStandard.autoFocus, + onChanged: widget.onChanged, + cursorHeight: 15.2.adaptedPx(), + style: TextStyle( + fontSize: widget.fontSize ?? textSize * 0.9, fontWeight: FontWeight.w500, color: Theme.of(context).textTheme.bodyText2?.color), + validator: (i) => widget.fieldStandard.validation.validate(i ?? ""), + inputFormatters: widget.fieldStandard.formatters, + obscureText: widget.fieldStandard.password && widget.showPassword == false, + decoration: InputDecoration( + isDense: true, + contentPadding: widget.padding ?? EdgeInsets.symmetric(horizontal: 15.adaptedPx(), vertical: 14.adaptedPx()), + errorMaxLines: 2, + suffixIcon: suffix(), + prefixIcon: widget.prefix, + disabledBorder: border, + enabled: widget.fieldStandard.pickerMode == null, + border: border, + enabledBorder: border, + filled: widget.fieldStandard.filled, + fillColor: widget.fieldStandard.fillColor, + focusedBorder: border.copyWith(borderSide: BorderSide(color: Theme.of(context).accentColor)), + focusedErrorBorder: border.copyWith(borderSide: BorderSide(color: Theme.of(context).accentColor)), + hintText: widget.fieldStandard.hint, + labelText: widget.fieldStandard.label, + errorStyle: TextStyle(color: Theme.of(context).errorColor), + errorBorder: border.copyWith(borderSide: BorderSide(color: Colors.redAccent)), + focusColor: Colors.red, + hintStyle: TextStyle( + color: Colors.grey.shade500, + ), + labelStyle: TextStyle( + color: hasFocus ? Theme.of(context).accentColor : Colors.grey.shade400, + ), + ), + ), + ), + ], + ), + ), + // widget.showBottomInfo ? widget.fieldStandard.bottomInfo ?? SizedBox.shrink() : SizedBox.shrink() + ], + ), + ); + } +} diff --git a/lib/components/abstractForm.dart b/lib/components/abstractForm.dart new file mode 100644 index 0000000..17d9177 --- /dev/null +++ b/lib/components/abstractForm.dart @@ -0,0 +1,216 @@ +import 'package:birzha/components/verifyPhoneDialog.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/components/TextInputCustom.dart'; +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/button.dart'; +import 'package:birzha/components/icon.dart'; +import 'package:birzha/models/settings/theme.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import '../core/manager/manager.dart'; +import '../models/user/userManager.dart'; +import 'indicator.dart'; + +mixin AbstractFormState on State { + String get title; + List get inputs; + List controllers = []; + List get before => []; + List get after => []; + Map get editedData => { + for (var i = 0; i < inputs.length; i++) + keyAfterFilter(inputs[i].key, controllers[i].text): valueAfterFilter( + inputs[i].key, + controllers[i].text, + ), + }; + String get buttonLabel; + bool get buttonIsLoading; + bool get shrinkWrap => false; + Alignment get listViewAlignment => Alignment.topCenter; + ScrollPhysics? get physics => null; + String keyAfterFilter(String key, String input); + String valueAfterFilter(String key, String input); + final GlobalKey formKey = GlobalKey(); + bool showPassword = false; + void act(); + void updateScreen(); + Positioned? get button => null; + bool get includeBackButton => true; + + Widget textField(TextInputMetaData meta, TextEditingController controller) { + return TextInputCustom( + fieldStandard: meta, + showPassword: showPassword, + suffix: suffix(meta), + controller: controller, + ); + } + + Widget? suffix(TextInputMetaData meta) { + if (meta.key == 'user_type') + return Icon( + Icons.arrow_drop_down, + size: 18.adaptedPx(), + ); + else if (meta.key == 'email' && meta.showSuffix) + return AppUserManager.of(context).dataSync.isEmailVerified + ? Container( + // width: 60, + child: SvgPicture.asset( + 'assets/icons/profile_screen/phone_verified.svg', + fit: BoxFit.scaleDown, + ), + ) + : ManagerSelector( + selector: (context, manager) => manager.getStatusByKey('verify_mail'), + shouldRebuild: (previous, next) => previous != next, + onUpdate: () { + updateScreen(); + }, + builder: (_, value) => GestureDetector( + onTap: () async { + debugPrint("verifyMail"); + AppUserManager.of(context).verifyMail(context); + }, + child: Container( + // width: 60, + child: value == TaskStatus.Loading + ? Indicator(size: 0.25.adaptedPx()) + : SvgPicture.asset( + 'assets/icons/profile_screen/phone_not_verified.svg', + fit: BoxFit.scaleDown, + ), + ), + ), + ); + else if (meta.key == 'username' && meta.showSuffix) + return AppUserManager.of(context).dataSync.isPhoneVerified + ? SvgPicture.asset( + 'assets/icons/profile_screen/phone_verified.svg', + fit: BoxFit.scaleDown, + ) + : GestureDetector( + onTap: () async { + debugPrint("openVerifyPhoneDialog"); + AppUserManager.of(context).sendSmsCode(context, () async { + await showDialog( + context: context, + builder: (_) => VerifyPhoneDialog(), + ); + updateScreen(); + }); + }, + child: SvgPicture.asset( + 'assets/icons/profile_screen/phone_not_verified.svg', + fit: BoxFit.scaleDown, + ), + ); + else if (meta.key == 'password' || meta.key == 'password_confirmation') + return AppIconButton( + icon: Icon(showPassword ? Icons.visibility_off : Icons.visibility), + onTap: () { + setState(() { + showPassword = !showPassword; + }); + }, + size: 18.adaptedPx(), + ); + + return null; + } + + void launchControllers() { + controllers = List.generate(inputs.length, (index) => TextEditingController()); + } + + void goBack() { + Navigator.of(context).pop(); + } + + Widget body(BuildContext context) => Form( + key: formKey, + child: Stack( + children: [ + Positioned.fill( + child: Align( + alignment: listViewAlignment, + child: ListView( + shrinkWrap: shrinkWrap, + physics: physics, + padding: EdgeInsets.symmetric(vertical: 10.adaptedPx(), horizontal: AppConstants.horizontalPadding(context)), + children: [ + ...before, + for (var i = 0; i < inputs.length; i++) Material(color: Colors.transparent, child: textField(inputs[i], controllers[i])), + ...after, + SizedBox( + height: 100.adaptedPx(), + ), + SizedBox(height: Adaptix.systemPadding.bottom) + ], + ), + ), + ), + button ?? + Positioned( + bottom: -1.adaptedPx(), + height: 70.adaptedPx(), + left: 0, + right: 0, + child: Container( + alignment: Alignment.bottomCenter, + padding: EdgeInsets.only( + top: 3.adaptedPx(), + bottom: 18.adaptedPx(), + left: AppConstants.horizontalPadding(context), + right: AppConstants.horizontalPadding(context)), + child: SizedBox( + width: 100.orientationWidth, + child: Row( + children: [ + Expanded( + child: MyButton( + text: buttonLabel.toUpperCase(), + inProgress: buttonIsLoading, + onTap: () { + if (formKey.currentState?.validate() ?? false) act(); + }, + height: 40.adaptedPx(), + ), + ) + ], + ), + ), + decoration: BoxDecoration(color: Colors.white, gradient: AppTheme.gradient(context)), + ), + ) + ], + ), + ); + + @override + void initState() { + super.initState(); + launchControllers(); + } + + @override + Widget build(BuildContext context) { + return BaseWidget( + appBar: BaseAppBar( + title: title, + goBack: () { + goBack(); + }, + includeBack: includeBackButton, + ), + body: Container( + color: Theme.of(context).backgroundColor, + child: body(context), + ), + ); + } +} diff --git a/lib/components/actionIcons/searchicon.dart b/lib/components/actionIcons/searchicon.dart new file mode 100644 index 0000000..0ae3f46 --- /dev/null +++ b/lib/components/actionIcons/searchicon.dart @@ -0,0 +1,22 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/components/icon.dart'; +import 'package:birzha/constants.dart'; + +class SearchIcon extends StatelessWidget { + const SearchIcon({Key? key, this.iconColor}) : super(key: key); + + final Color? iconColor; + + @override + Widget build(BuildContext context) { + return AppIconButton( + icon: Icon( + CupertinoIcons.search, + color: iconColor ?? Colors.white, + ), + onTap: () {}, + size: AppConstants.appBarIconSize, + ); + } +} diff --git a/lib/components/appBarIcons.dart b/lib/components/appBarIcons.dart new file mode 100644 index 0000000..8c1b40f --- /dev/null +++ b/lib/components/appBarIcons.dart @@ -0,0 +1,26 @@ +/// Flutter icons MyFlutterApp +/// Copyright (C) 2021 by original authors @ fluttericon.com, fontello.com +/// This font was generated by FlutterIcon.com, which is derived from Fontello. +/// +/// To use this font, place it in your fonts/ directory and include the +/// following in your pubspec.yaml +/// +/// flutter: +/// fonts: +/// - family: MyFlutterApp +/// fonts: +/// - asset: fonts/MyFlutterApp.ttf +/// +/// +/// +import 'package:flutter/widgets.dart'; + +class AppBarIcons { + AppBarIcons._(); + + static const _kFontFam = 'MyFlutterApp'; + static const String? _kFontPkg = null; + + static const IconData info = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData search = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); +} diff --git a/lib/components/askQuantity.dart b/lib/components/askQuantity.dart new file mode 100644 index 0000000..90570df --- /dev/null +++ b/lib/components/askQuantity.dart @@ -0,0 +1,73 @@ +import 'package:birzha/components/TextInputCustom.dart'; +import 'package:birzha/components/dialog.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:birzha/services/validator.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class AskQuantityDialog extends StatefulWidget { + AskQuantityDialog({Key? key, required this.initialQuantity}) : super(key: key); + + final double initialQuantity; + + @override + __AskQuantityDialogState createState() => __AskQuantityDialogState(); +} + +class __AskQuantityDialogState extends State { + late final TextEditingController _controller; + final GlobalKey _form = GlobalKey(); + + @override + void initState() { + super.initState(); + _controller = TextEditingController(text: widget.initialQuantity.toString()); + } + + @override + Widget build(BuildContext context) { + return AppDialog( + title: 'quantitySumm'.translation, + child: Form( + key: _form, + child: Row( + children: [ + Expanded( + child: TextInputCustom( + fieldStandard: TextInputMetaData( + name: 'enterQuantity'.translation, + label: 'enterQuantity'.translation, + validation: Validation(conditions: [ + (inp) { + return inp.isEmpty || (double.tryParse(inp.trim())) == null ? 'formatError'.translation : null; + } + ]), + formatters: [ + FilteringTextInputFormatter.allow(RegExp('[0-9.]')), + ], + key: 'quantity'), + controller: _controller), + ), + ], + )), + actions: [ + Expanded( + child: Center( + child: GestureDetector( + onTap: () { + if (_form.currentState?.validate() ?? false) Navigator.of(context).pop(double.tryParse(_controller.text)); + }, + child: Text( + MaterialLocalizations.of(context).continueButtonLabel.characters.first + + MaterialLocalizations.of(context).continueButtonLabel.substring(1).toLowerCase(), + style: TextStyle(color: Theme.of(context).accentColor, fontWeight: FontWeight.bold, fontSize: 12.99.adaptedPx()), + ), + ), + ), + ) + ], + ); + } +} diff --git a/lib/components/baseWidget.dart b/lib/components/baseWidget.dart new file mode 100644 index 0000000..e904651 --- /dev/null +++ b/lib/components/baseWidget.dart @@ -0,0 +1,202 @@ +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +import 'package:birzha/components/icon.dart'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/new/themes/colors.dart'; +import 'package:birzha/screens/settings/contact.dart'; + +import '../core/adaptix/adaptix.dart'; +import '../new/screens/news/screen.dart'; +import '../screens/settings/settingsScreen.dart'; + +class BaseWidget extends StatelessWidget { + const BaseWidget({ + Key? key, + this.bottom, + required this.appBar, + required this.body, + this.color, + }) : super(key: key); + + final BaseAppBar appBar; + final Widget body; + final Widget? bottom; + final Color? color; + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: appBar, + body: body, + backgroundColor: color ?? Theme.of(context).scaffoldBackgroundColor, + bottomNavigationBar: bottom, + ); + } +} + +class BaseAppBar extends StatelessWidget implements PreferredSizeWidget { + BaseAppBar({ + Key? key, + this.customChild, + this.after = const [], + this.title, + required this.goBack, + this.includeBack = true, + this.color = ThemeColor.mainColor, + }) : super(key: key); + + final Widget? customChild; + final List after; + final String? title; + final void Function() goBack; + final Color? color; + final bool includeBack; + + factory BaseAppBar.home(BuildContext context, VoidCallback goBack) { + debugPrint('BaseAppBar.home'); + List navigators = [ + new MyNavigator(id: 1, name: "searchShort".translation, path: "search"), + new MyNavigator(id: 2, name: "settings".translation, path: "settings"), + new MyNavigator(id: 3, name: "contact".translation, path: "contact"), + ]; + return BaseAppBar( + goBack: goBack, + color: Theme.of(context).brightness == Brightness.light ? Theme.of(context).accentColor : Theme.of(context).appBarTheme.backgroundColor, + customChild: Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + ), + child: Row( + children: [ + AppIconButton( + size: AppConstants.appBarIconSize, + onTap: () { + debugPrint('asd'); + Navigator.of(context).push(MaterialPageRoute(builder: (_) => NewsScreen())); + }, + icon: Icon( + Icons.newspaper_rounded, + color: ThemeColor.white, + ), + ), + Spacer(), + SvgPicture.asset( + 'assets/images/appBarIcon.svg', + height: AppConstants.clearAppBarHeight * 0.75, + width: AppConstants.clearAppBarHeight * 0.88, + ), + Container( + width: MediaQuery.of(context).size.width * 0.39, + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + icon: Icon( + Icons.more_vert_rounded, + color: ThemeColor.white, + size: 22.adaptedPx(), + ), + items: navigators.map( + (MyNavigator value) { + return DropdownMenuItem( + value: value, + child: Text( + value.name, + overflow: TextOverflow.ellipsis, + // style: AppTheme.selectedTxtStyle, + ), + ); + }, + ).toList(), + onChanged: (newValue) { + if (newValue!.path == 'search') { + Tabnavigator.maybeOf(context)?.changePage(1); + } else if (newValue.path == 'settings') { + Navigator.of(context, rootNavigator: true).push( + MaterialPageRoute(builder: (_) => SettingsScreen()), + ); + } else if (newValue.path == 'contact') { + Navigator.of(context, rootNavigator: true).push( + MaterialPageRoute(builder: (_) => ContactScreen()), + ); + } + }, + ), + ), + ), + ], + ), + ), + ); + } + + @override + Size get preferredSize => Size.fromHeight(AppConstants.appBarHeight); + + @override + Widget build(BuildContext context) { + return Container( + height: preferredSize.height, + padding: EdgeInsets.only(top: Adaptix.systemPadding.top), + color: color ?? Theme.of(context).appBarTheme.backgroundColor, + alignment: Alignment.centerLeft, + child: Material( + color: Colors.transparent, + child: Center( + child: customChild ?? + Padding( + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context)), + child: Row( + children: [ + if (includeBack) + AppIconButton( + icon: Icon( + CupertinoIcons.back, + color: ThemeColor.white, //Theme.of(context).appBarTheme.iconTheme?.color, + ), + onTap: goBack, + size: AppConstants.appBarIconSize), + SizedBox( + width: 10.adaptedPx(), + ), + Expanded( + child: Text( + title ?? "", + style: AppBarTheme.of(context).titleTextStyle?.copyWith( + fontWeight: FontWeight.w500, + color: ThemeColor.white, //Theme.of(context).accentTextTheme.headline2?.color, + ), + ), + ), + SizedBox( + width: 10.adaptedPx(), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + for (var option in after) ...[SizedBox(width: 1.5.orientationWidth), option] + ], + ) + ], + ), + ), + ), + ), + ); + } +} + +class MyNavigator { + int id; + String name; + String path; + MyNavigator({ + required this.id, + required this.name, + required this.path, + }); +} diff --git a/lib/components/button.dart b/lib/components/button.dart new file mode 100644 index 0000000..27fd9aa --- /dev/null +++ b/lib/components/button.dart @@ -0,0 +1,90 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/components/indicator.dart'; + +class MyButton extends StatefulWidget { + MyButton({ + Key? key, + this.onDisabled, + this.color, + this.isDisabled = false, + this.onTap, + this.inProgress, + this.padding, + this.borderRadius, + this.text, + this.height, + this.indicatorSize, + this.textSpan, + }) : super(key: key); + + final void Function()? onTap; + final EdgeInsets? padding; + final String? text; + final bool? inProgress; + final double? height; + final Widget? textSpan; + final bool isDisabled; + final void Function()? onDisabled; + final Color? color; + final double? indicatorSize; + final double? borderRadius; + + @override + _MyButtonState createState() => _MyButtonState(); +} + +class _MyButtonState extends State with TickerProviderStateMixin { + @override + Widget build(BuildContext context) { + Color? _backColor; + Color? _color; + + if (widget.color != null) { + bool isDark = Theme.of(context).brightness == Brightness.dark; + _color = isDark ? widget.color : Theme.of(context).textTheme.button?.color; + _backColor = isDark ? Theme.of(context).buttonColor : widget.color; + } else { + _color = Theme.of(context).textTheme.button?.color; + _backColor = Theme.of(context).buttonColor; + } + + return Opacity( + opacity: widget.isDisabled ? 0.5 : 1, + child: ClipRRect( + borderRadius: BorderRadius.circular(widget.borderRadius ?? 20.adaptedPx()), + child: Material( + color: _backColor, + child: InkWell( + onTap: () { + if (!(widget.inProgress ?? false) && widget.onTap != null && !widget.isDisabled) { + widget.onTap!(); + } else if (widget.isDisabled && widget.onDisabled != null) {} + }, + child: Container( + height: widget.height, + padding: widget.padding ?? EdgeInsets.symmetric(vertical: 5.adaptedPx(), horizontal: 15.adaptedPx()), + child: AnimatedSize( + duration: Duration(milliseconds: 200), + vsync: this, + child: (widget.inProgress ?? false) + ? Center( + child: Indicator( + size: widget.indicatorSize ?? 0.4.adaptedPx(), + color: Colors.white, + )) + : Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + widget.textSpan == null + ? Text('${widget.text}', style: TextStyle(color: _color, fontSize: 12.99.adaptedPx(), fontWeight: FontWeight.w500)) + : widget.textSpan! + ], + ), + ), + ), + ), + )), + ); + } +} diff --git a/lib/components/categoryBuilder.dart b/lib/components/categoryBuilder.dart new file mode 100644 index 0000000..b88c55a --- /dev/null +++ b/lib/components/categoryBuilder.dart @@ -0,0 +1,104 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/categories/products/pure.dart'; +import 'package:birzha/screens/productsScreen.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; + +class CategoryBuilder extends StatefulWidget { + const CategoryBuilder({Key? key, required this.category}) : super(key: key); + + final ProductsPureCategory category; + + @override + _CategoryBuilderState createState() => _CategoryBuilderState(); +} + +class _CategoryBuilderState extends State { + bool _isPressed = false; + + @override + Widget build(BuildContext context) { + return AnimatedContainer( + duration: Duration(milliseconds: 300), + curve: Curves.ease, + padding: EdgeInsets.all(_isPressed ? 8.adaptedPx() : 0), + child: LayoutBuilder( + builder: (context, constraints) => PhysicalModel( + color: Theme.of(context).accentColor.withOpacity(0.1), + borderRadius: BorderRadius.circular(constraints.biggest.height * 0.04), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + setState(() { + _isPressed = false; + }); + Navigator.of(context, rootNavigator: false) + .push(MaterialPageRoute(builder: (_) => ProductsScreen(route: 'category', category: widget.category.toRemote()))); + }, + borderRadius: BorderRadius.circular(constraints.biggest.height * 0.04), + onTapCancel: () { + setState(() { + _isPressed = false; + }); + }, + onTapDown: (details) { + setState(() { + _isPressed = true; + }); + }, + child: Align( + alignment: Alignment.center, + child: Flex( + direction: Axis.vertical, + children: [ + Spacer( + flex: 3, + ), + Expanded( + flex: 12, + child: ConstrainedBox( + constraints: BoxConstraints.expand(), + child: FittedBox( + child: CachedNetworkImage( + imageUrl: widget.category.icon, + placeholder: (_, __) { + return Icon( + Icons.category, + color: Theme.of(context).iconTheme.color?.withOpacity(0.5), + ); + }, + errorWidget: (_, __, ___) { + return Icon( + Icons.category, + color: Theme.of(context).iconTheme.color?.withOpacity(0.5), + ); + }, + ), + ), + ), + ), + Spacer(flex: 2), + Expanded( + flex: 6, + child: Padding( + padding: EdgeInsets.symmetric(horizontal: constraints.biggest.width * 0.1), + child: Text(widget.category.name, + textScaleFactor: 1, + maxLines: 2, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.headline2?.copyWith(fontSize: constraints.biggest.height * 0.074, height: 1.6)), + ), + ), + Spacer(flex: 3) + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/components/categoryNameWidget.dart b/lib/components/categoryNameWidget.dart new file mode 100644 index 0000000..01baa52 --- /dev/null +++ b/lib/components/categoryNameWidget.dart @@ -0,0 +1,36 @@ +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; + +class CategoryNameWidget extends StatelessWidget { + final String categoryName; + final TextStyle? textStyle; + + const CategoryNameWidget({ + Key? key, + required this.categoryName, + this.textStyle, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Container( + width: 4.adaptedPx(), + height: 29.adaptedPx(), + color: Theme.of(context).accentColor, + ), + SizedBox(width: 10.adaptedPx()), + Text( + categoryName, + style: textStyle ?? + Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontWeight: FontWeight.bold, + fontSize: AppConstants.h1FontSize, + ), + ), + ], + ); + } +} diff --git a/lib/components/contactInfo.dart b/lib/components/contactInfo.dart new file mode 100644 index 0000000..0cb0569 --- /dev/null +++ b/lib/components/contactInfo.dart @@ -0,0 +1,59 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; + +class ContactInfo extends StatelessWidget { + final IconData icon; + final String mainText; + final String description; + + const ContactInfo({ + Key? key, + required this.icon, + required this.mainText, + required this.description, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 40.adaptedPx(), + height: 40.adaptedPx(), + child: Icon(icon, + size: 25.adaptedPx(), + color: Theme.of(context).chipTheme.backgroundColor), + decoration: BoxDecoration( + color: Theme.of(context).accentColor, + borderRadius: BorderRadius.circular(30), + ), + ), + SizedBox(width: 8.adaptedPx()), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + mainText, + style: + Theme.of(context).accentTextTheme.headline2!.copyWith( + fontSize: 16.adaptedPx(), + fontWeight: FontWeight.bold, + ), + ), + Text( + description, + style: Theme.of(context).primaryTextTheme.headline2, + ), + ], + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/components/customCardWidget.dart b/lib/components/customCardWidget.dart new file mode 100644 index 0000000..4f46cf4 --- /dev/null +++ b/lib/components/customCardWidget.dart @@ -0,0 +1,78 @@ +import 'package:birzha/components/settingsIcons.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; + +class CustomCardWidget extends StatelessWidget { + final String name; + final Widget? nextSign; + final void Function()? onTap; + final Icon? icon; + final BorderRadius? borderRadius; + final Widget? trailing; + + CustomCardWidget({ + Key? key, + required this.name, + this.nextSign, + this.onTap, + this.icon, + this.trailing, + this.borderRadius, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: Theme.of(context).cardColor, + borderRadius: borderRadius ?? BorderRadius.circular(5.adaptedPx()), + child: InkWell( + onTap: onTap, + borderRadius: borderRadius ?? BorderRadius.circular(5.adaptedPx()), + child: Container( + alignment: Alignment.center, + padding: EdgeInsets.symmetric( + vertical: 26.adaptedPx(), + ), + child: Row( + children: [ + SizedBox(width: 13.adaptedPx()), + if (icon != null) + Icon( + icon!.icon, + size: 24.adaptedPx(), + color: icon?.color ?? Theme.of(context).accentColor, + ), + SizedBox(width: 12.adaptedPx()), + Expanded( + child: Text(name), + ), + SizedBox( + width: 5.adaptedPx(), + ), + if (trailing != null) ...[ + trailing!, + SizedBox( + width: 5.adaptedPx(), + ), + ], + Container( + child: + Icon(SettingsIcons.next_sign, + color: Theme.of(context).accentColor, + size: 18.adaptedPx()), + width: 19.adaptedPx(), + height: 19.adaptedPx(), + alignment: Alignment.center, + decoration: BoxDecoration( + color: Theme.of(context).accentColor.withOpacity(0.05), + borderRadius: BorderRadius.circular(20.adaptedPx()), + ), + ), + SizedBox(width: 10.adaptedPx()), + ], + ), + ), + ), + ); + } +} diff --git a/lib/components/dialog.dart b/lib/components/dialog.dart new file mode 100644 index 0000000..bfa0f97 --- /dev/null +++ b/lib/components/dialog.dart @@ -0,0 +1,73 @@ +import 'package:birzha/components/categoryNameWidget.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; + +class AppDialog extends StatelessWidget { + const AppDialog({ + Key? key, + this.title, + required this.child, + this.actions = const [], + }) : super(key: key); + + final String? title; + final Widget child; + final List actions; + + @override + Widget build(BuildContext context) { + return Dialog( + insetPadding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + ), + child: Container( + padding: EdgeInsets.all( + 14.adaptedPx(), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + Expanded( + child: CategoryNameWidget( + categoryName: title ?? "", + ), + ), + GestureDetector( + onTap: () { + Navigator.of(context).pop(); + }, + child: Icon( + Icons.cancel_outlined, + color: Theme.of(context).accentColor, + size: 22.adaptedPx(), + ), + ), + ], + ), + SizedBox( + height: 10.adaptedPx(), + ), + Flexible( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [child], + ), + ), + ), + SizedBox( + height: 10.adaptedPx(), + ), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: actions, + ) + ], + ), + ), + ); + } +} diff --git a/lib/components/fakeSearchBar.dart b/lib/components/fakeSearchBar.dart new file mode 100644 index 0000000..94a331c --- /dev/null +++ b/lib/components/fakeSearchBar.dart @@ -0,0 +1,90 @@ +import 'dart:math'; + +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/categories/products/search.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/components/icon.dart'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/screens/productsScreen.dart'; + +class FakeSearchBar extends StatelessWidget { + const FakeSearchBar({Key? key, this.fromHome = false, required this.route}) : super(key: key); + + final bool fromHome; + final String route; + + @override + Widget build(BuildContext context) { + final scaleFactor = min(1.35, MediaQuery.of(context).textScaleFactor); + return Hero( + tag: Tabnavigator.currentRoute(context) + '/$route', + child: Align( + alignment: Alignment.topCenter, + child: ConstrainedBox( + constraints: BoxConstraints.loose(Size(double.infinity, AppConstants.clearAppBarHeight)), + child: Material( + color: Colors.transparent, + child: GestureDetector( + onTap: () { + Navigator.of(context, rootNavigator: false).push( + CupertinoPageRoute( + builder: (_) => ProductsScreen( + route: route, + category: ProductsSearch(), + ), + ), + ); + }, + child: Container( + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context)), + height: AppConstants.clearAppBarHeight, + child: Row( + children: [ + if (!fromHome) ...[ + AppIconButton( + icon: Icon( + CupertinoIcons.back, + color: Theme.of(context).accentColor, + ), + onTap: () { + Tabnavigator.backDispatcher(context); + }, + size: AppConstants.appBarIconSize), + SizedBox( + width: 12.adaptedPx(), + ) + ], + Expanded( + child: Padding( + padding: EdgeInsets.symmetric(vertical: AppConstants.clearAppBarHeight * 0.18), + child: Container( + decoration: + BoxDecoration(color: Theme.of(context).dividerColor.withOpacity(0.06), borderRadius: BorderRadius.circular(5.adaptedPx())), + alignment: Alignment.centerLeft, + padding: EdgeInsets.symmetric(horizontal: 15.adaptedPx()), + child: Row( + children: [ + Expanded(child: Text('search'.translation, textScaleFactor: scaleFactor, style: TextStyle(fontWeight: FontWeight.w300))), + Icon( + CupertinoIcons.search, + color: Theme.of(context).accentColor, + size: AppConstants.appBarIconSize * 0.8, + ) + ], + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/components/icon.dart b/lib/components/icon.dart new file mode 100644 index 0000000..ae12c0b --- /dev/null +++ b/lib/components/icon.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +class AppIconButton extends StatelessWidget { + const AppIconButton({ + Key? key, + required this.icon, + required this.size, + this.onTap, + this.highlightColor, + this.splashColor + }) : super(key: key); + + final Icon icon; + final double size; + final Color? highlightColor; + final Color? splashColor; + final void Function()? onTap; + + @override + Widget build(BuildContext context) { + return IconButton( + icon: icon, + color: Colors.grey.shade400, + onPressed: (){ + if(onTap != null) + onTap!(); + }, + padding: EdgeInsets.zero, + splashRadius: size*1.1, + constraints: BoxConstraints(), + iconSize: size, + highlightColor: highlightColor ?? Colors.grey.withOpacity(0.1), + splashColor:splashColor ?? Theme.of(context).accentColor.withOpacity(0.1), + ); + } +} \ No newline at end of file diff --git a/lib/components/imagePlaceHolder.dart b/lib/components/imagePlaceHolder.dart new file mode 100644 index 0000000..40fd7b1 --- /dev/null +++ b/lib/components/imagePlaceHolder.dart @@ -0,0 +1,19 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; + +class AppImagePlaceholder extends StatelessWidget { + const AppImagePlaceholder({Key? key, this.size}) : super(key: key); + + final double? size; + + @override + Widget build(BuildContext context) { + return Center( + child: Icon( + Icons.image, + size: size ?? 45.adaptedPx(), + color: Theme.of(context).accentColor, + ), + ); + } +} diff --git a/lib/components/indicator.dart b/lib/components/indicator.dart new file mode 100644 index 0000000..ecc1c9a --- /dev/null +++ b/lib/components/indicator.dart @@ -0,0 +1,19 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; + +class Indicator extends StatelessWidget { + final double? size; + final Color? color; + + Indicator({this.size, this.color}); + + @override + Widget build(BuildContext context) { + return Transform.scale( + scale: size ?? 1.5.adaptedPx(), + child: CircularProgressIndicator( + valueColor: AlwaysStoppedAnimation(color ?? Theme.of(context).accentColor), + ), + ); + } +} diff --git a/lib/components/localizationOverride.dart b/lib/components/localizationOverride.dart new file mode 100644 index 0000000..7a4df0f --- /dev/null +++ b/lib/components/localizationOverride.dart @@ -0,0 +1,44 @@ +import 'package:flutter/material.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:birzha/models/tk_intl.dart'; + +class LocalizationOverride extends StatefulWidget { + const LocalizationOverride({Key? key, required this.builder}) : super(key: key); + + final Widget Function(BuildContext) builder; + + @override + _LocalizationOverrideState createState() => _LocalizationOverrideState(); +} + +class _LocalizationOverrideState extends State with WidgetsBindingObserver { + @override + void didChangeDependencies() { + WidgetsBinding.instance?.addObserver(this); + super.didChangeDependencies(); + } + + @override + Widget build(BuildContext context) { + return Localizations.override( + context: context, + locale: SettingsModel.of( + context, + ).language, + delegates: [ + AppLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + TkMaterialLocalizations.delegate + ], + child: Builder( + builder: (innerContext) { + return widget.builder(innerContext); + }, + ), + ); + } +} diff --git a/lib/components/postBuilderFactory.dart b/lib/components/postBuilderFactory.dart new file mode 100644 index 0000000..25fe1c8 --- /dev/null +++ b/lib/components/postBuilderFactory.dart @@ -0,0 +1,33 @@ +import 'package:birzha/components/productBuilder.dart'; +import 'package:birzha/models/chatroom/chatroom.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:birzha/models/transactions/transaction.dart'; +import 'package:birzha/screens/personalCabinet/messages/messages.dart'; +import 'package:birzha/screens/personalCabinet/topUp/topUpHistory.dart'; +import 'package:flutter/material.dart'; + +class PostBuilderFactory extends StatelessWidget { + const PostBuilderFactory({ Key? key, required this.post }) : super(key: key); + + final Post post; + + @override + Widget build(BuildContext context) { + + if(post is Product) + return ProductBuilder(product: post as Product); + + else if(post is Transaction) + return TopUpHistoryCard( + transaction: post as Transaction, + ); + + else if(post is Chatroom) + return MessagesCard( + chatroom: post as Chatroom, + ); + + return Container(); + } +} \ No newline at end of file diff --git a/lib/components/postlist.dart b/lib/components/postlist.dart new file mode 100644 index 0000000..d3543e3 --- /dev/null +++ b/lib/components/postlist.dart @@ -0,0 +1,79 @@ +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/components/postBuilderFactory.dart'; +import 'package:birzha/components/refreshButton.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../core/lazyload/lazyload.dart'; + +class PostList extends StatefulWidget { + const PostList({Key? key, required this.category, required this.fetchController, this.contentPadding, this.before = const [], this.after = const []}) + : super(key: key); + + final Serializer category; + final FetchController fetchController; + final EdgeInsets? contentPadding; + final List before; + final List after; + + @override + _PostListState createState() => _PostListState(); +} + +class _PostListState extends State { + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider.value( + value: widget.fetchController, + child: LazyLoadView( + data: (page, context) => widget.category.getPosts(context, page), + loaderWidget: SliverFillRemaining( + child: Center(child: Indicator(size: 0.7.adaptedPx())), + ), + loadMoreWidget: SliverToBoxAdapter( + child: Container( + margin: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + alignment: Alignment.center, + child: Row( + children: [ + Expanded( + child: Center(child: Indicator(size: 0.6.adaptedPx())), + ) + ], + ), + ), + ), + before: [...widget.before], + after: [...widget.after], + fetchController: widget.fetchController, + contentPadding: widget.contentPadding ?? EdgeInsets.zero, + errorWidget: (refresh, error) { + return SliverFillRemaining( + child: Center( + child: RefreshButton( + onTap: refresh, + size: 38.adaptedPx(), + ), + ), + ); + }, + gridDelegate: widget.category.gridDelegate(context), + errorOnLoadMoreWidget: (refresh, error) { + return Container( + margin: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + child: RefreshButton( + onTap: refresh, + size: 25.adaptedPx(), + ), + ); + }, + pageFactor: AppConstants.pageLimit, + needPagination: widget.category.needPagination, + itemBuilder: (context, model, index) => PostBuilderFactory(post: model)), + ); + } +} diff --git a/lib/components/productBuilder.dart b/lib/components/productBuilder.dart new file mode 100644 index 0000000..93b32da --- /dev/null +++ b/lib/components/productBuilder.dart @@ -0,0 +1,166 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/products/my_product.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/screens/details.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../core/lazyload/lazyload.dart'; + +class ProductBuilder extends StatelessWidget { + final Product product; + + const ProductBuilder({ + Key? key, + required this.product, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () async { + var shouldRefresh = await Navigator.of(context, rootNavigator: false).push(MaterialPageRoute(builder: (_) => ProductDetails(product: product))); + if (shouldRefresh is bool && shouldRefresh) { + try { + Provider.of>(context, listen: false).refresh(); + } catch (e) { + print(e); + } + } + }, + child: LayoutBuilder(builder: (context, constraints) { + Widget title(String name) { + return Expanded( + flex: 3, + child: Align( + alignment: Alignment.centerLeft, + child: Text( + name, + textScaleFactor: 1, + maxLines: 1, + style: Theme.of(context).primaryTextTheme.headline3?.copyWith( + fontSize: constraints.maxHeight * 0.034, + ), + ), + ), + ); + } + + Widget value(String name, [Color? color]) { + return Expanded( + flex: 3, + child: Text(name, + textScaleFactor: 1, + maxLines: 1, + style: + Theme.of(context).accentTextTheme.headline2?.copyWith(fontSize: constraints.maxHeight * 0.034, color: color, fontWeight: FontWeight.bold)), + ); + } + + return Container( + decoration: BoxDecoration( + border: Border.all(color: Theme.of(context).dividerColor, width: 0.8.adaptedPx()), + ), + padding: EdgeInsets.symmetric(horizontal: constraints.maxWidth * 0.07, vertical: constraints.maxHeight * 0.03), + child: Flex( + direction: Axis.vertical, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('lotNumber'.translation, + textScaleFactor: 1, + maxLines: 1, + style: Theme.of(context).primaryTextTheme.headline3?.copyWith( + fontSize: constraints.maxHeight * 0.04, + )), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text(product.id.toString(), + textScaleFactor: 1, + maxLines: 1, + style: Theme.of(context).accentTextTheme.headline2?.copyWith( + fontSize: constraints.maxHeight * 0.04, + )), + ), + ), + ], + ), + SizedBox( + height: constraints.maxHeight * 0.04, + ), + Container( + child: CachedNetworkImage( + width: constraints.maxWidth, + fit: BoxFit.cover, + height: constraints.maxWidth / (167 / 92), + placeholder: (context, child) { + return Center( + child: SizedBox( + height: constraints.maxWidth / (167 / 92), + child: Icon( + Icons.image, + color: Theme.of(context).accentColor, + size: constraints.maxHeight * 0.1, + ), + ), + ); + }, + errorWidget: (context, error, stackTrace) { + return Center( + child: SizedBox( + height: constraints.maxWidth / (167 / 92), + child: Icon( + Icons.broken_image, + color: Theme.of(context).accentColor, + size: constraints.maxHeight * 0.1, + ), + ), + ); + }, + imageUrl: product.mainImage, + ), + ), + SizedBox( + height: constraints.maxHeight * 0.02, + ), + Text( + product.name + '\n\n', + textScaleFactor: 1, + overflow: TextOverflow.ellipsis, + maxLines: 2, + style: Theme.of(context).accentTextTheme.headline2?.copyWith( + fontWeight: FontWeight.bold, + fontSize: constraints.maxHeight * 0.038, + ), + ), + SizedBox( + height: constraints.maxHeight * 0.01, + ), + title('productAmount'.translation), + Spacer(flex: 2), + value(product.quantityFormatted + " " + product.unit), + Spacer(flex: 2), + title('startingPrice'.translation), + Spacer(flex: 2), + value(product.priceFormatted), + Spacer(flex: 2), + title('expiryDate'.translation), + Spacer(flex: 2), + value(product.expiryDateFormatted), + Spacer(), + if (product is MyProduct) ...[ + value((product as MyProduct).statusLabel, (product as MyProduct).statusColor), + ] + ], + ), + ); + }), + ); + } +} diff --git a/lib/components/radio.dart b/lib/components/radio.dart new file mode 100644 index 0000000..373bd12 --- /dev/null +++ b/lib/components/radio.dart @@ -0,0 +1,95 @@ +import 'package:flutter/material.dart'; + +class RadioItem{ + late final String name; + late final T value; + late final T groupValue; + + RadioItem({required this.name,required this.value,required this.groupValue}); + +} + +///Widget that draw a beautiful checkbox rounded. Provided with animation if wanted +class RadioButton extends StatefulWidget { + const RadioButton({ + Key? key, + required this.checkedColor, + required this.uncheckedColor, + required this.value, + required this.onChange, + required this.borderColor, + required this.size, + required this.borderWidth, + required this.animationDuration, + required this.groupValue, + }) : + super(key: key); + + //Define borderWidth + + final double borderWidth; + + ///Define the color that is shown when Widgets is checked + final Color checkedColor; + + ///Define the color that is shown when Widgets is unchecked + final Color uncheckedColor; + + ///Define the border of the widget + final Color borderColor; + + ///Define the size of the checkbox + final double size; + + ///Define the duration of the animation. If any + final Duration animationDuration; + + // value of item + + final dynamic value; + + // onchange of value + + final Function(dynamic) onChange; + + //groupValue of radios + + final dynamic groupValue; + + @override + _RadioButtonState createState() => _RadioButtonState(); +} + +class _RadioButtonState extends State { + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + widget.onChange(widget.value); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(widget.size / 2), + child: AnimatedContainer( + duration: widget.animationDuration, + height: widget.size, + width: widget.size, + decoration: BoxDecoration( + color: widget.value == widget.groupValue ? widget.checkedColor : widget.uncheckedColor, + border: Border.all( + color: widget.value == widget.groupValue? widget.checkedColor: widget.borderColor, + width: widget.borderWidth + ), + borderRadius: BorderRadius.circular(widget.size / 2), + ), + child: Container() + ), + ), + ); + } +} diff --git a/lib/components/refreshButton.dart b/lib/components/refreshButton.dart new file mode 100644 index 0000000..b2c835f --- /dev/null +++ b/lib/components/refreshButton.dart @@ -0,0 +1,20 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/components/icon.dart'; + +class RefreshButton extends StatelessWidget { + const RefreshButton({Key? key, required this.onTap, this.size}) : super(key: key); + + final void Function() onTap; + final double? size; + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: Center( + child: AppIconButton(icon: Icon(Icons.refresh), onTap: onTap, size: size ?? 39.adaptedPx()), + ), + ); + } +} diff --git a/lib/components/searchBar.dart b/lib/components/searchBar.dart new file mode 100644 index 0000000..c05f86a --- /dev/null +++ b/lib/components/searchBar.dart @@ -0,0 +1,161 @@ +import 'package:birzha/components/icon.dart'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; + +class ActualSearchBar extends StatefulWidget { + const ActualSearchBar({Key? key, required this.onSubmit, required this.route}) : super(key: key); + + final void Function(String) onSubmit; + final String route; + + @override + _ActualSearchBarState createState() => _ActualSearchBarState(); +} + +class _ActualSearchBarState extends State { + late FocusNode _focusNode; + late TextEditingController _controller; + String _word = ''; + String _previousWord = ''; + + String get word => _word; + + set word(String s) { + if (s != word) { + _previousWord = _word; + _word = s; + } + } + + void _focusListener() { + setState(() {}); + } + + void _search() { + if (_previousWord != _word) { + setState(() { + _previousWord = _word; + }); + widget.onSubmit(_word); + } + } + + @override + void initState() { + super.initState(); + _focusNode = FocusNode(); + _controller = TextEditingController(); + _focusNode.addListener(_focusListener); + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) async { + await Future.delayed(Duration(milliseconds: 300)); + _focusNode.requestFocus(); + }); + } + + @override + void dispose() { + _focusNode.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Hero( + tag: widget.route, + child: Material( + child: Container( + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context)), + child: Row( + children: [ + ...[ + AppIconButton( + icon: Icon( + CupertinoIcons.back, + color: Theme.of(context).accentColor, + ), + onTap: () { + Tabnavigator.backDispatcher(context); + }, + size: AppConstants.appBarIconSize), + SizedBox( + width: 15.adaptedPx(), + ) + ], + Expanded( + child: Padding( + padding: EdgeInsets.symmetric(vertical: AppConstants.clearAppBarHeight * 0.2), + child: Container( + decoration: BoxDecoration(color: Theme.of(context).dividerColor.withOpacity(0.06), borderRadius: BorderRadius.circular(5.adaptedPx())), + alignment: Alignment.centerLeft, + padding: EdgeInsets.symmetric(horizontal: 15.adaptedPx()), + child: Row( + children: [ + Expanded( + child: Center( + child: TextField( + controller: _controller, + onChanged: (newWord) { + setState(() { + word = newWord; + }); + }, + focusNode: _focusNode, + autofocus: false, + onSubmitted: (_) => _search(), + style: Theme.of(context).textTheme.bodyText2, + cursorColor: Theme.of(context).accentColor, + decoration: InputDecoration( + border: InputBorder.none, + contentPadding: EdgeInsets.only(left: 10.adaptedPx()), + isDense: true, + hintText: 'search'.translation, + ), + ), + )), + AppIconButton( + onTap: () { + if (!_focusNode.hasFocus) + _focusNode.requestFocus(); + else + _search(); + }, + icon: Icon( + CupertinoIcons.search, + color: Theme.of(context).accentColor, + ), + size: AppConstants.appBarIconSize * 0.8, + ), + if (_focusNode.hasFocus) ...[ + SizedBox(width: 10.adaptedPx()), + AppIconButton( + onTap: () { + setState(() { + _controller.text = ''; + word = ''; + _search(); + _focusNode.unfocus(); + }); + }, + icon: Icon( + CupertinoIcons.clear, + color: Theme.of(context).accentColor, + ), + size: AppConstants.appBarIconSize * 0.8, + ) + ] + ], + ), + ), + ), + ), + ], + )), + ), + ); + } +} diff --git a/lib/components/settingsIcons.dart b/lib/components/settingsIcons.dart new file mode 100644 index 0000000..f1a7881 --- /dev/null +++ b/lib/components/settingsIcons.dart @@ -0,0 +1,29 @@ +/// Flutter icons Settings_Icons +/// Copyright (C) 2021 by original authors @ fluttericon.com, fontello.com +/// This font was generated by FlutterIcon.com, which is derived from Fontello. +/// +/// To use this font, place it in your fonts/ directory and include the +/// following in your pubspec.yaml +/// +/// flutter: +/// fonts: +/// - family: Settings_Icons +/// fonts: +/// - asset: fonts/Settings_Icons.ttf +/// +/// +/// +import 'package:flutter/widgets.dart'; + +class SettingsIcons { + SettingsIcons._(); + + static const _kFontFam = 'Settings_Icons'; + static const String? _kFontPkg = null; + + static const IconData language = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData feedback = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData next_sign = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData contact = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData confidentials = IconData(0xe804, fontFamily: _kFontFam, fontPackage: _kFontPkg); +} diff --git a/lib/components/slider.dart b/lib/components/slider.dart new file mode 100644 index 0000000..306efe0 --- /dev/null +++ b/lib/components/slider.dart @@ -0,0 +1,96 @@ +import 'dart:ui'; +import 'package:birzha/components/imagePlaceHolder.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/screens/photo.dart'; + +class PostImageSlider extends StatefulWidget { + PostImageSlider({Key? key, this.images = const [], this.fit, this.height}) : super(key: key); + + final List images; + final BoxFit? fit; + final double? height; + + @override + __SliderState createState() => __SliderState(); +} + +class __SliderState extends State { + List imageUrls = []; + int page = 0; + + @override + void initState() { + super.initState(); + imageUrls = [ + for (var url in widget.images) url, + ]..remove(''); + } + + @override + Widget build(BuildContext context) { + var bottomBarHeight = 20.adaptedPx(); + var circleHeight = 8.adaptedPx(); + + return Container( + height: widget.height ?? 320.adaptedPx(), + child: Stack( + alignment: Alignment.center, + children: [ + Positioned.fill(child: Container(color: Theme.of(context).cardColor)), + PageView( + children: [ + for (var image in imageUrls) + GestureDetector( + onTap: () { + Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(builder: (_) => PhotoScreen(imageUrls[page]))); + }, + child: CachedNetworkImage( + imageUrl: image, + fit: widget.fit ?? BoxFit.contain, + errorWidget: (context, url, error) => AppImagePlaceholder(), + placeholder: (_, __) => AppImagePlaceholder(), + alignment: Alignment.topCenter, + ), + ) + ], + onPageChanged: (_p) { + setState(() { + page = _p; + }); + }, + ), + Positioned( + bottom: AppConstants.horizontalPadding(context), + child: ClipRRect( + borderRadius: BorderRadius.circular(circleHeight), + child: Container( + height: bottomBarHeight, + decoration: BoxDecoration( + color: Colors.black.withOpacity(0.7), + ), + padding: EdgeInsets.symmetric(horizontal: circleHeight / 2), + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 12, sigmaY: 12), + child: Row( + children: List.generate(imageUrls.length, (index) { + bool isSelected = index == page; + return AnimatedContainer( + duration: Duration(milliseconds: 300), + decoration: BoxDecoration(color: Colors.white.withOpacity(isSelected ? 1 : 0.7), shape: BoxShape.circle), + height: circleHeight * (isSelected ? 1 : 0.7), + width: circleHeight * (isSelected ? 1 : 0.7), + margin: EdgeInsets.symmetric(horizontal: circleHeight / 3), + ); + })), + ), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/components/tab_nav_icons.dart b/lib/components/tab_nav_icons.dart new file mode 100644 index 0000000..ec6d975 --- /dev/null +++ b/lib/components/tab_nav_icons.dart @@ -0,0 +1,28 @@ +/// Flutter icons CustomIcons +/// Copyright (C) 2022 by original authors @ fluttericon.com, fontello.com +/// This font was generated by FlutterIcon.com, which is derived from Fontello. +/// +/// To use this font, place it in your fonts/ directory and include the +/// following in your pubspec.yaml +/// +/// flutter: +/// fonts: +/// - family: CustomIcons +/// fonts: +/// - asset: fonts/CustomIcons.ttf +/// +/// +/// +import 'package:flutter/widgets.dart'; + +class TabNavIcons { + TabNavIcons._(); + + static const _kFontFam = 'TabNavIcons'; + static const String? _kFontPkg = null; + + static const IconData news = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData user = IconData(0xe801, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData home = IconData(0xe802, fontFamily: _kFontFam, fontPackage: _kFontPkg); + static const IconData category = IconData(0xe803, fontFamily: _kFontFam, fontPackage: _kFontPkg); +} diff --git a/lib/components/tabview.dart b/lib/components/tabview.dart new file mode 100644 index 0000000..05a20dc --- /dev/null +++ b/lib/components/tabview.dart @@ -0,0 +1,218 @@ +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; +import 'package:google_nav_bar/google_nav_bar.dart'; +import 'package:provider/provider.dart'; + +class TabView extends StatefulWidget { + TabView({required this.items}); + + final List items; + + @override + _TabViewState createState() => _TabViewState(); +} + +class _TabViewState extends State { + late final List> navigatorKeys; + late final PageController controller; + + Future pop(BuildContext cntxt) async { + final tabnavigator = Provider.of(cntxt, listen: false); + bool canPop = await navigatorKeys[tabnavigator.index].currentState?.maybePop() ?? true; + if (canPop) { + return false; + } else if (tabnavigator.stack.length > 1) { + setState(() { + tabnavigator._removefromStack(); + changePage(tabnavigator.stack.last); + }); + return false; + } else if (tabnavigator.stack.length == 1 && tabnavigator.index != 0) { + setState(() { + tabnavigator._removefromStack(); + changePage(0); + }); + return false; + } + return true; + } + + void changePage(int index) { + controller.jumpToPage(index); + } + + void onPageChange(BuildContext cntxt, int index) { + Provider.of(cntxt, listen: false)._setIndex(index); + } + + @override + void initState() { + navigatorKeys = [for (var item in widget.items) LabeledGlobalKey(item.initialRouteName)]; + controller = PageController(); + super.initState(); + } + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider( + create: (_) => Tabnavigator( + currentRouteName: (index) { + return widget.items[index].initialRouteName; + }, + changePage: changePage, + pop: pop, + rootNavContext: context), + builder: (context, _) => WillPopScope( + onWillPop: () => pop(context), + child: Consumer( + builder: (context, tabnav, __) { + return Scaffold( + bottomNavigationBar: Container( + color: Theme.of(context).bottomNavigationBarTheme.backgroundColor ?? Colors.white, + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context) / 2).copyWith(bottom: Adaptix.systemPadding.bottom), + child: GNav( + tabBorderRadius: 20.adaptedPx(), + curve: Curves.easeInCubic, + duration: Duration(milliseconds: 280), + selectedIndex: tabnav.index, + backgroundColor: Colors.transparent, + gap: 10.adaptedPx(), + color: Theme.of(context).accentColor, + activeColor: Theme.of(context).accentColor, + iconSize: 18.7.adaptedPx(), + textStyle: Theme.of(context).textTheme.headline2?.copyWith( + color: Theme.of(context).accentColor, + fontSize: AppConstants.h2FontSize * 0.93, + // body text uly headlinedan kichi + fontWeight: FontWeight.w500, + height: 1.3), + tabBackgroundColor: Theme.of(context).bottomNavigationBarTheme.selectedItemColor ?? Colors.grey.shade300, + tabMargin: EdgeInsets.symmetric(vertical: 8.adaptedPx()), + padding: EdgeInsets.symmetric(horizontal: 10.adaptedPx(), vertical: 13.2.adaptedPx()), + onTabChange: (index) { + onPageChange(context, index); + changePage(index); + }, + tabs: [ + for (var item in widget.items) + + /// those items are integrated from each single tabconfig from widget.items + GButton( + icon: item.iconData, + text: item.routeLabel, + active: true, + ), + ], + ), + ), + body: Column( + children: [ + //will create as much Navigators as the length of widget.items.length + Expanded( + child: PageView.builder( + itemCount: widget.items.length, + onPageChanged: (newPageIndex) { + onPageChange(context, newPageIndex); + }, + controller: controller, + itemBuilder: (_, index) => Navigator( + initialRoute: widget.items[index].initialRouteName, + key: navigatorKeys[index], + onGenerateInitialRoutes: (_, __) { + return [ + //each first screen of each item in widget.items + MaterialPageRoute(builder: widget.items[index].firstScreen), + ]; + }, + ), + ), + ), + ], + ), + ); + }, + ), + ), + ); + } +} + +///describes each gbutton, each tab and e.t.c -> creaet list of items in [TabView] constructor +class TabConfigs { + final int index; + final Widget Function(BuildContext) firstScreen; + final String routeLabel; + final IconData iconData; + final String initialRouteName; + + TabConfigs({ + required this.index, + required this.firstScreen, + required this.routeLabel, + required this.iconData, + required this.initialRouteName, + }); +} + +class Tabnavigator extends ChangeNotifier { + int index = 0; + Set stack = {0}; + late final Future Function(BuildContext cntxt) pop; + late final String Function(int) currentRouteName; + late final void Function(int) _changePage; + late final BuildContext rootNavContext; + + Tabnavigator({required void Function(int) changePage, required this.currentRouteName, required this.pop, required this.rootNavContext}) { + _changePage = changePage; + } + + Map _routeSettingsTable = {}; + + void changePage(int page, [dynamic payload]) { + _routeSettingsTable[page] = payload; + _changePage(page); + notifyListeners(); + } + + dynamic getPayloadOf(int page) { + return _routeSettingsTable[page]; + } + + void _setIndex(int i) { + index = i; + stack.remove(i); + stack.add(i); + notifyListeners(); + } + + void _removefromStack() { + _routeSettingsTable.remove(stack.last); + var listFromStack = [...stack]..removeLast(); + stack = {...listFromStack}; + index = stack.last; + notifyListeners(); + } + + static Tabnavigator? maybeOf(BuildContext context) { + try { + return Provider.of(context, listen: false); + } catch (e) {} + } + + static backDispatcher(BuildContext context) { + if (Tabnavigator.maybeOf(context) == null) + Navigator.of(context).pop(); + else + Tabnavigator.maybeOf(context)!.pop(context); + } + + static String currentRoute(BuildContext context) { + var nav = Tabnavigator.maybeOf(context); + if (nav == null) { + return '/root'; + } else { + return nav.currentRouteName(nav.index); + } + } +} diff --git a/lib/components/unauthenticatedWidget.dart b/lib/components/unauthenticatedWidget.dart new file mode 100644 index 0000000..40f0a7e --- /dev/null +++ b/lib/components/unauthenticatedWidget.dart @@ -0,0 +1,51 @@ +import 'package:birzha/components/button.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/screens/auth/login.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; + +import '../core/manager/manager.dart'; + +class UnAuthenticated extends StatefulWidget { + const UnAuthenticated({Key? key}) : super(key: key); + @override + _UnAuthenticatedState createState() => _UnAuthenticatedState(); +} + +class _UnAuthenticatedState extends State { + TaskStatus status = TaskStatus.None; + final GlobalKey formKey = GlobalKey(); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + alignment: Alignment.center, + width: 50.orientationWidth, + height: 200.adaptedPx(), + child: SvgPicture.asset('assets/images/unauth.svg'), + ), + Text( + 'needToEnter'.translation, + style: TextStyle(fontSize: 17.adaptedPx(), fontWeight: FontWeight.w300, color: Theme.of(context).accentColor), + ), + SizedBox( + height: 20.adaptedPx(), + ), + MyButton( + text: 'login'.translation, + inProgress: false, + onTap: () { + Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(builder: (_) => LoginScreen())); + }, + height: 40.adaptedPx(), + ), + ], + ), + ); + } +} diff --git a/lib/components/verifyPhoneDialog.dart b/lib/components/verifyPhoneDialog.dart new file mode 100644 index 0000000..2fdf99d --- /dev/null +++ b/lib/components/verifyPhoneDialog.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import 'package:birzha/components/TextInputCustom.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:birzha/services/validator.dart'; + +import '../constants.dart'; +import '../core/manager/manager.dart'; +import '../models/user/userManager.dart'; +import '../services/modals.dart'; +import 'button.dart'; + +class VerifyPhoneDialog extends StatefulWidget { + @override + __VerifyPhoneDialogState createState() => __VerifyPhoneDialogState(); +} + +class __VerifyPhoneDialogState extends State with ManagerObserverMixin { + late final TextEditingController _controller; + final GlobalKey _form = GlobalKey(); + + TaskStatus status = TaskStatus.None; + + @override + void initState() { + super.initState(); + _controller = TextEditingController(); + } + + @override + Widget build(BuildContext context) { + return Dialog( + insetPadding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + ), + child: Container( + padding: EdgeInsets.all(14.adaptedPx()), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 10.adaptedPx(), + ), + Text( + "phoneConfirmation".translation, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontSize: AppConstants.h1FontSize, + ), + ), + SizedBox( + height: 15.adaptedPx(), + ), + Text( + "smsSentInfo".translation, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontWeight: FontWeight.normal, + fontSize: AppConstants.h1FontSize, + ), + textAlign: TextAlign.center, + ), + SizedBox( + height: 15.adaptedPx(), + ), + Form( + key: _form, + child: Row( + children: [ + Expanded( + child: TextInputCustom( + fieldStandard: TextInputMetaData( + name: 'enterSmsCode'.translation, + label: 'enterSmsCode'.translation, + type: TextInputType.number, + autoFocus: true, + validation: Validation(conditions: [ + (inp) { + return inp.isEmpty || (int.tryParse(inp.trim())) == null ? 'formatError'.translation : null; + } + ]), + formatters: [ + LengthLimitingTextInputFormatter(4), + FilteringTextInputFormatter.digitsOnly, + ], + key: 'sms_code', + ), + controller: _controller, + ), + ), + ], + ), + ), + SizedBox( + height: 8.adaptedPx(), + ), + Center( + child: ManagerSelector( + selector: (context, manager) => manager.getStatusByKey('sms_verify'), + shouldRebuild: (previous, next) => previous != next, + onUpdate: () { + if (mounted && AppUserManager.of(context).getStatusByKey('sms_verify') == TaskStatus.Success) { + Navigator.of(context).pop(true); + } + }, + builder: (_, value) => MyButton( + text: 'confirm'.translation, + inProgress: value == TaskStatus.Loading, + onTap: () { + AppUserManager.of(context).checkCode(context, _controller.text); + }, + height: 40.adaptedPx(), + ), + ), + ), + ], + ), + ), + ); + } + + @override + TaskStatus selector(BuildContext context, AppUserManager someManager) { + return someManager.getStatusByKey(_keyForTask); + } + + @override + bool shouldUpdateListener(TaskStatus old, TaskStatus newOne) { + return old != newOne; + } + + @override + void updateListener() { + if (mounted) + setState(() { + status = AppUserManager.of(context).getStatusByKey(_keyForTask); + if (status == TaskStatus.Success) showSnackBar(context, content: 'dataIsUpdated'.translation); + }); + } +} + +const _keyForTask = 'sms_verify'; diff --git a/lib/constants.dart b/lib/constants.dart new file mode 100644 index 0000000..9a9607a --- /dev/null +++ b/lib/constants.dart @@ -0,0 +1,86 @@ +import 'package:birzha/services/helpers.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; + +const kBannerAssetRatio = 1161 / 500; +const kProductAspectRatio = 189 / 357; + +typedef VoidWithParam = void Function(T); + +abstract class AppConstants { + static const appColor = Color.fromRGBO(0, 49, 151, 1); + static const backgroundColor = Colors.white; + static const kDefaultLanguage = 'tk'; + static const scaffoldColorLight = const Color.fromRGBO(242, 245, 255, 1); + static const supprtedLocales = [const Locale('en', 'US'), const Locale('ru'), const Locale('tk')]; + static double get appBarHeight => clearAppBarHeight + Adaptix.systemPadding.top; + static double get clearAppBarHeight => 50.adaptedPx(); + static double get appBarIconSize => clearAppBarHeight / 2.3; + static double get appBarFontSize => clearAppBarHeight * 0.29; + static double get b2FontSize => 13.2.adaptedPx(); + static double get b3FontSize => 12.95.adaptedPx(); + static double get h2FontSize => 14.adaptedPx(); + static double get h1FontSize => 16.adaptedPx(); + static double get h3FontSize => 13.8.adaptedPx(); + static const int pageLimit = 20; + static int categoryAxisCount(BuildContext context) { + return Resizer(small: 2, large: 3, xlarge: 3, totalWidth: MediaQuery.of(context).size.width).value; + } + + static double horizontalPadding(BuildContext context) => MediaQuery.of(context).size.width * 0.04; + static double verticalPadding(BuildContext context) => 20.adaptedPx(); + + static int productAxisCount(BuildContext context) { + return Resizer(small: 2, large: 3, xlarge: 3, totalWidth: MediaQuery.of(context).size.width).value; + } + + static SliverGridDelegate productsGridDelegate(BuildContext context) { + return SliverGridDelegateWithFixedCrossAxisCount( + childAspectRatio: kProductAspectRatio, + mainAxisSpacing: horizontalPadding(context), + crossAxisSpacing: horizontalPadding(context) / 2, + crossAxisCount: Resizer(small: 2, medium: 2, large: 3, xlarge: 4, totalWidth: MediaQuery.of(context).size.width).value, + ); + } + + static double productCarouselHeight(BuildContext context) { + final fullWidth = MediaQuery.of(context).size.width; + final divided = fullWidth / productAxisCount(context); + final clearWidth = divided - ((horizontalPadding(context) / 2) * 1.8); + return (clearWidth / kProductAspectRatio) / 1.07; + } + + static Map htmlContentStyle(BuildContext context) => { + '*': Style( + fontSize: FontSize(13.1.adaptedPx()), + alignment: Alignment.centerLeft, + textAlign: TextAlign.start, + margin: EdgeInsets.all(0), + lineHeight: LineHeight.number(1.2), + fontFamily: 'Segoe', + ), + 'p': Style(margin: EdgeInsets.only(bottom: 12.adaptedPx())), + 'a': Style(color: Theme.of(context).accentColor) + }; + + static Map htmlCustomRenderer(BuildContext context) => { + 'a': (elementContext, child) { + final String? text = elementContext.tree.children.first.toString().replaceAll('"', ''); + final String? url = elementContext.tree.attributes['href']; + return TextSpan( + children: [ + TextSpan( + text: '$text', + style: TextStyle(color: Theme.of(context).accentColor, decoration: TextDecoration.underline), + recognizer: TapGestureRecognizer() + ..onTap = () { + linkLauncher(url ?? ""); + }) + ], + ); + } + }; + static const passwordReset = 'https://tmex.gov.tm/ru/password-reset'; +} diff --git a/lib/core/adaptix/adaptix.dart b/lib/core/adaptix/adaptix.dart new file mode 100644 index 0000000..39277c7 --- /dev/null +++ b/lib/core/adaptix/adaptix.dart @@ -0,0 +1,48 @@ +library adaptix; + +import 'dart:ui'; +import 'package:flutter/material.dart'; +import 'package:nested/nested.dart'; +import 'package:provider/provider.dart'; +part 'models/sizing.dart'; +part 'models/resizer.dart'; +part 'widgets/initializer.dart'; + +abstract class Adaptix { + static EdgeInsets get systemPadding => _Sizing.systemPadding; + static double get systemAspectRatio => _Sizing.aspectRatio; + + static double xSmallScreenScaleFactor = 1.0; + static double smallScreenScaleFactor = 1.1; + static double mediumScreenScaleFactor = 1.15; + static double largeScreenScaleFactor = 1.2; + static double xLargeScreenScaleFactor = 1.25; + static double commonScaleFactor = 1.0; + + ///use under the context of [SizeInitializer] to notify widgets with constant constructors + static void depend(BuildContext context) { + try { + Provider.of<_SizingNotifierAdapter>(context, listen: true); + } catch (e) { + throw FlutterError('Use method Adaptix.depend only inside build methods under SizeInitializer widget\' context'); + } + } +} + +extension SizingExtendsion on num { + double get orientationWidth => _Sizing._blocksizeHorizontal * this; + + double get orientationHeight => _Sizing._blockSizeVertical * this; + + double adaptedPx() { + return this * + Resizer( + xSmall: Adaptix.xSmallScreenScaleFactor * Adaptix.commonScaleFactor, + small: Adaptix.smallScreenScaleFactor * Adaptix.commonScaleFactor, + medium: Adaptix.mediumScreenScaleFactor * Adaptix.commonScaleFactor, + large: Adaptix.largeScreenScaleFactor * Adaptix.commonScaleFactor, + xlarge: Adaptix.xLargeScreenScaleFactor * Adaptix.commonScaleFactor, + totalWidth: _Sizing._screenWidth) + .value; + } +} diff --git a/lib/core/adaptix/models/resizer.dart b/lib/core/adaptix/models/resizer.dart new file mode 100644 index 0000000..9c78423 --- /dev/null +++ b/lib/core/adaptix/models/resizer.dart @@ -0,0 +1,41 @@ +part of adaptix; + +class Resizer{ + + late final T _xSmall; + late final T _small; + late final T _medium; + late final T _large; + late final T _xlarge; + late final double totalWidth; + late final T value; + + T _invoke(){ + if(totalWidth <= 380 ){ + return _xSmall; + } + else if(totalWidth>380 && totalWidth <= 414){ + return _small; + } + else if(totalWidth>414 && totalWidth<=600){ + return _medium; + } + else if(totalWidth>600 && totalWidth<=800){ + return _large; + } + else{ + return _xlarge; + } + } + + Resizer({T? xSmall ,required T small, T? medium, T? large, T? xlarge,required this.totalWidth }): + _xSmall = xSmall ?? small, + _small = small, + _medium = medium ?? small, + _large = large ?? small, + _xlarge = xlarge ?? small + { + value = _invoke(); + } + +} \ No newline at end of file diff --git a/lib/core/adaptix/models/sizing.dart b/lib/core/adaptix/models/sizing.dart new file mode 100644 index 0000000..52c1275 --- /dev/null +++ b/lib/core/adaptix/models/sizing.dart @@ -0,0 +1,37 @@ +part of adaptix; + +_SizingNotifierAdapter _adapter = _SizingNotifierAdapter(); + +class _SizingNotifierAdapter with ChangeNotifier{ + + void setSizing(BoxConstraints constraints, Orientation orientation){ + _Sizing().._init(constraints, orientation); + notifyListeners(); + } + +} + +class _Sizing{ + static late double _screenWidth; + static late double _screenHeight; + static late double _blocksizeHorizontal = 0; + static late double _blockSizeVertical = 0; + static late double aspectRatio; + static late EdgeInsets systemPadding; + + void _init( BoxConstraints constraints, Orientation orientation ){ + if( orientation == Orientation.portrait ){ + _screenWidth = constraints.maxWidth; + _screenHeight = constraints.maxHeight; + } + else{ + _screenWidth = constraints.maxHeight; + _screenHeight = constraints.maxWidth; + } + _blocksizeHorizontal = _screenWidth/100; + _blockSizeVertical = _screenHeight/100; + + systemPadding = MediaQueryData.fromWindow(window).padding; + aspectRatio = _blockSizeVertical / _blocksizeHorizontal; + } +} \ No newline at end of file diff --git a/lib/core/adaptix/widgets/initializer.dart b/lib/core/adaptix/widgets/initializer.dart new file mode 100644 index 0000000..ba66383 --- /dev/null +++ b/lib/core/adaptix/widgets/initializer.dart @@ -0,0 +1,23 @@ +part of adaptix; + +class SizeInitializer extends SingleChildStatelessWidget { + const SizeInitializer({required this.builder}) : super(key: const Key('sizeInit')); + + final Widget Function(BuildContext context) builder; + + @override + Widget buildWithChild(BuildContext context, _) { + return OrientationBuilder( + builder: (context, orientation) { + return LayoutBuilder( + builder: (context, constraints) { + return ChangeNotifierProvider.value( + value: _adapter..setSizing(constraints, orientation), + builder: (_, __) => builder(context), + ); + }, + ); + }, + ); + } +} diff --git a/lib/core/lazyload/lazyload.dart b/lib/core/lazyload/lazyload.dart new file mode 100644 index 0000000..10042ff --- /dev/null +++ b/lib/core/lazyload/lazyload.dart @@ -0,0 +1,7 @@ +library lazyload; + +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +part 'widget.dart'; +part 'streamControl.dart'; diff --git a/lib/core/lazyload/streamControl.dart b/lib/core/lazyload/streamControl.dart new file mode 100644 index 0000000..990d6a6 --- /dev/null +++ b/lib/core/lazyload/streamControl.dart @@ -0,0 +1,41 @@ +part of lazyload; + +mixin _StreamControlledMixin on State{ + Future Function() get asyncAction; + StreamSubscription? channel; + bool isLoading = false; + void start(BuildContext context){} + void done(BuildContext context){} + void error(BuildContext context, dynamic error){} + void onDataRecived(BuildContext context, D data){} + + void cancel(){ + channel?.cancel(); + } + + void connect(BuildContext ctx){ + cancel(); + this.setState(() { + start(ctx); + isLoading = true; + this.channel = asyncAction().asStream() + .listen((event){ + this.onDataRecived(ctx, event); + }) + ..onDone((){ + done(ctx); + if(mounted) + this.setState(() { + isLoading = false; + }); + }) + ..onError((e){ + print('error from generics $e'); + error(ctx, e); + }) + ; + }); + } + + +} \ No newline at end of file diff --git a/lib/core/lazyload/widget.dart b/lib/core/lazyload/widget.dart new file mode 100644 index 0000000..a941277 --- /dev/null +++ b/lib/core/lazyload/widget.dart @@ -0,0 +1,308 @@ +part of lazyload; + +typedef PaginatedData = Future> Function(int page, BuildContext context); +typedef _GetterDelegate = T Function(); + +class FetchController with ChangeNotifier { + _GetterDelegate _refresh = () {}; + _GetterDelegate _currentPage = () => 0; + _GetterDelegate _isLoading = () => true; + _GetterDelegate _isError = () => false; + + void _update() { + if (SchedulerBinding.instance != null) + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + notifyListeners(); + }); + else + notifyListeners(); + } + + set _setRefresh(_GetterDelegate refreshDelegate) { + _refresh = refreshDelegate; + } + + set _setCurrentPage(_GetterDelegate currentPageDelegate) { + _currentPage = currentPageDelegate; + } + + set _setIsLoading(_GetterDelegate loadingDelegate) { + _isLoading = loadingDelegate; + } + + set _setIsError(_GetterDelegate isErrorDelegate) { + _isError = isErrorDelegate; + } + + void _init({ + required _GetterDelegate refreshDelegate, + required _GetterDelegate pageDelegate, + required _GetterDelegate loadingDelegate, + required _GetterDelegate isErrorDelegate, + }) { + _setRefresh = refreshDelegate; + _setCurrentPage = pageDelegate; + _setIsLoading = loadingDelegate; + _setIsError = isErrorDelegate; + _update(); + } + + @visibleForTesting + void init({ + required _GetterDelegate refreshDelegate, + required _GetterDelegate pageDelegate, + required _GetterDelegate loadingDelegate, + required _GetterDelegate isErrorDelegate, + }) { + _init(refreshDelegate: refreshDelegate, pageDelegate: pageDelegate, loadingDelegate: loadingDelegate, isErrorDelegate: isErrorDelegate); + } + + @override + void dispose() { + if (SchedulerBinding.instance == null) + super.dispose(); + else + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + super.dispose(); + }); + } + + void refresh() { + _refresh(); + } + + bool get isLoading => _isLoading(); + bool get isError => _isError(); + int get currentPage => _currentPage(); +} + +class LazyLoadView extends StatefulWidget { + LazyLoadView( + {Key? key, + required this.data, + this.fetchController, + this.before = const [], + this.after = const [], + this.contentPadding = const EdgeInsets.all(0), + required this.loaderWidget, + required this.loadMoreWidget, + required this.errorWidget, + required this.errorOnLoadMoreWidget, + this.scrollPhysics, + required this.itemBuilder, + this.pageFactor = 10, + this.gridDelegate, + this.emptyWidget = const SliverToBoxAdapter(), + this.needBottomSpace = true, + this.needPagination = true, + this.overridePullToRefresh, + this.disableScrollOnLoad = true, + this.scrollController}) + : super(key: key); + + final FetchController? fetchController; + final PaginatedData data; + final List before; + final List after; + final EdgeInsets contentPadding; + final Widget loaderWidget; + final Widget loadMoreWidget; + final SliverGridDelegate? gridDelegate; + final Widget Function(void Function() closure, dynamic e) errorWidget; + final Widget Function(void Function() closure, dynamic e) errorOnLoadMoreWidget; + final ScrollPhysics? scrollPhysics; + final Widget Function(BuildContext context, T model, int index) itemBuilder; + final int pageFactor; + final Widget emptyWidget; + final bool needBottomSpace; + final bool needPagination; + final void Function()? overridePullToRefresh; + final ScrollController? scrollController; + final bool disableScrollOnLoad; + + @override + LazyLoadViewState createState() => LazyLoadViewState(); +} + +class LazyLoadViewState<_T> extends State> with _StreamControlledMixin, List<_T>> { + late int _pagefactor; + List<_T> _data = []; + bool _isError = false; + StreamSubscription? _channel; + bool get _isErrorOnLoadMore => _data.isNotEmpty && _isError; + bool get _isLoadingMore => _data.isNotEmpty && isLoading; + late ScrollController controller; + dynamic errorTrace; + bool performingFrame = false; + + List<_T> get data => [..._data]; + + int get _page { + return (_data.length / _pagefactor).ceil(); + } + + @override + Future Function() get asyncAction => () => widget.data(_page + 1, context); + + @override + start(_) { + setState(() { + _isError = false; + widget.fetchController?._update(); + }); + } + + @override + done(_) { + widget.fetchController?._update(); + } + + @override + onDataRecived(cntxt, dataRecieved) { + var finalData = dataRecieved as List<_T>; + setState(() { + _data.addAll(finalData); + widget.fetchController?._update(); + }); + } + + @override + error(_, err) { + setState(() { + _isError = true; + errorTrace = err; + widget.fetchController?._update(); + }); + } + + @override + void cancel() { + widget.fetchController?._update(); + _channel?.cancel(); + } + + @override + get channel => _channel; + + @override + set channel(v) { + _channel = v + ?..onDone(() async { + if (_data.isNotEmpty && widget.needPagination && !performingFrame) await Future.delayed(Duration(milliseconds: 570)); + if (mounted) { + setState(() { + if (performingFrame) performingFrame = false; + isLoading = false; + widget.fetchController?._update(); + }); + } + }); + } + + void _scrollListener() { + if ((controller.offset >= controller.position.maxScrollExtent && widget.needPagination)) { + _loadMore(); + } + } + + void _loadMore() async { + if (_data.length == _pagefactor * _page && !isLoading && !_isLoadingMore && !_isError) { + setState(() { + widget.fetchController?._update(); + connect(context); + }); + } + } + + void refresh() { + setState(() { + _data.clear(); + isLoading = true; + performingFrame = true; + widget.fetchController?._update(); + }); + connect(context); + } + + void tryAgain() { + widget.fetchController?._update(); + connect(context); + } + + @override + void dispose() { + super.dispose(); + cancel(); + isLoading = false; + if (widget.scrollController == null) controller.dispose(); + channel?.cancel(); + } + + int _getPage() => _page; + bool _getIsLoading() => isLoading; + bool _getIsError() => _isError; + + @override + void initState() { + super.initState(); + _pagefactor = widget.pageFactor; + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + if (widget.fetchController != null) { + widget.fetchController?._init(refreshDelegate: refresh, pageDelegate: _getPage, loadingDelegate: _getIsLoading, isErrorDelegate: _getIsError); + } + }); + controller = (widget.scrollController ?? ScrollController())..addListener(_scrollListener); + connect(context); + } + + @override + Widget build(BuildContext context) { + return Container( + child: RefreshIndicator( + onRefresh: () async { + if (widget.overridePullToRefresh == null) + refresh(); + else + widget.overridePullToRefresh!(); + }, + child: CustomScrollView( + physics: isLoading && !_isLoadingMore && widget.disableScrollOnLoad ? NeverScrollableScrollPhysics() : widget.scrollPhysics, + controller: controller, + slivers: [ + if (isLoading && _data.isEmpty) + widget.loaderWidget + else if (_isError && _data.isEmpty) + widget.errorWidget(refresh, errorTrace) + else if (_data.isEmpty) + widget.emptyWidget + else if (widget.gridDelegate != null) + SliverPadding( + padding: widget.contentPadding, + sliver: SliverGrid( + delegate: SliverChildBuilderDelegate((_, index) => widget.itemBuilder(context, _data[index], index), childCount: _data.length), + gridDelegate: widget.gridDelegate!), + ) + else + SliverPadding( + padding: widget.contentPadding, + sliver: SliverList( + delegate: SliverChildBuilderDelegate((context, index) => widget.itemBuilder(context, _data[index], index), childCount: _data.length), + ), + ), + if (_isLoadingMore) widget.loadMoreWidget else if (_isErrorOnLoadMore) widget.errorOnLoadMoreWidget(tryAgain, errorTrace) + ] + ..insertAll(0, widget.before) + ..addAll([if (!isLoading && !_isLoadingMore) ...widget.after]) + ..addAll([ + if (widget.needBottomSpace) + SliverToBoxAdapter( + child: SizedBox( + height: (MediaQuery.of(context).size.height * 0.1) / 2, + ), + ) + ]), + ), + ), + ); + } +} diff --git a/lib/core/manager/manager.dart b/lib/core/manager/manager.dart new file mode 100644 index 0000000..b2092f1 --- /dev/null +++ b/lib/core/manager/manager.dart @@ -0,0 +1,19 @@ +library manager; + +import 'dart:math'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'dart:async'; +import 'package:rxdart/rxdart.dart'; +import 'package:provider/provider.dart'; +export 'manager.dart' show Manager; +export 'widgets/manager_selector.dart'; +part 'models/manager_model.dart'; +part 'models/task.dart'; +part 'widgets/manager_builder.dart'; +part 'models/paginated_manager.dart'; +part 'widgets/paginated_collection_builder.dart'; +part 'models/manager_state.dart'; +part 'models/manager_observer_mixin.dart'; + +const _kPaginatedTaskKey = 'pagino'; diff --git a/lib/core/manager/models/manager_model.dart b/lib/core/manager/models/manager_model.dart new file mode 100644 index 0000000..4649167 --- /dev/null +++ b/lib/core/manager/models/manager_model.dart @@ -0,0 +1,127 @@ +part of manager; + +abstract class Manager extends ChangeNotifier { + late BehaviorSubject value; + late Model _value; + + Model get dataSync => _value; + + Model transformer(Model newModel) { + return newModel; + } + + final Map?> _tasks = {}; + final Map _listeners = {}; + + Task? getTaskByKey(String id) => _tasks[id] == null + ? null + : Task(computation: _tasks[id]!.computation, key: _tasks[id]!.key) + ?.._stateController = _tasks[id]!._stateController + .._creationDate = _tasks[id]!._creationDate + .._subscriptionToFuture = _tasks[id]!._subscriptionToFuture; + + Stream>? taskStateOnly(String key) => _tasks[key]?.state; + + Stream> taskStateWithLatestValue(String key) => + CombineLatestStream.combine2, Model, + ManagerState>(_tasks[key]?.state ?? const Stream.empty(), + value, (a, b) => ManagerState(state: b, taskResult: a)); + + Future addTask(Task newTask, {bool shouldStart = true}) async { + try { + await _tasks[newTask.key]?._cancelInnerFutureSubscription(); + await _listeners[newTask.key]?.cancel(); + } catch (e) { + if (kDebugMode) { + print('Error in managers addtask function of $Model: $e'); + } + } + if (_tasks[newTask.key] == null) { + _tasks[newTask.key] = newTask; + } else { + _tasks[newTask.key]!.computation = newTask.computation; + _tasks[newTask.key]!._creationDate = DateTime.now(); + } + if (shouldStart) { + _tasks[newTask.key]!._register(); + _listeners[newTask.key] = _tasks[newTask.key]!.state.listen((event) { + if (event.status == TaskStatus.Success && event.value != null) { + value.add(transformer(event.value!)); + } + listenerCallBack(event, newTask.key); + }); + } + notifyListeners(); + } + + Future startTask(String taskID) async { + if (_tasks[taskID] != null) { + try { + await _tasks[taskID]?._cancelInnerFutureSubscription(); + await _listeners[taskID]?.cancel(); + } catch (e) { + if (kDebugMode) { + print('Error in managers startTask function of $Model: $e'); + } + } + _tasks[taskID]!._register(); + _tasks[taskID]!._creationDate = DateTime.now(); + _listeners[taskID] = _tasks[taskID]!.state.listen((event) { + listenerCallBack(event, taskID); + if (event.status == TaskStatus.Success && event.value != null) { + value.add(transformer(event.value!)); + } + }); + notifyListeners(); + } + } + + void refreshIfError(String key) async { + await _tasks[key]?._cancelInnerFutureSubscription(); + _tasks[key]?._register(); + } + + Stream> _destroy() async* { + for (var key in _tasks.keys) { + yield Future(() async { + await _listeners[key]?.cancel(); + await _tasks[key]?._destroy(); + _tasks[key] = null; + _listeners[key] = null; + }); + } + } + + Future destroy() async { + await for (var process in _destroy()) { + try { + await process; + // ignore: empty_catches + } catch (e) {} + } + notifyListeners(); + } + + Future destroyTask(String taskId) async { + await _listeners[taskId]?.cancel(); + await _tasks[taskId]?._destroy(); + _listeners[taskId] = null; + _tasks[taskId] = null; + notifyListeners(); + } + + void valueListener(Model newValue) { + _value = newValue; + notifyListeners(); + } + + void listenerCallBack(TaskResult result, String taskKey) {} + + static Duration globalTaskTimeOut = const Duration(minutes: 1); + + Manager(Model initialData) + : value = BehaviorSubject.seeded(initialData), + _value = initialData { + value.listen(valueListener); + } +} diff --git a/lib/core/manager/models/manager_observer_mixin.dart b/lib/core/manager/models/manager_observer_mixin.dart new file mode 100644 index 0000000..7b79014 --- /dev/null +++ b/lib/core/manager/models/manager_observer_mixin.dart @@ -0,0 +1,37 @@ +part of manager; + +mixin ManagerObserverMixin on State{ + + void updateListener(); + void _updateListener(){ + var _newVal = selector(context, Provider.of(context, listen: false)); + if(shouldUpdateListener(_oldVal, _newVal)){ + updateListener(); + } + _oldVal = _newVal; + } + + late M manager; + + V selector(BuildContext context, M someManager); + + late V _oldVal; + + bool shouldUpdateListener(V oldManager, V newManager); + + @mustCallSuper + @override + void initState() { + super.initState(); + manager = Provider.of(context, listen: false); + _oldVal = selector(context, Provider.of(context, listen: false)); + manager.addListener(_updateListener); + } + + @mustCallSuper + @override + void dispose(){ + manager.removeListener(_updateListener); + super.dispose(); + } +} \ No newline at end of file diff --git a/lib/core/manager/models/manager_state.dart b/lib/core/manager/models/manager_state.dart new file mode 100644 index 0000000..0b7377f --- /dev/null +++ b/lib/core/manager/models/manager_state.dart @@ -0,0 +1,10 @@ +part of manager; + +class ManagerState{ + + final TaskResult taskResult; + final Model state; + + ManagerState({required this.state,required this.taskResult}); + +} \ No newline at end of file diff --git a/lib/core/manager/models/paginated_manager.dart b/lib/core/manager/models/paginated_manager.dart new file mode 100644 index 0000000..c66b592 --- /dev/null +++ b/lib/core/manager/models/paginated_manager.dart @@ -0,0 +1,51 @@ +part of manager; + +Future delay() => Future.delayed(const Duration(microseconds: 100)); + +class Pagination { + final Set data; + final int page; + Pagination({this.data = const {}, this.page = 0}); +} + +abstract class PaginatedManager extends Manager> { + int get perPage; + Future> Function(int page) get computatiion; + + void _paginate() { + if (_value.data.length == perPage * _value.page) { + addTask(Task( + computation: () => computatiion(_value.page + 1), + key: _kPaginatedTaskKey)); + } + } + + void refresh() async { + value.add(Pagination()); + await addTask(Task( + computation: () async { + return Pagination(); + }, + key: _kPaginatedTaskKey)); + _paginate(); + } + + @override + transformer(newModel) { + late Pagination valueCopy = + Pagination(data: {..._value.data}, page: _value.page); + if (newModel.page == 0) { + valueCopy = newModel; + } else { + var merged = {...valueCopy.data, ...newModel.data}; + valueCopy = Pagination( + data: merged, page: max(1, (merged.length / perPage).truncate())); + } + return valueCopy; + } + + PaginatedManager({Pagination? initialData}) + : super(initialData ?? Pagination()) { + refresh(); + } +} diff --git a/lib/core/manager/models/task.dart b/lib/core/manager/models/task.dart new file mode 100644 index 0000000..199f20f --- /dev/null +++ b/lib/core/manager/models/task.dart @@ -0,0 +1,88 @@ +part of manager; + +enum TaskStatus { + // ignore: constant_identifier_names + Loading, + // ignore: constant_identifier_names + Error, + // ignore: constant_identifier_names + Success, + // ignore: constant_identifier_names + None +} + +class TaskResult { + final TaskStatus status; + final Model? value; + final Exception? errorTrace; + + TaskResult({this.value, required this.status, this.errorTrace}); +} + +class Task { + final String key; + late DateTime _creationDate; + // ignore: prefer_final_fields + BehaviorSubject> _stateController = BehaviorSubject(); + Future Function() computation; + Stream> get state => _stateController; + late StreamSubscription _subscriptionToFuture; + + @visibleForTesting + DateTime get timeStamp => _creationDate; + + void _register() { + if (!_stateController.isClosed) { + _stateController.add(TaskResult(status: TaskStatus.Loading)); + var _future = Future(() async { + try { + var newModel = await computation().timeout(Manager.globalTaskTimeOut); + return newModel; + } on TimeoutException catch (_) { + throw Exception('time exceeded'); + } + }); + _subscriptionToFuture = _future.asStream().listen((event) { + if (!_stateController.isClosed) { + _stateController + .add(TaskResult(status: TaskStatus.Success, value: event)); + } + }) + ..onError((e) { + var trace = e is Exception ? e : null; + if (kDebugMode) { + print('Error <$e> in Task:<$key>'); + } + if (!_stateController.isClosed) { + _stateController.add(TaskResult( + status: TaskStatus.Error, errorTrace: trace)); + } + }); + } + } + + Future _cancelInnerFutureSubscription() { + _stateController.add(TaskResult(status: TaskStatus.Loading)); + return _subscriptionToFuture.cancel(); + } + + Future _destroy() async { + _stateController.add(TaskResult(status: TaskStatus.None)); + await _subscriptionToFuture.cancel(); + return _stateController.close(); + } + + @override + bool operator ==(other) { + return other is Task && + hashCode == other.hashCode && + other._creationDate.isAtSameMomentAs(_creationDate); + } + + @override + int get hashCode => key.hashCode; + + Task({required this.computation, required this.key}) { + _creationDate = DateTime.now(); + } +} diff --git a/lib/core/manager/widgets/manager_builder.dart b/lib/core/manager/widgets/manager_builder.dart new file mode 100644 index 0000000..38277dd --- /dev/null +++ b/lib/core/manager/widgets/manager_builder.dart @@ -0,0 +1,23 @@ +part of manager; + +class TaskObserverBuilder, Model> extends StatelessWidget { + const TaskObserverBuilder({Key? key,required this.taskKey,required this.builder}) : super(key: key); + + final String taskKey; + final Widget Function(BuildContext context, TaskStatus status, Model model, void Function() refresh) builder; + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, manager, child) { + return StreamBuilder>( + stream: manager.taskStateWithLatestValue(taskKey), + builder: (context, snapshot) { + final TaskStatus status = snapshot.data?.taskResult.status ?? TaskStatus.Loading; + return builder(context, status, manager.dataSync, () => manager.refreshIfError(taskKey)); + }, + ); + }, + ); + } +} \ No newline at end of file diff --git a/lib/core/manager/widgets/manager_selector.dart b/lib/core/manager/widgets/manager_selector.dart new file mode 100644 index 0000000..74f1f58 --- /dev/null +++ b/lib/core/manager/widgets/manager_selector.dart @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import '../manager.dart'; + +class ManagerSelector extends StatefulWidget { + const ManagerSelector({Key? key, required this.selector, required this.shouldRebuild, required this.onUpdate, required this.builder}) : super(key: key); + + final V Function(BuildContext, M) selector; + final bool Function(V, V) shouldRebuild; + final VoidCallback onUpdate; + final Widget Function(BuildContext, V) builder; + + @override + _ManagerSelectorState createState() => _ManagerSelectorState(); +} + +class _ManagerSelectorState extends State> with ManagerObserverMixin, M, V> { + @override + Widget build(BuildContext context) { + return widget.builder(context, selector(context, manager)); + } + + @override + V selector(BuildContext context, M someManager) { + return widget.selector(context, someManager); + } + + @override + bool shouldUpdateListener(V oldVal, V newVal) { + return widget.shouldRebuild(oldVal, newVal); + } + + @override + void updateListener() { + widget.onUpdate(); + if (mounted) { + setState(() {}); + } + } +} diff --git a/lib/core/manager/widgets/paginated_collection_builder.dart b/lib/core/manager/widgets/paginated_collection_builder.dart new file mode 100644 index 0000000..4ecdd1e --- /dev/null +++ b/lib/core/manager/widgets/paginated_collection_builder.dart @@ -0,0 +1,204 @@ +part of manager; + +class PaginatedCollectionBuilder, Model> + extends StatefulWidget { + const PaginatedCollectionBuilder( + {Key? key, + this.before = const [], + this.after = const [], + this.contentPadding = const EdgeInsets.all(0), + required this.loaderWidget, + required this.loadMoreWidget, + required this.errorWidget, + required this.errorOnLoadMoreWidget, + this.scrollPhysics, + required this.itemBuilder, + this.gridDelegate, + this.filter, + this.emptyWidget = const SliverToBoxAdapter(), + this.needbottomSpace = true}) + : super(key: key); + + final List before; + final List after; + final EdgeInsets contentPadding; + final Widget loaderWidget; + final Widget loadMoreWidget; + final List Function(List m)? filter; + final SliverGridDelegate? gridDelegate; + final Widget Function(void Function() closure) errorWidget; + final Widget Function(void Function() closure) errorOnLoadMoreWidget; + final ScrollPhysics? scrollPhysics; + final Widget Function(BuildContext context, Model model, int index) + itemBuilder; + final Widget emptyWidget; + final bool needbottomSpace; + + @override + _PaginatedCollectionBuilderState createState() => + _PaginatedCollectionBuilderState(); +} + +class _PaginatedCollectionBuilderState<_T extends PaginatedManager<_Model>, + _Model> extends State> + with + ManagerObserverMixin, _T, + Task>?> { + // ignore: unused_field + int _page = 1; + List<_Model> _secretData = []; + + List<_Model> get _data { + return _secretData; + } + + set _data(List<_Model> other) { + _secretData = [ + if (widget.filter != null) ...widget.filter!([...other]) else ...other + ]; + } + + bool get _isError => _status == TaskStatus.Error; + StreamSubscription? _channel; + TaskStatus _status = TaskStatus.Loading; + bool get isLoading => _status == TaskStatus.Loading; + bool get _isErrorOnLoadMore => _data.isNotEmpty && _isError; + bool get _isLoadingMore => _data.isNotEmpty && isLoading; + late ScrollController controller; + + void _scrollListener() { + if ((controller.offset >= controller.position.maxScrollExtent)) { + _loadMore(); + } + } + + void _loadMore() async { + if (!isLoading && !_isLoadingMore && !_isError) { + setState(() { + Provider.of<_T>(context, listen: false)._paginate(); + }); + } + } + + void tryAgain() { + Provider.of<_T>(context, listen: false)._paginate(); + } + + void refresh() { + Provider.of<_T>(context, listen: false).refresh(); + } + + void initializeData() async { + setState(() { + _data = [...Provider.of<_T>(context, listen: false).dataSync.data]; + _page = Provider.of<_T>(context, listen: false).dataSync.page; + }); + } + + @override + selector(_, man) { + return man.getTaskByKey(_kPaginatedTaskKey); + } + + @override + shouldUpdateListener(prev, next) { + return prev != next; + } + + @override + updateListener() { + _channel = Provider.of<_T>(context, listen: false) + .taskStateWithLatestValue(_kPaginatedTaskKey) + .listen((event) async { + if (mounted) { + final newManagerState = event.state; + final _taskStatus = event.taskResult.status; + setState(() { + _status = _taskStatus; + }); + if (_taskStatus == TaskStatus.Success) { + setState(() { + _data = [...newManagerState.data]; + _page = newManagerState.page; + if (_data.isEmpty) { + controller.jumpTo(1); + } + }); + } + } + }); + } + + @override + void initState() { + super.initState(); + initializeData(); + controller = ScrollController(); + controller.addListener(_scrollListener); + updateListener(); + } + + @override + void dispose() { + _channel?.cancel(); + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return RefreshIndicator( + onRefresh: () async { + refresh(); + }, + child: CustomScrollView( + physics: isLoading && !_isLoadingMore + ? const NeverScrollableScrollPhysics() + : widget.scrollPhysics, + controller: controller, + slivers: [ + if (isLoading && _data.isEmpty) + widget.loaderWidget + else if (_isError && _data.isEmpty) + widget.errorWidget(refresh) + else if (_data.isEmpty) + widget.emptyWidget + else if (widget.gridDelegate != null) + SliverPadding( + padding: widget.contentPadding, + sliver: SliverGrid( + delegate: SliverChildBuilderDelegate( + (_, index) => + widget.itemBuilder(context, _data[index], index), + childCount: _data.length), + gridDelegate: widget.gridDelegate!), + ) + else + SliverPadding( + padding: widget.contentPadding, + sliver: SliverList( + delegate: SliverChildListDelegate(List.generate( + _data.length, + (index) => + widget.itemBuilder(context, _data[index], index))), + ), + ), + if (_isLoadingMore) + widget.loadMoreWidget + else if (_isErrorOnLoadMore) + widget.errorOnLoadMoreWidget(tryAgain) + ] + ..insertAll(0, widget.before) + ..addAll(widget.after) + ..addAll([ + if (widget.needbottomSpace) + SliverToBoxAdapter( + child: SizedBox( + height: (MediaQuery.of(context).size.height * 0.1) / 2, + ), + ) + ]), + ), + ); + } +} diff --git a/lib/core/orm/models/dao.dart b/lib/core/orm/models/dao.dart new file mode 100644 index 0000000..fe6b118 --- /dev/null +++ b/lib/core/orm/models/dao.dart @@ -0,0 +1,10 @@ +import '../orm.dart'; + +abstract class OrmDao { + Future apply(List records); + Future delete(List records); + Future> read(); + String get name; + Future getByKey(String fieldName, PKeyType key); + Future clear(); +} diff --git a/lib/core/orm/models/database/database.dart b/lib/core/orm/models/database/database.dart new file mode 100644 index 0000000..e48050d --- /dev/null +++ b/lib/core/orm/models/database/database.dart @@ -0,0 +1,96 @@ +import '../dao.dart'; +import '../../orm.dart'; +import 'package:sembast/sembast.dart'; +import 'package:sembast/timestamp.dart'; +import 'package:sembast/utils/value_utils.dart'; +import 'stub.dart' if (dart.library.io) 'mobile.dart' if (dart.library.html) 'web.dart'; + +const kCreatedTimeStampField = 'created_at'; + +typedef ConstructorDelegate = T Function(Map data); +typedef TransactionDelegate = Future Function(Transaction transaction); + +class OrmDataBase implements OrmDao { + OrmDataBase({required this.name, required this.constructorDelegate}); + + final String name; + final ConstructorDelegate constructorDelegate; + StoreRef get _getTable => intMapStoreFactory.store(name); + + @override + Future apply(List records, {bool withTimeStamp = false}) { + var store = _getTable; + return _makeTransaction((trans) async { + for (int i = 0; i < records.length; i++) { + var innerData = {...records[i].jSON}; + if (withTimeStamp && innerData[kCreatedTimeStampField] == null) innerData[kCreatedTimeStampField] = Timestamp.fromDateTime(DateTime.now()); + var postKey = await store.findFirst(trans, finder: Finder(filter: Filter.equals(records[i].primaryKeyField, records[i].primaryKey))); + if (postKey == null) + await store.add(trans, innerData); + else + await store.update(trans, innerData, finder: Finder(filter: Filter.equals(records[i].primaryKeyField, records[i].primaryKey))); + } + }); + } + + Future deleteWhere({Filter? filter}) { + var store = _getTable; + return _makeTransaction((trans) async { + await store.delete(trans, finder: Finder(filter: filter)); + }); + } + + @override + Future delete(List records) { + var store = _getTable; + return _makeTransaction((trans) async { + for (int i = 0; i < records.length; i++) { + var postKey = await store.findFirst(trans, finder: Finder(filter: Filter.equals(records[i].primaryKeyField, records[i].primaryKey))); + if (postKey != null) await store.record(postKey.key).delete(trans); + } + }); + } + + @override + Future> read({int? offset, int? limit, Filter? filter, bool getAll = false}) async { + var store = _getTable; + var finder = Finder(offset: getAll ? null : offset, limit: getAll ? null : limit, filter: filter); + + var list = await store.find(_database!, finder: finder); + return list.map((item) => constructorDelegate(cloneMap(item.value))).toList(); + } + + @override + Future getByKey(String fieldName, PKeyType key) async { + var store = _getTable; + var item = await store.findFirst(_database!, finder: Finder(filter: Filter.equals(fieldName, key))); + return item == null ? null : constructorDelegate(cloneMap(item.value)); + } + + @override + Future clear() { + var store = _getTable; + return store.delete(_database!); + } + + static Future get _localPath => getAppDbPath(); + + static Future _makeTransaction(TransactionDelegate action) async { + await _database!.transaction(action); + } + + static Future _launch() async { + String nameOfDataBase = 'ormDb'; + String path = await _localPath; + DatabaseFactory postFactory = appDataBaseFactory(); + return postFactory.openDatabase('$path/$nameOfDataBase'); + } + + static Database? _database; + + static Future init() async { + await _database?.close(); + _database = null; + _database = await _launch(); + } +} diff --git a/lib/core/orm/models/database/mobile.dart b/lib/core/orm/models/database/mobile.dart new file mode 100644 index 0000000..527f9d2 --- /dev/null +++ b/lib/core/orm/models/database/mobile.dart @@ -0,0 +1,11 @@ +import 'package:path_provider/path_provider.dart'; +import 'package:sembast/sembast.dart'; +import 'package:sembast/sembast_io.dart'; + +DatabaseFactory appDataBaseFactory() { + return databaseFactoryIo; +} + +Future getAppDbPath() async { + return (await getApplicationDocumentsDirectory()).path; +} diff --git a/lib/core/orm/models/database/stub.dart b/lib/core/orm/models/database/stub.dart new file mode 100644 index 0000000..4014c1b --- /dev/null +++ b/lib/core/orm/models/database/stub.dart @@ -0,0 +1,10 @@ +import 'package:sembast/sembast.dart'; + +DatabaseFactory appDataBaseFactory() { + throw UnimplementedError('OrmDatabase has no factory for current platform'); +} + +Future getAppDbPath() { + throw UnimplementedError( + 'OrmDatabase has no database path for current platform'); +} diff --git a/lib/core/orm/models/database/web.dart b/lib/core/orm/models/database/web.dart new file mode 100644 index 0000000..d7a84a9 --- /dev/null +++ b/lib/core/orm/models/database/web.dart @@ -0,0 +1,11 @@ +import 'package:flutter/foundation.dart'; +import 'package:sembast/sembast.dart'; +import 'package:sembast_web/sembast_web.dart'; + +DatabaseFactory appDataBaseFactory() { + return databaseFactoryWeb; +} + +Future getAppDbPath() { + return SynchronousFuture('web_storage'); +} diff --git a/lib/core/orm/orm.dart b/lib/core/orm/orm.dart new file mode 100644 index 0000000..429a0d9 --- /dev/null +++ b/lib/core/orm/orm.dart @@ -0,0 +1,34 @@ +library orm; + +import 'package:sembast/timestamp.dart'; +import 'models/database/database.dart'; +export 'models/database/database.dart' hide kCreatedTimeStampField; +export 'package:sembast/sembast.dart' show Filter; + +abstract class Orm { + Map jSON; + String get primaryKeyField; + + PKeyType get primaryKey => jSON[primaryKeyField] as PKeyType; + + bool operator ==(other) { + return (other is Orm && other.hashCode == this.hashCode); + } + + int get hashCode => primaryKey.hashCode; + + @override + String toString() { + return jSON.toString(); + } + + Orm(this.jSON); +} + +mixin CopyAbleMixin { + T get copy; +} + +abstract class CreationTime implements Orm { + Timestamp? get createdAt => jSON[kCreatedTimeStampField]; +} diff --git a/lib/countryCodes.dart b/lib/countryCodes.dart new file mode 100644 index 0000000..477d100 --- /dev/null +++ b/lib/countryCodes.dart @@ -0,0 +1,244 @@ +const countryCodes = [ + {"country_name": "Turkmenistan", "dial_code": "+993"}, + {"country_name": "Afghanistan", "dial_code": "+93"}, + {"country_name": "Aland Islands", "dial_code": "+358"}, + {"country_name": "Albania", "dial_code": "+355"}, + {"country_name": "Algeria", "dial_code": "+213"}, + {"country_name": "AmericanSamoa", "dial_code": "+1684"}, + {"country_name": "Andorra", "dial_code": "+376"}, + {"country_name": "Angola", "dial_code": "+244"}, + {"country_name": "Anguilla", "dial_code": "+1264"}, + {"country_name": "Antarctica", "dial_code": "+672"}, + {"country_name": "Antigua and Barbuda", "dial_code": "+1268"}, + {"country_name": "Argentina", "dial_code": "+54"}, + {"country_name": "Armenia", "dial_code": "+374"}, + {"country_name": "Aruba", "dial_code": "+297"}, + {"country_name": "Australia", "dial_code": "+61"}, + {"country_name": "Austria", "dial_code": "+43"}, + {"country_name": "Azerbaijan", "dial_code": "+994"}, + {"country_name": "Bahamas", "dial_code": "+1242"}, + {"country_name": "Bahrain", "dial_code": "+973"}, + {"country_name": "Bangladesh", "dial_code": "+880"}, + {"country_name": "Barbados", "dial_code": "+1246"}, + {"country_name": "Belarus", "dial_code": "+375"}, + {"country_name": "Belgium", "dial_code": "+32"}, + {"country_name": "Belize", "dial_code": "+501"}, + {"country_name": "Benin", "dial_code": "+229"}, + {"country_name": "Bermuda", "dial_code": "+1441"}, + {"country_name": "Bhutan", "dial_code": "+975"}, + {"country_name": "Bolivia, Plurinational State of", "dial_code": "+591"}, + {"country_name": "Bosnia and Herzegovina", "dial_code": "+387"}, + {"country_name": "Botswana", "dial_code": "+267"}, + {"country_name": "Brazil", "dial_code": "+55"}, + {"country_name": "British Indian Ocean Territory", "dial_code": "+246"}, + {"country_name": "Brunei Darussalam", "dial_code": "+673"}, + {"country_name": "Bulgaria", "dial_code": "+359"}, + {"country_name": "Burkina Faso", "dial_code": "+226"}, + {"country_name": "Burundi", "dial_code": "+257"}, + {"country_name": "Cambodia", "dial_code": "+855"}, + {"country_name": "Cameroon", "dial_code": "+237"}, + {"country_name": "Canada", "dial_code": "+1"}, + {"country_name": "Cape Verde", "dial_code": "+238"}, + {"country_name": "Cayman Islands", "dial_code": "+ 345"}, + {"country_name": "Central African Republic", "dial_code": "+236"}, + {"country_name": "Chad", "dial_code": "+235"}, + {"country_name": "Chile", "dial_code": "+56"}, + {"country_name": "China", "dial_code": "+86"}, + {"country_name": "Christmas Island", "dial_code": "+61"}, + {"country_name": "Cocos (Keeling) Islands", "dial_code": "+61"}, + {"country_name": "Colombia", "dial_code": "+57"}, + {"country_name": "Comoros", "dial_code": "+269"}, + {"country_name": "Congo", "dial_code": "+242"}, + {"country_name": "Congo, The Democratic Republic of the Congo", "dial_code": "+243"}, + {"country_name": "Cook Islands", "dial_code": "+682"}, + {"country_name": "Costa Rica", "dial_code": "+506"}, + {"country_name": "Cote d'Ivoire", "dial_code": "+225"}, + {"country_name": "Croatia", "dial_code": "+385"}, + {"country_name": "Cuba", "dial_code": "+53"}, + {"country_name": "Cyprus", "dial_code": "+357"}, + {"country_name": "Czech Republic", "dial_code": "+420"}, + {"country_name": "Denmark", "dial_code": "+45"}, + {"country_name": "Djibouti", "dial_code": "+253"}, + {"country_name": "Dominica", "dial_code": "+1767"}, + {"country_name": "Dominican Republic", "dial_code": "+1849"}, + {"country_name": "Ecuador", "dial_code": "+593"}, + {"country_name": "Egypt", "dial_code": "+20"}, + {"country_name": "El Salvador", "dial_code": "+503"}, + {"country_name": "Equatorial Guinea", "dial_code": "+240"}, + {"country_name": "Eritrea", "dial_code": "+291"}, + {"country_name": "Estonia", "dial_code": "+372"}, + {"country_name": "Ethiopia", "dial_code": "+251"}, + {"country_name": "Falkland Islands (Malvinas)", "dial_code": "+500"}, + {"country_name": "Faroe Islands", "dial_code": "+298"}, + {"country_name": "Fiji", "dial_code": "+679"}, + {"country_name": "Finland", "dial_code": "+358"}, + {"country_name": "France", "dial_code": "+33"}, + {"country_name": "French Guiana", "dial_code": "+594"}, + {"country_name": "French Polynesia", "dial_code": "+689"}, + {"country_name": "Gabon", "dial_code": "+241"}, + {"country_name": "Gambia", "dial_code": "+220"}, + {"country_name": "Georgia", "dial_code": "+995"}, + {"country_name": "Germany", "dial_code": "+49"}, + {"country_name": "Ghana", "dial_code": "+233"}, + {"country_name": "Gibraltar", "dial_code": "+350"}, + {"country_name": "Greece", "dial_code": "+30"}, + {"country_name": "Greenland", "dial_code": "+299"}, + {"country_name": "Grenada", "dial_code": "+1473"}, + {"country_name": "Guadeloupe", "dial_code": "+590"}, + {"country_name": "Guam", "dial_code": "+1671"}, + {"country_name": "Guatemala", "dial_code": "+502"}, + {"country_name": "Guernsey", "dial_code": "+44"}, + {"country_name": "Guinea", "dial_code": "+224"}, + {"country_name": "Guinea-Bissau", "dial_code": "+245"}, + {"country_name": "Guyana", "dial_code": "+595"}, + {"country_name": "Haiti", "dial_code": "+509"}, + {"country_name": "Holy See (Vatican City State)", "dial_code": "+379"}, + {"country_name": "Honduras", "dial_code": "+504"}, + {"country_name": "Hong Kong", "dial_code": "+852"}, + {"country_name": "Hungary", "dial_code": "+36"}, + {"country_name": "Iceland", "dial_code": "+354"}, + {"country_name": "India", "dial_code": "+91"}, + {"country_name": "Indonesia", "dial_code": "+62"}, + {"country_name": "Iran, Islamic Republic of Persian Gulf", "dial_code": "+98"}, + {"country_name": "Iraq", "dial_code": "+964"}, + {"country_name": "Ireland", "dial_code": "+353"}, + {"country_name": "Isle of Man", "dial_code": "+44"}, + {"country_name": "Israel", "dial_code": "+972"}, + {"country_name": "Italy", "dial_code": "+39"}, + {"country_name": "Jamaica", "dial_code": "+1876"}, + {"country_name": "Japan", "dial_code": "+81"}, + {"country_name": "Jersey", "dial_code": "+44"}, + {"country_name": "Jordan", "dial_code": "+962"}, + {"country_name": "Kazakhstan", "dial_code": "+77"}, + {"country_name": "Kenya", "dial_code": "+254"}, + {"country_name": "Kiribati", "dial_code": "+686"}, + {"country_name": "Korea, Democratic People's Republic of Korea", "dial_code": "+850"}, + {"country_name": "Korea, Republic of South Korea", "dial_code": "+82"}, + {"country_name": "Kuwait", "dial_code": "+965"}, + {"country_name": "Kyrgyzstan", "dial_code": "+996"}, + {"country_name": "Laos", "dial_code": "+856"}, + {"country_name": "Latvia", "dial_code": "+371"}, + {"country_name": "Lebanon", "dial_code": "+961"}, + {"country_name": "Lesotho", "dial_code": "+266"}, + {"country_name": "Liberia", "dial_code": "+231"}, + {"country_name": "Libyan Arab Jamahiriya", "dial_code": "+218"}, + {"country_name": "Liechtenstein", "dial_code": "+423"}, + {"country_name": "Lithuania", "dial_code": "+370"}, + {"country_name": "Luxembourg", "dial_code": "+352"}, + {"country_name": "Macao", "dial_code": "+853"}, + {"country_name": "Macedonia", "dial_code": "+389"}, + {"country_name": "Madagascar", "dial_code": "+261"}, + {"country_name": "Malawi", "dial_code": "+265"}, + {"country_name": "Malaysia", "dial_code": "+60"}, + {"country_name": "Maldives", "dial_code": "+960"}, + {"country_name": "Mali", "dial_code": "+223"}, + {"country_name": "Malta", "dial_code": "+356"}, + {"country_name": "Marshall Islands", "dial_code": "+692"}, + {"country_name": "Martinique", "dial_code": "+596"}, + {"country_name": "Mauritania", "dial_code": "+222"}, + {"country_name": "Mauritius", "dial_code": "+230"}, + {"country_name": "Mayotte", "dial_code": "+262"}, + {"country_name": "Mexico", "dial_code": "+52"}, + {"country_name": "Micronesia, Federated States of Micronesia", "dial_code": "+691"}, + {"country_name": "Moldova", "dial_code": "+373"}, + {"country_name": "Monaco", "dial_code": "+377"}, + {"country_name": "Mongolia", "dial_code": "+976"}, + {"country_name": "Montenegro", "dial_code": "+382"}, + {"country_name": "Montserrat", "dial_code": "+1664"}, + {"country_name": "Morocco", "dial_code": "+212"}, + {"country_name": "Mozambique", "dial_code": "+258"}, + {"country_name": "Myanmar", "dial_code": "+95"}, + {"country_name": "Namibia", "dial_code": "+264"}, + {"country_name": "Nauru", "dial_code": "+674"}, + {"country_name": "Nepal", "dial_code": "+977"}, + {"country_name": "Netherlands", "dial_code": "+31"}, + {"country_name": "Netherlands Antilles", "dial_code": "+599"}, + {"country_name": "New Caledonia", "dial_code": "+687"}, + {"country_name": "New Zealand", "dial_code": "+64"}, + {"country_name": "Nicaragua", "dial_code": "+505"}, + {"country_name": "Niger", "dial_code": "+227"}, + {"country_name": "Nigeria", "dial_code": "+234"}, + {"country_name": "Niue", "dial_code": "+683"}, + {"country_name": "Norfolk Island", "dial_code": "+672"}, + {"country_name": "Northern Mariana Islands", "dial_code": "+1670"}, + {"country_name": "Norway", "dial_code": "+47"}, + {"country_name": "Oman", "dial_code": "+968"}, + {"country_name": "Pakistan", "dial_code": "+92"}, + {"country_name": "Palau", "dial_code": "+680"}, + {"country_name": "Palestinian Territory, Occupied", "dial_code": "+970"}, + {"country_name": "Panama", "dial_code": "+507"}, + {"country_name": "Papua New Guinea", "dial_code": "+675"}, + {"country_name": "Paraguay", "dial_code": "+595"}, + {"country_name": "Peru", "dial_code": "+51"}, + {"country_name": "Philippines", "dial_code": "+63"}, + {"country_name": "Pitcairn", "dial_code": "+872"}, + {"country_name": "Poland", "dial_code": "+48"}, + {"country_name": "Portugal", "dial_code": "+351"}, + {"country_name": "Puerto Rico", "dial_code": "+1939"}, + {"country_name": "Qatar", "dial_code": "+974"}, + {"country_name": "Romania", "dial_code": "+40"}, + {"country_name": "Russia", "dial_code": "+7"}, + {"country_name": "Rwanda", "dial_code": "+250"}, + {"country_name": "Reunion", "dial_code": "+262"}, + {"country_name": "Saint Barthelemy", "dial_code": "+590"}, + {"country_name": "Saint Helena, Ascension and Tristan Da Cunha", "dial_code": "+290"}, + {"country_name": "Saint Kitts and Nevis", "dial_code": "+1869"}, + {"country_name": "Saint Lucia", "dial_code": "+1758"}, + {"country_name": "Saint Martin", "dial_code": "+590"}, + {"country_name": "Saint Pierre and Miquelon", "dial_code": "+508"}, + {"country_name": "Saint Vincent and the Grenadines", "dial_code": "+1784"}, + {"country_name": "Samoa", "dial_code": "+685"}, + {"country_name": "San Marino", "dial_code": "+378"}, + {"country_name": "Sao Tome and Principe", "dial_code": "+239"}, + {"country_name": "Saudi Arabia", "dial_code": "+966"}, + {"country_name": "Senegal", "dial_code": "+221"}, + {"country_name": "Serbia", "dial_code": "+381"}, + {"country_name": "Seychelles", "dial_code": "+248"}, + {"country_name": "Sierra Leone", "dial_code": "+232"}, + {"country_name": "Singapore", "dial_code": "+65"}, + {"country_name": "Slovakia", "dial_code": "+421"}, + {"country_name": "Slovenia", "dial_code": "+386"}, + {"country_name": "Solomon Islands", "dial_code": "+677"}, + {"country_name": "Somalia", "dial_code": "+252"}, + {"country_name": "South Africa", "dial_code": "+27"}, + {"country_name": "South Sudan", "dial_code": "+211"}, + {"country_name": "South Georgia and the South Sandwich Islands", "dial_code": "+500"}, + {"country_name": "Spain", "dial_code": "+34"}, + {"country_name": "Sri Lanka", "dial_code": "+94"}, + {"country_name": "Sudan", "dial_code": "+249"}, + {"country_name": "Suriname", "dial_code": "+597"}, + {"country_name": "Svalbard and Jan Mayen", "dial_code": "+47"}, + {"country_name": "Swaziland", "dial_code": "+268"}, + {"country_name": "Sweden", "dial_code": "+46"}, + {"country_name": "Switzerland", "dial_code": "+41"}, + {"country_name": "Syrian Arab Republic", "dial_code": "+963"}, + {"country_name": "Taiwan", "dial_code": "+886"}, + {"country_name": "Tajikistan", "dial_code": "+992"}, + {"country_name": "Tanzania, United Republic of Tanzania", "dial_code": "+255"}, + {"country_name": "Thailand", "dial_code": "+66"}, + {"country_name": "Timor-Leste", "dial_code": "+670"}, + {"country_name": "Togo", "dial_code": "+228"}, + {"country_name": "Tokelau", "dial_code": "+690"}, + {"country_name": "Tonga", "dial_code": "+676"}, + {"country_name": "Trinidad and Tobago", "dial_code": "+1868"}, + {"country_name": "Tunisia", "dial_code": "+216"}, + {"country_name": "Turkey", "dial_code": "+90"}, + {"country_name": "Turks and Caicos Islands", "dial_code": "+1649"}, + {"country_name": "Tuvalu", "dial_code": "+688"}, + {"country_name": "Uganda", "dial_code": "+256"}, + {"country_name": "Ukraine", "dial_code": "+380"}, + {"country_name": "United Arab Emirates", "dial_code": "+971"}, + {"country_name": "United Kingdom", "dial_code": "+44"}, + {"country_name": "United States", "dial_code": "+1"}, + {"country_name": "Uruguay", "dial_code": "+598"}, + {"country_name": "Uzbekistan", "dial_code": "+998"}, + {"country_name": "Vanuatu", "dial_code": "+678"}, + {"country_name": "Venezuela, Bolivarian Republic of Venezuela", "dial_code": "+58"}, + {"country_name": "Vietnam", "dial_code": "+84"}, + {"country_name": "Virgin Islands, British", "dial_code": "+1284"}, + {"country_name": "Virgin Islands, U.S.", "dial_code": "+1340"}, + {"country_name": "Wallis and Futuna", "dial_code": "+681"}, + {"country_name": "Yemen", "dial_code": "+967"}, + {"country_name": "Zambia", "dial_code": "+260"}, + {"country_name": "Zimbabwe", "dial_code": "+263"} +]; diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb new file mode 100644 index 0000000..a45dd74 --- /dev/null +++ b/lib/l10n/app_en.arb @@ -0,0 +1,191 @@ +{ + "yourMessage": " Your message...", + "similarProducts": "Similar products", + "nsm": "NSM", + "buyNow": "Buy Now", + "uploadReceipt": "Upload Receipt", + "payOnline": "Pay Online", + "sendMessage": "Send message", + "dataIsUpdated": "Data is updated", + "personalCabinet": "Personal cabinet", + "addPost": "Add Post", + "iu_company": "User company", + "iu_about": "User about info", + "phone_error": "Enter a valid phone number", + "email_error": "Enter a valid email address", + "username": "Username", + "noAccount": "No Account?", + "yourPassword": "Your password", + "yourLogin": "Your login", + "yourEmail": "Your email address", + "link": "link", + "loginText": "If you have forgotten your username or password, please restore it from the @ .", + "expiryDate": "Expiry Date", + "sellerContact": "Seller contact", + "address": "Address", + "realAddress": "744000, Turkmenistan Ashgabat city, Archabil avenue 52", + "mail": "E-mail", + "telephone": "Telephone", + "lotNumber": "Lot", + "productNumber": "Product number", + "productMark": "Product Mark", + "productAmount": "Product amount", + "startingPrice": "Starting price", + "producer": "Producer", + "producerCountry": "Country of origin", + "description": "Description", + "unit": "Unit", + "paymentTerms": "Terms of payment", + "deliveryTerms": "Terms of delivery", + "station": "Station", + "packing": "Packing", + "english": "English", + "russian": "Russian", + "turkmen": "Turkmen", + "localeLabel": "English", + "backendCode": "en", + "save_changes": "Save changes", + "email": "Email address", + "message": "Messages", + "top_up_history": "Top-up history", + "personal_data": "Personal data", + "news_feed": "News", + "feedback": "Feedback", + "privacy_policy": "Privacy Policy", + "contact": "Contact details", + "home": "Home", + "category": "Categories", + "favourites": "Wishlist", + "settings": "Settings", + "login": "Login", + "phone": "Phone number", + "password": "Password", + "or": "or", + "register": "Register", + "first_name": "Name", + "last_name": "Surname", + "lang": "Language", + "phoneValidator": "Enter the phone correctly", + "empty": "The field must not be empty", + "forgot": "Forgot Password?", + "search": "Search goods by a keyword", + "cart": "Cart", + "addToCart": "Add to Cart", + "addedToCart": "Added to Cart!", + "removedFromCart": "Removed from Cart!", + "inCart": "Already in Cart", + "allPrice": "Total price", + "wantDelete": "Do you really want to delete the item?", + "hit": "Top goods", + "newGoods": "New products", + "emptyPosts": "No data", + "order": "Create an order", + "account": "Account", + "otherException": "Error occured, try later", + "password_confirmation": "Confirm password", + "password_confirmation_error": "Passwords do not match", + "profile": "Profile", + "unauthenticated": "Your session is exprired, please re-login", + "needToEnter": "Please enter your account", + "logout": "Log out", + "logging_out": "Logging out...", + "sure_log_out": "Do you really want to log out?", + "date": "Date", + "status": "Status", + "products": "Products", + "smsCodeSent": "Sms code is sent to the phone", + "codeLabel": "Code", + "passwordError": "Password must contain at least 6 symbols", + "verify": "Verification", + "sendingCode": "Sending code...", + "sendCode": "Send again", + "rules": "the User Agreement", + "agree": "If you agree with conditions of @ click 'CONTINUE'", + "about": "About us", + "quantitySumm": "Summ", + "enterQuantity": "Enter quantity", + "formatError": "Invalid format", + "tapToLoadMore": "Load more", + "similiarProducts": "Related products", + "dialCode": "Dial code", + "verificationMailSent": "Please, check your email. Follow the verification link we've sent.", + "verifyMail": "Verify your email", + "verifyPhone": "Verify your phon number", + "sms_code": "Sms code", + "check": "Verify", + "myProducts": "My products", + "firstStep": "Step 1", + "addPosts": "Add product", + "addPostName": "Title", + "mark": "Mark", + "manufacturer": "Manufacturer", + "marketType": "Market type", + "country": "Country", + "inMarket": "Internal", + "outMarket": "External", + "addPostDescription": "Description", + "price": "Price", + "place": "Place", + "quantity": "Quantity", + "measure": "Measure", + "currency": "Currency", + "paymentTerm": "Payment term", + "deliveryTerm": "Delivery term", + "secondStep": "Step 2", + "packaging": "Packaging", + "yes": "Yes", + "no": "No", + "notANumber": "Not a number", + "selectImages": "Select images", + "localImages": "New images", + "selectAtLeastImage": "Select at least 1 image", + "statusNote": "Notes", + "draft": "Draft", + "approved": "Approved", + "denied": "Denied", + "published": "Sent", + "none": "Unknown", + "edit": "Edit", + "approve": "Send for revision", + "loadedImages": "Uploaded images", + "legalizationNumber": "Legalization Number", + "newPassword": "New password", + "newPasswordConfirmation": "Confirm new password", + "phoneConfirmation": "Confirmation", + "smsSentInfo": "An SMS with a code will be sent to the number you indicated, enter it below", + "enterSmsCode": "Enter sms code", + "confirm": "Confirm", + "verifyPhoneWarning": "Confirm your phone number by clicking on the button", + "topUpBalance": "Top up balance", + "selectPaymentMethod": "Select payment method", + "bankTransfer": "Bank transfer", + "selectFile": "Select file", + "upload": "Upload", + "fileNotSelected": "File not selected", + "send": "Send", + "reminderInfo": "Before sending, make sure that the transfer was made correctly and you have a receipt", + "taxCode": "Tax code:", + "manatAccount": "Manat account:", + "corrAccount": "Correspondent account:", + "bankAddress": "Bank address:", + "selectBank": "Select bank", + "transferAmount": "Transfer amount", + "enterAmount": "enter amount", + "searchShort": "Search", + "newsNotFount": "News not found", + "errorOccurred": "Error occurred", + "registeredDate": "Registered date", + "filters": "Filters", + "selectCategory": "Select category", + "selectUnit": "Select unit", + "selectCurrency": "Select currency", + "selectPayment": "Select payment", + "selectSendType": "Select send type", + "selectCountry": "Select country", + "clear": "Clear", + "apply": "Apply", + "importPrice": "Import prices", + "quotes": "Quotes", + "notFound": "Not found", + "verifyEmailWarning": "Press icon to confirm email" +} \ No newline at end of file diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb new file mode 100644 index 0000000..3cb5bbd --- /dev/null +++ b/lib/l10n/app_ru.arb @@ -0,0 +1,191 @@ +{ + "yourMessage": " Ваше сообщение...", + "similarProducts": "Похожие товары", + "nsm": "ФИО", + "buyNow": "Купить сейчас", + "uploadReceipt": "Загрузить квитанцию", + "payOnline": "Оплатить онлайн", + "sendMessage": "Отправить оообщение", + "dataIsUpdated": "Данные обновлены", + "personalCabinet": "Персональные данные", + "addPost": "Добавить объявления", + "iu_company": "Компания-пользователь", + "iu_about": "Информация о пользователе", + "phone_error": "Введите действующий номер телефона", + "email_error": "Введите корректный электронный адрес", + "username": "Имя пользователя", + "noAccount": "Нет аккаунта?", + "yourPassword": "Ваш пароль", + "yourLogin": "Ваш логин", + "yourEmail": "Ваш электронный адрес", + "link": "ссылке", + "loginText": "Если вы забыли свой логин или пароль, просим вас восстановить его по @ .", + "expiryDate": "Дата окончания", + "sellerContact": "Контакты продавца", + "address": "Адрес", + "realAddress": "744000, Туркменистан г.Ашгабат, Арчабиль шаелы 52", + "mail": "Почта", + "telephone": "Телефон", + "lotNumber": "Лот:", + "productNumber": "Номер товара", + "productMark": "Марка товара", + "productAmount": "Количество товара", + "startingPrice": "Стартовая цена за единицу", + "producer": "Производитель", + "producerCountry": "Страна производителя", + "description": "Описание", + "unit": "Единица измерения", + "paymentTerms": "Условия оплаты", + "deliveryTerms": "Условия поставки", + "station": "Пункт", + "packing": "Упаковка", + "english": "Английский", + "russian": "Русский", + "turkmen": "Туркменский", + "localeLabel": "Русский", + "save_changes": "Сохранить изменения", + "backendCode": "ru", + "email": "Электронный адрес", + "message": "Сообщения", + "top_up_history": "История пополнений", + "personal_data": "Персональные данные", + "news_feed": "Новости", + "feedback": "Обратная связь", + "privacy_policy": "Политика конфиденциальности", + "contact": "Контакты", + "home": "Главная", + "category": "Категории", + "favourites": "Желания", + "settings": "Настройки", + "login": "Войти", + "phone": "Номер телефона", + "password": "Пароль", + "or": "или", + "register": "Создать", + "first_name": "Имя", + "last_name": "Фамилия", + "lang": "Язык приложения", + "phoneValidator": "Введите телефон правильно", + "empty": "Поле не должно быть пустым", + "forgot": "Забыли пароль?", + "search": "Поиск по названию товара", + "cart": "Корзина", + "addToCart": "Добавить в корзину", + "addedToCart": "Добавлено в корзину!", + "removedFromCart": "Удалено из корзины!", + "inCart": "Уже в корзине", + "allPrice": "Общая сумма", + "wantDelete": "Вы действительно хотите убрать товар из корзины?", + "hit": "Хиты продаж", + "newGoods": "Новые товары", + "emptyPosts": "Пусто", + "order": "Оформить заказ", + "account": "Аккаунт", + "otherException": "Возникла ошибка, попробуйте заново", + "password_confirmation": "Подтвердите пароль", + "password_confirmation_error": "Пароли не совпадают", + "profile": "Кабинет", + "unauthenticated": "Ваша сессия истекла, войдите заново в аккаунт", + "needToEnter": "Войдите в свой аккаунт", + "logout": "Выйти", + "logging_out": "Выходим из системы...", + "sure_log_out": "Вы действительно хотите выйти?", + "date": "Дата", + "status": "Статус", + "products": "Товары", + "smsCodeSent": "Код отправлен на ваш номер телефона", + "codeLabel": "Код", + "passwordError": "Пароль должен содержать не менее 6 символов", + "verify": "Верификация", + "sendingCode": "Отправка кода...", + "sendCode": "Отправить заново", + "rules": "Пользовательского соглашения", + "agree": "Если вы согласны с условиями @, нажмите 'ПРОДОЛЖИТЬ'", + "about": "О нас", + "quantitySumm": "Сумма", + "enterQuantity": "Введите сумму", + "formatError": "Неверный формат", + "tapToLoadMore": "Загрузить ещё", + "similiarProducts": "Рекомендуемые товары", + "dialCode": "Телефонный код", + "verificationMailSent": "Пожалуйста, проверьте вашу электронную почту. Мы отправили вам письмо со ссылкой на подтверждение", + "verifyMail": "Подтвердить почту", + "verifyPhone": "Подтвердить номер телефона", + "sms_code": "Код подтверждения", + "check": "Подтвердить", + "myProducts": "Мои товары", + "firstStep": "Шаг 1", + "addPosts": "Добавить товар", + "addPostName": "Название", + "mark": "Марка", + "manufacturer": "Изготовитель", + "marketType": "Тип рынка", + "country": "Страна", + "inMarket": "Внутренний", + "outMarket": "Внешний", + "addPostDescription": "Описание", + "price": "Цена", + "place": "Место", + "quantity": "Количество", + "measure": "Мера измерения", + "currency": "Валюта", + "paymentTerm": "Метод оплаты", + "deliveryTerm": "Метод доставки", + "secondStep": "Шаг 2", + "packaging": "Упаковка", + "yes": "Да", + "no": "Нет", + "notANumber": "Введите число", + "selectImages": "Выбрать картинки", + "localImages": "Новые картинки", + "selectAtLeastImage": "Выберите хотя бы 1 картинку", + "statusNote": "Примечания", + "draft": "Черновик", + "approved": "Одобрен", + "denied": "Отклонен", + "published": "Отправлен", + "none": "Неизвестно", + "edit": "Изменить", + "approve": "Отправить на проверку", + "loadedImages": "Загруженные картинки", + "legalizationNumber": "Номер легализации", + "newPassword": "Новый пароль", + "newPasswordConfirmation": "Подтвердите новый пароль", + "phoneConfirmation": "Подтверждение", + "smsSentInfo": "На номер который Вы указали придет смс с кодом, введите его ниже", + "enterSmsCode": "Введите код", + "confirm": "Подтвердить", + "verifyPhoneWarning": "Подтвердите Ваш номер телефона, нажав на кнопку", + "topUpBalance": "Пополнить баланс", + "selectPaymentMethod": "Выберите метод оплаты", + "bankTransfer": "Банковский перевод", + "selectFile": "Выбрать файл", + "upload": "Загрузить", + "fileNotSelected": "Ничего не выбранно", + "send": "Отправить", + "reminderInfo": "Перед отправкой убедитесь что перевод был осуществлен верно и у вас имеется чек", + "taxCode": "Налоговый код:", + "manatAccount": "Манатный счёт:", + "corrAccount": "Корреспондент счет:", + "bankAddress": "Адрес банка:", + "selectBank": "Выберите банк", + "transferAmount": "Сумма перевода", + "enterAmount": "введите сумму", + "searchShort": "Поиск", + "newsNotFount": "Новости не найдены", + "errorOccurred": "Возникла ошибка", + "registeredDate": "Дата регистрации", + "filters": "Фильтры", + "selectCategory": "Выбрать категорию", + "selectUnit": "Выберите единицу измерения", + "selectCurrency": "Выберите валюту", + "selectPayment": "Выберите платеж", + "selectSendType": "Выберите тип отправки", + "selectCountry": "Выберите страну", + "clear": "Очистить", + "apply": "Применить", + "importPrice": "Импортные цены", + "quotes": "Котировки", + "notFound": "Не найден", + "verifyEmailWarning": "Нажмите значок, чтобы подтвердить адрес электронной почты" +} \ No newline at end of file diff --git a/lib/l10n/app_tk.arb b/lib/l10n/app_tk.arb new file mode 100644 index 0000000..d184852 --- /dev/null +++ b/lib/l10n/app_tk.arb @@ -0,0 +1,191 @@ +{ + "yourMessage": " Siziň hatyňyz...", + "similarProducts": "Meňzeş harytlar", + "nsm": "AFA", + "buyNow": "Satyn almak", + "uploadReceipt": "Kwitansiýaňyzy ýükläň", + "payOnline": "Online töleg", + "sendMessage": "Ugratmak", + "dataIsUpdated": "Maglumatlar täzelendi", + "personalCabinet": "Şahsy otag", + "addPost": "Bildiriş goşmak", + "iu_company": "Ulanyjy kompaniýasy", + "iu_about": "Ulanyjy barada maglumat", + "phone_error": "Dogry telefon belgisini giriziň", + "email_error": "Dogry e-poçta salgysyny giriziň", + "username": "Ulanyjy ady", + "noAccount": "Akkaundyňyz ýokmy?", + "yourPassword": "Açar sözüňiz", + "yourLogin": "Siziň loginiňiz", + "yourEmail": "Siziň elektron salgyňyz", + "link": "salgy boýunça", + "loginText": "Ulanyjy adyňyzy ýa-da parolyňyzy ýatdan çykaran bolsaňyz, şu @ dikeltmegiňizi haýyş edýäris", + "expiryDate": "Möhleti", + "sellerContact": "Habarlaşmak üçin", + "address": "Adres", + "realAddress": "744000, Türkmenistan ş.Aşgabat, Arçabil şaýoly 52", + "mail": "E-mail", + "telephone": "Telefon", + "lotNumber": "Lot:", + "productNumber": "Harydyň belgisi", + "productMark": "Harydyň markasy", + "productAmount": "Harydyň möçberi", + "startingPrice": "Başlangyç bahasy", + "producer": "Öndüriji", + "producerCountry": "Öndürilen ýurdy", + "description": "Beýany", + "unit": "Birligi", + "paymentTerms": "Töleg şertleri", + "deliveryTerms": "Eltip bermegiň şertleri", + "station": "Ýeri", + "packing": "Gaplamak", + "english": "Iňlis", + "russian": "Rus", + "turkmen": "Türkmen", + "localeLabel": "Türkmen", + "save_changes": "Ýatda sakla", + "backendCode": "tm", + "email": "Elektron salgysy", + "message": "Hatlarym", + "top_up_history": "Pul geçirimleriň taryhy", + "personal_data": "Şahsy maglumat", + "news_feed": "Habarlar", + "feedback": "Hat ýazmak", + "privacy_policy": "Gizlinlik syýasaty", + "contact": "Habarlaşmak üçin", + "home": "Baş sahypa", + "category": "Kategoriýa", + "favourites": "Islegler", + "settings": "Sazlama", + "login": "Girmek", + "phone": "Telefon nomer", + "password": "Parol", + "or": "ýa-da", + "register": "Döretmek", + "first_name": "Adyňyz", + "last_name": "Familiýaňyz", + "lang": "Dili", + "phoneValidator": "Telefony dogry giriziň", + "empty": "Boş durmaly däl", + "forgot": "Paroly unutdyňyzmy?", + "search": "Harydy adyndan gözle", + "cart": "Sebet", + "addToCart": "Sebede goş", + "addedToCart": "Sebede goşuldy!", + "removedFromCart": "Sebetden pozuldy!", + "inCart": "Sebetde", + "allPrice": "Umumy bahasy", + "wantDelete": "Harydy çyndanam sebetden pozmak isleýärsiňizmi?", + "hit": "Iň köp satylan", + "newGoods": "Täze harytlar", + "emptyPosts": "Maglumat ýok", + "order": "Sargydy jemlemek", + "account": "Akkaunt", + "otherException": "Ýalnyş döredi, täzeden barlap görüň", + "password_confirmation": "Paroly gaýtalaň", + "password_confirmation_error": "Parollar gabat gelenok", + "profile": "Profil", + "unauthenticated": "Siziň sessiýaňyz gutardy, täzeden giriň", + "needToEnter": "Akkaundyňyza giriň", + "logout": "Ulgamdan çykmak", + "logging_out": "Ulgamdan çykýarys...", + "sure_log_out": "Ulgamdan çyndanam çykmakçy my?", + "date": "Senesi", + "status": "Status", + "products": "Harytlar", + "smsCodeSent": "Telefon nomeryňyza iberilen kody giriziň", + "codeLabel": "Kod", + "passwordError": "Parol azyndan 6 belgiden ybarat bolmaly", + "verify": "Sms barlag", + "sendingCode": "Kody iberýäris...", + "sendCode": "Täzeden iber", + "rules": "Ulanyjy şertnamasy", + "agree": "Eger @ bilen razy bolsaňyz, dowam ediň", + "about": "Biz barada", + "quantitySumm": "Jemi", + "enterQuantity": "Doldurmaly jemi", + "formatError": "Nädogry format", + "tapToLoadMore": "Ýene görkez", + "similiarProducts": "Bagly harytlar", + "dialCode": "Telefon kody", + "verificationMailSent": "Siziň e-mail salgyňyza hat ugradyldy. Hatyň içindäki ugradyjyny yzarlamagyňyzy haýyş edýäris.", + "verifyMail": "E-mail tassyklamak", + "verifyPhone": "Telefon belgini tassyklamak", + "sms_code": "Sms kod", + "check": "Barla", + "myProducts": "Harytlarym", + "firstStep": "Ädim 1", + "addPosts": "Harydy goşmak", + "addPostName": "Harydyň ady", + "mark": "Markasy", + "manufacturer": "Öndüriji", + "marketType": "Bazaryň görnüşi", + "country": "Ýurdy", + "inMarket": "Içki", + "outMarket": "Daşky", + "addPostDescription": "Mazmuny", + "price": "Baha", + "place": "Ýeri", + "quantity": "Mukdary", + "measure": "Ölçegi", + "currency": "Walýuta", + "paymentTerm": "Töleg usuly", + "deliveryTerm": "Eltmek usuly", + "secondStep": "Ädim 2", + "packaging": "Gaplamak", + "yes": "Hawa", + "no": "Ýok", + "notANumber": "Sany giriziň", + "selectImages": "Suratlary saýla", + "localImages": "Täze suratlar", + "selectAtLeastImage": "Azyndan 1 surat saýlaň", + "statusNote": "Bellikler", + "draft": "Garalama", + "approved": "Tassyklanan", + "denied": "Inkär edilen", + "published": "Ugradyldy", + "none": "Unknown", + "edit": "Üýtget", + "approve": "Barlaga ugrat", + "loadedImages": "Ýüklenen suratlar", + "legalizationNumber": "Kanunylaşdyrmagyň belgisi", + "newPassword": "Täze açar sözi", + "newPasswordConfirmation": "Täze açar sözüni tassyklaň", + "phoneConfirmation": "Tassyklaň", + "smsSentInfo": "Görkezilen belgä SMS kody iberiler. SMS koduny giriziň", + "enterSmsCode": "Kody giriziň", + "confirm": "Tassykla", + "verifyPhoneWarning": "Düwmä basyp, telefon belgiňizi tassyklaň", + "topUpBalance": "Hasaby dolduryň", + "selectPaymentMethod": "Töleg usulyny saýlaň", + "bankTransfer": "Bank arkaly töleg", + "selectFile": "Faýl saýlaň", + "upload": "Ýükle", + "fileNotSelected": "Faýl saýlanmady", + "send": "Ugrat", + "reminderInfo": "Ibermezden ozal, geçirişiň dogry edilendigine we kwitansiýaňyzyň bardygyna göz ýetiriň", + "taxCode": "Nalog kody:", + "manatAccount": "Manat hasaby:", + "corrAccount": "Habarçy hasaby:", + "bankAddress": "Bankyň adresi:", + "selectBank": "Banky saýlaň", + "transferAmount": "Pul geçirimiň mukdary", + "enterAmount": "mukdary girziň", + "searchShort": "Gözleg", + "newsNotFount": "Habar tapylmady", + "errorOccurred": "Näsazlyk ýüze çykdy", + "registeredDate": "Hasaba alnan senesi", + "filters": "Süzgüçler", + "selectCategory": "Kategoriýany saýlaň", + "selectUnit": "Birlik saýlaň", + "selectCurrency": "Walýuta saýlaň", + "selectPayment": "Töleg görnüşini saýlaň", + "selectSendType": "Ibermegiň görnüşini saýlaň", + "selectCountry": "Ýurt saýlaň", + "clear": "Arassala", + "apply": "Ýerine ýetir", + "importPrice": "Import bahalary", + "quotes": "Kotirowkalar", + "notFound": "Tapylmady", + "verifyEmailWarning": "Düwmä basyp, e-poçtaňyzy tassyklaň" +} \ No newline at end of file diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..b4477f2 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,73 @@ +import 'package:birzha/models/products/composableProduct.dart'; +import 'package:birzha/models/settings/theme.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/primal.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:get/get.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + +import 'core/adaptix/adaptix.dart'; + +//homeCateogryId: -1 +//relatedProductsCategory id: -2 +//masterCategoey id: -3 +//transactionsSerializer id: -4 +//chatroomSerializer id: -5 +//search category id: -6 +//my products category id: -7 + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); // flutter packet loaded + final prefs = await SharedPreferences.getInstance(); // loads memory + await SettingsModel.initLocalization(prefs.getString('language') ?? kDefaultLanguage); + runApp(MultiProvider( + providers: [ + ChangeNotifierProvider(create: (_) => SettingsModel(prefs)), + ChangeNotifierProvider(create: (_) => AppUserManager(prefs)), + ChangeNotifierProvider.value(value: ComposableProduct()) + ], + child: MyApp(), + )); +} + +class MyApp extends StatefulWidget { + @override + _MyAppState createState() => _MyAppState(); +} + +class _MyAppState extends State { + late Locale _locale; + + void setLocale(Locale locale) { + setState(() { + _locale = _locale; + }); + } + + @override + Widget build(BuildContext context) { + return SizeInitializer( + builder: (context) => GetMaterialApp( + debugShowCheckedModeBanner: false, + theme: AppTheme.appLightTheme, + localizationsDelegates: [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + AppLocalizations.delegate, + ], + locale: Locale('ru', ''), + supportedLocales: [ + Locale('en', ''), + Locale('ru', ''), + Locale('tk', ''), + ], + home: Primal(), + ), + ); + } +} diff --git a/lib/models/attributes/attribute.dart b/lib/models/attributes/attribute.dart new file mode 100644 index 0000000..0b1bf85 --- /dev/null +++ b/lib/models/attributes/attribute.dart @@ -0,0 +1,72 @@ +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:birzha/services/validator.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/services/modals.dart'; +import 'package:birzha/core/orm/orm.dart'; + +abstract class AttributeSelectableDelegate { + T? get groupValue; + Future dialogBuilder(BuildContext context); +} + +class SingleOptionSelectableDelegate extends AttributeSelectableDelegate { + SingleOptionSelectableDelegate(this.groupValue, this.options); + + @override + Future dialogBuilder(BuildContext context) { + return attributeSelector(context, groupValue, options); + } + + @override + final AttributeWithValueNameMixin? groupValue; + + final List options; +} + +mixin AttributeLabelMixin { + String get label; + String toQueryString(); +} + +mixin OptionedAttributeMixin on KeyIndexedAttributeMixin { + List get options; +} + +mixin SelectableAttributeMixin on KeyIndexedAttributeMixin { + AttributeSelectableDelegate selectDelegate(V? groupValue); + + TextInputMetaData metaData({required V? groupValue, required void Function(V?) onSelected}) { + return TextInputMetaData( + name: label, + label: label, + pickerMode: (context) async { + var option = await selectDelegate(groupValue).dialogBuilder(context); + onSelected(option); + if (option is AttributeWithValueNameMixin) { + return option.value.toString(); + } else if (option != null) { + return option.toString(); + } + }, + validation: Validation(conditions: [(inp) => inp.isEmpty ? 'empty'.translation : null]), + key: key); + } +} + +mixin KeyIndexedAttributeMixin on PostAttribute { + String get key; +} + +mixin AttributeWithValueNameMixin on PostAttribute { + String get value; +} + +abstract class PostAttribute extends Orm with AttributeLabelMixin { + PostAttribute(Map jSON) : super(jSON); + + @override + String toQueryString() { + return primaryKey.toString(); + } +} diff --git a/lib/models/attributes/category.dart b/lib/models/attributes/category.dart new file mode 100644 index 0000000..4bb10f7 --- /dev/null +++ b/lib/models/attributes/category.dart @@ -0,0 +1,52 @@ +import 'dart:convert'; + +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/models/categories/products/pure.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/requests.dart'; + +class CategoryOption extends PostAttribute with AttributeWithValueNameMixin { + final ProductsPureCategory category; + + CategoryOption._(this.category) : super(category.jSON); + + @override + String get label => category.name; + + @override + String get primaryKeyField => 'id'; + + @override + String get value => label; +} + +class CategoryAttribute extends PostAttribute + with KeyIndexedAttributeMixin, SelectableAttributeMixin, OptionedAttributeMixin { + CategoryAttribute._(this.options) : super({'key': 'category_id'}); + + static Future getAttribute() async { + var categories = await FutureGetList(baseUrl(path: kApiPath + '/categories', queryParameters: {}), parser: (response) { + final map = jsonDecode(response.body); + final products = map?['data'] as List; + return products.map((jsonData) => ProductsPureCategory(data: jsonData)).toList(); + }).fetch(); + return CategoryAttribute._(categories.map((e) => CategoryOption._(e)).toList()); + } + + @override + String get key => 'category_id'; + + @override + String get label => 'category'.translation; + + @override + String get primaryKeyField => 'key'; + + @override + selectDelegate(groupValue) { + return SingleOptionSelectableDelegate(groupValue, options); + } + + @override + final List options; +} diff --git a/lib/models/attributes/market_type.dart b/lib/models/attributes/market_type.dart new file mode 100644 index 0000000..bab2dc2 --- /dev/null +++ b/lib/models/attributes/market_type.dart @@ -0,0 +1,66 @@ +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; + +enum MarketType { inMarket, outMarket } + +class MarketTypeOption extends PostAttribute + with AttributeWithValueNameMixin { + final MarketType marketType; + + MarketTypeOption._(this.marketType) : super({'id': _idToSet(marketType)}); + + static String _idToSet(MarketType type) { + switch (type) { + case MarketType.inMarket: + return 'in'; + case MarketType.outMarket: + return 'out'; + } + } + + @override + String get label { + switch (marketType) { + case MarketType.inMarket: + return 'inMarket'.translation; + case MarketType.outMarket: + return 'outMarket'.translation; + } + } + + @override + String get primaryKeyField => 'id'; + + @override + String get value => label; +} + +class MarketTypeAttribute extends PostAttribute + with + KeyIndexedAttributeMixin, + SelectableAttributeMixin, + OptionedAttributeMixin { + MarketTypeAttribute._(this.options) : super({'key': 'market_type'}); + + static MarketTypeAttribute getAttribute() { + return MarketTypeAttribute._( + MarketType.values.map((e) => MarketTypeOption._(e)).toList()); + } + + @override + String get key => 'market_type'; + + @override + String get label => 'marketType'.translation; + + @override + String get primaryKeyField => 'key'; + + @override + selectDelegate(groupValue) { + return SingleOptionSelectableDelegate(groupValue, options); + } + + @override + final List options; +} diff --git a/lib/models/attributes/miscelaneous.dart b/lib/models/attributes/miscelaneous.dart new file mode 100644 index 0000000..647794f --- /dev/null +++ b/lib/models/attributes/miscelaneous.dart @@ -0,0 +1,94 @@ +import 'dart:convert'; + +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/requests.dart'; + +class MiscAttributeOption extends PostAttribute + with AttributeWithValueNameMixin, TranslatableMixin { + MiscAttributeOption({required Map data}) : super(data) { + configureTranslationModel(); + } + + @override + String get label => + translationModel?.translationOf('name', jSON['name'] ?? '') ?? + jSON['name'] ?? + ''; + + @override + String get primaryKeyField => 'id'; + + @override + String get value => label; +} + +class MiscAttribute extends PostAttribute + with + KeyIndexedAttributeMixin, + SelectableAttributeMixin, + OptionedAttributeMixin { + MiscAttribute._( + {required this.options, required String key, required String labelKey}) + : super({'key': key, 'label': labelKey}); + + static Future getAttrbute( + {required String key, required String labelKey, required Uri uri}) async { + var options = + await FutureGetList(uri, parser: (response) { + final map = jsonDecode(response.body); + final products = map?['data'] as List; + return products + .map( + (jsonData) => MiscAttributeOption(data: jsonData)) + .toList(); + }).fetch(); + return MiscAttribute._(options: options, key: key, labelKey: labelKey); + } + + static Future> getAttrbutes() async { + return [ + await MiscAttribute.getAttrbute( + key: 'country', + labelKey: 'country', + uri: baseUrl(path: kApiPath + '/countries')), + await MiscAttribute.getAttrbute( + key: 'measure_id', + labelKey: 'measure', + uri: baseUrl(path: kApiPath + '/measures')), + await MiscAttribute.getAttrbute( + key: 'currency_id', + labelKey: 'currency', + uri: baseUrl(path: kApiPath + '/currencies')), + await MiscAttribute.getAttrbute( + key: 'payment_term_id', + labelKey: 'paymentTerm', + uri: baseUrl( + path: kApiPath + '/terms', queryParameters: {'type': 'payment'})), + await MiscAttribute.getAttrbute( + key: 'delivery_term_id', + labelKey: 'deliveryTerm', + uri: baseUrl( + path: kApiPath + '/terms', + queryParameters: {'type': 'delivery'})), + ]; + } + + @override + String get key => primaryKey; + + @override + String get label => jSON['label'].toString().translation; + + @override + String get primaryKeyField => 'key'; + + @override + selectDelegate(groupValue) { + return SingleOptionSelectableDelegate(groupValue, options); + } + + @override + final List options; +} diff --git a/lib/models/attributes/packaging.dart b/lib/models/attributes/packaging.dart new file mode 100644 index 0000000..49e64a7 --- /dev/null +++ b/lib/models/attributes/packaging.dart @@ -0,0 +1,66 @@ +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; + +enum PackagingType { yes, no } + +class PackagingOption extends PostAttribute + with AttributeWithValueNameMixin { + final PackagingType marketType; + + PackagingOption._(this.marketType) : super({'id': _idToSet(marketType)}); + + static String _idToSet(PackagingType type) { + switch (type) { + case PackagingType.yes: + return 'yes'; + case PackagingType.no: + return 'no'; + } + } + + @override + String get label { + switch (marketType) { + case PackagingType.yes: + return 'yes'.translation; + case PackagingType.no: + return 'no'.translation; + } + } + + @override + String get primaryKeyField => 'id'; + + @override + String get value => label; +} + +class PackagingAttribute extends PostAttribute + with + KeyIndexedAttributeMixin, + SelectableAttributeMixin, + OptionedAttributeMixin { + PackagingAttribute._(this.options) : super({'key': 'packaging'}); + + static PackagingAttribute getAttribute() { + return PackagingAttribute._( + PackagingType.values.map((e) => PackagingOption._(e)).toList()); + } + + @override + String get key => 'packaging'; + + @override + String get label => 'packaging'.translation; + + @override + String get primaryKeyField => 'key'; + + @override + selectDelegate(groupValue) { + return SingleOptionSelectableDelegate(groupValue, options); + } + + @override + final List options; +} diff --git a/lib/models/categories/category.dart b/lib/models/categories/category.dart new file mode 100644 index 0000000..eebcbc3 --- /dev/null +++ b/lib/models/categories/category.dart @@ -0,0 +1,35 @@ +library category_lib; + +import 'dart:convert'; + +import 'package:birzha/models/categories/home.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/queries/query.dart'; +import 'package:birzha/new/utils/locale.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/orm/orm.dart'; + +part 'package:birzha/models/categories/pureCategory.dart'; +part 'package:birzha/models/categories/interfaces.dart'; +part 'package:birzha/models/categories/remoteCategory.dart'; + +/// This is the starting point of all categories in the app +/// Important things to know: RemoteCategories are unpredictable that's why they are assigned with ids (primary key) +/// Local categories such as [HomeCategory] are signed with negative id to predict their appeareance +/// In current architecture EVERY model that can give you a Future> is considered as category + +abstract class Serializer extends Orm with CopyAbleMixin { + Serializer(Map jSON) : super(jSON); + + Future> getPosts(BuildContext context, int page); + String get name; + SliverGridDelegate? gridDelegate(BuildContext context) => null; + + @override + String get primaryKeyField => 'id'; + + T postBuilderDelegate(Map data); + + bool get needPagination => true; +} diff --git a/lib/models/categories/home.dart b/lib/models/categories/home.dart new file mode 100644 index 0000000..7050e67 --- /dev/null +++ b/lib/models/categories/home.dart @@ -0,0 +1,44 @@ +import 'package:birzha/constants.dart'; +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:birzha/models/queries/query.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/material.dart'; + +class HomeCategory extends RemoteCategory with AddQueryMixin { + HomeCategory() : super(data: {}); + + List subCategoryQueries = []; + + @override + int get primaryKey => -1; + + @override + String get name => 'newGoods'.translation; + + @override + SliverGridDelegate? gridDelegate(BuildContext context) { + return AppConstants.productsGridDelegate(context); + } + + @override + Uri postUri(BuildContext context, int page) { + debugPrint("eeeeeeeeeeeeeeeeeeee"); + return baseUrl(path: kApiPath + '/products', queryParameters: { + 'page': page.toString(), + 'custom_per_page': AppConstants.pageLimit.toString(), + }); + } + + /// Before the first page is loaded we get set of Subcategories turned into list of [SubCategoryQuery] + /// After the first page is loaded all subscribed widgets will be notified about that + + @override + Product postBuilderDelegate(Map data) { + return Product(data: {...data}); + } + + @override + HomeCategory get copy => HomeCategory(); +} diff --git a/lib/models/categories/interfaces.dart b/lib/models/categories/interfaces.dart new file mode 100644 index 0000000..d827c98 --- /dev/null +++ b/lib/models/categories/interfaces.dart @@ -0,0 +1,57 @@ +part of category_lib; + +typedef GetSubCategoriesDelegate = Future> Function(BuildContext context, int page); + +mixin _GetRemotePostssMixin on Serializer { + Uri postUri(BuildContext context, int page); + + Future> _getAndParsePosts(BuildContext context, int page) async { + String locale = await getLocale(); + return FutureGetList(postUri(context, page), parser: (response) { + final map = jsonDecode(response.body); + final products = map?['data'] as List; + return products.map((data) => postBuilderDelegate(data)).toList(); + }).fetch({ + 'Accept': 'application/json', + 'locale': locale, + }); + } +} + +mixin SearchableMixin on AddQueryMixin { + void search(String word) { + applyQuery(SearchQuery(word)); + applyQuery(LocaleQuery()); + } +} + +mixin AddQueryMixin on Serializer { + Set _queries = {}; + + void resetQueries(Set newQueries) { + _queries = {...newQueries}; + } + + Set get queriesSetCopy => {..._queries}; + + void applyQuery(CategoryQuery categoryQuery) { + if (_queries.contains(categoryQuery)) { + _queries.remove(categoryQuery); + } + _queries.add(categoryQuery); + } + + void applyAllQueries(Set queriesNew) { + _queries = {...queriesNew, ..._queries}; + } + + void removeQuery(CategoryQuery query) { + _queries.remove(query); + } + + Map get queries => {for (var query in _queries) ...query.query}..removeWhere((key, value) => value.isEmpty); + + void removeWhere(bool Function(CategoryQuery) condition) { + _queries.removeWhere(condition); + } +} diff --git a/lib/models/categories/products/my_products.dart b/lib/models/categories/products/my_products.dart new file mode 100644 index 0000000..a0ddabd --- /dev/null +++ b/lib/models/categories/products/my_products.dart @@ -0,0 +1,59 @@ +import 'dart:convert'; + +import 'package:birzha/constants.dart'; +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/products/my_product.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/material.dart'; + +import '../../../new/utils/locale.dart'; + +class MyProducts extends RemoteCategory { + MyProducts() : super(data: {'id': -7}); + + @override + SliverGridDelegate? gridDelegate(BuildContext context) { + return AppConstants.productsGridDelegate(context); + } + + @override + get copy => MyProducts(); + + @override + String get name => 'myProducts'.translation; + + @override + postBuilderDelegate(Map data) { + return MyProduct(data: data); + } + + @override + Uri postUri(BuildContext context, int page) { + debugPrint("myProducts"); + return baseUrl( + path: kApiPath + '/my-products', + queryParameters: { + 'page': page.toString(), + 'custom_per_page': AppConstants.pageLimit.toString(), + }, + ); + } + + @override + Future> getPosts(BuildContext context, int page) async { + String locale = await getLocale(); + return FutureGetList(postUri(context, page), parser: (response) { + final map = jsonDecode(response.body); + final products = map?['data'] as List; + return products.map((data) => postBuilderDelegate(data)).toList(); + }).fetch( + { + 'Accept': 'application/json', + 'Authorization': 'Bearer ${AppUserManager.of(context).dataSync.token}', + 'locale': locale, + }, + ); + } +} diff --git a/lib/models/categories/products/pure.dart b/lib/models/categories/products/pure.dart new file mode 100644 index 0000000..8ec75e8 --- /dev/null +++ b/lib/models/categories/products/pure.dart @@ -0,0 +1,20 @@ +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/categories/products/remote.dart'; +import 'package:birzha/models/products/product.dart'; + +class ProductsPureCategory extends PureAppCategory { + ProductsPureCategory({required Map data}) + : super(data: {...data}); + + ProductsRemoteCategory toRemote() { + return ProductsRemoteCategory.fromPureCategory(this); + } + + @override + get copy => ProductsPureCategory(data: {...jSON}); + + @override + Product postBuilderDelegate(Map data) { + return Product(data: {...data}); + } +} diff --git a/lib/models/categories/products/remote.dart b/lib/models/categories/products/remote.dart new file mode 100644 index 0000000..6fd3348 --- /dev/null +++ b/lib/models/categories/products/remote.dart @@ -0,0 +1,101 @@ +import 'dart:convert'; + +import 'package:birzha/constants.dart'; +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/categories/products/pure.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:birzha/models/queries/query.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +class MasterProductsRemoteCategory implements Serializer { + MasterProductsRemoteCategory(); + + Future> getSubCategories(BuildContext context, + {int page = 1}) async { + var categories = await FutureGetList( + baseUrl(path: kApiPath + '/categories', queryParameters: { + 'page': page.toString(), + 'per_page': AppConstants.pageLimit.toString() + }), parser: (response) { + final map = jsonDecode(response.body); + final products = map?['data'] as List; + return products + .map( + (jsonData) => ProductsPureCategory(data: jsonData)) + .toList(); + }).fetch(); + return categories; + } + + @override + int get primaryKey => -3; + + @override + String get name => 'news_feed'.translation; + + @override + get copy => MasterProductsRemoteCategory(); + + @override + Product postBuilderDelegate(Map data) { + return Product(data: {...data}); + } + + @override + SliverGridDelegate? gridDelegate(BuildContext context) { + return AppConstants.productsGridDelegate(context); + } + + @override + Map jSON = {}; + + @override + Future> getPosts(BuildContext context, int page) { + return SynchronousFuture(const []); + } + + @override + bool get needPagination => false; + + @override + String get primaryKeyField => 'id'; +} + +class ProductsRemoteCategory extends RemoteCategory + with AddQueryMixin, SearchableMixin { + ProductsRemoteCategory.fromPureCategory(ProductsPureCategory pureCategory) + : super(data: {...pureCategory.jSON, 'name': pureCategory.name}) { + applyQuery(SubCategoryQuery(pureCategory)); + } + + @override + ProductsRemoteCategory get copy => ProductsRemoteCategory.fromPureCategory( + ProductsPureCategory(data: {...jSON})) + ..applyAllQueries({...queriesSetCopy}); + + @override + Product postBuilderDelegate(Map data) { + return Product(data: {...data}); + } + + @override + SliverGridDelegate? gridDelegate(BuildContext context) { + return AppConstants.productsGridDelegate(context); + } + + @override + Uri postUri(BuildContext context, int page) { + debugPrint('adsdasdasdasdasdasdasdasdasdasd'); + return baseUrl(path: kApiPath + '/products', queryParameters: { + ...queries, + 'page': page.toString(), + 'custom_per_page': AppConstants.pageLimit.toString() + }); + } + + @override + String get name => jSON['name'] ?? ""; +} diff --git a/lib/models/categories/products/search.dart b/lib/models/categories/products/search.dart new file mode 100644 index 0000000..dc2931a --- /dev/null +++ b/lib/models/categories/products/search.dart @@ -0,0 +1,38 @@ +import 'package:birzha/constants.dart'; +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/categories/products/remote.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/material.dart'; + +class ProductsSearch extends RemoteCategory + with AddQueryMixin, SearchableMixin + implements ProductsRemoteCategory { + ProductsSearch() : super(data: {'id': -6}); + + @override + get copy => ProductsSearch()..applyAllQueries(queriesSetCopy); + + @override + String get name => 'search'.translation; + + @override + Product postBuilderDelegate(Map data) { + return Product(data: {...data}); + } + + @override + Uri postUri(BuildContext context, int page) { + return baseUrl(path: kApiPath + '/products', queryParameters: { + ...queries, + 'page': page.toString(), + 'custom_per_page': AppConstants.pageLimit.toString() + }); + } + + @override + SliverGridDelegate? gridDelegate(BuildContext context) { + return AppConstants.productsGridDelegate(context); + } +} diff --git a/lib/models/categories/pureCategory.dart b/lib/models/categories/pureCategory.dart new file mode 100644 index 0000000..9932cdf --- /dev/null +++ b/lib/models/categories/pureCategory.dart @@ -0,0 +1,21 @@ +part of category_lib; + +abstract class PureAppCategory extends Serializer + with TranslatableMixin { + PureAppCategory({required Map data}) : super(data) { + configureTranslationModel(); + } + + @override + Future> getPosts(BuildContext context, int page) async { + return const []; + } + + @override + String get name => + translationModel?.translationOf('name', _defaultName) ?? _defaultName; + + String get icon => jSON['icon'] ?? ""; + + String get _defaultName => jSON['name'] ?? ""; +} diff --git a/lib/models/categories/relatedProducts.dart b/lib/models/categories/relatedProducts.dart new file mode 100644 index 0000000..641fee4 --- /dev/null +++ b/lib/models/categories/relatedProducts.dart @@ -0,0 +1,65 @@ +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/material.dart'; + +class RelatedProductsCategory extends RemoteCategory { + RelatedProductsCategory.fromProduct(Product product) + : super(data: { + 'product': {...product.jSON}, + 'products': [] + }); + + Product get product => Product(data: {...jSON['product']}); + + List get _products => [ + for (Map p in jSON['products']) Product(data: {...p}) + ]; + + set _products(List products) { + jSON['products'] = [ + for (Product p in products) {...p.jSON} + ]; + } + + Map getProductsForDetails() { + return { + 'relatedProducts': [ + for (Product product in _products) {...product.jSON} + ] + }; + } + + @override + String get name => 'relatedProducts'.translation; + + @override + int get primaryKey => -2; + + @override + Future> getPosts(BuildContext context, int page) async { + var productsList = await super.getPosts(context, page); + _products = [...productsList]; + return [..._products]; + } + + @override + Uri postUri(BuildContext context, int page) { + debugPrint('ggggggggggggggggggggggggg'); + return baseUrl(path: kApiPath + '/products', queryParameters: { + 'product_id': product.id.toString(), + 'page': '1', + 'custom_per_page': '10' + }); + } + + @override + Product postBuilderDelegate(Map data) { + return Product(data: {...data}); + } + + @override + get copy => + RelatedProductsCategory.fromProduct(product).._products = [..._products]; +} diff --git a/lib/models/categories/remoteCategory.dart b/lib/models/categories/remoteCategory.dart new file mode 100644 index 0000000..34494d3 --- /dev/null +++ b/lib/models/categories/remoteCategory.dart @@ -0,0 +1,13 @@ +part of category_lib; + +abstract class RemoteCategory extends Serializer with _GetRemotePostssMixin { + RemoteCategory({required Map data}) : super(data); + + @override + Future> getPosts(BuildContext context, int page) { + return _getAndParsePosts(context, page); + } + + @override + RemoteCategory get copy; +} diff --git a/lib/models/chatroom/chatroom.dart b/lib/models/chatroom/chatroom.dart new file mode 100644 index 0000000..1edf8cc --- /dev/null +++ b/lib/models/chatroom/chatroom.dart @@ -0,0 +1,303 @@ +import 'dart:collection'; +import 'dart:convert'; +import 'package:http/http.dart' as http; +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/chatroom/message.dart'; +import 'package:birzha/models/exceptions/exception.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:birzha/core/orm/orm.dart'; +import 'package:provider/provider.dart'; + +class Chatroom extends Manager<_ChatroomData> implements _ChatroomData { + Set _availableLocalMessages = {}; + Set get _availableRemoteMessages => { + for (var data in jSON['messages'] ?? []) RemoteMessage(data: {...data}) + }; + + Set get messages => UnmodifiableSetView({..._availableLocalMessages, ..._availableRemoteMessages}); + + int get lastIndexOfLocalMessages => _lastMessageInBufferId; + + void _clearSentMessages() { + _availableLocalMessages.removeWhere((element) => element.status == MessagesStatus.sent); + } + + @override + get jSON => {...dataSync.jSON}; + + @override + set jSON(other) {} + + int _lastMessageInBufferId = -1; + + Chatroom({required Map data}) : super(_ChatroomData(data: {...data})); + + factory Chatroom.init({required Map data}) { + var newData = {...data}; + newData['id'] = data['chatroom_id']; + newData['messages'] = []; + return Chatroom(data: {...newData}); + } + + @override + int get primaryKey => jSON[primaryKeyField]; + + @override + String get primaryKeyField => 'id'; + + @override + Vendor? get sender => dataSync.sender; + + @override + String get subTitile => dataSync.subTitile; + + @override + String get title => dataSync.title; + + @override + int get unread => dataSync.unread; + + @override + bool get hasNewMessages => dataSync.hasNewMessages; + + @override + @protected + _ChatroomData get dataSync => super.dataSync; + + @override + @protected + get value => super.value; + + @override + @protected + set value(other) { + super.value = other; + } + + @override + void listenerCallBack(TaskResult<_ChatroomData?> result, String taskKey) { + _statusTable[taskKey] = result.status; + notifyListeners(); + } + + @override + Future destroyTask(String taskId) async { + _statusTable.remove(taskId); + return super.destroyTask(taskId); + } + + Map _statusTable = {}; + + TaskStatus getStatusByKey(String key) { + return _statusTable[key] ?? TaskStatus.None; + } + + void loadPastMessages(BuildContext context, [VoidCallback? onDone]) { + addTask(Task( + key: 'load', + computation: () async { + try { + var response = await _loadMoreRequest(AppUserManager.of(context).dataSync.token ?? "", dataSync, _howManyMessagesToSkip); + var decoded = jsonDecode(response.body); + var isSuccess = decoded['status_code'] == 200 || decoded['status_code'] == '200'; + if (!isSuccess) { + throw AppExceptions.recognizer(decoded); + } else { + var data = decoded['data']; + var newMessages = data['messages']; + List processed = []; + if (newMessages is Iterable) { + processed = [...newMessages]; + } else { + var mapMessages = newMessages as Map; + processed = [for (var key in mapMessages.keys) mapMessages[key]]; + } + if (onDone != null) { + onDone(); + } + return dataSync.copy..jSON['messages'] = [...jSON['messages'], ...processed.reversed]; + } + } catch (ex) { + if (onDone != null) { + onDone(); + } + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + })); + } + + void refresh(BuildContext context, [VoidCallback? onDone]) { + addTask(Task( + key: 'load', + computation: () async { + try { + var response = await _loadMoreRequest(AppUserManager.of(context).dataSync.token ?? "", dataSync, 0); + var decoded = jsonDecode(response.body); + var isSuccess = decoded['status_code'] == 200 || decoded['status_code'] == '200'; + if (!isSuccess) { + throw AppExceptions.recognizer(decoded); + } else { + var data = decoded['data']; + var newMessages = data['messages']; + List processed = []; + if (newMessages is Iterable) { + processed = [...newMessages]; + } else { + var mapMessages = newMessages as Map; + processed = [for (var key in mapMessages.keys) mapMessages[key]]; + } + if (onDone != null) { + onDone(); + } + _clearSentMessages(); + return dataSync.copy + ..jSON['messages'] = [ + ...processed.reversed, + ...jSON['messages'], + ]; + } + } catch (ex, trace) { + print(trace); + if (onDone != null) { + onDone(); + } + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + })); + } + + int get _howManyMessagesToSkip { + var sentMessages = messages.where((element) => element.status == MessagesStatus.sent); + return sentMessages.length; + } + + void retextMessage(BuildContext context, Message message) { + _availableLocalMessages.remove(message); + notifyListeners(); + textMessage(context, message.text); + } + + void textMessage(BuildContext context, String text) { + addTask(Task( + computation: () async { + var message = LocalMessage(date: DateTime.fromMillisecondsSinceEpoch(DateTime.now().millisecondsSinceEpoch), id: _lastMessageInBufferId, text: text); + try { + _lastMessageInBufferId--; + message.status = MessagesStatus.sending; + _availableLocalMessages = {message, ..._availableLocalMessages}; + notifyListeners(); + var response = await _sendMessageRequest( + message, + AppUserManager.of(context).dataSync.token ?? "", + dataSync, + ); + var decoded = jsonDecode(response.body); + var isSuccess = decoded['status_code'] == 200 || decoded['status_code'] == '200'; + if (!isSuccess) { + throw AppExceptions.recognizer(decoded); + } else { + message.status = MessagesStatus.sent; + return dataSync.copy..jSON['last_message'] = {...message.toRemoteMessage().jSON}; + } + } catch (ex) { + message.status = MessagesStatus.failed; + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'message' + (_lastMessageInBufferId).toString())); + } + + @protected + @override + _ChatroomData get copy => throw UnimplementedError(); + + static Chatroom of(BuildContext context, {bool listen = false}) { + return Provider.of(context, listen: listen); + } +} + +Future _sendMessageRequest(LocalMessage message, String token, _ChatroomData chatroom) { + return http.post(baseUrl(path: kApiPath + '/messages/' + chatroom.primaryKey.toString()), body: jsonEncode({'msg': message.text}), headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }); +} + +Future _loadMoreRequest(String token, _ChatroomData chatroom, int skip) { + return http.get(baseUrl(path: kApiPath + '/messages/chatroom/' + chatroom.primaryKey.toString() + '/load-more', queryParameters: {'skip': skip.toString()}), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer $token', + }); +} + +class _ChatroomData extends Post with CopyAbleMixin<_ChatroomData> { + _ChatroomData({required Map data}) : super(data); + + Vendor? get sender { + if (jSON['vendor'] != null) { + return Vendor(data: {...jSON['vendor']}); + } + if (jSON['users'] is! Iterable) { + return null; + } + var users = jSON['users'] as Iterable; + if (users.isEmpty) { + return null; + } + + return Vendor(data: {...users.first}); + } + + String get title => (sender?.name.isEmpty ?? true) ? (sender?.phone ?? "") : sender!.name; + String get subTitile => jSON['last_message'] is! Map ? '' : RemoteMessage(data: {...jSON['last_message']}).text; + int get unread => jSON['count_unread_messages'] is! int ? 0 : jSON['count_unread_messages']; + bool get hasNewMessages => unread > 0; + + @override + _ChatroomData get copy => _ChatroomData(data: {...jSON}); +} + +class ChatroomSerializer extends RemoteCategory { + ChatroomSerializer() : super(data: {'id': -5}); + + @override + get copy => ChatroomSerializer(); + + @override + String get name => 'messages'.translation; + + @override + Chatroom postBuilderDelegate(Map data) => Chatroom(data: {...data}); + + @override + Uri postUri(BuildContext context, int page) { + return baseUrl(path: kApiPath + '/messages'); + } + + @override + Future> getPosts(BuildContext context, int page) { + return FutureGetList( + postUri(context, page), + parser: (response) { + var decoded = jsonDecode(response.body); + var chatrooms = decoded['data']['chatrooms'] as Iterable; + return [ + for (var chatroomRaw in chatrooms) Chatroom(data: {...chatroomRaw}) + ]; + }, + ).fetch({'Accept': 'application/json', 'Authorization': 'Bearer ${AppUserManager.of(context).dataSync.token}'}); + } + + @override + bool get needPagination => false; +} diff --git a/lib/models/chatroom/message.dart b/lib/models/chatroom/message.dart new file mode 100644 index 0000000..2503cc6 --- /dev/null +++ b/lib/models/chatroom/message.dart @@ -0,0 +1,79 @@ +import 'package:birzha/models/user/userManager.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:birzha/core/orm/orm.dart'; + +enum MessagesStatus { sending, sent, failed, none } + +abstract class Message { + String get text; + DateTime? get date; + int get id; + MessagesStatus get status; + bool isMyMessage(BuildContext context); +} + +class RemoteMessage extends Orm implements Message { + RemoteMessage({required Map data}) : super(data); + + @override + DateTime? get date => DateTime.tryParse(jSON["send_at"] ?? ""); + + @override + int get id => primaryKey; + + @override + String get primaryKeyField => 'id'; + + @override + String get text => jSON['message'] ?? ""; + + @override + MessagesStatus get status => MessagesStatus.sent; + + RemoteMessage._fromLocalMessage(int id, String text) : this(data: {'id': id, 'message': text}); + + @override + bool isMyMessage(context) => AppUserManager.of(context).dataSync.primaryKey == jSON['sender_id']; +} + +class LocalMessage implements Message { + LocalMessage({required this.id, required DateTime date, required this.text}) { + _date = date; + } + + MessagesStatus _status = MessagesStatus.none; + + late final DateTime _date; + + DateTime get date => _date.toLocal(); + + @override + final int id; + + @override + final String text; + + @override + bool operator ==(other) { + return other is LocalMessage && other.hashCode == hashCode; + } + + RemoteMessage toRemoteMessage() { + return RemoteMessage._fromLocalMessage(id, text); + } + + @override + int get hashCode => id.hashCode; + + @override + // ignore: unnecessary_getters_setters + MessagesStatus get status => _status; + + // ignore: unnecessary_getters_setters + set status(MessagesStatus other) { + _status = other; + } + + @override + bool isMyMessage(_) => true; +} diff --git a/lib/models/exceptions/exception.dart b/lib/models/exceptions/exception.dart new file mode 100644 index 0000000..4700e06 --- /dev/null +++ b/lib/models/exceptions/exception.dart @@ -0,0 +1,55 @@ +import 'package:flutter/material.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/screens/auth/login.dart'; +import 'package:birzha/services/modals.dart'; + +abstract class AppExceptions implements Exception { + final String message; + AppExceptions({required this.message}); + + factory AppExceptions.recognizer(Map data) { + var message = data['error']; + if (message != null && message is Map) { + var translated = message['backendCode'.translation]; + return MessageException(translated); + } else + return OtherException(); + } + + static void exceptionHandler(BuildContext context, dynamic exception) { + if (exception is OtherException) { + showSnackBar(context, content: exception.message.translation); + } else if (exception is CartProblemException) + showSnackBar(context, + content: exception.message, duration: Duration(seconds: 4)); + else if (exception is UnAuthenticatedException) + Navigator.of(context, rootNavigator: true) + .push(MaterialPageRoute(builder: (_) => LoginScreen())); + else if (exception is MessageException) { + showSnackBar(context, content: exception.message); + } else { + showSnackBar(context, content: OtherException().message.translation); + } + } + + @override + String toString() { + return message; + } +} + +class OtherException extends AppExceptions { + OtherException() : super(message: 'otherException'); +} + +class MessageException extends AppExceptions { + MessageException(String message) : super(message: message); +} + +class UnAuthenticatedException extends MessageException { + UnAuthenticatedException() : super('unauthenticated'.translation); +} + +class CartProblemException extends MessageException { + CartProblemException() : super('cartProblem'.translation); +} diff --git a/lib/models/products/composable.dart b/lib/models/products/composable.dart new file mode 100644 index 0000000..72b4bb3 --- /dev/null +++ b/lib/models/products/composable.dart @@ -0,0 +1,25 @@ +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/core/orm/orm.dart'; + +enum PostCompositionMode { create, update } + +mixin ComposableMixin on Orm { + Map _attributeCache = {}; + + PostAttribute? getModelData(String key) { + return _attributeCache[key]; + } + + String getBasicFieldValue(String key) { + return jSON[key] ?? ""; + } + + void setBasicTypeField(String key, String value) { + jSON[key] = value; + } + + void setModelField(String key, PostAttribute model) { + _attributeCache[key] = model; + jSON[key] = model.primaryKey.toString(); + } +} diff --git a/lib/models/products/composableProduct.dart b/lib/models/products/composableProduct.dart new file mode 100644 index 0000000..214acd4 --- /dev/null +++ b/lib/models/products/composableProduct.dart @@ -0,0 +1,126 @@ +import 'dart:collection'; +import 'dart:convert'; + +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/models/attributes/category.dart'; +import 'package:birzha/models/attributes/market_type.dart'; +import 'package:birzha/models/attributes/miscelaneous.dart'; +import 'package:birzha/models/attributes/packaging.dart'; +import 'package:birzha/models/products/composable.dart'; +import 'package:birzha/models/products/my_product.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/orm/orm.dart'; +import 'package:http/http.dart' as http; + +abstract class ImageModel extends Orm { + ImageModel._({required Map data}) : super(data); + + @override + String get primaryKeyField => 'path'; +} + +class LocalImageModel extends ImageModel { + LocalImageModel._fromPath(String path) : super._(data: {'path': path}); + LocalImageModel._fromModel({required Map data}) : super._(data: {...data}); +} + +class RemoteImageModel extends ImageModel { + RemoteImageModel._fromPath(String path, int id) : super._(data: {'path': path, 'id': id}); + RemoteImageModel._fromModel({required Map data}) : super._(data: {...data}); + + int? get id => jSON['id']; +} + +class ComposableProduct extends Orm with ComposableMixin, ChangeNotifier { + ComposableProduct._() : super({}); + + static ComposableProduct? _singletone; + + factory ComposableProduct() { + return _singletone ??= ComposableProduct._(); + } + + static Future getAttributes(BuildContext context, MyProduct? product) async { + List options = []; + if (ComposableProduct().attrbiutes.isEmpty) { + options = await _getAttributes(context); + } else { + options = await SynchronousFuture([...ComposableProduct().attrbiutes]); + } + ComposableProduct()._attributes = [...options]; + if (product != null) { + await ComposableProduct()._changeAttributes(context, product.primaryKey); + } + } + + List _attributes = []; + + List get attrbiutes => UnmodifiableListView(_attributes); + + Future _changeAttributes(BuildContext context, int productId) async { + var token = AppUserManager.of(context).dataSync.token; + var editedData = await http.get(baseUrl(path: kApiPath + '/my-products/$productId'), headers: {'Authorization': 'Bearer $token'}); + var decoded = jsonDecode(editedData.body); + jSON = {...decoded}; + print(jSON['old_img']); + jSON['old_img'] = [ + for (var item in ((decoded['old_img'] ?? []) as Iterable).where((element) => element['path'] is String && (element['path'] as String).isNotEmpty)) + RemoteImageModel._fromPath(item?['path'] ?? "", item['id']).jSON + ]; + for (var attribute in _attributes) { + var id = jSON[attribute.key]; + if (id != null) { + try { + var matchingOption = attribute.options.firstWhere((element) => element.primaryKey == id); + setModelField(attribute.key, matchingOption); + } catch (e) {} + } + } + saveProgress(decoded['id']); + } + + void saveProgress(int? id) { + jSON['productForEditing'] = id; + notifyListeners(); + } + + Map sendData() { + return {...jSON}; + } + + void removeImage(BuildContext context, ImageModel image) { + if (image is LocalImageModel) { + (jSON['new_img'] as List).removeWhere((element) => LocalImageModel._fromModel(data: element).primaryKey == image.primaryKey); + } else if (image is RemoteImageModel) { + AppUserManager.of(context).deleteImage(context, this, image, () { + try { + (jSON['old_img'] as List).removeWhere((element) => RemoteImageModel._fromModel(data: element).primaryKey == image.primaryKey); + } catch (e) {} + }); + } + notifyListeners(); + } + + void pickImages() async { + var result = await FilePicker.platform.pickFiles(type: FileType.custom, allowMultiple: true, withReadStream: true, allowedExtensions: ['jpg', 'png']); + if (result != null) { + jSON['new_img'] = [for (var image in result.files.where((element) => element.path != null)) LocalImageModel._fromPath(image.path!).jSON]; + notifyListeners(); + } + } + + List get localImages => [for (var item in jSON['new_img'] ?? []) LocalImageModel._fromModel(data: item)]; + + List get remoteImages => [for (var item in jSON['old_img'] ?? []) RemoteImageModel._fromPath(item['path'], item['id'])]; + + @override + String get primaryKeyField => 'productForEditing'; +} + +Future> _getAttributes(BuildContext context) async { + return [await CategoryAttribute.getAttribute(), ...await MiscAttribute.getAttrbutes(), MarketTypeAttribute.getAttribute(), PackagingAttribute.getAttribute()]; +} diff --git a/lib/models/products/my_product.dart b/lib/models/products/my_product.dart new file mode 100644 index 0000000..c7f55b7 --- /dev/null +++ b/lib/models/products/my_product.dart @@ -0,0 +1,70 @@ +import 'package:birzha/constants.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter/material.dart'; + +enum MyProductStatus { approved, puiblished, draft, denied, none } + +class MyProduct extends Product { + MyProduct({required Map data}) : super(data: data); + + String get statusNotes => jSON['status_note'] ?? ""; + + bool get isAbleToEdit { + return status == MyProductStatus.draft || status == MyProductStatus.denied; + } + + Color get statusColor { + switch (status) { + case MyProductStatus.approved: + return Colors.green; + case MyProductStatus.puiblished: + return Colors.orange; + case MyProductStatus.draft: + return AppConstants.appColor; + case MyProductStatus.denied: + return Colors.redAccent; + case MyProductStatus.none: + return AppConstants.appColor; + } + } + + String get statusLabel { + switch (status) { + case MyProductStatus.approved: + return 'approved'.translation; + case MyProductStatus.puiblished: + return 'published'.translation; + case MyProductStatus.draft: + return 'draft'.translation; + case MyProductStatus.denied: + return 'denied'.translation; + case MyProductStatus.none: + return 'none'.translation; + } + } + + MyProductStatus get status { + switch (jSON['status']) { + case 'approved': + return MyProductStatus.approved; + case 'new': + return MyProductStatus.puiblished; + case 'draft': + return MyProductStatus.draft; + case 'denied': + return MyProductStatus.denied; + default: + return MyProductStatus.none; + } + } + + @override + get copy => MyProduct(data: {...jSON}); + + @override + get characteristics => [ + ProductCharacteristics('status'.translation, statusLabel), + ...super.characteristics + ]; +} diff --git a/lib/models/products/post.dart b/lib/models/products/post.dart new file mode 100644 index 0000000..a031ac3 --- /dev/null +++ b/lib/models/products/post.dart @@ -0,0 +1,31 @@ +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/translationModel.dart'; +import 'package:birzha/services/translationServices.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/orm/orm.dart'; + +abstract class PostCharacteristics { + String get translatedLabel; + String get value; +} + +mixin RemoteDetailsMixin on Post { + Future loadDetails(BuildContext context); +} + +mixin TranslatableMixin on Orm { + void configureTranslationModel() { + var translationsRaw = jSON['translations']; + if (translationsRaw != null && translationsRaw is Iterable) + (translationsRaw as List).removeWhere((element) => TranslationModel({...element}).primaryKey != 'backendCode'.translation); + } + + TranslationModel? get translationModel => getTranslationAccordingToLocale(translationsFromMap(jSON)); +} + +abstract class Post extends Orm { + Post(Map jSON) : super(jSON); + + @override + String get primaryKeyField => 'id'; +} diff --git a/lib/models/products/product.dart b/lib/models/products/product.dart new file mode 100644 index 0000000..c8caa87 --- /dev/null +++ b/lib/models/products/product.dart @@ -0,0 +1,137 @@ +import 'dart:convert'; +import 'dart:math' as math; +import 'package:birzha/models/categories/relatedProducts.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/services/helpers.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/foundation.dart'; +import 'package:http/http.dart' as http; +import 'package:birzha/core/orm/orm.dart'; + +const _characLabelKeys = [ + 'productNumber', + 'productAmount', + 'productMark', + 'producer', + 'producerCountry', +]; + +const _characValueKeys = ['id', 'quantity', 'mark', 'manufacturer', 'country']; + +class ProductCharacteristics implements PostCharacteristics { + @override + final String translatedLabel; + + @override + final String value; + + ProductCharacteristics(this.translatedLabel, this.value); +} + +class Product extends Post with RemoteDetailsMixin, CopyAbleMixin, TranslatableMixin { + Product({required Map data}) : super(data) { + configureTranslationModel(); + } + + int get id => primaryKey; + + @protected + String get quantity => jSON['quantity'] ?? '0'; + + String get quantityFormatted => quantity.toString(); + + @protected + DateTime? get expiryDate => DateTime.tryParse(jSON['ends_at'] ?? ""); + + @protected + double get price => double.tryParse('${jSON["price"]}') ?? 0; + + String get expiryDateFormatted => safeValueDate(expiryDate); + + String get priceFormatted => priceFormatter(price); + + String get _defaultName => jSON['name'] ?? ""; + + String get _defaultDescription => jSON['description'] ?? ""; + + String get unit => jSON['unit']["name"] ?? ""; + + String get name { + return translationModel?.translationOf('name', _defaultName) ?? _defaultName; + } + + String get description { + return translationModel?.translationOf('description', _defaultDescription) ?? _defaultDescription; + } + + List get images => [ + for (var image in [...?jSON['images']]) image['path'] + ]..removeWhere((element) => element.isEmpty); + + String get mainImage => images.isEmpty ? '' : images.first; + + @override + Future loadDetails(context) async { + var user = AppUserManager.of(context).dataSync; + var data = await http.get(baseUrl(path: kApiPath + '/products/' + id.toString()), + headers: {if (user.isRegistered) 'Authorization': 'Bearer ${user.token}', 'Content-Type': 'application/json'}); + var result = jsonDecode(data.body); + var category = RelatedProductsCategory.fromProduct(this); + await category.getPosts(context, 1); + jSON = {...jSON, ...result, ...category.getProductsForDetails()}; + } + + List get relatedProducts => [ + for (var productRaw in [...?jSON['relatedProducts']]) Product(data: {...productRaw}) + ]; + + @override + Product get copy => Product(data: {...jSON}); + + List get characteristics => [ + ...[ + for (var i = 0; i < math.min(_characLabelKeys.length, _characValueKeys.length); i++) + ProductCharacteristics(_characLabelKeys[i].translation, jSON[_characValueKeys[i]]?.toString() ?? ""), + ]..insert(1, ProductCharacteristics('startingPrice'.translation, priceFormatted)) + ]; + + Vendor? get vendor { + if (jSON['vendor'] == null) { + return null; + } else { + return Vendor(data: {...jSON['vendor']}); + } + } +} + +/* { + id: 4, + deleted_at: null, + created_at: 2021-06-24 06:01:38, + updated_at: 2021-10-19 16:42:48, + name: in.m, + code: in.m, + translations: [ + { + locale: en, + model_id: 4, + attribute_data: + { + "name":"sq.m", + "code":"sq.m" + } + }, + { + locale: ru, + model_id: 4, + attribute_data: + { + "name":"кв.м", + "code":"кв.м" + } + } + ] +} */ \ No newline at end of file diff --git a/lib/models/queries/query.dart b/lib/models/queries/query.dart new file mode 100644 index 0000000..446214b --- /dev/null +++ b/lib/models/queries/query.dart @@ -0,0 +1,46 @@ +library query_lib; + +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +part 'package:birzha/models/queries/subCategoryQuery.dart'; + +int _suCategoryQueryHasCode = -1; + +/// This is a starting point of queries namespace +/// Important thins to know: All queries will be summed up into one Set of queries in [AddQueryMixin] of categories +/// That means - you may not have to identical queries in one Set (depends on the [CategoryQuery.hashCodeIdentificator]) +/// Some queries are forced to be single in one set: that's why I used negative constant [_suCategoryQueryHasCode] for [SubCategoryQuery] + +abstract class CategoryQuery { + final String name; + final String value; + + Map get query => {name: value}; + + @override + bool operator ==(other) { + return other is CategoryQuery && hashCode == other.hashCode; + } + + @override + int get hashCode => hashCodeIdentificator; + + int get hashCodeIdentificator; + + CategoryQuery({required this.name, required this.value}); +} + +class SearchQuery extends CategoryQuery { + SearchQuery(String word) : super(name: 'q', value: word); + + @override + int get hashCodeIdentificator => -6; +} + +class LocaleQuery extends CategoryQuery { + LocaleQuery() : super(name: 'locale', value: 'backendCode'.translation); + + @override + int get hashCodeIdentificator => -7; +} diff --git a/lib/models/queries/subCategoryQuery.dart b/lib/models/queries/subCategoryQuery.dart new file mode 100644 index 0000000..b931c31 --- /dev/null +++ b/lib/models/queries/subCategoryQuery.dart @@ -0,0 +1,11 @@ +part of query_lib; + +class SubCategoryQuery extends CategoryQuery{ + + PureAppCategory categoryReference; + + SubCategoryQuery(this.categoryReference) : super(name: 'category_id', value: categoryReference.primaryKey.toString()); + + @override + int get hashCodeIdentificator => _suCategoryQueryHasCode.hashCode; +} \ No newline at end of file diff --git a/lib/models/settings/settingsModel.dart b/lib/models/settings/settingsModel.dart new file mode 100644 index 0000000..eaa9b72 --- /dev/null +++ b/lib/models/settings/settingsModel.dart @@ -0,0 +1,246 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +const kDefaultLanguage = 'tk'; + +class SettingsModel extends ChangeNotifier { + String _language = kDefaultLanguage; + bool pushEnabled = true; + + static AppLocalizations? _localization; + static Future initLocalization(String l) async { + _localization = await AppLocalizations.delegate.load(Locale(l, l == 'en' ? 'US' : '')); + } + + Future setLanguage(String l) async { + _language = l; + await initLocalization(l); + var prefs = await SharedPreferences.getInstance(); + await prefs.setString('language', _language); + notifyListeners(); + } + + Locale get language { + switch (_language) { + case 'ru': + return const Locale('ru', ''); + case 'en': + return const Locale('en', 'US'); + case 'tk': + return const Locale('tk', ''); + default: + return const Locale('tk', ''); + } + } + + void launch(SharedPreferences prefs) { + _language = prefs.getString('language') ?? _language; + notifyListeners(); + } + + SettingsModel(SharedPreferences prefs) { + launch(prefs); + } + + static SettingsModel of(BuildContext context, [bool listen = false]) { + return Provider.of(context, listen: listen); + } +} + +extension LocalMessageExt on String { + String get translation { + return { + "yourMessage": SettingsModel._localization?.yourMessage, + "nsm": SettingsModel._localization?.nsm, + "buyNow": SettingsModel._localization?.buyNow, + "uploadReceipt": SettingsModel._localization?.uploadReceipt, + "payOnline": SettingsModel._localization?.payOnline, + "sendMessage": SettingsModel._localization?.sendMessage, + "dataIsUpdated": SettingsModel._localization?.dataIsUpdated, + "personalCabinet": SettingsModel._localization?.personalCabinet, + "addPost": SettingsModel._localization?.addPost, + "iu_company": SettingsModel._localization?.iu_company, + "iu_about": SettingsModel._localization?.iu_about, + "phone_error": SettingsModel._localization?.phone_error, + "email_error": SettingsModel._localization?.email_error, + "username": SettingsModel._localization?.username, + "noAccount": SettingsModel._localization?.noAccount, + "yourPassword": SettingsModel._localization?.yourPassword, + "yourLogin": SettingsModel._localization?.yourLogin, + "yourEmail": SettingsModel._localization?.yourEmail, + "link": SettingsModel._localization?.link, + "loginText": SettingsModel._localization?.loginText, + "expiryDate": SettingsModel._localization?.expiryDate, + "sellerContact": SettingsModel._localization?.sellerContact, + "address": SettingsModel._localization?.address, + "realAddress": SettingsModel._localization?.realAddress, + "mail": SettingsModel._localization?.mail, + "telephone": SettingsModel._localization?.telephone, + "lotNumber": SettingsModel._localization?.lotNumber, + "productNumber": SettingsModel._localization?.productNumber, + "productMark": SettingsModel._localization?.productMark, + "productAmount": SettingsModel._localization?.productAmount, + "startingPrice": SettingsModel._localization?.startingPrice, + "producer": SettingsModel._localization?.producer, + "producerCountry": SettingsModel._localization?.producerCountry, + "description": SettingsModel._localization?.description, + "unit": SettingsModel._localization?.unit, + "paymentTerms": SettingsModel._localization?.paymentTerms, + "deliveryTerms": SettingsModel._localization?.deliveryTerms, + "station": SettingsModel._localization?.station, + "packing": SettingsModel._localization?.packing, + "english": SettingsModel._localization?.english, + "russian": SettingsModel._localization?.russian, + "turkmen": SettingsModel._localization?.turkmen, + "localeLabel": SettingsModel._localization?.localeLabel, + "backendCode": SettingsModel._localization?.backendCode, + "save_changes": SettingsModel._localization?.save_changes, + "email": SettingsModel._localization?.email, + "message": SettingsModel._localization?.message, + "top_up_history": SettingsModel._localization?.top_up_history, + "personal_data": SettingsModel._localization?.personal_data, + "news_feed": SettingsModel._localization?.news_feed, + "feedback": SettingsModel._localization?.feedback, + "privacy_policy": SettingsModel._localization?.privacy_policy, + "contact": SettingsModel._localization?.contact, + "home": SettingsModel._localization?.home, + "category": SettingsModel._localization?.category, + "favourites": SettingsModel._localization?.favourites, + "settings": SettingsModel._localization?.settings, + "login": SettingsModel._localization?.login, + "phone": SettingsModel._localization?.phone, + "password": SettingsModel._localization?.password, + "or": SettingsModel._localization?.or, + "register": SettingsModel._localization?.register, + "first_name": SettingsModel._localization?.first_name, + "last_name": SettingsModel._localization?.last_name, + "lang": SettingsModel._localization?.lang, + "phoneValidator": SettingsModel._localization?.phoneValidator, + "empty": SettingsModel._localization?.empty, + "forgot": SettingsModel._localization?.forgot, + "search": SettingsModel._localization?.search, + 'cart': SettingsModel._localization?.cart, + 'addToCart': SettingsModel._localization?.addToCart, + 'addedToCart': SettingsModel._localization?.addedToCart, + "removedFromCart": SettingsModel._localization?.removedFromCart, + "inCart": SettingsModel._localization?.inCart, + "allPrice": SettingsModel._localization?.allPrice, + 'wantDelete': SettingsModel._localization?.wantDelete, + 'hit': SettingsModel._localization?.hit, + 'newGoods': SettingsModel._localization?.newGoods, + "emptyPosts": SettingsModel._localization?.emptyPosts, + "order": SettingsModel._localization?.order, + "account": SettingsModel._localization?.account, + "otherException": SettingsModel._localization?.otherException, + "password_confirmation": SettingsModel._localization?.password_confirmation, + "password_confirmation_error": SettingsModel._localization?.password_confirmation_error, + 'profile': SettingsModel._localization?.profile, + "unauthenticated": SettingsModel._localization?.unauthenticated, + "needToEnter": SettingsModel._localization?.needToEnter, + "logout": SettingsModel._localization?.logout, + "logging_out": SettingsModel._localization?.logging_out, + "sure_log_out": SettingsModel._localization?.sure_log_out, + "date": SettingsModel._localization?.date, + "status": SettingsModel._localization?.status, + "products": SettingsModel._localization?.products, + "smsCodeSent": SettingsModel._localization?.smsCodeSent, + "codeLabel": SettingsModel._localization?.codeLabel, + "passwordError": SettingsModel._localization?.passwordError, + "verify": SettingsModel._localization?.verify, + "sendingCode": SettingsModel._localization?.sendingCode, + "sendCode": SettingsModel._localization?.sendCode, + "rules": SettingsModel._localization?.rules, + "agree": SettingsModel._localization?.agree, + "about": SettingsModel._localization?.about, + "quantitySumm": SettingsModel._localization?.quantitySumm, + "enterQuantity": SettingsModel._localization?.enterQuantity, + "formatError": SettingsModel._localization?.formatError, + "tapToLoadMore": SettingsModel._localization?.tapToLoadMore, + "similiarProducts": SettingsModel._localization?.similiarProducts, + "dialCode": SettingsModel._localization?.dialCode, + "verificationMailSent": SettingsModel._localization?.verificationMailSent, + "verifyMail": SettingsModel._localization?.verifyMail, + "verifyPhone": SettingsModel._localization?.verifyPhone, + "sms_code": SettingsModel._localization?.sms_code, + "check": SettingsModel._localization?.check, + "myProducts": SettingsModel._localization?.myProducts, + "firstStep": SettingsModel._localization?.firstStep, + "addPosts": SettingsModel._localization?.addPosts, + "addPostName": SettingsModel._localization?.addPostName, + "mark": SettingsModel._localization?.mark, + "manufacturer": SettingsModel._localization?.manufacturer, + "marketType": SettingsModel._localization?.marketType, + "country": SettingsModel._localization?.country, + "inMarket": SettingsModel._localization?.inMarket, + "outMarket": SettingsModel._localization?.outMarket, + "addPostDescription": SettingsModel._localization?.addPostDescription, + "price": SettingsModel._localization?.price, + "place": SettingsModel._localization?.place, + "quantity": SettingsModel._localization?.quantity, + "measure": SettingsModel._localization?.measure, + "currency": SettingsModel._localization?.currency, + "paymentTerm": SettingsModel._localization?.paymentTerm, + "deliveryTerm": SettingsModel._localization?.deliveryTerm, + "secondStep": SettingsModel._localization?.secondStep, + "packaging": SettingsModel._localization?.packaging, + "yes": SettingsModel._localization?.yes, + "no": SettingsModel._localization?.no, + "notANumber": SettingsModel._localization?.notANumber, + "selectImages": SettingsModel._localization?.selectImages, + "localImages": SettingsModel._localization?.localImages, + "selectAtLeastImage": SettingsModel._localization?.selectAtLeastImage, + "statusNote": SettingsModel._localization?.statusNote, + "draft": SettingsModel._localization?.draft, + "approved": SettingsModel._localization?.approved, + "denied": SettingsModel._localization?.denied, + "published": SettingsModel._localization?.published, + "none": SettingsModel._localization?.none, + "edit": SettingsModel._localization?.edit, + "approve": SettingsModel._localization?.approve, + "loadedImages": SettingsModel._localization?.loadedImages, + "legalizationNumber": SettingsModel._localization?.legalizationNumber, + "newPassword": SettingsModel._localization?.newPassword, + "newPasswordConfirmation": SettingsModel._localization?.newPasswordConfirmation, + "phoneConfirmation": SettingsModel._localization?.phoneConfirmation, + "smsSentInfo": SettingsModel._localization?.smsSentInfo, + "enterSmsCode": SettingsModel._localization?.enterSmsCode, + "confirm": SettingsModel._localization?.confirm, + "verifyPhoneWarning": SettingsModel._localization?.verifyPhoneWarning, + "verifyEmailWarning": SettingsModel._localization?.verifyEmailWarning, + "topUpBalance": SettingsModel._localization?.topUpBalance, + "selectPaymentMethod": SettingsModel._localization?.selectPaymentMethod, + "bankTransfer": SettingsModel._localization?.bankTransfer, + "selectFile": SettingsModel._localization?.selectFile, + "upload": SettingsModel._localization?.upload, + "fileNotSelected": SettingsModel._localization?.fileNotSelected, + "send": SettingsModel._localization?.send, + "reminderInfo": SettingsModel._localization?.reminderInfo, + "taxCode": SettingsModel._localization?.taxCode, + "manatAccount": SettingsModel._localization?.manatAccount, + "corrAccount": SettingsModel._localization?.corrAccount, + "bankAddress": SettingsModel._localization?.bankAddress, + "selectBank": SettingsModel._localization?.selectBank, + "transferAmount": SettingsModel._localization?.transferAmount, + "enterAmount": SettingsModel._localization?.enterAmount, + "searchShort": SettingsModel._localization?.searchShort, + "newsNotFount": SettingsModel._localization?.newsNotFount, + "errorOccurred": SettingsModel._localization?.errorOccurred, + "registeredDate": SettingsModel._localization?.registeredDate, + "filters": SettingsModel._localization?.filters, + "selectCategory": SettingsModel._localization?.selectCategory, + "selectUnit": SettingsModel._localization?.selectUnit, + "selectCurrency": SettingsModel._localization?.selectCurrency, + "selectPayment": SettingsModel._localization?.selectPayment, + "selectSendType": SettingsModel._localization?.selectSendType, + "selectCountry": SettingsModel._localization?.selectCountry, + "clear": SettingsModel._localization?.clear, + "apply": SettingsModel._localization?.apply, + "importPrice": SettingsModel._localization?.importPrice, + "quotes": SettingsModel._localization?.quotes, + "notFound": SettingsModel._localization?.notFound, + }[this] ?? + this; + } +} diff --git a/lib/models/settings/theme.dart b/lib/models/settings/theme.dart new file mode 100644 index 0000000..fb53138 --- /dev/null +++ b/lib/models/settings/theme.dart @@ -0,0 +1,143 @@ +import 'package:flutter/material.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; + +abstract class AppTheme { + static final _darkTheme = ThemeData.dark(); + static final _lightTheme = ThemeData.light(); + + static LinearGradient gradient(BuildContext context) { + var isDark = false; + + return LinearGradient( + begin: FractionalOffset.topCenter, + end: FractionalOffset.bottomCenter, + colors: [ + if (isDark) ...[ + Color.fromRGBO(43, 43, 43, 0), + Theme.of(context).backgroundColor, + Color.fromRGBO(60, 60, 60, 1) + ] else ...[ + Colors.grey.shade200.withOpacity(0.03), + Colors.white, + Colors.white + ] + ], + stops: !isDark ? null : [0.0, 0.6, 1.0]); + } + + static get appLightTheme => _lightTheme.copyWith( + accentColor: AppConstants.appColor, + primaryTextTheme: _lightTheme.textTheme.copyWith( + headline2: _lightTheme.textTheme.headline2?.copyWith( + fontSize: AppConstants.h2FontSize, + color: Colors.black, + fontWeight: FontWeight.w500, + ), + headline3: TextStyle(fontSize: AppConstants.h3FontSize, color: Colors.grey)), + accentTextTheme: _lightTheme.textTheme.copyWith( + headline2: _lightTheme.textTheme.headline2?.copyWith( + fontSize: AppConstants.h2FontSize, + color: AppConstants.appColor, + fontWeight: FontWeight.w500, + ), + ), + textTheme: _lightTheme.textTheme.copyWith( + bodyText2: _lightTheme.textTheme.bodyText2?.copyWith(fontSize: AppConstants.b2FontSize, color: Colors.grey.shade800), + button: TextStyle( + color: Colors.white, + ), + headline1: _lightTheme.textTheme.headline2?.copyWith(fontSize: AppConstants.h1FontSize, color: Colors.grey.shade700, fontWeight: FontWeight.w500), + headline2: _lightTheme.textTheme.headline2?.copyWith(fontSize: AppConstants.h2FontSize, color: Colors.grey.shade700, fontWeight: FontWeight.w500), + ), + chipTheme: _lightTheme.chipTheme.copyWith( + backgroundColor: Colors.white, + side: BorderSide(color: Colors.grey.shade300), + padding: EdgeInsets.symmetric(vertical: 4.adaptedPx(), horizontal: 3.adaptedPx()), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 10.adaptedPx(), + ), + ), + labelStyle: _lightTheme.chipTheme.labelStyle?.copyWith( + fontSize: AppConstants.b3FontSize, + ), + ), + colorScheme: ColorScheme.fromSwatch().copyWith(secondary: AppConstants.appColor), + appBarTheme: AppBarTheme( + color: Colors.white, + foregroundColor: AppConstants.appColor, + iconTheme: IconThemeData(color: AppConstants.appColor), + textTheme: TextTheme(), + titleTextStyle: TextStyle(fontSize: AppConstants.appBarFontSize, fontWeight: FontWeight.bold)), + iconTheme: IconThemeData(color: Colors.white), + cardTheme: CardTheme(color: Colors.grey.shade300), + textButtonTheme: TextButtonThemeData( + style: ButtonStyle( + padding: MaterialStateProperty.all( + EdgeInsets.all( + 2.adaptedPx(), + ), + ), + textStyle: MaterialStateProperty.all(TextStyle(fontSize: AppConstants.b2FontSize)), + overlayColor: MaterialStateProperty.all(AppConstants.appColor.withOpacity(0.2)), + foregroundColor: MaterialStateProperty.all(AppConstants.appColor)), + ), + backgroundColor: Colors.white, + // backgroundColor: Color.fromRGBO(242, 245, 255, 1), + buttonColor: AppConstants.appColor, + scaffoldBackgroundColor: AppConstants.scaffoldColorLight, + bottomNavigationBarTheme: _bottomAppBarTheme.copyWith(backgroundColor: AppConstants.backgroundColor)); + + static get appDarkTheme => _darkTheme.copyWith( + accentColor: AppConstants.appColor, + brightness: Brightness.dark, + cardColor: const Color.fromRGBO(38, 38, 38, 1), + colorScheme: ColorScheme.fromSwatch().copyWith(secondary: AppConstants.appColor), + appBarTheme: _darkTheme.appBarTheme.copyWith( + backgroundColor: Color.fromRGBO(25, 25, 25, 1), titleTextStyle: TextStyle(fontSize: AppConstants.appBarFontSize, fontWeight: FontWeight.w500)), + chipTheme: _darkTheme.chipTheme.copyWith( + labelStyle: _darkTheme.chipTheme.labelStyle?.copyWith(fontSize: AppConstants.b3FontSize, color: AppConstants.appColor), + backgroundColor: Colors.black26, + padding: EdgeInsets.symmetric(vertical: 4.adaptedPx(), horizontal: 3.adaptedPx()), + side: BorderSide(color: Colors.grey.shade500), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10.adaptedPx())), + ), + buttonColor: Colors.grey.shade900, + accentTextTheme: _darkTheme.textTheme.copyWith( + headline2: _darkTheme.textTheme.headline2?.copyWith( + fontSize: AppConstants.h2FontSize, + fontWeight: FontWeight.w500, + ), + ), + primaryTextTheme: _darkTheme.textTheme.copyWith( + headline2: _darkTheme.textTheme.headline2?.copyWith( + fontSize: AppConstants.h2FontSize, + fontWeight: FontWeight.w500, + ), + headline3: TextStyle(fontSize: AppConstants.h3FontSize, color: Colors.grey)), + textButtonTheme: TextButtonThemeData( + style: ButtonStyle( + padding: MaterialStateProperty.all(EdgeInsets.all(2.adaptedPx())), + textStyle: MaterialStateProperty.all(TextStyle(fontSize: AppConstants.b2FontSize)), + overlayColor: MaterialStateProperty.all(AppConstants.appColor.withOpacity(0.2)), + foregroundColor: MaterialStateProperty.all(AppConstants.appColor)), + ), + cardTheme: CardTheme( + color: Colors.grey.shade500, + ), + textTheme: _darkTheme.textTheme.copyWith( + bodyText2: _darkTheme.textTheme.bodyText2?.copyWith(fontSize: AppConstants.b2FontSize), + button: TextStyle(color: AppConstants.appColor), + headline2: _darkTheme.textTheme.headline2?.copyWith(fontSize: AppConstants.h2FontSize, fontWeight: FontWeight.w500), + headline1: _darkTheme.textTheme.headline2?.copyWith(fontSize: AppConstants.h1FontSize, fontWeight: FontWeight.w500), + ), + backgroundColor: Color.fromRGBO(29, 29, 29, 1), + snackBarTheme: SnackBarThemeData(backgroundColor: Colors.white), + scaffoldBackgroundColor: Color.fromRGBO(29, 29, 29, 1), + bottomNavigationBarTheme: _bottomAppBarTheme.copyWith(backgroundColor: Colors.grey.shade900, selectedItemColor: Color.fromRGBO(25, 25, 25, 1))); + + static const _bottomAppBarTheme = BottomNavigationBarThemeData( + selectedItemColor: Color.fromRGBO(229, 234, 244, 100), + ); +} diff --git a/lib/models/tk_intl.dart b/lib/models/tk_intl.dart new file mode 100644 index 0000000..df39649 --- /dev/null +++ b/lib/models/tk_intl.dart @@ -0,0 +1,577 @@ +import 'dart:async'; + +import 'package:intl/intl.dart' as intl; +import 'package:intl/date_symbols.dart' as intl; +import 'package:intl/date_symbol_data_custom.dart' as date_symbol_data_custom; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; + +const _tkDatePatterns = {"d":"d","E":"ccc","EEEE":"cccc","LLL":"LLL","LLLL":"LLLL","M":"L","Md":"dd/MM","MEd":"EEE, dd/MM","MMM":"LLL","MMMd":"d MMM","MMMEd":"EEE, d MMM","MMMM":"LLLL","MMMMd":"d MMMM","MMMMEEEEd":"EEEE, d MMMM","QQQ":"QQQ","QQQQ":"QQQQ","y":"y","yM":"MM/y","yMd":"dd/MM/y","yMEd":"EEE, dd/MM/y","yMMM":"MMM y","yMMMd":"d MMM y","yMMMEd":"EEE, d MMM y","yMMMM":"MMMM y","yMMMMd":"d MMMM y","yMMMMEEEEd":"EEEE, d MMMM y","yQQQ":"QQQ y","yQQQQ":"QQQQ y","H":"HH","Hm":"HH:mm","Hms":"HH:mm:ss","j":"HH","jm":"HH:mm","jms":"HH:mm:ss","jmv":"HH:mm v","jmz":"HH:mm z","jz":"HH z","m":"m","ms":"mm:ss","s":"s","v":"v","z":"z","zzzz":"zzzz","ZZZZ":"ZZZZ"}; + + +const _tkSymbols = { + "NAME":"tk", + "ERAS":["BC","AD"], + "ERANAMES":["Before Christ","Anno Domini"], + "NARROWMONTHS":["Ý","F","M","A","M","I","I","A","S","O","N","D"], + "STANDALONENARROWMONTHS":["Ý","F","M","A","M","I","I","A","S","O","N","D"], + "MONTHS":["Ýanwar","Fewral","Mart","Aprel","Maý","Iýun","Iýul","Awgust","Sentýabr","Oktýabr","Noýabr","Dekabr"], + "STANDALONEMONTHS":["Ýanwar","Fewral","Mart","Aprel","Maý","Iýun","Iýul","Awgust","Sentýabr","Oktýabr","Noýabr","Dekabr"], + "SHORTMONTHS":["Ýan","Few","Mar","Apr","Maý","Iýu","Iýl","Awg","Sen","Okt","Noý","Dek"], + "STANDALONESHORTMONTHS":["Ýan","Few","Mar","Apr","Maý","Iýu","Iýl","Awg","Sen","Okt","Noý","Dek"], + "WEEKDAYS":["Ýekşenbe","Duşenbe","Sişenbe","Çarşenbe","Penşenbe","Anna","Şenbe"], + "STANDALONEWEEKDAYS":["Ýekşenbe","Duşenbe","Sişenbe","Çarşenbe","Penşenbe","Anna","Şenbe"], + "SHORTWEEKDAYS":["Ýek","Duş","Siş","Çar","Pen","Ann","Şen"], + "STANDALONESHORTWEEKDAYS":["Ýek","Duş","Siş","Çar","Pen","Ann","Şen"], + "NARROWWEEKDAYS":["Ý","D","S","Ç","P","A","Ş"], + "STANDALONENARROWWEEKDAYS":["Ý","D","S","Ç","P","A","Ş"], + "SHORTQUARTERS":["K1","K2","K3","K4"], + "QUARTERS":["1-nji kwartal","2-nji kwartal","3-nji kwartal","4-nji kwartal"], + "AMPMS":["am","pm"], + "DATEFORMATS":["EEEE, d MMMM y","d MMMM y","d MMM y","dd/MM/y"], + "TIMEFORMATS":["HH:mm:ss zzzz","HH:mm:ss z","HH:mm:ss","HH:mm"], + "AVAILABLEFORMATS":null, + "FIRSTDAYOFWEEK":0, + "WEEKENDRANGE":[6], + "FIRSTWEEKCUTOFFDAY":3, + "DATETIMEFORMATS":["{1}, {0}","{1}, {0}","{1}, {0}","{1}, {0}"]}; + + + class _TkMaterialLocalizationsDelegate + extends LocalizationsDelegate { + const _TkMaterialLocalizationsDelegate(); + + @override + bool isSupported(Locale locale) => locale.languageCode == 'tk'; + + @override + Future load(Locale locale) async { + final String localeName = intl.Intl.canonicalizedLocale(locale.toString()); + + // The locale (in this case `nn`) needs to be initialized into the custom + // date symbols and patterns setup that Flutter uses. + date_symbol_data_custom.initializeDateFormattingCustom( + locale: localeName, + patterns: _tkDatePatterns, + symbols: intl.DateSymbols.deserializeFromMap(_tkSymbols), + ); + + return SynchronousFuture( + TkMaterialLocalizations( + localeName: localeName, + // The `intl` library's NumberFormat class is generated from CLDR data + // (see https://github.com/dart-lang/intl/blob/master/lib/number_symbols_data.dart). + // Unfortunately, there is no way to use a locale that isn't defined in + // this map and the only way to work around this is to use a listed + // locale's NumberFormat symbols. So, here we use the number formats + // for 'en_US' instead. + decimalFormat: intl.NumberFormat('#,##0.###', 'en_US'), + twoDigitZeroPaddedFormat: intl.NumberFormat('00', 'en_US'), + // DateFormat here will use the symbols and patterns provided in the + // `date_symbol_data_custom.initializeDateFormattingCustom` call above. + // However, an alternative is to simply use a supported locale's + // DateFormat symbols, similar to NumberFormat above. + fullYearFormat: intl.DateFormat('y', localeName), + compactDateFormat: intl.DateFormat('yMd', localeName), + shortDateFormat: intl.DateFormat('yMMMd', localeName), + mediumDateFormat: intl.DateFormat('EEE, MMM d', localeName), + longDateFormat: intl.DateFormat('EEEE, MMMM d, y', localeName), + yearMonthFormat: intl.DateFormat('MMMM y', localeName), + shortMonthDayFormat: intl.DateFormat('MMM d'), + ), + ); + } + + @override + bool shouldReload(_TkMaterialLocalizationsDelegate old) => false; +} +// #enddocregion Delegate + +/// A custom set of localizations for the 'nn' locale. In this example, only +/// the value for openAppDrawerTooltip was modified to use a custom message as +/// an example. Everything else uses the American English (en_US) messages +/// and formatting. +class TkMaterialLocalizations extends GlobalMaterialLocalizations { + const TkMaterialLocalizations({ + String localeName = 'tk', + required intl.DateFormat fullYearFormat, + required intl.DateFormat compactDateFormat, + required intl.DateFormat shortDateFormat, + required intl.DateFormat mediumDateFormat, + required intl.DateFormat longDateFormat, + required intl.DateFormat yearMonthFormat, + required intl.DateFormat shortMonthDayFormat, + required intl.NumberFormat decimalFormat, + required intl.NumberFormat twoDigitZeroPaddedFormat, + }) : super( + localeName: localeName, + fullYearFormat: fullYearFormat, + compactDateFormat: compactDateFormat, + shortDateFormat: shortDateFormat, + mediumDateFormat: mediumDateFormat, + longDateFormat: longDateFormat, + yearMonthFormat: yearMonthFormat, + shortMonthDayFormat: shortMonthDayFormat, + decimalFormat: decimalFormat, + twoDigitZeroPaddedFormat: twoDigitZeroPaddedFormat, + ); + +// #docregion Getters + @override + String get moreButtonTooltip => r'Giňişleýin'; + + @override + String get firstPageTooltip => 'Baş sahypa'; + + @override + String get lastPageTooltip => 'Soňky sahypa'; + + @override + String get aboutListTileTitleRaw => r'$applicationName hakda'; + + @override + String get alertDialogLabel => r'Üns beriň'; +// #enddocregion Getters + + @override + String get anteMeridiemAbbreviation => r'AM'; + + @override + String get backButtonTooltip => r'Dolan'; + + @override + String get cancelButtonLabel => r'ÖÇÜR'; + + @override + String get closeButtonLabel => r'ÝAPMAK'; + + @override + String get closeButtonTooltip => r'Ýapmak'; + + @override + String get collapsedIconTapHint => r'Giňelt'; + + @override + String get continueButtonLabel => r'DOWAM ET'; + + @override + String get copyButtonLabel => r'GÖÇÜR'; + + @override + String get cutButtonLabel => r'KES'; + + @override + String get deleteButtonTooltip => r'Poz'; + + @override + String get dialogLabel => r'Dialog'; + + @override + String get drawerLabel => r'Nawigasiýa menýusy'; + + @override + String get expandedIconTapHint => r'Kiçelt'; + + @override + String get hideAccountsLabel => r'Akkaundy gizle'; + + @override + String get licensesPageTitle => r'Lisenziýalar'; + + @override + String get modalBarrierDismissLabel => r'Öçür'; + + @override + String get nextMonthTooltip => r'Indiki aý'; + + @override + String get nextPageTooltip => r'Indiki sahypa'; + + @override + String get okButtonLabel => r'OK'; + + @override + // A custom drawer tooltip message. + String get openAppDrawerTooltip => r'Custom Navigation Menu Tooltip'; + +// #docregion Raw + @override + String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow of $rowCount'; + + @override + String get pageRowsInfoTitleApproximateRaw => + r'$firstRow–$lastRow of about $rowCount'; +// #enddocregion Raw + + @override + String get pasteButtonLabel => r'GIRIZ'; + + @override + String get popupMenuLabel => r'Popup menýu'; + + @override + String get postMeridiemAbbreviation => r'PM'; + + @override + String get previousMonthTooltip => r'Öňki aý'; + + @override + String get previousPageTooltip => r'Öňki sahypa'; + + @override + String get refreshIndicatorSemanticLabel => r'Täzele'; + + @override + String? get remainingTextFieldCharacterCountFew => null; + + @override + String? get remainingTextFieldCharacterCountMany => null; + + @override + String get remainingTextFieldCharacterCountOne => r'1 harp galdy'; + + @override + String get remainingTextFieldCharacterCountOther => + r'$remainingCount harplar galdy'; + + @override + String? get remainingTextFieldCharacterCountTwo => null; + + @override + String get remainingTextFieldCharacterCountZero => r'Hiç harp galmady'; + + @override + String get reorderItemDown => r'Aşak geçir'; + + @override + String get reorderItemLeft => r'Çepe geçir'; + + @override + String get reorderItemRight => r'Saga geçir'; + + @override + String get reorderItemToEnd => r'Soňuna geçir'; + + @override + String get reorderItemToStart => r'Başyna geçir'; + + @override + String get reorderItemUp => r'Yokary geçir'; + + @override + String get rowsPerPageTitle => r'Sahypa başyna hatar:'; + + @override + ScriptCategory get scriptCategory => ScriptCategory.englishLike; + + @override + String get searchFieldLabel => r'Gözle'; + + @override + String get selectAllButtonLabel => r'HEMMESINI SAÝLA'; + + @override + String? get selectedRowCountTitleFew => null; + + @override + String? get selectedRowCountTitleMany => null; + + @override + String get selectedRowCountTitleOne => r'1 element saýlandy'; + + @override + String get selectedRowCountTitleOther => r'$selectedRowCount elementler saýlandy'; + + @override + String? get selectedRowCountTitleTwo => null; + + @override + String get selectedRowCountTitleZero => r'Hiç element saýlanmady'; + + @override + String get showAccountsLabel => r'Akkauntlary aç'; + + @override + String get showMenuTooltip => r'Menýuny aç'; + + @override + String get signedInLabel => r'Ulgamda'; + + @override + String get tabLabelRaw => r'$tabCount içinden $tabIndex tab'; + + @override + TimeOfDayFormat get timeOfDayFormatRaw => TimeOfDayFormat.h_colon_mm_space_a; + + @override + String get timePickerHourModeAnnouncement => r'Sagady saýlaň'; + + @override + String get timePickerMinuteModeAnnouncement => r'Minudy saýlaň'; + + @override + String get viewLicensesButtonLabel => r'LISENZIÝALARY GÖRKEZ'; + + @override + List get narrowWeekdays => + const ['Ý', 'D', 'S', 'Ç', 'P', 'A', 'Ş']; + + @override + int get firstDayOfWeekIndex => 0; + + static const LocalizationsDelegate delegate = + _TkMaterialLocalizationsDelegate(); + + @override + String get calendarModeButtonLabel => r'Senenama geç'; + + @override + String get dateHelpText => r'mm/dd/yyyy'; + + @override + String get dateInputLabel => r'Senesini giriziň'; + + @override + String get dateOutOfRangeLabel => r'Aralykdan geçdi.'; + + @override + String get datePickerHelpText => r'SENESINI SAÝLAŇ'; + + @override + String get dateRangeEndDateSemanticLabelRaw => r'Gutarýan sene $fullDate'; + + @override + String get dateRangeEndLabel => r'Gutarýan sene'; + + @override + String get dateRangePickerHelpText => 'SENE ARALYGY'; + + @override + String get dateRangeStartDateSemanticLabelRaw => 'Başlangyç sene \$fullDate'; + + @override + String get dateRangeStartLabel => 'Başlangyç sene'; + + @override + String get dateSeparator => '/'; + + @override + String get dialModeButtonLabel => 'Belgi saýlaýyja geçmek'; + + @override + String get inputDateModeButtonLabel => 'Girizmege geç'; + + @override + String get inputTimeModeButtonLabel => 'Tekst girizmege geç'; + + @override + String get invalidDateFormatLabel => 'Ýalňyş format.'; + + @override + String get invalidDateRangeLabel => 'Ýalňyş format.'; + + @override + String get invalidTimeLabel => 'Dogry wagty giriziň'; + + @override + String get licensesPackageDetailTextOther => '\$licenseCount licenses'; + + @override + String get saveButtonLabel => 'ÝATDA SAKLA'; + + @override + String get selectYearSemanticsLabel => 'Ýyly saýlaň'; + + @override + String get timePickerDialHelpText => 'WAGTY SAÝLAŇ'; + + @override + String get timePickerHourLabel => 'Sagat'; + + @override + String get timePickerInputHelpText => 'WAGTY GIRIZIŇ'; + + @override + String get timePickerMinuteLabel => 'Minut'; + + @override + String get unspecifiedDate => 'Sene'; + + @override + String get unspecifiedDateRange => 'Sene aralygy'; + + @override + String get keyboardKeyAlt => ""; + + @override + String get keyboardKeyAltGraph => ""; + + @override + String get keyboardKeyBackspace => ""; + + @override + String get keyboardKeyCapsLock => ""; + + @override + String get keyboardKeyChannelDown => ""; + + @override + String get keyboardKeyChannelUp => ""; + + @override + String get keyboardKeyControl => ""; + + @override + String get keyboardKeyDelete => ""; + + @override + String get keyboardKeyEisu => ""; + + @override + String get keyboardKeyEject => ""; + + @override + String get keyboardKeyEnd => ""; + + @override + String get keyboardKeyEscape => ""; + + @override + String get keyboardKeyFn => ""; + + @override + String get keyboardKeyHangulMode => ""; + + @override + String get keyboardKeyHanjaMode => ""; + + @override + String get keyboardKeyHankaku => ""; + + @override + String get keyboardKeyHiragana => ""; + + @override + String get keyboardKeyHiraganaKatakana => ""; + + @override + String get keyboardKeyHome => ""; + + @override + String get keyboardKeyInsert => ""; + + @override + String get keyboardKeyKanaMode => ""; + + @override + String get keyboardKeyKanjiMode => ""; + + @override + String get keyboardKeyKatakana => ""; + + @override + String get keyboardKeyMeta => ""; + + @override + String get keyboardKeyMetaMacOs => ""; + + @override + String get keyboardKeyMetaWindows => ""; + + @override + String get keyboardKeyNumLock => ""; + + @override + String get keyboardKeyNumpad0 => ""; + + @override + String get keyboardKeyNumpad1 => ""; + + @override + String get keyboardKeyNumpad2 => ""; + + @override + String get keyboardKeyNumpad3 => ""; + + @override + String get keyboardKeyNumpad4 => ""; + + @override + String get keyboardKeyNumpad5 => ""; + + @override + String get keyboardKeyNumpad6 => ""; + + @override + String get keyboardKeyNumpad7 => ""; + + @override + String get keyboardKeyNumpad8 => ""; + + @override + String get keyboardKeyNumpad9 => ""; + + @override + String get keyboardKeyNumpadAdd => ""; + + @override + String get keyboardKeyNumpadComma => ""; + + @override + String get keyboardKeyNumpadDecimal => ""; + + @override + String get keyboardKeyNumpadDivide => ""; + + @override + String get keyboardKeyNumpadEnter => ""; + + @override + String get keyboardKeyNumpadEqual => ""; + + @override + String get keyboardKeyNumpadMultiply => ""; + + @override + String get keyboardKeyNumpadParenLeft => ""; + + @override + String get keyboardKeyNumpadParenRight => ""; + + @override + String get keyboardKeyNumpadSubtract => ""; + + @override + String get keyboardKeyPageDown => ""; + + @override + String get keyboardKeyPageUp => ""; + + @override + String get keyboardKeyPower => ""; + + @override + String get keyboardKeyPowerOff => ""; + + @override + String get keyboardKeyPrintScreen => ""; + + @override + String get keyboardKeyRomaji => ""; + + @override + String get keyboardKeyScrollLock => ""; + + @override + String get keyboardKeySelect => ""; + + @override + String get keyboardKeySpace => ""; + + @override + String get keyboardKeyZenkaku => ""; + + @override + String get keyboardKeyZenkakuHankaku => ""; +} \ No newline at end of file diff --git a/lib/models/transactions/serializer.dart b/lib/models/transactions/serializer.dart new file mode 100644 index 0000000..e0cc698 --- /dev/null +++ b/lib/models/transactions/serializer.dart @@ -0,0 +1,55 @@ +import 'dart:convert'; +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/transactions/transaction.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/material.dart'; + +class TransactionSerializer extends RemoteCategory{ + + TransactionSerializer() : super( + data: { + 'id':-4, + } + ); + + + @override + Future> getPosts(BuildContext context, int page) async{ + var user = AppUserManager.of(context).dataSync; + var transactions = await FutureGetList( + postUri(context, page), + parser: (res){ + final map = jsonDecode(res.body); + final products = map?['data'] as List; + return products.map((data) => postBuilderDelegate(data)).toList(); + } + ).fetch({ + 'Authorization':'Bearer ${user.token}' + }); + return [...transactions]; + } + + @override + get copy => TransactionSerializer(); + + @override + String get name => 'top_up_history'.translation; + + @override + postBuilderDelegate(Map data) { + return Transaction(data: data); + } + + @override + Uri postUri(context, int page) { + return baseUrl( + path: kApiPath + '/transactions', + queryParameters: { + 'page':page.toString() + } + ); + } + +} \ No newline at end of file diff --git a/lib/models/transactions/transaction.dart b/lib/models/transactions/transaction.dart new file mode 100644 index 0000000..20407ce --- /dev/null +++ b/lib/models/transactions/transaction.dart @@ -0,0 +1,23 @@ +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/helpers.dart'; + +class Transaction extends Post { + Transaction({required Map data}) : super(data); + + double get _amountDouble => double.tryParse('${jSON["amount"]}') ?? 0.0; + + double get amountDouble => _amountDouble; + + double get _amount => double.tryParse('${jSON["amount"]}') ?? 0.0; + + String get amount => priceFormatter(_amount); + + DateTime? get _date => DateTime.tryParse('${jSON["updated_at"]}'); + + String get date => safeValueDate(_date); + + String get description => jSON['description'] ?? ""; + + String get stateName => jSON['state_${"backendCode".translation}']; +} diff --git a/lib/models/translationModel.dart b/lib/models/translationModel.dart new file mode 100644 index 0000000..e4eb057 --- /dev/null +++ b/lib/models/translationModel.dart @@ -0,0 +1,16 @@ +import 'dart:convert'; + +import 'package:birzha/core/orm/orm.dart'; + +class TranslationModel extends Orm { + TranslationModel(Map data) : super(data); + + String translationOf(String field, String defaultValue) { + return this.attributeData?[field] ?? defaultValue; + } + + @override + String get primaryKeyField => "locale"; + + Map? get attributeData => jSON['attribute_data'] == null || jSON['attribute_data'].toString().isEmpty ? null : jsonDecode(jSON['attribute_data']); +} diff --git a/lib/models/user/simpleUser.dart b/lib/models/user/simpleUser.dart new file mode 100644 index 0000000..8ff2738 --- /dev/null +++ b/lib/models/user/simpleUser.dart @@ -0,0 +1,10 @@ +part of user_lib; + +class SimpleUser extends User{ + + SimpleUser._(Map data) : super({...data}); + + @override + SimpleUser get copy => SimpleUser._({...jSON}); + +} \ No newline at end of file diff --git a/lib/models/user/user.dart b/lib/models/user/user.dart new file mode 100644 index 0000000..c47b218 --- /dev/null +++ b/lib/models/user/user.dart @@ -0,0 +1,408 @@ +library user_lib; + +import 'dart:convert'; + +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/helpers.dart'; +import 'package:birzha/services/modals.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:birzha/services/validator.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:birzha/core/orm/orm.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +part 'simpleUser.dart'; + +abstract class User extends Orm with CopyAbleMixin { + User(Map jSON) : super(jSON); + + factory User.spawnFromPrefs(SharedPreferences prefs) { + var dataString = prefs.getString('user'); + Map? data; + try { + if (dataString != null) data = jsonDecode(dataString); + } catch (e) {} + + if (data == null) + return SampleUser(data: {}); + else { + debugPrint('sampleUser data: $data'); + return SimpleUser._(data); + } + } + + List get smsVerificationMetaData => [ + TextInputMetaData( + name: 'sms_code'.translation, + label: 'sms_code'.translation, + hint: 'XXXX', + formatters: [LengthLimitingTextInputFormatter(4), FilteringTextInputFormatter.digitsOnly], + validation: Validation(conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ]), + key: 'sms_code', + ) + ]; + + List get loginMetaData => [ + TextInputMetaData( + name: 'dialCode', + label: 'dialCode'.translation, + pickerMode: (context) async { + var dialCode = await showCountryCodesSheet(context); + if (dialCode == null) { + return null; + } else { + return dialCode.toString(); + } + }, + validation: Validation(conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ]), + key: 'dial_code'), + TextInputMetaData( + name: 'phone'.translation, + label: 'phone'.translation, + type: TextInputType.phone, + validation: Validation(conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ]), + key: 'username'), + TextInputMetaData( + name: 'password'.translation, + label: 'password'.translation, + password: true, + validation: Validation(conditions: [(_inp) => _inp.isEmpty ? 'empty'.translation : null]), + key: 'password', + ), + ]; + + List get registerMetaData => [ + TextInputMetaData( + name: 'yourEmail'.translation, + label: 'yourEmail'.translation, + type: TextInputType.emailAddress, + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + (_inp) { + if (Validation.emailValidator(_inp)) + return null; + else + return 'email_error'.translation; + } + ], + ), + key: 'email', + ), + TextInputMetaData( + name: 'dialCode', + label: 'dialCode'.translation, + pickerMode: (context) async { + var dialCode = await showCountryCodesSheet(context); + if (dialCode == null) { + return null; + } else { + return dialCode.toString(); + } + }, + validation: Validation(conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ]), + key: 'dial_code'), + TextInputMetaData( + name: 'phone'.translation, + label: 'phone'.translation, + type: TextInputType.emailAddress, + validation: Validation( + conditions: [(_inp) => _inp.isEmpty ? 'empty'.translation : null], + ), + key: 'username', + ), + TextInputMetaData( + name: 'yourPassword'.translation, + label: 'yourPassword'.translation, + password: true, + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'password', + ), + ]; + + List get updateMetaData => [ + // name + TextInputMetaData( + name: 'first_name'.translation, + label: 'first_name'.translation, + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'name', + ), + + // surname + TextInputMetaData( + name: 'last_name'.translation, + label: 'last_name'.translation, + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'surname', + ), + + //email + TextInputMetaData( + name: 'yourEmail'.translation, + label: 'yourEmail'.translation, + type: TextInputType.emailAddress, + showSuffix: true, + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + (_inp) { + if (Validation.emailValidator(_inp)) + return null; + else + return 'email_error'.translation; + } + ], + ), + key: 'email', + ), + + // phone number + TextInputMetaData( + name: 'phone'.translation, + label: 'phone'.translation, + type: TextInputType.number, + readOnly: true, + filled: true, + showSuffix: true, + validation: Validation( + conditions: [], + ), + key: 'username', + ), + + // company + TextInputMetaData( + name: 'iu_company'.translation, + label: 'iu_company'.translation, + validation: Validation( + conditions: [ + // (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'company', + ), + + // legalization number + TextInputMetaData( + name: 'legalizationNumber'.translation, + label: 'legalizationNumber'.translation, + type: TextInputType.emailAddress, + validation: Validation( + conditions: [ + // (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'zip', + ), + + // new password confirmation + TextInputMetaData( + name: 'newPassword'.translation, + label: 'newPassword'.translation, + password: true, + validation: Validation( + conditions: [ + // (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'password', + ), + + // new password confirmation + TextInputMetaData( + name: 'newPasswordConfirmation'.translation, + label: 'newPasswordConfirmation'.translation, + password: true, + validation: Validation( + conditions: [ + // (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'password_confirmation', + ), + ]; + + List get addPostMetaData => [ + TextInputMetaData( + name: 'addPostName'.translation + ' (EN)', + label: 'addPostName'.translation + ' (EN)', + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'name_en'), + TextInputMetaData( + name: 'addPostName'.translation + ' (RU)', + label: 'addPostName'.translation + ' (RU)', + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'name_ru'), + TextInputMetaData( + name: 'addPostName'.translation + ' (TM)', + label: 'addPostName'.translation + ' (TM)', + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'name_tm'), + TextInputMetaData( + name: 'mark'.translation, + label: 'mark'.translation, + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'mark'), + TextInputMetaData( + name: 'manufacturer'.translation, + label: 'manufacturer'.translation, + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'manufacturer'), + ]; + + List get addMoreMetaData => [ + TextInputMetaData( + name: 'addPostDescription'.translation + ' (EN)', + label: 'addPostDescription'.translation + ' (EN)', + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'description_en'), + TextInputMetaData( + name: 'addPostDescription'.translation + ' (RU)', + label: 'addPostDescription'.translation + ' (RU)', + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'description_ru'), + TextInputMetaData( + name: 'addPostDescription'.translation + ' (TM)', + label: 'addPostDescription'.translation + ' (TM)', + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'description_tm'), + TextInputMetaData( + name: 'price'.translation, + label: 'price'.translation, + validation: Validation( + conditions: [ + (_inp) => double.tryParse(_inp) == null ? 'notANumber'.translation : null, + ], + ), + formatters: [FilteringTextInputFormatter.allow(RegExp('[0-9.]'))], + key: 'price'), + TextInputMetaData( + name: 'place'.translation, + label: 'place'.translation, + validation: Validation( + conditions: [ + (_inp) => _inp.isEmpty ? 'empty'.translation : null, + ], + ), + key: 'place'), + TextInputMetaData( + name: 'quantity'.translation, + label: 'quantity'.translation, + validation: Validation( + conditions: [ + (_inp) => double.tryParse(_inp) == null ? 'notANumber'.translation : null, + ], + ), + formatters: [FilteringTextInputFormatter.allow(RegExp('[0-9.]'))], + key: 'quantity'), + ]; + + String? get token => jSON['token']; + + bool get isRegistered => token != null; + + bool get isEmailVerified => isRegistered && boolParser(jSON['email_verified']); + + bool get isPhoneVerified => isRegistered && boolParser(jSON['phone_verified']); + + @override + int get primaryKey => jSON[primaryKeyField] ?? -1; + + @override + String get primaryKeyField => 'id'; + + List get keysAllowedToStore => [ + 'id', + 'name', + 'surname', + 'token', + 'username', + 'company', + 'zip', + 'email', + 'email_verified', + 'phone_verified', + ]; + + Map get storingData => {...jSON}..removeWhere( + (key, value) => !keysAllowedToStore.contains(key), + ); +} + +class SampleUser extends User { + SampleUser({required Map data}) : super(data); + + User castToRealUser() { + return SimpleUser._({...jSON}); + } + + @override + get copy => SampleUser(data: {...jSON}); +} + +class Vendor extends User { + Vendor({required Map data}) : super(data); + + String get name => jSON['name'] ?? ""; + String get surname => jSON['surname'] ?? ""; + String get email => jSON['email'] ?? ""; + String get phone => jSON['username'] ?? ""; + + @override + User get copy => Vendor(data: {...jSON}); +} diff --git a/lib/models/user/userManager.dart b/lib/models/user/userManager.dart new file mode 100644 index 0000000..7de709b --- /dev/null +++ b/lib/models/user/userManager.dart @@ -0,0 +1,629 @@ +import 'dart:convert'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/models/chatroom/chatroom.dart'; +import 'package:birzha/models/products/composableProduct.dart'; +import 'package:birzha/models/products/my_product.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/helpers.dart'; +import 'package:birzha/services/imageUpload.dart'; +import 'package:birzha/services/modals.dart'; +import 'package:birzha/services/requests.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:http/http.dart' as http; +import 'package:birzha/models/exceptions/exception.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:provider/provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:flutter/material.dart'; +import 'package:file_picker/file_picker.dart' as picker; +import 'dart:async'; +import 'dart:io'; +import 'package:async/async.dart'; + +class AppUserManager extends Manager { + static AppUserManager of(BuildContext context, {bool listen = false}) { + return Provider.of(context, listen: listen); + } + + AppUserManager(SharedPreferences prefs) : super(User.spawnFromPrefs(prefs)); + + void checkCode(BuildContext context, String code) { + addTask( + Task( + computation: () async { + try { + var response = await _checkSmsCode(dataSync.token ?? "", code); + + var decoded = jsonDecode(response.body); + + if (decoded is Map) { + final success = decoded["status"]; + final message = decoded['message']?['backendCode'.translation]; + + if (!success && message != null && message is String) { + throw MessageException(message); + } else if (!success && message is! String) { + throw OtherException(); + } + } + + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + syncAccount(context); + }); + + return dataSync.copy; + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'sms_verify', + ), + ); + } + + void syncAccount(BuildContext context) { + addTask( + Task( + computation: () async { + try { + var newSample = dataSync.copy; + if (newSample.isRegistered) { + var userAccountResponse = await _getAccountRequest(newSample.token!); + var decoded = jsonDecode(userAccountResponse.body); + if (decoded['me'] != null) newSample.jSON = {...newSample.jSON, ...decoded['me']}; + } + return newSample; + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'sync', + ), + ); + } + + void sendSmsCode(BuildContext context, VoidCallback onSuccess) { + addTask( + Task( + computation: () async { + try { + debugPrint('dataSync.token: ${dataSync.token}'); + + var response = await _sendSmsCode(dataSync.token ?? ""); + + var decoded = jsonDecode(response.body); + bool success = decoded['result'] == 0 || decoded['result'] == '0'; + if (success) { + onSuccess(); + return dataSync.copy; + } else { + var message = decoded['message']?['backendCode'.translation]; + if (message != null && message is String) { + throw MessageException(message); + } else { + throw OtherException(); + } + } + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'send_sms'), + ); + } + + void verifyMail(BuildContext context) { + addTask(Task( + computation: () async { + try { + print('backendCode'.translation); + String? message; + var response = await _verifyEmailRequest(dataSync.token ?? ""); + var decoded = jsonDecode(response.body); + print(decoded); + if (decoded is String) { + message = decoded; + } + showSnackBar( + context, + content: message ?? 'verificationMailSent'.translation, + backgroundColor: Colors.blue, + textColor: Colors.white, + duration: const Duration(seconds: 10), + ); + return dataSync.copy; + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'verify_mail')); + } + + void login(BuildContext context, SampleUser user) { + addTask( + Task( + computation: () async { + try { + var response = await _loginRequest(user); + var decoded = jsonDecode(response.body); + if (decoded['user'] == null) + throw AppExceptions.recognizer(decoded); + else { + var newSample = SampleUser(data: {...decoded['user'], 'token': decoded['token']}); + if (newSample.isRegistered) { + var userAccountResponse = await _getAccountRequest(newSample.token!); + var decoded = jsonDecode(userAccountResponse.body); + if (decoded['me'] != null) newSample.jSON = {...newSample.jSON, ...decoded['me']}; + } + return newSample.castToRealUser(); + } + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'login', + ), + ); + } + + void register(BuildContext context, SampleUser user) { + addTask(Task( + computation: () async { + try { + var response = await _registerRequest(user); + var decoded = jsonDecode(response.body); + if (decoded['user'] == null) + throw AppExceptions.recognizer(decoded); + else { + var newSample = SampleUser(data: {...decoded['user'], 'token': decoded['token']}); + if (newSample.isRegistered) { + var userAccountResponse = await _getAccountRequest(newSample.token!); + var decoded = jsonDecode(userAccountResponse.body); + if (decoded['me'] != null) newSample.jSON = {...newSample.jSON, ...decoded['me']}; + } + return newSample.castToRealUser(); + } + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'register')); + } + + void logout() async { + addTask(Task( + computation: () { + return SynchronousFuture(SampleUser(data: {})); + }, + key: 'logout')); + } + + void update(BuildContext context, SampleUser user) { + addTask( + Task( + computation: () async { + try { + debugPrint('sample user $user'); + + var response = await _updateRequest(user, dataSync.token!); + + debugPrint('response: $response'); + + var decoded = jsonDecode(response.body); + debugPrint('decoded: $decoded'); + + if (decoded['me'] == null) + throw AppExceptions.recognizer(decoded); + else { + var newSample = SampleUser(data: { + ...dataSync.jSON, + ...decoded['me'], + }); + + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + syncAccount(context); + }); + + return newSample.castToRealUser(); + } + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'update', + ), + ); + } + + void balanceUp(BuildContext context, String cardType, double amount) { + addTask( + Task( + computation: () async { + try { + var response = await _balanceUpRequest(dataSync.token!, cardType, amount); + var decoded = jsonDecode(response.body); + + var status = decoded['formUrl'] != null && decoded['formUrl'] is String; + if (!status) + throw AppExceptions.recognizer(decoded); + else + linkLauncher(decoded['formUrl']); + + return dataSync.copy; + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'balanceUp', + ), + ); + } + + void uploadBill(BuildContext context, picker.PlatformFile? file) { + addTask( + Task( + computation: () async { + try { + String? message; + if (file != null) { + debugPrint('file ${file.name}'); + message = await uploadImage( + baseUrl(path: kApiPath + '/balance_update'), + dataSync, + file, //fileResult!.files.first, + 'bank_file', + { + 'type': 'bank', + }, + onUploadProgressCallback: (a, b) { + debugPrint('a $a'); + debugPrint('b $b'); + }, + ); + } + + debugPrint('message $message'); + if (message != null) { + showSnackBar( + context, + content: message, + backgroundColor: Colors.blue, + textColor: Colors.white, + duration: const Duration(seconds: 3), + ); + } + + return dataSync.copy; + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'uploadBill'), + ); + } + + void buyFromSeller(BuildContext navigatorContext, Vendor vendor, void Function(Chatroom room) onSuccess) { + addTask(Task( + computation: () async { + try { + if (!dataSync.isRegistered) { + Tabnavigator.maybeOf(navigatorContext)?.changePage(2); + return dataSync.copy; + } + await Future.delayed(Duration(seconds: 3)); + var response = await _initChatRequest(dataSync.token ?? "", vendor); + var data = jsonDecode(response.body); + var isSuccess = data['data'] != null; + if (isSuccess) { + onSuccess(Chatroom.init(data: { + ...data['data'], + 'vendor': {...vendor.jSON} + })); + return dataSync.copy; + } else { + throw AppExceptions.recognizer(data); + } + } catch (ex) { + AppExceptions.exceptionHandler(navigatorContext, ex); + throw ex; + } + }, + key: 'buy')); + } + + void composeStep1(BuildContext context, List sendKeys) { + addTask(Task( + computation: () async { + try { + var composable = ComposableProduct(); + await Future.delayed(const Duration(seconds: 3)); + var response = await _postCompositionRequest(composable, dataSync.token ?? "", sendKeys); + var decoded = jsonDecode(response.body); + var success = decoded["status_code"] == 200 || decoded["status_code"] == '200'; + if (success) { + int? id = decoded['data']?['product']?['id']; + ComposableProduct().saveProgress(id); + return dataSync.copy; + } else { + throw AppExceptions.recognizer(decoded); + } + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'compose_1')); + } + + void composeStep2(BuildContext context, List sendKeys) { + addTask(Task( + computation: () async { + try { + var composable = ComposableProduct(); + if ((composable.localImages.isEmpty && composable.primaryKey == null) || (composable.localImages.isEmpty && composable.remoteImages.isEmpty)) { + throw MessageException('selectAtLeastImage'.translation); + } + var response = await _postMoreRequest(composable, dataSync.token ?? "", sendKeys); + var byteArray = await response.stream.toBytes(); + var stringBody = utf8.decode(byteArray); + print(stringBody); + var decoded = jsonDecode(stringBody); + var success = decoded["status_code"] == 200 || decoded["status_code"] == '200'; + if (success) { + ComposableProduct().jSON.clear(); + return dataSync.copy; + } else { + throw AppExceptions.recognizer(decoded); + } + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'compose_2')); + } + + void deletePost(BuildContext context, MyProduct product) { + addTask(Task( + computation: () async { + try { + var response = await _deletePost(product, dataSync.token ?? ""); + var decoded = jsonDecode(response.body); + var success = decoded["status_code"] == 200 || decoded["status_code"] == '200'; + if (success) { + return dataSync.copy; + } else { + throw AppExceptions.recognizer(decoded); + } + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'delete_post')); + } + + void deleteImage(BuildContext context, ComposableProduct product, RemoteImageModel image, void Function() onSuccess) { + addTask(Task( + computation: () async { + var navContext = Navigator.of(context).context; + try { + var response = await _deleteImage(product, image, dataSync.token ?? ""); + print(response.body); + var decoded = jsonDecode(response.body); + var success = decoded["status_code"] == 200 || decoded["status_code"] == '200'; + if (success) { + onSuccess(); + return dataSync.copy; + } else { + throw AppExceptions.recognizer(decoded); + } + } catch (ex) { + AppExceptions.exceptionHandler(navContext, ex); + throw ex; + } + }, + key: 'delete_image')); + } + + void publishPost(BuildContext context, MyProduct product) { + addTask(Task( + computation: () async { + try { + var response = await _publish(product, dataSync.token ?? ""); + var decoded = jsonDecode(response.body); + var success = decoded["status_code"] == 200 || decoded["status_code"] == '200'; + if (success) { + return dataSync.copy; + } else { + throw AppExceptions.recognizer(decoded); + } + } catch (ex) { + AppExceptions.exceptionHandler(context, ex); + throw ex; + } + }, + key: 'publish_post')); + } + + Map _statusTable = {}; + + TaskStatus getStatusByKey(String key) { + return _statusTable[key] ?? TaskStatus.None; + } + + @override + Future destroyTask(String taskId) async { + _statusTable.remove(taskId); + return super.destroyTask(taskId); + } + + @override + Future valueListener(newValue) async { + super.valueListener(newValue); + var prefs = await SharedPreferences.getInstance(); + if (newValue.jSON.isEmpty) + prefs.remove('user'); + else + await prefs.setString('user', jsonEncode({...newValue.storingData})); + } + + @override + void listenerCallBack(TaskResult result, String taskKey) { + _statusTable[taskKey] = result.status; + notifyListeners(); + } +} + +Future _loginRequest(SampleUser user) { + return http.post( + baseUrl(path: 'api' + '/login'), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, + body: jsonEncode( + {...user.jSON}, + ), + ); +} + +Future _registerRequest(SampleUser user) { + return http.post( + baseUrl(path: 'api' + '/signup'), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json'}, + body: jsonEncode( + {...user.jSON}, + ), + ); +} + +Future _updateRequest(SampleUser user, String token) { + return http.post( + baseUrl(path: 'api' + '/me'), + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Bearer $token', + }, + body: jsonEncode( + {...user.jSON}, + ), + ); +} + +Future _postCompositionRequest(ComposableProduct composition, String token, List keys) { + return http.post( + baseUrl(path: kApiPath + '/products'), + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Bearer $token', + }, + body: jsonEncode( + {...composition.jSON}..removeWhere((key, value) => !keys.contains(key)), + ), + ); +} + +Future _deletePost(MyProduct composition, String token) { + return http.delete(baseUrl(path: kApiPath + '/my-products/${composition.primaryKey}'), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer $token'}); +} + +Future _deleteImage(ComposableProduct product, RemoteImageModel image, String token) { + return http.delete(baseUrl(path: kApiPath + '/products/${product.primaryKey}/image-delete/${image.id}'), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer $token'}); +} + +Future _publish(MyProduct composition, String token) { + return http.post(baseUrl(path: kApiPath + '/products/${composition.primaryKey}/publish'), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer $token'}); +} + +Future _postMoreRequest(ComposableProduct composition, String token, List keys) { + var multipart = http.MultipartRequest('POST', baseUrl(path: kApiPath + '/products/${composition.primaryKey}')); + var images = composition.localImages; + var files = []; + for (var image in images) { + var file = File(image.primaryKey); + var stream = http.ByteStream(DelegatingStream(file.openRead())); + var multipartFile = http.MultipartFile('new_img[]', stream, file.lengthSync(), filename: image.primaryKey.split('/').last); + files.add(multipartFile); + } + if (files.isNotEmpty) { + multipart.files.addAll(files); + } + multipart.fields.addAll({ + for (var key in composition.jSON.keys.where((element) => keys.contains(element)).where((element) => element != 'new_img')) + key: composition.jSON[key].toString(), + }); + for (var i = 0; i < composition.remoteImages.length; i++) { + multipart.fields['old_img[$i]'] = composition.remoteImages[i].primaryKey; + } + multipart.headers.addAll( + {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer $token'}, + ); + return multipart.send(); +} + +Future _balanceUpRequest(String token, String cardType, double amount) { + return http.post( + baseUrl(path: kApiPath + '/balance_update'), + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Bearer $token', + }, + body: jsonEncode( + { + 'type': 'online', + 'amount': amount.toString(), + 'card_type': cardType, + }, + ), + ); +} + +Future _getAccountRequest(String token) { + return http.get( + baseUrl(path: 'api' + '/me'), + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + 'Authorization': 'Bearer $token', + }, + ); +} + +Future _initChatRequest(String token, Vendor vendor) { + return http.post( + baseUrl(path: kApiPath + '/messages/initialize-chatting/' + vendor.primaryKey.toString()), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer $token'}, + ); +} + +Future _verifyEmailRequest(String token) { + print(jsonEncode({'locale': 'backendCode'.translation})); + return http.post(baseUrl(path: kApiPath + '/send-email-verification-link'), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer $token'}, + body: jsonEncode({'locale': 'backendCode'.translation})); +} + +Future _sendSmsCode(String token) { + return http.post(baseUrl(path: kApiPath + '/send-sms-code'), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer $token'}); +} + +Future _checkSmsCode(String token, String code) { + return http.post(baseUrl(path: kApiPath + '/check-sms-code'), + headers: {'Content-Type': 'application/json', 'Accept': 'application/json', 'Authorization': 'Bearer $token'}, body: jsonEncode({"sms_code": code})); +} diff --git a/lib/new/api/a.rest b/lib/new/api/a.rest new file mode 100644 index 0000000..c6161a4 --- /dev/null +++ b/lib/new/api/a.rest @@ -0,0 +1,10 @@ +@url = https://tmex.gov.tm/api/v1/news?per_page=2&locale=tm +@contentType = application/json + + +### 1. get news +GET {{ url }} HTTP/1.1 + +### 1. get news +@url = https://tmex.gov.tm/api/v1/ +GET {{ url }} HTTP/1.1 \ No newline at end of file diff --git a/lib/new/api/bank.dart b/lib/new/api/bank.dart new file mode 100644 index 0000000..e5ed846 --- /dev/null +++ b/lib/new/api/bank.dart @@ -0,0 +1,60 @@ +import 'package:birzha/new/models/bank.dart'; +import 'package:birzha/new/models/bank_info.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../utils/constants.dart'; +import '../utils/http_util.dart'; + +class BankApi { + static String className = 'BankApi'; + static Future getBankInfo() async { + final String fnName = 'getBankInfo'; + + SharedPreferences prefs = await SharedPreferences.getInstance(); + + final String locale = prefs.getString('language') ?? 'tm'; + + try { + final Map params = { + 'locale': locale == 'tk' ? 'tm' : locale, + }; + + debugPrint('class: $className, method: $fnName , params: $params'); + + final String path = Constants.BASE_URL + 'api/v1/bank-info'; + + final response = await HttpUtil().get(path: path, queryParameters: params); + + return BankInfoModel.fromJson(response); + } catch (e) { + debugPrint('ERROR: class: $className, method: $fnName, error: $e '); + return null; + } + } + + static Future?> getBankTypes() async { + final String fnName = 'getBankTypes'; + + SharedPreferences prefs = await SharedPreferences.getInstance(); + + final String locale = prefs.getString('language') ?? 'tm'; + + try { + final Map params = { + 'locale': locale == 'tk' ? 'tm' : locale, + }; + + debugPrint('class: $className, method: $fnName , params: $params'); + + final String path = Constants.BASE_URL + 'api/v1/bank-types'; + + final response = await HttpUtil().get(path: path, queryParameters: params); + + return BankType.listFromJson(response as List); + } catch (e) { + debugPrint('ERROR: class: $className, method: $fnName, error: $e '); + return null; + } + } +} diff --git a/lib/new/api/news.dart b/lib/new/api/news.dart new file mode 100644 index 0000000..5e4d006 --- /dev/null +++ b/lib/new/api/news.dart @@ -0,0 +1,36 @@ +import 'package:birzha/new/models/news.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../utils/constants.dart'; +import '../utils/http_util.dart'; + +class NewsApi { + static String className = 'NewsApi'; + static Future> get(int page) async { + final String fnName = 'get'; + + SharedPreferences prefs = await SharedPreferences.getInstance(); + + final String locale = prefs.getString('language') ?? 'tm'; + + try { + final Map params = { + 'page': '$page', + 'per_page': '10', + 'locale': locale == 'tk' ? 'tm' : locale, + }; + + debugPrint('class: $className, method: $fnName , params: $params'); + + final String path = Constants.BASE_URL + 'api/v1/news'; + + final response = await HttpUtil().get(path: path, queryParameters: params); + + return NewsModel.listFromJson(response['data'] as List); + } catch (e) { + debugPrint('ERROR: class: $className, method: $fnName, error: $e '); + throw e; + } + } +} diff --git a/lib/new/api/sort.dart b/lib/new/api/sort.dart new file mode 100644 index 0000000..9df390c --- /dev/null +++ b/lib/new/api/sort.dart @@ -0,0 +1,124 @@ +import 'package:birzha/new/models/category_filter.dart'; +import 'package:birzha/new/models/export.dart'; +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import '../models/import.dart'; +import '../models/sort_group.dart'; +import '../utils/constants.dart'; +import '../utils/http_util.dart'; +import '../utils/locale.dart'; + +class SortApi { + static String className = 'SortApi'; + + static String metaText = ''; + + static Future> getGroups(String type) async { + final String fnName = 'getGroups'; + + SharedPreferences prefs = await SharedPreferences.getInstance(); + + final String locale = prefs.getString('language') ?? 'tm'; + + try { + final Map params = { + 'type': '$type', + 'locale': locale == 'tk' ? 'tm' : locale, + }; + + debugPrint('class: $className, method: $fnName , params: $params'); + + final String path = Constants.BASE_URL + 'app/api/groups'; + + final response = await HttpUtil().get(path: path, queryParameters: params); + + return SortGroupModel.listFromJson(response as List); + } catch (e) { + debugPrint('ERROR: class: $className, method: $fnName, error: $e '); + return []; + } + } + + static Future> getExports(Map params) async { + final String fnName = 'getExports'; + + try { + debugPrint('class: $className, method: $fnName , params: $params'); + + final String path = Constants.BASE_URL + 'app/api/exports'; + + final response = await HttpUtil().get(path: path, queryParameters: params); + + metaText = response['meta_text']; + + return ExportModel.listFromJson(response['exports'] as List); + } catch (e) { + debugPrint('ERROR: class: $className, method: $fnName, error: $e '); + throw e; + } + } + + static Future> getImports(Map params) async { + final String fnName = 'getImports'; + + try { + debugPrint('class: $className, method: $fnName , params: $params'); + + final String path = Constants.BASE_URL + 'app/api/imports'; + + final response = await HttpUtil().get(path: path, queryParameters: params); + + return ImportModel.listFromJson(response['imports'] as List); + } catch (e) { + debugPrint('ERROR: class: $className, method: $fnName, error: $e '); + throw e; + } + } + + static Future> getOtherFilters(Map params) async { + final String fnName = 'getOtherFilters'; + + try { + String locale = await getLocale(); + + params.addAll({ + 'locale': locale, + }); + + debugPrint('class: $className, method: $fnName , params: $params'); + + final String path = Constants.BASE_URL + 'app/api/other-filters'; + + final response = await HttpUtil().get(path: path, queryParameters: params); + + return response.cast(); + } catch (e) { + debugPrint('ERROR: class: $className, method: $fnName, error: $e '); + throw e; + } + } + + static Future> getCategoryFilters() async { + final String fnName = 'getCategoryFilters'; + + try { + String locale = await getLocale(); + + final Map params = { + 'locale': locale, + }; + + debugPrint('class: $className, method: $fnName , params: $params'); + + final String path = Constants.BASE_URL + 'app/api/categories'; + + final response = await HttpUtil().get(path: path, queryParameters: params); + + return CategoryFilterModel.listFromJson(response as List); + } catch (e) { + debugPrint('ERROR: class: $className, method: $fnName, error: $e '); + throw e; + } + } +} diff --git a/lib/new/global/form_field_decoration.dart b/lib/new/global/form_field_decoration.dart new file mode 100644 index 0000000..def6798 --- /dev/null +++ b/lib/new/global/form_field_decoration.dart @@ -0,0 +1,87 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../themes/colors.dart'; + +class MyTextFormField extends StatelessWidget { + final TextEditingController controller; + final String label; + final String? hintText; + final int maxLines; + final bool obscureText; + final TextInputType inputType; + final Widget? suffix; + final List? inputFormatters; + final Function(String value)? onChangeCallback; + + MyTextFormField({ + required this.controller, + required this.label, + this.hintText, + this.maxLines = 1, + this.obscureText = false, + this.inputType = TextInputType.text, + this.suffix, + this.inputFormatters, + this.onChangeCallback, + }); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only( + left: 16.adaptedPx(), + right: 16.adaptedPx(), + ), + decoration: new BoxDecoration( + color: ThemeColor.colorEFF0F4, + borderRadius: BorderRadius.circular(8), + ), + child: TextFormField( + obscureText: this.obscureText, + controller: this.controller, + maxLines: this.maxLines, + cursorColor: ThemeColor.cursorColor, + style: TextStyle(color: ThemeColor.black, fontSize: 16.adaptedPx()), + keyboardType: inputType, + inputFormatters: inputFormatters != null ? [...inputFormatters!] : [], + textInputAction: TextInputAction.done, + decoration: inputDecoration(), + validator: (value) => _validator(value), + onChanged: (value) => onChangeCallback != null ? onChangeCallback!(value) : null, + ), + ); + } + + InputDecoration inputDecoration() { + final txtStyle = new TextStyle( + color: ThemeColor.black.withOpacity(0.60), + fontSize: 16.adaptedPx(), + ); + return InputDecoration( + alignLabelWithHint: maxLines != 1, + hintText: hintText ?? this.label, + hintStyle: txtStyle, + // labelText: this.label, + labelStyle: txtStyle, + suffixIcon: this.suffix, + suffixIconConstraints: BoxConstraints(), + // floatingLabelBehavior: FloatingLabelBehavior.never, + border: InputBorder.none, + focusedBorder: InputBorder.none, + enabledBorder: InputBorder.none, + disabledBorder: InputBorder.none, + ); + } + + String? _validator(String? value) { + if (this.obscureText) { + //FIXME: add translation + return (value == null || value.trim().length < 6) ? 'min_6_char'.translation : null; + } + + return (value == null || value.trim().length == 0) ? '$label ' + 'is_required'.translation : null; + } +} diff --git a/lib/new/global/full_width_button.dart b/lib/new/global/full_width_button.dart new file mode 100644 index 0000000..4a6ac38 --- /dev/null +++ b/lib/new/global/full_width_button.dart @@ -0,0 +1,48 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; + +import '../themes/colors.dart'; + +class FullWidthButton extends StatelessWidget { + final String title; + final Color btnColor; + final Color txtColor; + final VoidCallback? callback; + + FullWidthButton({ + required this.title, + required this.callback, + this.txtColor = ThemeColor.white, + this.btnColor = ThemeColor.mainColor, + }); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + height: 48.adaptedPx(), + child: TextButton( + style: ButtonStyle( + // elevation: MaterialStateProperty.all(5), + shape: MaterialStateProperty.all((RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)))), + // padding: MaterialStateProperty.all(EdgeInsets.zero), + backgroundColor: MaterialStateProperty.all(this.btnColor), // <-- Button color + overlayColor: MaterialStateProperty.resolveWith((states) { + if (states.contains(MaterialState.pressed)) + return this.btnColor == ThemeColor.mainColor ? ThemeColor.grey.withOpacity(0.50) : ThemeColor.mainColor.withOpacity(0.30); // <-- Splash color + return null; + }), + ), + onPressed: this.callback != null ? () => callback!() : null, + child: Text( + this.title, + style: new TextStyle( + fontSize: 14.adaptedPx(), + fontWeight: FontWeight.w500, + color: this.txtColor, + ), + ), + ), + ); + } +} diff --git a/lib/new/models/bank.dart b/lib/new/models/bank.dart new file mode 100644 index 0000000..a9662ae --- /dev/null +++ b/lib/new/models/bank.dart @@ -0,0 +1,16 @@ +class BankType { + late String name; + late String cardType; + + BankType({ + required this.name, + required this.cardType, + }); + + BankType.fromJson(Map json) { + name = json['name']; + cardType = json['api_val']; + } + + static List listFromJson(list) => List.from(list.map((x) => BankType.fromJson(x))); +} diff --git a/lib/new/models/bank_info.dart b/lib/new/models/bank_info.dart new file mode 100644 index 0000000..ebd9eff --- /dev/null +++ b/lib/new/models/bank_info.dart @@ -0,0 +1,23 @@ +class BankInfoModel { + late String taxCode; + late String bab; + late String manatAccount; + late String correspondentAccount; + late String bankAddress; + + BankInfoModel({ + required this.taxCode, + required this.bab, + required this.manatAccount, + required this.correspondentAccount, + required this.bankAddress, + }); + + BankInfoModel.fromJson(Map json) { + taxCode = json['tax_code']; + bab = json['bab']; + manatAccount = json['manat_account']; + correspondentAccount = json['correspondent_account']; + bankAddress = json['bank_address']; + } +} diff --git a/lib/new/models/category_filter.dart b/lib/new/models/category_filter.dart new file mode 100644 index 0000000..74dbc23 --- /dev/null +++ b/lib/new/models/category_filter.dart @@ -0,0 +1,16 @@ +class CategoryFilterModel { + late int id; + late String title; + + CategoryFilterModel({ + required this.id, + required this.title, + }); + + CategoryFilterModel.fromJson(Map json) { + id = json['id']; + title = json['title']; + } + + static List listFromJson(list) => List.from(list.map((x) => CategoryFilterModel.fromJson(x))); +} diff --git a/lib/new/models/export.dart b/lib/new/models/export.dart new file mode 100644 index 0000000..10bc484 --- /dev/null +++ b/lib/new/models/export.dart @@ -0,0 +1,55 @@ +class ExportModel { + late int id; + late int groupId; + late String type; + late String title; + late String country; + late String unit; + late String amount; + late String point; + late String place; + late String currency; + late String payment; + late String send; + late String seller; + late String price; + late String total; + + ExportModel({ + required this.id, + required this.groupId, + required this.type, + required this.title, + required this.country, + required this.unit, + required this.amount, + required this.point, + required this.place, + required this.currency, + required this.payment, + required this.send, + required this.seller, + required this.price, + required this.total, + }); + + ExportModel.fromJson(Map json) { + id = json['id']; + groupId = json['group_id']; + type = json['type']; + title = json['title']; + country = json['country']; + unit = json['unit']; + amount = json['amount'].toString(); + point = json['point']; + place = json['place']; + currency = json['currency']; + payment = json['payment']; + send = json['send']; + seller = json['seller']; + price = json['price'].toString(); + total = json['total'].toString(); + } + + static List listFromJson(list) => List.from(list.map((x) => ExportModel.fromJson(x))); +} diff --git a/lib/new/models/filter.dart b/lib/new/models/filter.dart new file mode 100644 index 0000000..e69de29 diff --git a/lib/new/models/import.dart b/lib/new/models/import.dart new file mode 100644 index 0000000..14cea60 --- /dev/null +++ b/lib/new/models/import.dart @@ -0,0 +1,43 @@ +class ImportModel { + late int id; + late int groupId; + late String title; + late String country; + late String unit; + late String currency; + late String price; + late String registeredAt; + late String locale; + late String createdAt; + late String updatedAt; + + ImportModel({ + required this.id, + required this.groupId, + required this.title, + required this.country, + required this.unit, + required this.currency, + required this.price, + required this.registeredAt, + required this.locale, + required this.createdAt, + required this.updatedAt, + }); + + ImportModel.fromJson(Map json) { + id = json['id']; + groupId = json['group_id']; + title = json['title']; + country = json['country']; + unit = json['unit']; + currency = json['currency']; + price = json['price']; + registeredAt = json['registered_at']; + locale = json['locale']; + createdAt = json['created_at']; + updatedAt = json['updated_at']; + } + + static List listFromJson(list) => List.from(list.map((x) => ImportModel.fromJson(x))); +} diff --git a/lib/new/models/news.dart b/lib/new/models/news.dart new file mode 100644 index 0000000..6056d5b --- /dev/null +++ b/lib/new/models/news.dart @@ -0,0 +1,51 @@ +class NewsModel { + late int id; + late String title; + late String publishedAt; + late List featuredImages; + late String contentHtml; + + NewsModel({ + required this.id, + required this.title, + required this.publishedAt, + required this.featuredImages, + required this.contentHtml, + }); + + NewsModel.fromJson(Map json) { + id = json['id']; + title = json['title']; + publishedAt = json['published_at']; + if (json['featured_images'] != null) { + featuredImages = []; + json['featured_images'].forEach((v) { + featuredImages.add(new FeaturedImages.fromJson(v)); + }); + } + contentHtml = json['content_html']; + } + + static List listFromJson(list) => List.from(list.map((x) => NewsModel.fromJson(x))); +} + +class FeaturedImages { + late int id; + late String diskName; + late String fileName; + late String path; + + FeaturedImages({ + required this.id, + required this.diskName, + required this.fileName, + required this.path, + }); + + FeaturedImages.fromJson(Map json) { + id = json['id']; + diskName = json['disk_name']; + fileName = json['file_name']; + path = json['path']; + } +} diff --git a/lib/new/models/sort_group.dart b/lib/new/models/sort_group.dart new file mode 100644 index 0000000..c7aa7b3 --- /dev/null +++ b/lib/new/models/sort_group.dart @@ -0,0 +1,28 @@ +class SortGroupModel { + late int id; + late String title; + late String type; + String? file; + int? isDefault; + String? hashId; + + SortGroupModel({ + required this.id, + required this.title, + required this.type, + this.file, + this.isDefault, + this.hashId, + }); + + SortGroupModel.fromJson(Map json) { + id = json['id']; + title = json['title']; + type = json['type']; + file = json['file']; + isDefault = json['is_default']; + hashId = json['hashid']; + } + + static List listFromJson(list) => List.from(list.map((x) => SortGroupModel.fromJson(x))); +} diff --git a/lib/new/screens/news/binding.dart b/lib/new/screens/news/binding.dart new file mode 100644 index 0000000..c3198f6 --- /dev/null +++ b/lib/new/screens/news/binding.dart @@ -0,0 +1,9 @@ +import 'package:birzha/new/screens/news/controller.dart'; +import 'package:get/get.dart'; + +class NewsBinding extends Bindings { + @override + void dependencies() { + Get.put(NewsController()); + } +} diff --git a/lib/new/screens/news/controller.dart b/lib/new/screens/news/controller.dart new file mode 100644 index 0000000..022f192 --- /dev/null +++ b/lib/new/screens/news/controller.dart @@ -0,0 +1,50 @@ +import 'package:birzha/new/api/news.dart'; +import 'package:birzha/new/models/news.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +class NewsController extends GetxController with StateMixin>, ScrollMixin { + List repositories = []; + int page = 1; + bool getFirstData = false; + RxBool lastPage = false.obs; + @override + void onInit() { + getNews(); + super.onInit(); + } + + Future getNews() async { + await NewsApi.get(page).then( + (result) { + final bool emptyRepositories = result.isEmpty; + if (!getFirstData && emptyRepositories) { + change(null, status: RxStatus.empty()); + } else if (getFirstData && emptyRepositories) { + lastPage.value = true; + } else { + getFirstData = true; + repositories.addAll(result); + change(repositories, status: RxStatus.success()); + } + }, + onError: (err) { + change(null, status: RxStatus.error(err.toString())); + }, + ); + } + + @override + Future onEndScroll() async { + debugPrint('onEndScroll'); + if (!lastPage.value) { + page += 1; + await getNews(); + } + } + + @override + Future onTopScroll() async { + debugPrint('onTopScroll'); + } +} diff --git a/lib/new/screens/news/details_screen.dart b/lib/new/screens/news/details_screen.dart new file mode 100644 index 0000000..e9395b6 --- /dev/null +++ b/lib/new/screens/news/details_screen.dart @@ -0,0 +1,108 @@ +import 'package:animate_do/animate_do.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:url_launcher/url_launcher.dart'; + +import '../../../components/baseWidget.dart'; +import '../../../components/tabview.dart'; +import '../../../constants.dart'; +import '../../models/news.dart'; + +class NewsDetailScreen extends StatefulWidget { + final NewsModel news; + const NewsDetailScreen({ + Key? key, + required this.news, + }) : super(key: key); + + @override + _NewsDetailScreenState createState() => _NewsDetailScreenState(); +} + +class _NewsDetailScreenState extends State with AutomaticKeepAliveClientMixin { + @override + bool get wantKeepAlive => true; + + @override + Widget build(BuildContext context) { + super.build(context); + final deviceHeight = MediaQuery.of(context).size.height; + return BaseWidget( + appBar: BaseAppBar( + title: 'news_feed'.translation, + goBack: () { + Tabnavigator.backDispatcher(context); + }, + ), + body: ListView( + children: [ + ZoomIn( + child: CachedNetworkImage( + imageUrl: widget.news.featuredImages.first.path, + height: deviceHeight * 0.25, + width: double.infinity, + errorWidget: (context, url, error) { + return Container( + height: deviceHeight * 0.25, + width: double.infinity, + alignment: Alignment.center, + child: Icon(Icons.image), + ); + }, + placeholder: (context, url) => Container( + height: deviceHeight * 0.20, + width: double.infinity, + alignment: Alignment.center, + child: Icon(Icons.broken_image), + ), + fit: BoxFit.cover, + ), + ), + Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + vertical: AppConstants.verticalPadding(context), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.news.title, + style: new TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16.adaptedPx(), + ), + ), + SizedBox(height: 8.adaptedPx()), + Text( + widget.news.publishedAt, + style: new TextStyle( + fontSize: 14.adaptedPx(), + color: Colors.black, + ), + ), + SizedBox(height: 8.adaptedPx()), + Html( + data: widget.news.contentHtml, + style: { + "body": Style( + padding: EdgeInsets.zero, + margin: EdgeInsets.zero, + fontSize: FontSize.large, + ) + }, + onLinkTap: (String? url, RenderContext context, Map attributes, _) async { + if (!await launch('$url')) throw 'Could not launch $url'; + }, + ) + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/new/screens/news/screen.dart b/lib/new/screens/news/screen.dart new file mode 100644 index 0000000..1f4f854 --- /dev/null +++ b/lib/new/screens/news/screen.dart @@ -0,0 +1,181 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/new/screens/news/details_screen.dart'; +import 'package:birzha/new/themes/colors.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../components/baseWidget.dart'; +import '../../../components/indicator.dart'; +import '../../models/news.dart'; +import 'controller.dart'; + +class NewsScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BaseWidget( + color: Theme.of(context).chipTheme.backgroundColor, + appBar: BaseAppBar( + after: [], + goBack: () { + Navigator.of(context).pop(); + }, + title: 'news_feed'.translation, + ), + // appBar: BaseAppBar.home( + // context, + // () {}, + // ), + // color: ThemeColor.white, + body: GetX( + init: NewsController(), + builder: (nc) { + final bool isLastPage = nc.lastPage.value; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Column( + children: [ + Expanded( + child: nc.obx( + (state) => state != null + ? RefreshIndicator( + onRefresh: nc.getNews, + color: ThemeColor.mainColor, + child: ListView.builder( + padding: EdgeInsets.only(top: 12), + shrinkWrap: true, + controller: nc.scroll, + itemCount: state.length + 1, + itemBuilder: (context, index) { + if (index < state.length) { + final NewsModel news = state[index]; + return InkWell( + onTap: () { + Navigator.of(context, rootNavigator: true).push( + MaterialPageRoute(builder: (_) => NewsDetailScreen(news: news)), + ); + }, + child: Container( + padding: EdgeInsets.symmetric( + vertical: 8.adaptedPx(), + horizontal: 8.adaptedPx(), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(8.0), + child: CachedNetworkImage( + imageUrl: news.featuredImages.first.path, + height: 70.adaptedPx(), + width: 120.adaptedPx(), + errorWidget: (context, url, error) { + return Container( + height: 70.adaptedPx(), + width: 120.adaptedPx(), + alignment: Alignment.center, + child: Icon(Icons.image), + ); + }, + placeholder: (context, url) => Container( + padding: const EdgeInsets.all(3.0), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(8)), + border: Border.all( + color: Colors.grey.withOpacity(0.50), + ), + ), + height: 70.adaptedPx(), + width: 120.adaptedPx(), + alignment: Alignment.center, + child: Icon( + Icons.broken_image, + color: Colors.grey, + ), + ), + fit: BoxFit.cover, + ), + ), + Expanded( + child: Container( + padding: EdgeInsets.only(left: 10.adaptedPx()), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + news.title, + style: TextStyle( + fontSize: 13.adaptedPx(), + color: Color(0xFF003197), + ), + maxLines: 4, + overflow: TextOverflow.ellipsis, + ), + SizedBox(height: 8), + Text( + news.publishedAt, + style: TextStyle( + fontSize: 12.adaptedPx(), + color: Colors.black, + ), + ), + ], + ), + ), + ), + ], + ), + ), + ); + } else if (index == state.length && !isLastPage) + return Padding( + padding: const EdgeInsets.only(top: 10, bottom: 40), + child: Center( + child: Indicator( + size: 0.6.adaptedPx(), + ), + ), + ); + else { + return SizedBox.shrink(); + } + }, + ), + ) + : Center( + child: Text( + 'errorOccurred'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + onLoading: Center(child: Indicator(size: 0.7.adaptedPx())), + onEmpty: Center( + child: Text( + 'newsNotFount'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + onError: (error) => Center( + child: Text( + 'errorOccurred'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + ), + ), + ], + ), + ), + ], + ); + }, + ), + ); + } +} diff --git a/lib/new/screens/quotes/controller.dart b/lib/new/screens/quotes/controller.dart new file mode 100644 index 0000000..cdcf4e0 --- /dev/null +++ b/lib/new/screens/quotes/controller.dart @@ -0,0 +1,29 @@ +// import 'package:flutter/rendering.dart'; +// import 'package:get/get.dart'; + +// import '../../api/sort.dart'; +// import '../../models/quotes.dart'; +// import 'state.dart'; + +// class QuotesController extends GetxController with StateMixin>, ScrollMixin { +// // final state = SortState(); + +// @override +// void onInit() { +// super.onInit(); +// } + +// @override +// Future onEndScroll() async { +// debugPrint('onEndScroll'); +// // if (!lastPage.value) { +// // page += 1; +// // await getNews(); +// // } +// } + +// @override +// Future onTopScroll() async { +// debugPrint('onTopScroll'); +// } +// } diff --git a/lib/new/screens/quotes/exports/controller.dart b/lib/new/screens/quotes/exports/controller.dart new file mode 100644 index 0000000..7561a7f --- /dev/null +++ b/lib/new/screens/quotes/exports/controller.dart @@ -0,0 +1,222 @@ +import 'package:birzha/new/utils/capitalize.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../api/sort.dart'; +import '../../../models/export.dart'; +import '../../../models/sort_group.dart'; +import '../../../utils/locale.dart'; +import 'state.dart'; + +class ExportsController extends GetxController with StateMixin>, ScrollMixin { + final exportState = ExportState(); + + @override + void onInit() { + debugPrint('ExportsController onInit'); + initialize(); + super.onInit(); + } + + /// reset pagination data + void resetPaginationParams() { + exportState.page = 1; + exportState.getFirstData = false; + exportState.lastPage.value = false; + exportState.repositories.clear(); + } + + /// dropdown change + void onSelectedSortGroupChanged(value) { + debugPrint('onSelectedSortGroupChanged $value'); + exportState.selectedGroup.value = value; + + resetPaginationParams(); + change(null, status: RxStatus.loading()); + getExports(); + } + + /// filter change + void onFilterChanged(value, filter) { + debugPrint('onFilterChanged $value, filter: $filter'); + if (filter == 'country') { + exportState.country.value = value; + } else if (filter == 'unit') { + exportState.unit.value = value; + } else if (filter == 'currency') { + exportState.currency.value = value; + } else if (filter == 'payment') { + exportState.payment.value = value; + } else if (filter == 'send') { + exportState.send.value = value; + } + + countAppliedFilters(); + } + + void onSelectedCategoryFilterChanged(value) { + debugPrint('onSelectedCategoryFilterChanged $value'); + exportState.selectedCategoryFilter.value = value; + + countAppliedFilters(); + } + + void countAppliedFilters() { + int count = 0; + if (exportState.selectedCategoryFilter.value != null) count++; + + if (exportState.country.value.isNotEmpty) count++; + + if (exportState.unit.value.isNotEmpty) count++; + + if (exportState.currency.value.isNotEmpty) count++; + + if (exportState.payment.value.isNotEmpty) count++; + + if (exportState.send.value.isNotEmpty) count++; + + exportState.appliedFilterCount.value = count; + + update(); + } + + void onApplyBtnTapped() { + resetPaginationParams(); + change(null, status: RxStatus.loading()); + getExports(); + } + + void onClearBtnTapped() { + exportState.selectedCategoryFilter.value = null; + exportState.country.value = ''; + exportState.unit.value = ''; + exportState.currency.value = ''; + exportState.payment.value = ''; + exportState.send.value = ''; + + countAppliedFilters(); + } + + Future initialize() async { + resetPaginationParams(); + await getSortGroups(); + getExports(); + } + + Future getSortGroups() async { + if (exportState.sortGroups.isNotEmpty) return; + + exportState.isLoading.value = true; + + final result = await SortApi.getGroups('export'); + if (result.isNotEmpty) { + exportState.selectedGroup.value = result.firstWhereOrNull((group) => group.isDefault == 1); + exportState.sortGroups.addAll(result); + } + + exportState.isLoading.value = false; + } + + Future getFilters() async { + exportState.isLoadingFilters.value = true; + getOtherFilters('country', exportState.countryFilters); + getOtherFilters('unit', exportState.unitFilters); + getOtherFilters('currency', exportState.currencyFilters); + getOtherFilters('payment', exportState.paymentFilters); + getOtherFilters('send', exportState.sendFilters); + exportState.isLoadingFilters.value = false; + } + + Future getExports() async { + final Map params = { + 'per_page': exportState.itemPerPage, + 'page': exportState.page, + 'locale': await getLocale(), + 'group': exportState.selectedGroup.value?.id, + 'payment': exportState.payment.value, + 'send': exportState.send.value, + 'country': exportState.country.value, + 'unit': exportState.unit.value, + 'currency': exportState.currency.value, + }; + + final categoryId = exportState.selectedCategoryFilter.value?.id.toString(); + + if (categoryId != null && categoryId.isNotEmpty) { + params.addAll({'category': categoryId}); + } + + await SortApi.getExports(params).then( + (result) { + exportState.metaText.value = SortApi.metaText; + final bool emptyRepositories = result.isEmpty; + if (!exportState.getFirstData && emptyRepositories) { + change(null, status: RxStatus.empty()); + } else if (exportState.getFirstData && emptyRepositories) { + exportState.lastPage.value = true; + } else { + exportState.getFirstData = true; + exportState.repositories.addAll(result); + + if (result.length < exportState.itemPerPage) { + exportState.lastPage.value = true; + } + + change(exportState.repositories, status: RxStatus.success()); + } + }, + onError: (err) { + change(null, status: RxStatus.error(err.toString())); + }, + ); + } + + Future getOtherFilters(String filter, List filterList) async { + final SortGroupModel? groupValue = exportState.selectedGroup.value ?? null; + + if (groupValue == null) { + // TODO: show error message + return; + } + + if (filterList.isNotEmpty) return; + + final result = await SortApi.getOtherFilters({ + 'group': groupValue.id, + 'model': groupValue.type.capitalizeFirstLetter(), + 'filter': filter, + }); + + if (result.isNotEmpty) filterList.addAll(result); + + update(); + } + + Future getCategoryFilters() async { + if (exportState.categoryFilters.isNotEmpty) return; + exportState.isLoadingCategory.value = true; + + final result = await SortApi.getCategoryFilters(); + if (result.isNotEmpty) { + exportState.categoryFilters.addAll(result); + } + + exportState.isLoadingCategory.value = false; + + update(); + } + + @override + Future onEndScroll() async { + debugPrint('onEndScroll'); + if (!exportState.lastPage.value) { + exportState.page += 1; + await getExports(); + } + } + + @override + Future onTopScroll() async { + debugPrint('onTopScroll'); + } +} diff --git a/lib/new/screens/quotes/exports/screen.dart b/lib/new/screens/quotes/exports/screen.dart new file mode 100644 index 0000000..5c24364 --- /dev/null +++ b/lib/new/screens/quotes/exports/screen.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; + +import '../../../../components/indicator.dart'; +import '../../../../constants.dart'; +import '../../../themes/colors.dart'; +import 'controller.dart'; +import 'widgets/expandable_card.dart'; +import 'widgets/filter_widget.dart'; + +class ExportsScreen extends StatelessWidget { + const ExportsScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric( + // vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + color: ThemeColor.white, + child: GetX( + init: ExportsController(), + builder: (exc) { + final bool isLastPage = exc.exportState.lastPage.value; + return exc.exportState.isLoading.value + ? Center(child: Indicator(size: 0.7.adaptedPx())) + : CustomScrollView( + controller: exc.scroll, + slivers: [ + SliverToBoxAdapter( + child: Padding( + padding: EdgeInsets.only(top: AppConstants.verticalPadding(context)), + child: Column( + children: [ + ExportFilterWidget(), + SizedBox(height: 16.adaptedPx()), + Text(exc.exportState.metaText.value), + ], + ), + ), + ), + SliverToBoxAdapter( + child: SizedBox(height: 16.adaptedPx()), + ), + SliverToBoxAdapter( + child: exc.obx( + (state) => state != null + ? RefreshIndicator( + onRefresh: exc.getExports, + color: ThemeColor.mainColor, + child: ListView.builder( + physics: ClampingScrollPhysics(), + shrinkWrap: true, + itemCount: state.length + 1, + itemBuilder: (context, index) { + if (index < state.length) { + return ExportExpandableCard(index: index + 1, model: state[index]); + } else if (index == state.length && !isLastPage) + return Center( + child: Indicator( + size: 0.6.adaptedPx(), + ), + ); + else { + return SizedBox.shrink(); + } + }, + ), + ) + : Center( + child: Text( + 'errorOccurred'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + onLoading: Center(child: Indicator(size: 0.7.adaptedPx())), + onEmpty: Center( + child: Text( + 'notFound'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + onError: (error) => Center( + child: Text( + 'errorOccurred'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + ), + ), + ], + ); + }, + ), + ); + } +} diff --git a/lib/new/screens/quotes/exports/state.dart b/lib/new/screens/quotes/exports/state.dart new file mode 100644 index 0000000..c32076b --- /dev/null +++ b/lib/new/screens/quotes/exports/state.dart @@ -0,0 +1,46 @@ +import 'package:birzha/new/models/export.dart'; +import 'package:get/get.dart'; + +import '../../../models/category_filter.dart'; +import '../../../models/sort_group.dart'; + +class ExportState { + /// loadings + RxBool isLoading = false.obs; + RxBool isLoadingFilters = false.obs; + RxBool isLoadingCategory = false.obs; + + RxList sortGroups = [].obs; + + /// [selectedGroup] is import or export + Rxn selectedGroup = Rxn(); + + /// [metaText] displayed top of the list + RxString metaText = ''.obs; + + /// dropdown items + RxList categoryFilters = [].obs; + RxList countryFilters = [].obs; + RxList unitFilters = [].obs; + RxList currencyFilters = [].obs; + RxList paymentFilters = [].obs; + RxList sendFilters = [].obs; + + /// pagination data + List repositories = []; + int itemPerPage = 10; + int page = 1; + bool getFirstData = false; + RxBool lastPage = false.obs; + + /// filters + Rxn selectedCategoryFilter = Rxn(); + RxString country = ''.obs; + RxString unit = ''.obs; + RxString currency = ''.obs; + RxString payment = ''.obs; + RxString send = ''.obs; + + /// total applied filter + RxInt appliedFilterCount = 0.obs; +} diff --git a/lib/new/screens/quotes/exports/widgets/expandable_card.dart b/lib/new/screens/quotes/exports/widgets/expandable_card.dart new file mode 100644 index 0000000..ccb2d41 --- /dev/null +++ b/lib/new/screens/quotes/exports/widgets/expandable_card.dart @@ -0,0 +1,177 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:expandable/expandable.dart'; +import 'package:flutter/material.dart'; + +import '../../../../models/export.dart'; +import '../../../../themes/colors.dart'; + +class ExportExpandableCard extends StatelessWidget { + final ExportModel model; + final int index; + const ExportExpandableCard({ + Key? key, + required this.model, + required this.index, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + Widget buildCollapsed() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CardTitle(), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + child: Column( + children: [ + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'quantity'.translation + ':', text2: model.amount, text3: model.unit), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'price'.translation + ':', text2: model.price, text3: model.currency), + ], + ), + ), + ], + ), + ], + ); + } + + Widget buildExpanded() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CardTitle(), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + child: Column( + children: [ + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'quantity'.translation + ':', text2: model.amount, text3: model.unit), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'price'.translation + ':', text2: model.price, text3: model.currency), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'paymentTerms'.translation + ':', text2: model.payment), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'deliveryTerms'.translation + ':', text2: model.send), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'station'.translation + ':', text2: model.point), + ], + ), + ), + ], + ), + ], + ); + } + + return ExpandableNotifier( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: ScrollOnExpand( + child: Container( + decoration: BoxDecoration( + // color: Colors.grey, + border: Border.all( + color: ThemeColor.colorE2E2E2, + width: 1.5, + ), + borderRadius: BorderRadius.circular(6), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expandable( + collapsed: buildCollapsed(), + expanded: buildExpanded(), + ), + // bottom expandable button + Center( + child: Container( + color: Colors.white, + child: Builder( + builder: (context) { + var controller = ExpandableController.of(context, required: true)!; + return InkWell( + onTap: controller.toggle, + child: Container( + decoration: new BoxDecoration( + color: ThemeColor.mainColor, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(6), + topRight: Radius.circular(6), + ), + ), + width: 80.adaptedPx(), + child: Icon( + controller.expanded ? Icons.arrow_drop_up : Icons.arrow_drop_down, + size: 20.adaptedPx(), + ), + ), + ); + }, + ), + ), + ), + ], + ), + ), + ), + ), + ); + } + + Widget RowTextBuilder({required String text1, required String text2, String? text3}) { + return Row( + children: [ + Expanded( + flex: 2, + child: Text( + text1, + style: TextStyle( + color: ThemeColor.color717278, + fontSize: 12.adaptedPx(), + ), + ), + ), + Spacer(), + Expanded( + flex: 2, + child: Text( + '$text2 ${text3 ?? ''}', + textAlign: TextAlign.right, + style: TextStyle( + color: ThemeColor.black, + fontSize: 12.adaptedPx(), + ), + ), + ), + ], + ); + } + + Widget CardTitle() { + return Container( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + width: double.infinity, + decoration: new BoxDecoration( + color: ThemeColor.colorE5E5E5, + ), + child: Text( + "$index. ${model.title}", + style: TextStyle( + color: ThemeColor.color3A3A3A, + fontSize: 13.adaptedPx(), + ), + ), + ); + } +} diff --git a/lib/new/screens/quotes/exports/widgets/filter_dialog.dart b/lib/new/screens/quotes/exports/widgets/filter_dialog.dart new file mode 100644 index 0000000..82bb32b --- /dev/null +++ b/lib/new/screens/quotes/exports/widgets/filter_dialog.dart @@ -0,0 +1,235 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../../../components/button.dart'; +import '../../../../../components/categoryNameWidget.dart'; +import '../../../../../components/indicator.dart'; +import '../../../../models/category_filter.dart'; +import '../../../../models/sort_group.dart'; +import '../../../../themes/colors.dart'; +import '../../widgets/custom_dd.dart'; +import '../controller.dart'; + +final Widget divider = SizedBox(height: 10.adaptedPx()); + +class ExportFilterDialog extends StatelessWidget { + @override + Widget build(BuildContext context) { + return GetBuilder( + init: ExportsController(), + builder: (ec) => AlertDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + titlePadding: EdgeInsets.zero, + scrollable: true, + title: Container( + padding: const EdgeInsets.only(top: 24, bottom: 24, right: 8, left: 24), + decoration: new BoxDecoration( + // color: ThemeColor.color3A3A3A, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + topRight: Radius.circular(8), + ), + ), + child: Row( + children: [ + CategoryNameWidget( + categoryName: 'filters'.translation, + ), + Spacer(), + Material( + shape: CircleBorder(), + child: InkWell( + customBorder: CircleBorder(), + onTap: () => Get.back(), + child: Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration(shape: BoxShape.circle), + child: Icon( + Icons.close, + color: ThemeColor.mainColor, + size: 18.adaptedPx(), + ), + ), + ), + ), + ], + ), + ), + contentPadding: const EdgeInsets.all(16), + insetPadding: EdgeInsets.zero, + content: Builder( + builder: (context) { + final width = MediaQuery.of(context).size.width - 70; + final SortGroupModel? groupValue = ec.exportState.selectedGroup.value ?? null; + return groupValue != null + ? ec.exportState.isLoadingFilters.value + ? Center(child: Indicator(size: 0.7.adaptedPx())) + : Container( + width: width > 0 ? width : double.infinity, + child: Column( + children: [ + ec.exportState.isLoadingCategory.value + ? Center( + child: Indicator( + size: 0.4.adaptedPx(), + ), + ) + : CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + value: ec.exportState.selectedCategoryFilter.value, + hint: Text('selectCategory'.translation), + items: ec.exportState.categoryFilters.map( + (CategoryFilterModel value) { + return DropdownMenuItem( + value: value, + child: Text(value.title), + ); + }, + ).toList(), + onChanged: (newValue) => ec.onSelectedCategoryFilterChanged(newValue), + ), + ), + ), + SizedBox(height: 12.adaptedPx()), + CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + hint: Text(ec.exportState.unit.value.isEmpty ? 'selectUnit'.translation : ec.exportState.unit.value), + items: ec.exportState.unitFilters.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }, + ).toList(), + onChanged: (newValue) => ec.onFilterChanged(newValue, 'unit'), + ), + ), + ), + SizedBox(height: 12.adaptedPx()), + CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + hint: Text(ec.exportState.currency.value.isEmpty ? 'selectCurrency'.translation : ec.exportState.currency.value), + items: ec.exportState.currencyFilters.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }, + ).toList(), + onChanged: (newValue) => ec.onFilterChanged(newValue, 'currency'), + ), + ), + ), + SizedBox(height: 12.adaptedPx()), + CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + hint: Text(ec.exportState.payment.value.isEmpty ? 'selectPayment'.translation : ec.exportState.payment.value), + items: ec.exportState.paymentFilters.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }, + ).toList(), + onChanged: (newValue) => ec.onFilterChanged(newValue, 'payment'), + ), + ), + ), + SizedBox(height: 12.adaptedPx()), + CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + hint: Text(ec.exportState.send.value.isEmpty ? 'selectSendType'.translation : ec.exportState.send.value), + items: ec.exportState.sendFilters.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }, + ).toList(), + onChanged: (newValue) => ec.onFilterChanged(newValue, 'send'), + ), + ), + ), + SizedBox(height: 12.adaptedPx()), + CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + hint: Text(ec.exportState.country.value.isEmpty ? 'selectCountry'.translation : ec.exportState.country.value), + items: ec.exportState.countryFilters.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }, + ).toList(), + onChanged: (newValue) => ec.onFilterChanged(newValue, 'country'), + ), + ), + ), + SizedBox(height: 18.adaptedPx()), + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Expanded( + child: MyButton( + text: 'clear'.translation, + inProgress: false, + onTap: ec.onClearBtnTapped, + height: 40.adaptedPx(), + ), + ), + SizedBox(width: 20.adaptedPx()), + Expanded( + child: MyButton( + text: 'apply'.translation, + inProgress: false, + onTap: () { + debugPrint('apply tapped'); + ec.onApplyBtnTapped(); + Get.back(); + }, + height: 40.adaptedPx(), + ), + ), + ], + ), + ) + ], + ), + ) + : Text('errorOccurred'.translation); + }, + ), + ), + ); + } +} diff --git a/lib/new/screens/quotes/exports/widgets/filter_widget.dart b/lib/new/screens/quotes/exports/widgets/filter_widget.dart new file mode 100644 index 0000000..3bfe326 --- /dev/null +++ b/lib/new/screens/quotes/exports/widgets/filter_widget.dart @@ -0,0 +1,90 @@ +import 'package:badges/badges.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../../../constants.dart'; +import '../../../../models/sort_group.dart'; +import '../../../../themes/colors.dart'; +import '../controller.dart'; +import 'filter_dialog.dart'; + +class ExportFilterWidget extends StatelessWidget { + const ExportFilterWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return GetX( + init: ExportsController(), + builder: (ec) => Row( + children: [ + Material( + child: InkWell( + splashColor: Colors.grey.shade200, + onTap: () { + debugPrint('Filter Widget'); + ec.getCategoryFilters(); + ec.getFilters(); + Get.dialog(ExportFilterDialog()); + }, + child: Badge( + badgeColor: ThemeColor.mainColor, + padding: const EdgeInsets.all(6), + position: BadgePosition.topEnd( + top: -16, + ), + badgeContent: Text( + ec.exportState.appliedFilterCount.toString(), + style: TextStyle(color: Colors.white, fontSize: 11.adaptedPx()), + ), + child: Container( + height: 40.adaptedPx(), + width: 40.adaptedPx(), + // padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: Border.all( + color: ThemeColor.mainColor, + ), + ), + child: Icon( + Icons.filter_list_alt, + size: 20.adaptedPx(), + color: ThemeColor.mainColor, + ), + ), + ), + ), + ), + Spacer(), + Container( + width: MediaQuery.of(context).size.width - AppConstants.horizontalPadding(context) - 40.adaptedPx() - 30.adaptedPx(), + height: 40.adaptedPx(), + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: BorderSide(color: ThemeColor.mainColor), + borderRadius: BorderRadius.all(Radius.circular(5.0)), + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + borderRadius: BorderRadius.circular(16), + value: ec.exportState.selectedGroup.value, + items: ec.exportState.sortGroups.map( + (SortGroupModel value) { + return DropdownMenuItem( + value: value, + child: Text(value.title), + ); + }, + ).toList(), + onChanged: (newValue) => ec.onSelectedSortGroupChanged(newValue), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/new/screens/quotes/imports/controller.dart b/lib/new/screens/quotes/imports/controller.dart new file mode 100644 index 0000000..394eaa2 --- /dev/null +++ b/lib/new/screens/quotes/imports/controller.dart @@ -0,0 +1,176 @@ +import 'package:birzha/new/models/import.dart'; +import 'package:birzha/new/utils/capitalize.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../api/sort.dart'; +import '../../../models/sort_group.dart'; +import '../../../utils/locale.dart'; +import 'state.dart'; + +class ImportsController extends GetxController with StateMixin>, ScrollMixin { + final importState = ImportState(); + + @override + void onInit() { + debugPrint('ExportsController onInit'); + initialize(); + super.onInit(); + } + + void resetPaginationParams() { + // reset pagination data + importState.page = 1; + importState.getFirstData = false; + importState.lastPage.value = false; + importState.repositories.clear(); + } + + void onSelectedSortGroupChanged(value) { + debugPrint('onSelectedSortGroupChanged $value'); + importState.selectedGroup.value = value; + + resetPaginationParams(); + change(null, status: RxStatus.loading()); + getImports(); + } + + void onFilterChanged(value, filter) { + debugPrint('onFilterChanged $value, filter: $filter'); + if (filter == 'country') { + importState.country.value = value; + } else if (filter == 'unit') { + importState.unit.value = value; + } else if (filter == 'currency') { + importState.currency.value = value; + } + + countAppliedFilters(); + } + + void countAppliedFilters() { + int count = 0; + + if (importState.country.value.isNotEmpty) count++; + + if (importState.unit.value.isNotEmpty) count++; + + if (importState.currency.value.isNotEmpty) count++; + + importState.appliedFilterCount.value = count; + + update(); + } + + void onApplyBtnTapped() { + resetPaginationParams(); + change(null, status: RxStatus.loading()); + getImports(); + } + + void onClearBtnTapped() { + importState.country.value = ''; + importState.unit.value = ''; + importState.currency.value = ''; + + countAppliedFilters(); + } + + Future initialize() async { + resetPaginationParams(); + await getSortGroups(); + getImports(); + } + + Future getSortGroups() async { + if (importState.sortGroups.isNotEmpty) return; + + importState.isLoading.value = true; + + final result = await SortApi.getGroups('import'); + if (result.isNotEmpty) { + importState.selectedGroup.value = result.firstWhereOrNull((group) => group.isDefault == 1); + importState.sortGroups.addAll(result); + } + + importState.isLoading.value = false; + } + + Future getFilters() async { + importState.isLoadingFilters.value = true; + getOtherFilters('country', importState.countryFilters); + getOtherFilters('unit', importState.unitFilters); + getOtherFilters('currency', importState.currencyFilters); + importState.isLoadingFilters.value = false; + } + + Future getImports() async { + final Map params = { + 'per_page': importState.itemPerPage, + 'page': importState.page, + 'locale': await getLocale(), + 'group': importState.selectedGroup.value?.id, + 'country': importState.country.value, + 'unit': importState.unit.value, + 'currency': importState.currency.value, + }; + + await SortApi.getImports(params).then( + (result) { + final bool emptyRepositories = result.isEmpty; + if (!importState.getFirstData && emptyRepositories) { + change(null, status: RxStatus.empty()); + } else if (importState.getFirstData && emptyRepositories) { + importState.lastPage.value = true; + } else { + importState.getFirstData = true; + importState.repositories.addAll(result); + + if (result.length < importState.itemPerPage) { + importState.lastPage.value = true; + } + + change(importState.repositories, status: RxStatus.success()); + } + }, + onError: (err) { + change(null, status: RxStatus.error(err.toString())); + }, + ); + } + + Future getOtherFilters(String filter, List filterList) async { + final SortGroupModel? groupValue = importState.selectedGroup.value ?? null; + + if (groupValue == null) { + // TODO: show error message + return; + } + + if (filterList.isNotEmpty) return; + + final result = await SortApi.getOtherFilters({ + 'group': groupValue.id, + 'model': groupValue.type.capitalizeFirstLetter(), + 'filter': filter, + }); + + if (result.isNotEmpty) filterList.addAll(result); + + update(); + } + + @override + Future onEndScroll() async { + debugPrint('onEndScroll'); + if (!importState.lastPage.value) { + importState.page += 1; + await getImports(); + } + } + + @override + Future onTopScroll() async { + debugPrint('onTopScroll'); + } +} diff --git a/lib/new/screens/quotes/imports/screen.dart b/lib/new/screens/quotes/imports/screen.dart new file mode 100644 index 0000000..5119fe6 --- /dev/null +++ b/lib/new/screens/quotes/imports/screen.dart @@ -0,0 +1,101 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; + +import '../../../../components/indicator.dart'; +import '../../../../constants.dart'; +import '../../../themes/colors.dart'; +import 'controller.dart'; +import 'widgets/expandable_card.dart'; +import 'widgets/filter_widget.dart'; + +class ImportsScreen extends StatelessWidget { + const ImportsScreen({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + ), + color: ThemeColor.white, + child: GetX( + init: ImportsController(), + builder: (ic) { + final bool isLastPage = ic.importState.lastPage.value; + return ic.importState.isLoading.value + ? Center(child: Indicator(size: 0.7.adaptedPx())) + : CustomScrollView( + controller: ic.scroll, + slivers: [ + SliverToBoxAdapter( + child: Padding( + padding: EdgeInsets.only(top: AppConstants.verticalPadding(context)), + child: Column( + children: [ + ImportFilterWidget(), + ], + ), + ), + ), + SliverToBoxAdapter( + child: SizedBox(height: 16.adaptedPx()), + ), + SliverToBoxAdapter( + child: ic.obx( + (state) => state != null + ? RefreshIndicator( + onRefresh: ic.getImports, + color: ThemeColor.mainColor, + child: ListView.builder( + physics: ClampingScrollPhysics(), + shrinkWrap: true, + itemCount: state.length + 1, + itemBuilder: (context, index) { + if (index < state.length) { + return ImportExpandableCard(index: index + 1, model: state[index]); + } else if (index == state.length && !isLastPage) + return Center( + child: Indicator( + size: 0.6.adaptedPx(), + ), + ); + else { + return SizedBox.shrink(); + } + }, + ), + ) + : Center( + child: Text( + 'errorOccurred'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + onLoading: Center(child: Indicator(size: 0.7.adaptedPx())), + onEmpty: Center( + child: Text( + 'notFound'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + onError: (error) => Center( + child: Text( + 'errorOccurred'.translation, + style: TextStyle(fontSize: 18), + textAlign: TextAlign.center, + ), + ), + ), + ), + ], + ); + }, + ), + ); + } +} diff --git a/lib/new/screens/quotes/imports/state.dart b/lib/new/screens/quotes/imports/state.dart new file mode 100644 index 0000000..0e0d46c --- /dev/null +++ b/lib/new/screens/quotes/imports/state.dart @@ -0,0 +1,34 @@ +import 'package:get/get.dart'; + +import '../../../models/import.dart'; +import '../../../models/sort_group.dart'; + +class ImportState { + RxBool isLoading = false.obs; + RxBool isLoadingFilters = false.obs; + + /// [sortGroups] dates that displayed in the dropdown + RxList sortGroups = [].obs; + + Rxn selectedGroup = Rxn(); + + /// pagination data + List repositories = []; + int itemPerPage = 10; + int page = 1; + bool getFirstData = false; + RxBool lastPage = false.obs; + + /// filter arrays + RxList countryFilters = [].obs; + RxList unitFilters = [].obs; + RxList currencyFilters = [].obs; + + /// filters + RxString country = ''.obs; + RxString unit = ''.obs; + RxString currency = ''.obs; + + /// total count for applied filters + RxInt appliedFilterCount = 0.obs; +} diff --git a/lib/new/screens/quotes/imports/widgets/expandable_card.dart b/lib/new/screens/quotes/imports/widgets/expandable_card.dart new file mode 100644 index 0000000..fa35e2c --- /dev/null +++ b/lib/new/screens/quotes/imports/widgets/expandable_card.dart @@ -0,0 +1,177 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/new/models/import.dart'; +import 'package:expandable/expandable.dart'; +import 'package:flutter/material.dart'; + +import '../../../../themes/colors.dart'; + +class ImportExpandableCard extends StatelessWidget { + final ImportModel model; + final int index; + const ImportExpandableCard({ + Key? key, + required this.model, + required this.index, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + Widget buildCollapsed() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CardTitle(), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + child: Column( + children: [ + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'price'.translation + ':', text2: model.price), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'currency'.translation + ':', text2: model.currency), + ], + ), + ), + ], + ), + ], + ); + } + + Widget buildExpanded() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + CardTitle(), + Padding( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + child: Column( + children: [ + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'registeredDate'.translation + ':', text2: model.registeredAt), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'price'.translation + ':', text2: model.price), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'currency'.translation + ':', text2: model.currency), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'country'.translation + ':', text2: model.country), + SizedBox(height: 8.adaptedPx()), + RowTextBuilder(text1: 'unit'.translation + ':', text2: model.unit), + ], + ), + ), + ], + ), + ], + ); + } + + return ExpandableNotifier( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: ScrollOnExpand( + child: Container( + decoration: BoxDecoration( + // color: Colors.grey, + border: Border.all( + color: ThemeColor.colorE2E2E2, + width: 1.5, + ), + borderRadius: BorderRadius.circular(6), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expandable( + collapsed: buildCollapsed(), + expanded: buildExpanded(), + ), + // bottom expandable button + Center( + child: Container( + color: Colors.white, + child: Builder( + builder: (context) { + var controller = ExpandableController.of(context, required: true)!; + return InkWell( + onTap: controller.toggle, + child: Container( + decoration: new BoxDecoration( + color: ThemeColor.mainColor, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(6), + topRight: Radius.circular(6), + ), + ), + width: 80.adaptedPx(), + child: Icon( + controller.expanded ? Icons.arrow_drop_up : Icons.arrow_drop_down, + size: 20.adaptedPx(), + ), + ), + ); + }, + ), + ), + ), + ], + ), + ), + ), + ), + ); + } + + Widget RowTextBuilder({required String text1, required String text2, String? text3}) { + return Row( + children: [ + Expanded( + flex: 2, + child: Text( + text1, + style: TextStyle( + color: ThemeColor.color717278, + fontSize: 12.adaptedPx(), + ), + ), + ), + Spacer(), + Expanded( + flex: 2, + child: Text( + '$text2 ${text3 ?? ''}', + textAlign: TextAlign.right, + style: TextStyle( + color: ThemeColor.black, + fontSize: 12.adaptedPx(), + ), + ), + ), + ], + ); + } + + Widget CardTitle() { + return Container( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 16), + width: double.infinity, + decoration: new BoxDecoration( + color: ThemeColor.colorE5E5E5, + ), + child: Text( + "$index. ${model.title}", + style: TextStyle( + color: ThemeColor.color3A3A3A, + fontSize: 13.adaptedPx(), + ), + ), + ); + } +} diff --git a/lib/new/screens/quotes/imports/widgets/filter_dialog.dart b/lib/new/screens/quotes/imports/widgets/filter_dialog.dart new file mode 100644 index 0000000..a4b4d6c --- /dev/null +++ b/lib/new/screens/quotes/imports/widgets/filter_dialog.dart @@ -0,0 +1,173 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/new/screens/quotes/widgets/custom_dd.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../../../components/button.dart'; +import '../../../../../components/categoryNameWidget.dart'; +import '../../../../../components/indicator.dart'; +import '../../../../models/sort_group.dart'; +import '../../../../themes/colors.dart'; +import '../controller.dart'; + +final Widget divider = SizedBox(height: 10.adaptedPx()); + +class ImportFilterDialog extends StatelessWidget { + @override + Widget build(BuildContext context) { + return GetBuilder( + init: ImportsController(), + builder: (ic) => AlertDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + titlePadding: EdgeInsets.zero, + scrollable: true, + title: Container( + padding: const EdgeInsets.only(top: 24, bottom: 24, right: 8, left: 24), + decoration: new BoxDecoration( + // color: ThemeColor.color3A3A3A, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(8), + topRight: Radius.circular(8), + ), + ), + child: Row( + children: [ + CategoryNameWidget( + categoryName: 'filters'.translation, + ), + Spacer(), + Material( + shape: CircleBorder(), + child: InkWell( + customBorder: CircleBorder(), + onTap: () => Get.back(), + child: Container( + padding: const EdgeInsets.all(6), + decoration: BoxDecoration(shape: BoxShape.circle), + child: Icon( + Icons.close, + color: ThemeColor.mainColor, + size: 18.adaptedPx(), + ), + ), + ), + ), + ], + ), + ), + contentPadding: const EdgeInsets.all(16), + insetPadding: EdgeInsets.zero, + content: Builder( + builder: (context) { + final width = MediaQuery.of(context).size.width - 70; + final SortGroupModel? groupValue = ic.importState.selectedGroup.value ?? null; + return groupValue != null + ? ic.importState.isLoadingFilters.value + ? Center(child: Indicator(size: 0.7.adaptedPx())) + : Container( + width: width > 0 ? width : double.infinity, + child: Column( + children: [ + CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + // value: ac.state.unit.value, + hint: Text(ic.importState.unit.value.isEmpty ? 'selectUnit'.translation : ic.importState.unit.value), + items: ic.importState.unitFilters.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }, + ).toList(), + onChanged: (newValue) => ic.onFilterChanged(newValue, 'unit'), + ), + ), + ), + SizedBox(height: 12.adaptedPx()), + CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + // value: ac.state.unit.value, + hint: Text(ic.importState.currency.value.isEmpty ? 'selectCurrency'.translation : ic.importState.currency.value), + items: ic.importState.currencyFilters.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }, + ).toList(), + onChanged: (newValue) => ic.onFilterChanged(newValue, 'currency'), + ), + ), + ), + SizedBox(height: 12.adaptedPx()), + CustomDropDown( + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + // value: ac.state.unit.value, + hint: Text(ic.importState.country.value.isEmpty ? 'selectCountry'.translation : ic.importState.country.value), + items: ic.importState.countryFilters.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text(value), + ); + }, + ).toList(), + onChanged: (newValue) => ic.onFilterChanged(newValue, 'country'), + ), + ), + ), + SizedBox(height: 18.adaptedPx()), + Padding( + padding: const EdgeInsets.all(8.0), + child: Row( + children: [ + Expanded( + child: MyButton( + text: 'clear'.translation, + inProgress: false, + onTap: ic.onClearBtnTapped, + height: 40.adaptedPx(), + ), + ), + SizedBox(width: 20.adaptedPx()), + Expanded( + child: MyButton( + text: 'apply'.translation, + inProgress: false, + onTap: () { + debugPrint('apply tapped'); + ic.onApplyBtnTapped(); + Get.back(); + }, + height: 40.adaptedPx(), + ), + ), + ], + ), + ) + ], + ), + ) + : Text('errorOccurred'.translation); + }, + ), + ), + ); + } +} diff --git a/lib/new/screens/quotes/imports/widgets/filter_widget.dart b/lib/new/screens/quotes/imports/widgets/filter_widget.dart new file mode 100644 index 0000000..97b0fe3 --- /dev/null +++ b/lib/new/screens/quotes/imports/widgets/filter_widget.dart @@ -0,0 +1,89 @@ +import 'package:badges/badges.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../../../constants.dart'; +import '../../../../models/sort_group.dart'; +import '../../../../themes/colors.dart'; +import '../controller.dart'; +import 'filter_dialog.dart'; + +class ImportFilterWidget extends StatelessWidget { + const ImportFilterWidget({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return GetX( + init: ImportsController(), + builder: (ic) => Row( + children: [ + Material( + child: InkWell( + splashColor: Colors.grey.shade200, + onTap: () { + debugPrint('ImportFilterDialog Widget'); + ic.getFilters(); + Get.dialog(ImportFilterDialog()); + }, + child: Badge( + badgeColor: ThemeColor.mainColor, + padding: const EdgeInsets.all(6), + position: BadgePosition.topEnd( + top: -16, + ), + badgeContent: Text( + ic.importState.appliedFilterCount.toString(), + style: TextStyle(color: Colors.white, fontSize: 11.adaptedPx()), + ), + child: Container( + height: 40.adaptedPx(), + width: 40.adaptedPx(), + // padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + border: Border.all( + color: ThemeColor.mainColor, + ), + ), + child: Icon( + Icons.filter_list_alt, + size: 20.adaptedPx(), + color: ThemeColor.mainColor, + ), + ), + ), + ), + ), + Spacer(), + Container( + width: MediaQuery.of(context).size.width - AppConstants.horizontalPadding(context) - 40.adaptedPx() - 30.adaptedPx(), + height: 40.adaptedPx(), + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: BorderSide(color: ThemeColor.mainColor), + borderRadius: BorderRadius.all(Radius.circular(5.0)), + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + borderRadius: BorderRadius.circular(16), + value: ic.importState.selectedGroup.value, + items: ic.importState.sortGroups.map( + (SortGroupModel value) { + return DropdownMenuItem( + value: value, + child: Text(value.title), + ); + }, + ).toList(), + onChanged: (newValue) => ic.onSelectedSortGroupChanged(newValue), + ), + ), + ), + ], + ), + ); + } +} diff --git a/lib/new/screens/quotes/screen.dart b/lib/new/screens/quotes/screen.dart new file mode 100644 index 0000000..0e7f699 --- /dev/null +++ b/lib/new/screens/quotes/screen.dart @@ -0,0 +1,48 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/new/screens/quotes/imports/screen.dart'; +import 'package:birzha/new/themes/colors.dart'; +import 'package:flutter/material.dart'; + +import '../../../components/baseWidget.dart'; +import 'exports/screen.dart'; + +class QuotesScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BaseWidget( + appBar: BaseAppBar.home( + context, + () {}, + ), + color: ThemeColor.white, + body: DefaultTabController( + length: 2, + child: Scaffold( + backgroundColor: ThemeColor.white, + appBar: PreferredSize( + preferredSize: Size(double.infinity, 50.adaptedPx()), + child: AppBar( + elevation: 0.50, + bottom: TabBar( + indicatorSize: TabBarIndicatorSize.label, + indicatorColor: ThemeColor.mainColor, + // indicatorWeight: 10, + tabs: [ + Tab(child: Text('quotes'.translation)), + Tab(child: Text('importPrice'.translation)), + ], + ), + ), + ), + body: TabBarView( + children: [ + ExportsScreen(), + ImportsScreen(), + ], + ), + ), + ), + ); + } +} diff --git a/lib/new/screens/quotes/state.dart b/lib/new/screens/quotes/state.dart new file mode 100644 index 0000000..6b803ee --- /dev/null +++ b/lib/new/screens/quotes/state.dart @@ -0,0 +1,29 @@ +import 'package:get/get.dart'; + +import '../../models/category_filter.dart'; +import '../../models/sort_group.dart'; + +class SortState { + RxBool isLoading = false.obs; + RxList exportSortGroups = [].obs; + + /// [selectedExportSortGroup] is import or export + Rxn selectedExportSortGroup = Rxn(); + + RxList categoryFilters = [].obs; + RxList countryFilters = [].obs; + RxList unitFilters = [].obs; + RxList currencyFilters = [].obs; + RxList paymentFilters = [].obs; + RxList sendFilters = [].obs; + + /// filters + Rxn selectedCategoryFilter = Rxn(); + RxString country = ''.obs; + RxString unit = ''.obs; + RxString currency = ''.obs; + RxString payment = ''.obs; + RxString send = ''.obs; + + RxInt appliedFilterCount = 0.obs; +} diff --git a/lib/new/screens/quotes/widgets/custom_dd.dart b/lib/new/screens/quotes/widgets/custom_dd.dart new file mode 100644 index 0000000..6addcef --- /dev/null +++ b/lib/new/screens/quotes/widgets/custom_dd.dart @@ -0,0 +1,96 @@ +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/new/api/sort.dart'; +import 'package:flutter/material.dart'; + +import 'package:birzha/core/adaptix/adaptix.dart'; + +import '../../../../constants.dart'; +import '../../../themes/colors.dart'; + +class CustomDropDown extends StatelessWidget { + final Widget child; + const CustomDropDown({ + Key? key, + required this.child, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: MediaQuery.of(context).size.width - AppConstants.horizontalPadding(context) - 40.adaptedPx() - 30.adaptedPx(), + height: 40.adaptedPx(), + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: BorderSide(color: ThemeColor.mainColor), + borderRadius: BorderRadius.all(Radius.circular(5.0)), + ), + ), + child: child, + ); + } +} + +class CustomDropDown2 extends StatefulWidget { + final void Function(String?) onSelectionChanged; + final String filter; + final String value; + final List items; + const CustomDropDown2({ + Key? key, + required this.filter, + required this.value, + required this.items, + required this.onSelectionChanged, + }) : super(key: key); + + @override + State> createState() => _CustomDropDown2State(); +} + +class _CustomDropDown2State extends State> { + late var _selectedValue; + + @override + void initState() { + super.initState(); + _selectedValue = widget.value; + } + + @override + Widget build(BuildContext context) { + return Container( + width: MediaQuery.of(context).size.width - AppConstants.horizontalPadding(context) - 40.adaptedPx() - 30.adaptedPx(), + height: 40.adaptedPx(), + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: BorderSide(color: ThemeColor.mainColor), + borderRadius: BorderRadius.all(Radius.circular(5.0)), + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + borderRadius: BorderRadius.circular(16), + hint: Text(_selectedValue), + // value: _selectedValue, + items: widget.items.map( + (String value) { + return DropdownMenuItem( + value: value, + child: Text('$value'), + ); + }, + ).toList(), + onChanged: (newValue) { + debugPrint('newValue $newValue'); + setState(() { + if (newValue != null) _selectedValue = newValue; + widget.onSelectionChanged(newValue); + }); + }, + ), + ), + ); + } +} diff --git a/lib/new/screens/top_up_balance/bank_top_up_screen.dart b/lib/new/screens/top_up_balance/bank_top_up_screen.dart new file mode 100644 index 0000000..57c291b --- /dev/null +++ b/lib/new/screens/top_up_balance/bank_top_up_screen.dart @@ -0,0 +1,338 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import 'package:birzha/components/actionIcons/searchicon.dart'; +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/new/global/full_width_button.dart'; +import 'package:birzha/new/themes/colors.dart'; + +import '../../../components/button.dart'; +import '../../../components/categoryNameWidget.dart'; +import '../../../components/indicator.dart'; +import '../../../constants.dart'; +import '../../../core/manager/manager.dart'; +import '../../../models/user/userManager.dart'; +import 'controller.dart'; + +class BankTopUpBalance extends StatelessWidget { + @override + Widget build(BuildContext context) { + return GetBuilder( + init: BalanceController(), + builder: (tb) => BaseWidget( + // color: Theme.of(context).scaffoldBackgroundColor, + color: ThemeColor.white, + appBar: BaseAppBar( + title: 'topUpBalance'.translation, + after: [SearchIcon()], + goBack: () { + Navigator.of(context, rootNavigator: false).pop(); + }, + ), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: CategoryNameWidget( + categoryName: 'topUpBalance'.translation, + ), + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: RichText( + text: new TextSpan( + text: "selectPaymentMethod".translation, + style: new TextStyle( + color: Colors.black, + fontWeight: FontWeight.w500, + fontSize: 14.adaptedPx(), + ), + children: [ + new TextSpan( + text: ' *', + style: new TextStyle( + fontWeight: FontWeight.w400, + color: Colors.red, + fontSize: 12.adaptedPx(), + ), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsets.symmetric( + // vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: FullWidthButton( + callback: () {}, + title: 'payOnline'.translation, + btnColor: Color(0xFFF2F6FF), + txtColor: ThemeColor.mainColor, + ), + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: FullWidthButton( + callback: () {}, + title: "bankTransfer".translation, + ), + ), + + // info + Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + ), + child: tb.state.isLoadingBankInfo.value + ? Center(child: Indicator(size: 0.7.adaptedPx())) + : tb.state.hasErrorBankInfo.value + ? Center(child: Text('errorOccurred'.translation)) + : Column( + children: [ + InfoCard( + header: 'taxCode'.translation, + content: tb.state.bankInfo.value?.taxCode ?? '', + ), + SizedBox(height: 8.adaptedPx()), + InfoCard( + header: 'manatAccount'.translation, + content: tb.state.bankInfo.value?.manatAccount ?? '', + ), + SizedBox(height: 8.adaptedPx()), + InfoCard( + header: 'corrAccount'.translation, + content: '21101934110100700005000', + ), + SizedBox(height: 8.adaptedPx()), + InfoCard( + header: 'bankAddress'.translation, + content: tb.state.bankInfo.value?.bankAddress ?? '', + ), + SizedBox(height: 8.adaptedPx()), + InfoCard( + header: 'МФО:', + content: tb.state.bankInfo.value?.bab ?? '', + ), + SizedBox(height: 8.adaptedPx()), + ], + ), + ), + + // upload file + Padding( + padding: EdgeInsets.only( + top: AppConstants.verticalPadding(context), + left: AppConstants.horizontalPadding(context), + right: AppConstants.horizontalPadding(context), + bottom: 8.adaptedPx(), + // vertical: AppConstants.verticalPadding(context), + // horizontal: AppConstants.horizontalPadding(context), + ), + child: RichText( + text: new TextSpan( + text: "selectFile".translation, + style: new TextStyle( + color: Color(0xFFC9C9C9), + fontWeight: FontWeight.w500, + fontSize: 14.adaptedPx(), + ), + children: [ + new TextSpan( + text: ' *', + style: new TextStyle( + fontWeight: FontWeight.w400, + color: Colors.red, + fontSize: 12.adaptedPx(), + ), + ), + ], + ), + ), + ), + + Padding( + padding: EdgeInsets.symmetric( + // vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: Color(0xFFE5E5E5), + ), + ), + child: IntrinsicHeight( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + InkWell( + onTap: tb.uploadFile, + child: Container( + width: MediaQuery.of(context).size.width * 0.30, + height: double.infinity, + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Color(0xFFE2E2E2), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + "upload".translation, + style: new TextStyle( + color: Colors.black, + fontSize: 14.adaptedPx(), + ), + ), + ), + ), + SizedBox(width: 12.adaptedPx()), + Expanded( + child: Center( + child: Text( + tb.state.file.value == null ? 'fileNotSelected'.translation : tb.state.file.value!.name, + style: new TextStyle( + color: Colors.black, + fontSize: 14.adaptedPx(), + ), + ), + ), + ) + ], + ), + ), + ), + ), + + SizedBox(height: 12.adaptedPx()), + + ManagerSelector( + onUpdate: () { + debugPrint('onUpdate'); + tb.resetFile(); + }, + selector: (context, manager) => manager.getStatusByKey('uploadBill'), + shouldRebuild: (prev, next) => prev != next, + builder: (context, status) => Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + ), + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.40, + child: MyButton( + text: 'send'.translation, + borderRadius: 8.0, + // isDisabled: tb.topUpAmount.value < 100, + inProgress: status == TaskStatus.Loading, + onTap: () async { + debugPrint('uploadBill'); + AppUserManager.of(context).uploadBill(context, tb.state.file.value); + }, + height: 48.adaptedPx(), + ), + ), + ), + ), + + Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: RichText( + text: new TextSpan( + text: '* ', + style: new TextStyle( + color: Colors.red, + fontWeight: FontWeight.w500, + fontSize: 12.adaptedPx(), + ), + children: [ + new TextSpan( + text: 'reminderInfo'.translation, + style: new TextStyle( + fontWeight: FontWeight.w400, + color: Colors.black, + fontSize: 14.adaptedPx(), + ), + ), + ], + ), + ), + ), + ], + ), + ), + ), + ); + } +} + +class InfoCard extends StatelessWidget { + final String header; + final String content; + + const InfoCard({ + Key? key, + required this.header, + required this.content, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + width: double.infinity, + decoration: BoxDecoration( + border: Border.all( + color: Color(0xFFF2F6FF), + ), + ), + child: Column( + children: [ + Container( + padding: EdgeInsets.all(16.adaptedPx()), + color: Color(0xFFF2F6FF), + child: Center( + child: Text( + header, + style: new TextStyle( + color: Colors.black, + fontWeight: FontWeight.w400, + fontSize: 14.adaptedPx(), + ), + ), + ), + ), + Container( + color: Colors.white, + padding: EdgeInsets.all(16.adaptedPx()), + child: Center( + child: Text( + content, + style: new TextStyle( + color: Colors.black, + fontWeight: FontWeight.w400, + fontSize: 14.adaptedPx(), + ), + ), + ), + ) + ], + ), + ); + } +} diff --git a/lib/new/screens/top_up_balance/controller.dart b/lib/new/screens/top_up_balance/controller.dart new file mode 100644 index 0000000..c0ec17e --- /dev/null +++ b/lib/new/screens/top_up_balance/controller.dart @@ -0,0 +1,93 @@ +import 'package:birzha/new/models/bank.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:file_picker/file_picker.dart' as picker; + +import '../../api/bank.dart'; +import 'state.dart'; + +class BalanceController extends GetxController { + final state = TopUpBalanceState(); + + @override + void onInit() { + getBankTypes(); + super.onInit(); + } + + @override + void onClose() { + state.balanceTopUpCtrl.dispose(); + super.onClose(); + } + + void onBankChange(BankType? model) { + debugPrint('onShippingRateChange'); + state.selectedBank.value = model; + update(); + } + + void onChange(String value) { + state.topUpAmount.value = double.tryParse(value.trim()) ?? 0.0; + update(); + } + + void resetFile() { + state.file.value = null; + update(); + } + + Future getBankInfo() async { + if (state.bankInfo.value != null) return; + + state.hasErrorBankInfo.value = false; + state.isLoadingBankInfo.value = true; + final result = await BankApi.getBankInfo(); + + if (result == null) { + state.hasErrorBankInfo.value = true; + state.isLoadingBankInfo.value = false; + update(); + return; + } + + state.bankInfo.value = result; + + state.isLoadingBankInfo.value = false; + update(); + } + + Future getBankTypes() async { + if (state.banks.isNotEmpty) return; + + state.hasErrorBankType.value = false; + state.isLoadingBankType.value = true; + final result = await BankApi.getBankTypes(); + + if (result == null) { + state.hasErrorBankType.value = true; + state.isLoadingBankType.value = false; + update(); + return; + } + + state.banks.addAll(result); + + state.selectedBank.value = state.banks.first; + + state.isLoadingBankType.value = false; + update(); + } + + Future uploadFile() async { + debugPrint('uploadFile'); + var fileResult = await picker.FilePicker.platform.pickFiles( + type: picker.FileType.custom, + allowedExtensions: ['pdf', 'png', 'jpg', 'jpeg', 'JPG', 'PNG'], + ); + if (fileResult?.files.isNotEmpty ?? false) { + state.file.value = fileResult?.files.first; + update(); + } + } +} diff --git a/lib/new/screens/top_up_balance/online_top_up_screen.dart b/lib/new/screens/top_up_balance/online_top_up_screen.dart new file mode 100644 index 0000000..bd09531 --- /dev/null +++ b/lib/new/screens/top_up_balance/online_top_up_screen.dart @@ -0,0 +1,239 @@ +import 'package:birzha/components/actionIcons/searchicon.dart'; +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/new/global/full_width_button.dart'; +import 'package:birzha/new/models/bank.dart'; +import 'package:birzha/new/themes/colors.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../components/button.dart'; +import '../../../components/categoryNameWidget.dart'; +import '../../../components/indicator.dart'; +import '../../../constants.dart'; +import '../../../core/manager/manager.dart'; +import '../../../models/user/userManager.dart'; +import '../../global/form_field_decoration.dart'; +import 'bank_top_up_screen.dart'; +import 'controller.dart'; + +class OnlineTopUpBalance extends StatelessWidget { + @override + Widget build(BuildContext context) { + return GetBuilder( + init: BalanceController(), + builder: (tb) => BaseWidget( + // color: Theme.of(context).scaffoldBackgroundColor, + color: ThemeColor.white, + appBar: BaseAppBar( + title: 'topUpBalance'.translation, + after: [SearchIcon()], + goBack: () { + Navigator.of(context).pop(); + }, + ), + body: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: CategoryNameWidget( + categoryName: 'topUpBalance'.translation, + ), + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: RichText( + text: new TextSpan( + text: 'selectPaymentMethod'.translation, + style: new TextStyle( + color: Colors.black, + fontWeight: FontWeight.w500, + fontSize: 14.adaptedPx(), + ), + children: [ + new TextSpan( + text: ' *', + style: new TextStyle( + fontWeight: FontWeight.w400, + color: Colors.red, + fontSize: 12.adaptedPx(), + ), + ), + ], + ), + ), + ), + Padding( + padding: EdgeInsets.symmetric( + // vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: FullWidthButton( + callback: () {}, + title: 'payOnline'.translation, + ), + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: FullWidthButton( + callback: () { + tb.getBankInfo(); + Navigator.of(context).push(MaterialPageRoute(builder: (_) => BankTopUpBalance())); + }, + title: 'bankTransfer'.translation, + btnColor: Color(0xFFF2F6FF), + txtColor: ThemeColor.mainColor, + ), + ), + SizedBox(height: 16.adaptedPx()), + Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + ), + child: RichText( + text: new TextSpan( + text: 'selectBank'.translation, + style: new TextStyle( + color: Colors.black, + fontWeight: FontWeight.w500, + fontSize: 14.adaptedPx(), + ), + children: [ + new TextSpan( + text: ' *', + style: new TextStyle( + fontWeight: FontWeight.w400, + color: Colors.red, + fontSize: 12.adaptedPx(), + ), + ), + ], + ), + ), + ), + tb.state.isLoadingBankType.value + ? Center(child: Indicator(size: 0.7.adaptedPx())) + : tb.state.hasErrorBankType.value + ? Center(child: Text('errorOccurred'.translation)) + : Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + vertical: 8.adaptedPx(), + ), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: ShapeDecoration( + shape: RoundedRectangleBorder( + side: BorderSide(color: ThemeColor.colorE2E2E2), + borderRadius: BorderRadius.all(Radius.circular(5.0)), + ), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + isExpanded: true, + borderRadius: BorderRadius.circular(16), + value: tb.state.selectedBank.value, + items: tb.state.banks.map( + (BankType value) { + return DropdownMenuItem( + value: value, + child: Text( + value.name, + // style: AppTheme.selectedTxtStyle, + ), + ); + }, + ).toList(), + onChanged: (newValue) => tb.onBankChange(newValue), + ), + ), + ), + ), + SizedBox(height: 16.adaptedPx()), + Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + ), + child: RichText( + text: new TextSpan( + text: 'transferAmount'.translation, + style: new TextStyle( + color: Colors.black, + fontWeight: FontWeight.w500, + fontSize: 14.adaptedPx(), + ), + children: [ + new TextSpan( + text: ' *', + style: new TextStyle( + fontWeight: FontWeight.w400, + color: Colors.red, + fontSize: 12.adaptedPx(), + ), + ), + ], + ), + ), + ), + Padding( + // padding: const EdgeInsets.all(8), + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + vertical: 8.adaptedPx(), + ), + child: MyTextFormField( + label: 'transferAmount'.translation, + controller: tb.state.balanceTopUpCtrl, + hintText: 'enterAmount'.translation, + onChangeCallback: (value) => tb.onChange(value), + ), + ), + ManagerSelector( + onUpdate: () {}, + selector: (context, manager) => manager.getStatusByKey('balanceUp'), + shouldRebuild: (prev, next) => prev != next, + builder: (context, status) => Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.40, + child: MyButton( + text: 'send'.translation, + borderRadius: 8.0, + isDisabled: tb.state.topUpAmount.value < 1, + inProgress: status == TaskStatus.Loading, + onTap: () async { + debugPrint('balanceUp'); + if (tb.state.topUpAmount.value >= 1) + AppUserManager.of(context).balanceUp( + context, + tb.state.selectedBank.value!.cardType, + tb.state.topUpAmount.value, + ); + }, + height: 48.adaptedPx(), + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/new/screens/top_up_balance/state.dart b/lib/new/screens/top_up_balance/state.dart new file mode 100644 index 0000000..cdf32ed --- /dev/null +++ b/lib/new/screens/top_up_balance/state.dart @@ -0,0 +1,31 @@ +import 'package:birzha/new/models/bank.dart'; +import 'package:birzha/new/models/bank_info.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:file_picker/file_picker.dart' as picker; + +class TopUpBalanceState { + // List banks = [ + // new BankType( name: 'Altyn asyr karty', cardType: 'halkbank'), + // new BankType( name: 'Rysgal bank', cardType: 'rysgal'), + // new BankType( name: 'Senagat bank', cardType: 'senagat'), + // ]; + + // bank type + RxBool hasErrorBankType = false.obs; + RxBool isLoadingBankType = false.obs; + RxList banks = [].obs; + + TextEditingController balanceTopUpCtrl = new TextEditingController(); + RxDouble topUpAmount = 0.0.obs; + + Rxn file = Rxn(); + + Rxn selectedBank = Rxn(); + + // Bank info + RxBool hasErrorBankInfo = false.obs; + RxBool isLoadingBankInfo = false.obs; + + Rxn bankInfo = Rxn(); +} diff --git a/lib/new/themes/colors.dart b/lib/new/themes/colors.dart new file mode 100644 index 0000000..a3ad4a5 --- /dev/null +++ b/lib/new/themes/colors.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class ThemeColor { + static const Color mainColor = Color(0xFF003197); + static const Color grey = Colors.grey; + static const Color white = Color(0xFFFFFFFF); + static const Color colorEFF0F4 = Color(0xFFEFF0F4); + static const Color colorE2E2E2 = Color(0xFFE2E2E2); + static const Color colorE5E5E5 = Color(0xFFE5E5E5); + static const Color color717278 = Color(0xFF717278); + static const Color color3A3A3A = Color(0xFF73A3A3A); + static const Color colorC9C9C9 = Color(0xFFC9C9C9); + static const Color black = Color(0xFF000000); + static const Color cursorColor = Colors.grey; +} diff --git a/lib/new/utils/capitalize.dart b/lib/new/utils/capitalize.dart new file mode 100644 index 0000000..26ad4b7 --- /dev/null +++ b/lib/new/utils/capitalize.dart @@ -0,0 +1,5 @@ +extension StringExtension on String { + String capitalizeFirstLetter() { + return "${this[0].toUpperCase()}${this.substring(1).toLowerCase()}"; + } +} diff --git a/lib/new/utils/constants.dart b/lib/new/utils/constants.dart new file mode 100644 index 0000000..d2181ca --- /dev/null +++ b/lib/new/utils/constants.dart @@ -0,0 +1,3 @@ +class Constants { + static const BASE_URL = 'https://tmex.gov.tm/'; +} diff --git a/lib/new/utils/http_util.dart b/lib/new/utils/http_util.dart new file mode 100644 index 0000000..031fbf8 --- /dev/null +++ b/lib/new/utils/http_util.dart @@ -0,0 +1,328 @@ +import 'dart:async'; + +import 'package:birzha/models/user/userManager.dart'; +import 'package:dio/dio.dart'; +import 'package:get/get.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +import 'constants.dart'; + +class HttpUtil { + static HttpUtil _instance = HttpUtil._internal(); + + factory HttpUtil() => _instance; + + late Dio dio; + CancelToken cancelToken = new CancelToken(); + + HttpUtil._internal() { + BaseOptions options = new BaseOptions( + baseUrl: Constants.BASE_URL, + connectTimeout: 100000, + receiveTimeout: 500000, + headers: {}, + contentType: 'application/json; charset=utf-8', + ); + + dio = new Dio(options); + + // CookieJar cookieJar = CookieJar(); + // dio.interceptors.add(CookieManager(cookieJar)); + + dio.interceptors.add(InterceptorsWrapper( + onRequest: (options, handler) { + // Do something before request is sent + return handler.next(options); //continue + // If you want to complete the request and return some custom data, + // you can resolve a Response object `handler.resolve(response)`. + // In this way, the request will be terminated, the upper then will be called, + // and the data returned in then will be your custom response. + // If you want to terminate the request and trigger an error, + // you can return a `DioError` object, such as `handler.reject(error)`, + // In this way, the request will be aborted and an exception will be triggered, + // and the upper catchError will be called + }, + onResponse: (response, handler) { + // Do something with response data + return handler.next(response); // continue + // If you want to terminate the request and trigger an error, you can reject a `DioError` object, such as `handler.reject(error)`, + // In this way, the request will be aborted and an exception will be triggered, and the upper-level catchError will be called. + }, + onError: (DioError e, handler) { + // Do something with response error + ErrorEntity eInfo = createErrorEntity(e); + + switch (eInfo.code) { + case 401: // No permission to log in again + // navigateToLoginScreen(); + // setLoginStatus(false); + break; + default: + } + return handler.next(e); //continue + }, + )); + } + +/* + + Error unified processing + */ + // error message + ErrorEntity createErrorEntity(DioError error) { + switch (error.type) { + case DioErrorType.cancel: + return ErrorEntity(code: -1, message: 'Request cancellation'); + case DioErrorType.connectTimeout: + return ErrorEntity(code: -1, message: 'Connection timed out'); + case DioErrorType.sendTimeout: + return ErrorEntity(code: -1, message: 'Request timed out'); + case DioErrorType.receiveTimeout: + return ErrorEntity(code: -1, message: 'Response timeout'); + case DioErrorType.response: + { + try { + int? errCode = error.response?.statusCode; + // String errMsg = error.response.statusMessage; + // return ErrorEntity(code: errCode, message: errMsg); + switch (errCode) { + case 400: + return ErrorEntity(code: errCode, message: 'Request syntax error'); + case 401: + return ErrorEntity(code: errCode, message: 'Permission denied'); + case 403: + return ErrorEntity(code: errCode, message: 'Server refused to execute'); + case 404: + return ErrorEntity(code: errCode, message: 'Can not reach server'); + case 405: + return ErrorEntity(code: errCode, message: 'Request method is forbidden'); + case 500: + return ErrorEntity(code: errCode, message: 'Server internal error'); + case 502: + return ErrorEntity(code: errCode, message: 'Invalid request'); + case 503: + return ErrorEntity(code: errCode, message: 'Server hung up'); + case 505: + return ErrorEntity(code: errCode, message: 'Does not support HTTP protocol request'); + default: + { + // return ErrorEntity(code: errCode, message: 'Unknown error'); + return ErrorEntity( + code: errCode, + message: error.response?.statusMessage, + ); + } + } + } on Exception catch (_) { + // showSnack('error'.tr, 'internet_conn_err'.tr, SnackType.ERROR); + return ErrorEntity(code: -1, message: 'Unknown error'); + } + } + default: + { + return ErrorEntity(code: -1, message: error.message); + } + } + } + + /* + Cancel Request + The same cancel token can be used for multiple requests. When a cancel token is cancelled, + all requests using the cancel token will be cancelled. So the parameters are optional + */ + void cancelRequests(CancelToken token) { + token.cancel('cancelled'); + } + + Future> getAuthorizationHeader() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + Map headers; + String? accessToken = prefs.getString('token'); + headers = { + 'Authorization': 'Bearer $accessToken', + 'Accept': 'application/json', + 'Content-Type': 'application/json', + }; + return headers; + } + + /// restful get + /// refresh false + /// noCache true + /// list false + /// cacheKey + /// cacheDisk + Future get({ + required String path, + Map? queryParameters, + Options? options, + bool refresh = false, + bool noCache = false, + bool list = false, + String cacheKey = '', + bool cacheDisk = false, + }) async { + Options requestOptions = options ?? Options(); + if (requestOptions.extra == null) { + requestOptions.extra = Map(); + } + requestOptions.extra!.addAll({ + 'refresh': refresh, + 'noCache': noCache, + 'list': list, + 'cacheKey': cacheKey, + 'cacheDisk': cacheDisk, + }); + requestOptions.headers = requestOptions.headers ?? {}; + Map? authorization = await getAuthorizationHeader(); + requestOptions.headers!.addAll(authorization); + + var response = await dio.get(path, queryParameters: queryParameters, options: requestOptions, cancelToken: cancelToken); + return response.data; + } + + /// restful post + Future post( + String path, { + dynamic data, + Map? queryParameters, + Options? options, + }) async { + Options requestOptions = options ?? Options(); + requestOptions.headers = requestOptions.headers ?? {}; + Map? authorization = await getAuthorizationHeader(); + requestOptions.headers!.addAll(authorization); + var response = await dio.post( + path, + data: data, + queryParameters: queryParameters, + options: requestOptions, + cancelToken: cancelToken, + ); + return response.data; + } + + /// restful put + Future put( + String path, { + dynamic data, + Map? queryParameters, + Options? options, + }) async { + Options requestOptions = options ?? Options(); + requestOptions.headers = requestOptions.headers ?? {}; + Map? authorization = await getAuthorizationHeader(); + requestOptions.headers!.addAll(authorization); + var response = await dio.put( + path, + data: data, + queryParameters: queryParameters, + options: requestOptions, + cancelToken: cancelToken, + ); + return response.data; + } + + /// restful patch + Future patch( + String path, { + dynamic data, + Map? queryParameters, + Options? options, + }) async { + Options requestOptions = options ?? Options(); + requestOptions.headers = requestOptions.headers ?? {}; + Map? authorization = await getAuthorizationHeader(); + requestOptions.headers!.addAll(authorization); + var response = await dio.patch( + path, + data: data, + queryParameters: queryParameters, + options: requestOptions, + cancelToken: cancelToken, + ); + return response.data; + } + + /// restful delete + Future delete( + String path, { + dynamic data, + Map? queryParameters, + Options? options, + }) async { + Options requestOptions = options ?? Options(); + requestOptions.headers = requestOptions.headers ?? {}; + Map? authorization = await getAuthorizationHeader(); + requestOptions.headers!.addAll(authorization); + var response = await dio.delete( + path, + data: data, + queryParameters: queryParameters, + options: requestOptions, + cancelToken: cancelToken, + ); + return response.data; + } + + /// restful post form +/*Future postForm( + String path, { + required Map data, + Map? queryParameters, + Options? options, + }) async { + Options requestOptions = options ?? Options(); + requestOptions.headers = requestOptions.headers ?? {}; + Map? authorization = getAuthorizationHeader(); + requestOptions.headers!.addAll(authorization); + var response = await dio.post( + path, + data: FormData.fromMap(data), + queryParameters: queryParameters, + options: requestOptions, + cancelToken: cancelToken, + ); + return response.data; + }*/ + + /// restful post Stream +/*Future postStream( + String path, { + dynamic data, + int dataLength = 0, + Map? queryParameters, + Options? options, + }) async { + Options requestOptions = options ?? Options(); + requestOptions.headers = requestOptions.headers ?? {}; + Map? authorization = getAuthorizationHeader(); + if (authorization != null) { + requestOptions.headers!.addAll(authorization); + } + requestOptions.headers!.addAll({ + Headers.contentLengthHeader: dataLength.toString(), + }); + var response = await dio.post( + path, + data: Stream.fromIterable(data.map((e) => [e])), + queryParameters: queryParameters, + options: requestOptions, + cancelToken: cancelToken, + ); + return response.data; + } */ +} + +// Exception handling +class ErrorEntity implements Exception { + int? code; + String? message; + + ErrorEntity({this.code, this.message}); + + @override + String toString() { + if (message == null) return 'Exception'; + return 'Exception: code $code, $message'; + } +} diff --git a/lib/new/utils/locale.dart b/lib/new/utils/locale.dart new file mode 100644 index 0000000..72a48a6 --- /dev/null +++ b/lib/new/utils/locale.dart @@ -0,0 +1,9 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +Future getLocale() async { + SharedPreferences prefs = await SharedPreferences.getInstance(); + final String locale = prefs.getString('language') ?? 'tm'; + if (locale == 'tk') return 'tm'; + + return locale; +} diff --git a/lib/screens/auth/login.dart b/lib/screens/auth/login.dart new file mode 100644 index 0000000..598885a --- /dev/null +++ b/lib/screens/auth/login.dart @@ -0,0 +1,158 @@ +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/auth/register.dart'; +import 'package:birzha/screens/first_page.dart'; +import 'package:birzha/services/helpers.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/components/abstractForm.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:flutter/scheduler.dart'; + +class LoginScreen extends StatefulWidget { + LoginScreen({Key? key}) : super(key: key); + + @override + _LoginScreenState createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State with AbstractFormState, ManagerObserverMixin { + SampleUser sampleUser = SampleUser(data: {}); + + TaskStatus status = TaskStatus.None; + + @override + bool get includeBackButton => false; + + @override + List get before => [ + Text( + 'login'.translation, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontWeight: FontWeight.bold, + fontSize: AppConstants.h1FontSize, + ), + ), + SizedBox(height: 5.adaptedPx()), + Container( + margin: EdgeInsets.symmetric(vertical: 15.adaptedPx()), + child: Text.rich(TextSpan(children: [ + for (var word in 'loginText'.translation.split(' ')) + word == '@' + ? (TextSpan( + style: Theme.of(context).primaryTextTheme.bodyText2!.copyWith( + color: Theme.of(context).accentColor, + ), + text: 'link'.translation + ' ', + recognizer: TapGestureRecognizer() + ..onTap = () { + linkLauncher(AppConstants.passwordReset); + })) + : TextSpan(text: word + ' '), + ])), + ) + ]; + + @override + List get after => [ + SizedBox( + height: 15.adaptedPx(), + ), + Row( + children: [ + Text('noAccount'.translation, style: TextStyle(fontWeight: FontWeight.w300)), + SizedBox(width: 5.adaptedPx()), + GestureDetector( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => RegisterScreen()), + ); + }, + child: Text( + 'register'.translation, + style: TextStyle(color: Theme.of(context).accentColor, fontWeight: FontWeight.w600), + ), + ) + ], + ), + SizedBox( + height: 15.adaptedPx(), + ) + ]; + + @override + List get inputs => sampleUser.loginMetaData; + + @override + String get title => ''; + + @override + String get buttonLabel => 'login'.translation; + + @override + bool get buttonIsLoading => status == TaskStatus.Loading; + + @override + String keyAfterFilter(String key, String input) { + return key; + } + + @override + String valueAfterFilter(String key, String input) { + if (key == 'dial_code') { + return input.split(' ').last; + } + return input; + } + + @override + void act() { + sampleUser.jSON = {...editedData}; + AppUserManager.of(context).login(context, sampleUser); + } + + @override + void dispose() { + super.dispose(); + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + manager.destroyTask(_keyForTask); + }); + } + + @override + TaskStatus selector(BuildContext context, AppUserManager someManager) { + return someManager.getStatusByKey(_keyForTask); + } + + @override + bool shouldUpdateListener(TaskStatus old, TaskStatus newOne) { + return old != newOne; + } + + @override + void updateListener() { + if (mounted) + setState(() { + status = AppUserManager.of(context).getStatusByKey(_keyForTask); + if (status == TaskStatus.Success) { + Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (_) => FirstPage()), (route) => false); + } + }); + } + + @override + void initState() { + super.initState(); + } + + @override + void updateScreen() { + debugPrint('updateScreen'); + } +} + +const _keyForTask = 'login'; diff --git a/lib/screens/auth/logout.dart b/lib/screens/auth/logout.dart new file mode 100644 index 0000000..9fa9755 --- /dev/null +++ b/lib/screens/auth/logout.dart @@ -0,0 +1,85 @@ +import 'dart:async'; + +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/models/exceptions/exception.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/first_page.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; + +class Logout extends StatefulWidget { + Logout({Key? key}) : super(key: key); + + @override + _LogoutState createState() => _LogoutState(); +} + +class _LogoutState extends State with ManagerObserverMixin?> { + StreamSubscription? _subscription; + + @override + selector(BuildContext context, AppUserManager someManager) { + return someManager.getTaskByKey('logout'); + } + + @override + bool shouldUpdateListener(oldVal, newVal) { + return oldVal != newVal; + } + + @override + void updateListener() async { + await _subscription?.cancel(); + _subscription = AppUserManager.of(context).taskStateOnly('logout')?.listen((event) { + var navigatorContext = Navigator.of(context, rootNavigator: true).context; + if (event.status == TaskStatus.Success && mounted) { + Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (_) => FirstPage()), (route) => false); + } else if (event.status == TaskStatus.Error) { + AppExceptions.exceptionHandler(navigatorContext, event.errorTrace); + Navigator.of(context).pop(); + } + }); + } + + @override + void initState() { + super.initState(); + manager.logout(); + updateListener(); + } + + @override + void dispose() { + _subscription?.cancel().then((value) { + manager.destroyTask('logout'); + }); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + alignment: Alignment.center, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Center( + child: Indicator(), + ), + SizedBox( + height: 30.adaptedPx(), + ), + Text( + 'logging_out'.translation, + style: TextStyle(fontSize: 17.adaptedPx(), fontWeight: FontWeight.w300, color: Theme.of(context).accentColor), + ) + ], + ), + ), + ); + } +} diff --git a/lib/screens/auth/register.dart b/lib/screens/auth/register.dart new file mode 100644 index 0000000..4f1e3a2 --- /dev/null +++ b/lib/screens/auth/register.dart @@ -0,0 +1,109 @@ +import 'package:birzha/components/abstractForm.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/first_page.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; + +class RegisterScreen extends StatefulWidget { + RegisterScreen({Key? key}) : super(key: key); + + @override + _RegisterScreenState createState() => _RegisterScreenState(); +} + +class _RegisterScreenState extends State + with AbstractFormState, ManagerObserverMixin { + SampleUser sampleUser = SampleUser(data: {}); + + TaskStatus status = TaskStatus.None; + + @override + void initState() { + super.initState(); + } + + @override + List get before => [ + Text( + 'register'.translation, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontWeight: FontWeight.bold, + fontSize: AppConstants.h1FontSize, + ), + ), + SizedBox(height: 5.adaptedPx()), + ]; + + @override + List get after => []; + + @override + List get inputs => sampleUser.registerMetaData; + + @override + String get title => ''; + + @override + String get buttonLabel => 'register'.translation; + + @override + bool get buttonIsLoading => status == TaskStatus.Loading; + + @override + String keyAfterFilter(String key, String input) { + return key; + } + + @override + String valueAfterFilter(String key, String input) { + if (key == 'dial_code') { + return input.split(' ').last; + } + + return input; + } + + @override + void act() { + sampleUser.jSON = {...editedData}; + AppUserManager.of(context).register(context, sampleUser); + } + + @override + void dispose() { + super.dispose(); + } + + @override + void updateScreen() { + debugPrint('updateScreen'); + } + + @override + TaskStatus selector(BuildContext context, AppUserManager someManager) { + return someManager.getStatusByKey(_keyForTask); + } + + @override + bool shouldUpdateListener(TaskStatus old, TaskStatus newOne) { + return old != newOne; + } + + @override + void updateListener() { + if (mounted) + setState(() { + status = AppUserManager.of(context).getStatusByKey(_keyForTask); + if (status == TaskStatus.Success) { + Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (_) => FirstPage()), (route) => false); + } + }); + } +} + +const _keyForTask = 'register'; diff --git a/lib/screens/auth/smsVerification.dart b/lib/screens/auth/smsVerification.dart new file mode 100644 index 0000000..13c7c23 --- /dev/null +++ b/lib/screens/auth/smsVerification.dart @@ -0,0 +1,99 @@ +import 'package:birzha/components/abstractForm.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; +import 'package:birzha/core/manager/manager.dart'; + +class SmsVerificationScreen extends StatefulWidget { + const SmsVerificationScreen({Key? key}) : super(key: key); + + @override + _SmsVerificationScreenState createState() => _SmsVerificationScreenState(); +} + +class _SmsVerificationScreenState extends State + with AbstractFormState, ManagerObserverMixin { + TaskStatus status = TaskStatus.None; + + late User user; + + @override + List get before => [ + Text( + 'smsCodeSent'.translation, + ), + ]; + + @override + void initState() { + user = AppUserManager.of(context).dataSync; + super.initState(); + } + + @override + void act() { + var code = editedData.values.first; + AppUserManager.of(context).checkCode(context, code); + } + + @override + bool get buttonIsLoading => status == TaskStatus.Loading; + + @override + String get buttonLabel => 'check'.translation; + + @override + List get inputs => user.smsVerificationMetaData; + + @override + String keyAfterFilter(String key, String input) { + return key; + } + + @override + String get title => 'verifyPhone'.translation; + + @override + String valueAfterFilter(String key, String input) { + return input; + } + + @override + TaskStatus selector(BuildContext context, AppUserManager someManager) { + return someManager.getStatusByKey(_keyForTask); + } + + @override + bool shouldUpdateListener(TaskStatus oldVal, TaskStatus newVal) { + return oldVal != newVal; + } + + @override + void updateListener() { + if (mounted) + setState(() { + status = AppUserManager.of(context).getStatusByKey(_keyForTask); + if (status == TaskStatus.Success && mounted) { + Navigator.of(context).pop(); + } + }); + } + + @override + void updateScreen() { + debugPrint('updateScreen'); + } + + @override + void dispose() { + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + manager.destroyTask(_keyForTask); + }); + super.dispose(); + } +} + +const _keyForTask = 'sms_verify'; diff --git a/lib/screens/auth/update.dart b/lib/screens/auth/update.dart new file mode 100644 index 0000000..814cdff --- /dev/null +++ b/lib/screens/auth/update.dart @@ -0,0 +1,142 @@ +import 'package:birzha/components/abstractForm.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/services/modals.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; + +class UpdateScreen extends StatefulWidget { + UpdateScreen({Key? key}) : super(key: key); + + @override + _UpdateScreenState createState() => _UpdateScreenState(); +} + +class _UpdateScreenState extends State with AbstractFormState, ManagerObserverMixin { + SampleUser sampleUser = SampleUser(data: {}); + + TaskStatus status = TaskStatus.None; + + @override + Widget textField(TextInputMetaData meta, TextEditingController controller) { + final bool isPhoneVerified = AppUserManager.of(context).dataSync.isPhoneVerified; + final bool isEmailVerified = AppUserManager.of(context).dataSync.isEmailVerified; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + super.textField(meta, controller), + if (meta.key == 'username' && !isPhoneVerified) + new RichText( + text: new TextSpan( + text: '*', + style: new TextStyle(color: Colors.red), + children: [ + new TextSpan( + text: 'verifyPhoneWarning'.translation, + style: new TextStyle( + fontWeight: FontWeight.w400, + color: Colors.black, + fontSize: 12.adaptedPx(), + ), + ), + ], + ), + ), + if (meta.key == 'email' && !isEmailVerified) + new RichText( + text: new TextSpan( + text: '*', + style: new TextStyle(color: Colors.red), + children: [ + new TextSpan( + text: 'verifyEmailWarning'.translation, + style: new TextStyle( + fontWeight: FontWeight.w400, + color: Colors.black, + fontSize: 12.adaptedPx(), + ), + ), + ], + ), + ), + ], + ); + } + + @override + List get before => []; + + @override + List get after => []; + + @override + List get inputs => sampleUser.updateMetaData; + + @override + String get title => 'personal_data'.translation; + + @override + String get buttonLabel => 'save_changes'.translation; + + @override + bool get buttonIsLoading => status == TaskStatus.Loading; + + @override + String keyAfterFilter(String key, String input) { + return key; + } + + @override + String valueAfterFilter(String key, String input) { + return input; + } + + @override + void act() { + sampleUser.jSON = {...editedData}..removeWhere((key, value) => value.isEmpty); + AppUserManager.of(context).update(context, sampleUser); + } + + @override + void initState() { + super.initState(); + launchControllers(); + } + + @override + void launchControllers() { + super.launchControllers(); + for (var i = 0; i < controllers.length; i++) controllers[i].text = AppUserManager.of(context).dataSync.jSON[inputs[i].key] ?? ""; + } + + @override + TaskStatus selector(BuildContext context, AppUserManager someManager) { + return someManager.getStatusByKey(_keyForTask); + } + + @override + bool shouldUpdateListener(TaskStatus old, TaskStatus newOne) { + return old != newOne; + } + + @override + void updateScreen() { + debugPrint('updateScreen'); + launchControllers(); + setState(() {}); + } + + @override + void updateListener() { + if (mounted) + setState(() { + status = AppUserManager.of(context).getStatusByKey(_keyForTask); + if (status == TaskStatus.Success) showSnackBar(context, content: 'dataIsUpdated'.translation); + }); + } +} + +const _keyForTask = 'update'; diff --git a/lib/screens/details.dart b/lib/screens/details.dart new file mode 100644 index 0000000..42b70ad --- /dev/null +++ b/lib/screens/details.dart @@ -0,0 +1,409 @@ +import 'dart:ui'; + +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/button.dart'; +import 'package:birzha/components/categoryNameWidget.dart'; +import 'package:birzha/components/contactInfo.dart'; +import 'package:birzha/components/dialog.dart'; +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/components/productBuilder.dart'; +import 'package:birzha/components/refreshButton.dart'; +import 'package:birzha/components/slider.dart'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/models/products/my_product.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/personalCabinet/addPost/step1.dart'; +import 'package:birzha/screens/personalCabinet/messages/personalChat.dart'; +import 'package:birzha/services/helpers.dart'; +import 'package:birzha/services/streamFetchService.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter_html/flutter_html.dart'; +import 'package:birzha/core/manager/manager.dart'; + +class ProductDetails extends StatefulWidget { + final Product product; + + const ProductDetails({ + Key? key, + required this.product, + }) : super(key: key); + + @override + _ProductDetailsState createState() => _ProductDetailsState(); +} + +class _ProductDetailsState extends State with StreamControlledMixin { + late Product product; + bool _isError = false; + + @override + void initState() { + super.initState(); + product = widget.product.copy; + connect(context); + } + + @override + Widget build(BuildContext context) { + return BaseWidget( + color: Theme.of(context).chipTheme.backgroundColor, + appBar: BaseAppBar( + goBack: () { + Tabnavigator.backDispatcher(context); + }, + title: product.name, + ), + body: isLoading + ? Center( + child: Indicator(size: 0.7.adaptedPx()), + ) + : _isError + ? RefreshButton( + onTap: () { + connect(context); + }, + ) + : ListView( + children: [ + if (product.images.isNotEmpty) + PostImageSlider( + images: [...product.images], + fit: BoxFit.cover, + ), + Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: CategoryNameWidget(categoryName: product.name), + ), + SizedBox( + height: 25.adaptedPx(), + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + ), + ), + if (product is MyProduct && (product as MyProduct).statusNotes.isNotEmpty) + Container( + padding: EdgeInsets.symmetric(vertical: 25.adaptedPx(), horizontal: 15.adaptedPx()), + width: 30.adaptedPx(), + color: Theme.of(context).scaffoldBackgroundColor, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(left: 8.adaptedPx(), right: 8.adaptedPx(), bottom: 12.adaptedPx()), + child: Text( + 'statusNote'.translation, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontWeight: FontWeight.w600, + fontSize: AppConstants.h1FontSize, + ), + ), + ), + Padding( + padding: EdgeInsets.only(left: 8.adaptedPx(), right: 8.adaptedPx(), bottom: 12.adaptedPx()), + child: Text((product as MyProduct).statusNotes)), + ], + ), + ), + Container( + padding: EdgeInsets.symmetric(vertical: 25.adaptedPx(), horizontal: 15.adaptedPx()), + width: 30.adaptedPx(), + color: Theme.of(context).chipTheme.backgroundColor, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(left: 8.adaptedPx(), right: 8.adaptedPx(), bottom: 12.adaptedPx()), + child: Text( + 'description'.translation, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontWeight: FontWeight.w600, + fontSize: AppConstants.h1FontSize, + ), + ), + ), + Padding( + padding: EdgeInsets.only(left: 8.adaptedPx(), right: 8.adaptedPx(), bottom: 12.adaptedPx()), + child: Html( + data: product.description, + customRender: AppConstants.htmlCustomRenderer(context), + style: AppConstants.htmlContentStyle(context), + )), + ], + ), + ), + for (var i = 0; i < product.characteristics.length; i++) + DetailsScreenRow( + name: product.characteristics[i].translatedLabel, + value: product.characteristics[i].value, + backgroundColor: i.isOdd ? Theme.of(context).chipTheme.backgroundColor : null, + ), + if (product.relatedProducts.isNotEmpty) + SizedBox( + height: 25.adaptedPx(), + child: Container( + color: Theme.of(context).scaffoldBackgroundColor, + ), + ), + if (product.vendor != null && product is! MyProduct) + Padding( + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + Expanded( + child: MyButton( + text: 'sellerContact'.translation, + color: Colors.green.shade600, + onTap: () { + showDialog( + context: context, + builder: (context) { + return _ContactDialog( + vendor: product.vendor!, + ); + }); + }, + height: 40.adaptedPx(), + ), + ), + SizedBox(width: AppConstants.horizontalPadding(context) / 2), + if (AppUserManager.of(context, listen: true).dataSync != product.vendor) + Expanded( + child: ManagerSelector( + selector: (context, manager) => manager.getStatusByKey('buy'), + onUpdate: () {}, + shouldRebuild: (prev, next) => prev != next, + builder: (context, taskStatus) => MyButton( + text: 'buyNow'.translation, + onTap: () { + AppUserManager.of(context).buyFromSeller(Navigator.of(context).context, product.vendor!, (chatroom) { + if (mounted) + Navigator.of(context, rootNavigator: true).push(MaterialPageRoute( + builder: (context) => PersonalChat(chatroom: chatroom), + )); + }); + }, + inProgress: taskStatus == TaskStatus.Loading, + height: 40.adaptedPx(), + ), + ), + ), + ], + ), + ) + else if (product is MyProduct && (product as MyProduct).isAbleToEdit) ...[ + Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding( + context, + )), + child: Row( + children: [ + Expanded( + child: ManagerSelector( + selector: (contex, manager) => manager.getStatusByKey('delete_post'), + shouldRebuild: (previous, next) => previous != next, + onUpdate: () { + if (mounted && AppUserManager.of(context).getStatusByKey('delete_post') == TaskStatus.Success) { + Navigator.of(context).pop(true); + } + }, + builder: (context, value) => MyButton( + text: caitalize(MaterialLocalizations.of(context).deleteButtonTooltip), + color: Colors.redAccent, + inProgress: value == TaskStatus.Loading, + onTap: () { + AppUserManager.of(context).deletePost(context, product as MyProduct); + }, + height: 40.adaptedPx(), + ), + ), + ), + SizedBox(width: AppConstants.horizontalPadding(context) / 2), + Expanded( + child: MyButton( + text: 'edit'.translation, + onTap: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => AddBasicInformationScreen(forEditing: product as MyProduct), + )); + }, + height: 40.adaptedPx(), + ), + ), + ], + ), + ), + SizedBox( + height: 10.adaptedPx(), + ), + Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding( + context, + )), + child: Row( + children: [ + Expanded( + child: ManagerSelector( + selector: (contex, manager) => manager.getStatusByKey('publish_post'), + shouldRebuild: (previous, next) => previous != next, + onUpdate: () { + if (mounted && AppUserManager.of(context).getStatusByKey('publish_post') == TaskStatus.Success) { + Navigator.of(context).pop(true); + } + }, + builder: (context, value) => MyButton( + text: 'approve'.translation, + color: Colors.green, + inProgress: value == TaskStatus.Loading, + onTap: () { + AppUserManager.of(context).publishPost(context, product as MyProduct); + }, + height: 40.adaptedPx(), + ), + ), + ), + ], + ), + ) + ], + if (product.relatedProducts.isNotEmpty) + Padding( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + vertical: AppConstants.verticalPadding(context), + ), + child: CategoryNameWidget(categoryName: 'similiarProducts'.translation), + ), + if (product.relatedProducts.isNotEmpty) + Container( + height: AppConstants.productCarouselHeight(context), + width: MediaQuery.of(context).size.width, + child: ListView.separated( + scrollDirection: Axis.horizontal, + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context)), + itemBuilder: (context, index) { + return AspectRatio(aspectRatio: kProductAspectRatio, child: ProductBuilder(product: product.relatedProducts[index])); + }, + separatorBuilder: (_, __) { + return SizedBox(width: AppConstants.horizontalPadding(context) / 2); + }, + itemCount: product.relatedProducts.length), + ), + SizedBox(height: 20.adaptedPx()) + ], + ), + ); + } + + @override + Future Function() get asyncAction => () => product.loadDetails(context); + + @override + void onDataRecived(BuildContext context, void data) { + setState(() {}); + } + + @override + void error(BuildContext context, error) { + setState(() { + _isError = true; + }); + } + + @override + void start(BuildContext context) { + setState(() { + _isError = false; + }); + } + + @override + void dispose() { + cancel(); + super.dispose(); + } +} + +class _ContactDialog extends StatelessWidget { + const _ContactDialog({Key? key, required this.vendor}) : super(key: key); + + final Vendor vendor; + + @override + Widget build(BuildContext context) { + return AppDialog( + title: 'sellerContact'.translation, + child: Column( + children: [ + SizedBox(height: 10.adaptedPx()), + ContactInfo(icon: Icons.person_outline, mainText: 'nsm'.translation + ':', description: [vendor.name, vendor.surname].join(' ')), + SizedBox(height: 25.adaptedPx()), + ContactInfo(icon: Icons.phone_outlined, mainText: 'telephone'.translation + ':', description: vendor.phone), + SizedBox(height: 25.adaptedPx()), + ContactInfo(icon: Icons.mail_outlined, mainText: 'mail'.translation + ':', description: vendor.email), + ], + ), + ); + } +} + +class DetailsScreenRow extends StatelessWidget { + final String name; + final Color? backgroundColor; + final Widget? nextSign; + final Icon? icon; + final String value; + + const DetailsScreenRow({ + Key? key, + required this.name, + this.backgroundColor, + this.nextSign, + this.icon, + required this.value, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Material( + color: backgroundColor ?? Theme.of(context).scaffoldBackgroundColor, + child: InkWell( + child: Container( + alignment: Alignment.center, + padding: EdgeInsets.symmetric(vertical: 26.adaptedPx(), horizontal: 20.adaptedPx()), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Text(name, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontWeight: FontWeight.w400, + )), + SizedBox( + width: 10.adaptedPx(), + ), + Expanded( + child: Align( + alignment: Alignment.centerRight, + child: Text( + value, + style: Theme.of(context).accentTextTheme.headline2!.copyWith(fontWeight: FontWeight.w400), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/first_page.dart b/lib/screens/first_page.dart new file mode 100644 index 0000000..1d0ddef --- /dev/null +++ b/lib/screens/first_page.dart @@ -0,0 +1,18 @@ +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/auth/login.dart'; +import 'package:birzha/screens/primal.dart'; +import 'package:flutter/material.dart'; + +class FirstPage extends StatelessWidget { + const FirstPage({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + debugPrint('FirstPage'); + if (AppUserManager.of(context).dataSync.isRegistered) { + return Primal(); + } else { + return LoginScreen(); + } + } +} diff --git a/lib/screens/home/homeScreen.dart b/lib/screens/home/homeScreen.dart new file mode 100644 index 0000000..cef941c --- /dev/null +++ b/lib/screens/home/homeScreen.dart @@ -0,0 +1,124 @@ +import 'dart:ui'; + +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/categoryNameWidget.dart'; +import 'package:birzha/components/imagePlaceHolder.dart'; +import 'package:birzha/components/postlist.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/core/lazyload/lazyload.dart'; +import 'package:birzha/models/categories/home.dart'; +import 'package:birzha/models/products/product.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/scheduler.dart'; + +class HomeScreen extends StatefulWidget { + @override + State createState() => _HomeScreenState(); +} + +class _HomeScreenState extends State with AutomaticKeepAliveClientMixin { + FetchController controller = FetchController(); + var category = HomeCategory(); + + @override + void initState() { + debugPrint('HomeScreen.initState'); + super.initState(); + SchedulerBinding.instance?.addPostFrameCallback((timeStamp) { + controller.refresh(); + }); + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + super.build(context); + return BaseWidget( + appBar: BaseAppBar.home( + context, + () {}, + ), + color: Theme.of(context).backgroundColor, + body: PostList( + category: category, + before: [ + SliverToBoxAdapter( + child: Padding( + padding: EdgeInsets.symmetric( + vertical: AppConstants.verticalPadding(context), + horizontal: AppConstants.horizontalPadding(context), + ), + child: CategoryNameWidget(categoryName: category.name), + ), + ) + ], + contentPadding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context)), + fetchController: controller, + ), + ); + } + + @override + bool get wantKeepAlive => true; +} + +class HomeScreenButton extends StatelessWidget { + final String? name; + final Color? color; + final void Function() onTap; + final String? iconLink; + + const HomeScreenButton({ + Key? key, + this.iconLink, + required this.name, + this.color, + required this.onTap, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 10.adaptedPx(), vertical: 10.adaptedPx()), + child: InkWell( + onTap: onTap, + hoverColor: Theme.of(context).cardColor, // alternative color dividerColor; + borderRadius: BorderRadius.circular(15.adaptedPx()), + child: Container( + decoration: BoxDecoration(color: Theme.of(context).accentColor.withOpacity(0.1), borderRadius: BorderRadius.circular(10.adaptedPx())), + padding: EdgeInsets.symmetric( + horizontal: 10.adaptedPx(), + vertical: 13.2.adaptedPx(), + ), + child: Row( + children: [ + SizedBox(width: 13.adaptedPx()), + if (iconLink != null) + CachedNetworkImage( + height: 35.adaptedPx(), + width: 35.adaptedPx(), + imageUrl: iconLink!, + placeholder: (_, __) => AppImagePlaceholder(size: 30.adaptedPx()), + errorWidget: (_, __, ___) => AppImagePlaceholder(size: 30.adaptedPx()), + ), + SizedBox(width: 15.adaptedPx()), + Expanded( + child: Text( + name!, + style: Theme.of(context).accentTextTheme.headline2!.copyWith(fontWeight: FontWeight.bold, fontSize: AppConstants.h2FontSize * 0.95), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/masterCategoryScreen.dart b/lib/screens/masterCategoryScreen.dart new file mode 100644 index 0000000..ff7bce4 --- /dev/null +++ b/lib/screens/masterCategoryScreen.dart @@ -0,0 +1,85 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/categoryBuilder.dart'; +import 'package:birzha/components/fakeSearchBar.dart'; +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/components/refreshButton.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/models/categories/products/pure.dart'; +import 'package:birzha/models/categories/products/remote.dart'; +import 'package:birzha/new/themes/colors.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/lazyload/lazyload.dart'; + +class MasterCategoryScreen extends StatefulWidget { + const MasterCategoryScreen({Key? key}) : super(key: key); + + @override + _MasterCategoryScreenState createState() => _MasterCategoryScreenState(); +} + +class _MasterCategoryScreenState extends State with AutomaticKeepAliveClientMixin { + final category = MasterProductsRemoteCategory(); + + @override + Widget build(BuildContext context) { + super.build(context); + return BaseWidget( + appBar: BaseAppBar( + color: ThemeColor.white, + goBack: () {}, + customChild: FakeSearchBar( + route: 'category', + ), + ), + color: Theme.of(context).backgroundColor, + body: LazyLoadView( + data: (page, context) => category.getSubCategories(context, page: page), + loaderWidget: SliverFillRemaining( + child: Center(child: Indicator(size: 0.7.adaptedPx())), + ), + loadMoreWidget: SliverToBoxAdapter( + child: Container( + margin: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + alignment: Alignment.center, + child: Row( + children: [ + Expanded( + child: Center(child: Indicator(size: 0.6.adaptedPx())), + ) + ], + ), + ), + ), + contentPadding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context) / 1.2, vertical: 15.adaptedPx()), + errorWidget: (refresh, error) { + return SliverFillRemaining( + child: Center( + child: RefreshButton( + onTap: refresh, + size: 38.adaptedPx(), + ), + ), + ); + }, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: AppConstants.categoryAxisCount(context), + childAspectRatio: 1, + mainAxisSpacing: AppConstants.horizontalPadding(context) / 1.2, + crossAxisSpacing: AppConstants.horizontalPadding(context) / 1.2), + errorOnLoadMoreWidget: (refresh, error) { + return Container( + margin: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + child: RefreshButton( + onTap: refresh, + size: 25.adaptedPx(), + ), + ); + }, + needPagination: false, + itemBuilder: (context, model, index) => CategoryBuilder(category: model))); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/screens/personalCabinet/addPost/step1.dart b/lib/screens/personalCabinet/addPost/step1.dart new file mode 100644 index 0000000..33c10a7 --- /dev/null +++ b/lib/screens/personalCabinet/addPost/step1.dart @@ -0,0 +1,205 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/components/abstractForm.dart'; +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/components/refreshButton.dart'; +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/models/products/composableProduct.dart'; +import 'package:birzha/models/products/my_product.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/personalCabinet/addPost/step2.dart'; +import 'package:birzha/services/streamFetchService.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/manager/manager.dart'; + +class AddBasicInformationScreen extends StatefulWidget { + const AddBasicInformationScreen({Key? key, required this.forEditing}) : super(key: key); + + final MyProduct? forEditing; + + @override + State createState() => _AddBasicInformationScreenState(); +} + +class _AddBasicInformationScreenState extends State + with AbstractFormState, StreamControlledMixin, ManagerObserverMixin { + TaskStatus status = TaskStatus.None; + + late final User user; + + bool isError = false; + + Map selectedAttrbiutes = {}; + + @override + body(BuildContext context) { + if (isLoading) + return Center( + child: Indicator( + size: 0.7.adaptedPx(), + ), + ); + else if (isError) + return Center( + child: Container( + height: 120.adaptedPx(), + child: RefreshButton( + onTap: () { + connect(context); + }, + ), + ), + ); + return super.body(context); + } + + @override + bool get shrinkWrap => isLoading; + + @override + void launchControllers([bool force = false]) { + if (force) { + var product = ComposableProduct(); + controllers = List.generate(inputs.length, (index) => TextEditingController(text: "")); + if (product.primaryKey != null) { + for (var i = 0; i < controllers.length; i++) { + var controller = controllers[i]; + var input = inputs[i]; + if (input.pickerMode == null) { + controller.text = product.jSON[input.key]?.toString() ?? ""; + } else if (product.getModelData(input.key) is AttributeWithValueNameMixin) { + var value = product.getModelData(input.key) as AttributeWithValueNameMixin; + selectedAttrbiutes[input.key] = value; + controller.text = value.label.toString(); + } + } + } + } else { + super.launchControllers(); + } + } + + @override + void dispose() { + cancel(); + super.dispose(); + } + + @override + void initState() { + user = AppUserManager.of(context).dataSync.copy; + connect(context); + super.initState(); + } + + @override + void act() { + for (int i = 0; i < inputs.length; i++) { + ComposableProduct().setBasicTypeField(inputs[i].key, controllers[i].text); + } + for (var attributeKey in selectedAttrbiutes.keys) { + ComposableProduct().setModelField(attributeKey, selectedAttrbiutes[attributeKey]!); + } + + var product = ComposableProduct(); + + AppUserManager.of(context).composeStep1(context, [...inputs.map((el) => el.key), if (product.primaryKey != null) product.primaryKeyField.toString()]); + } + + @override + bool get buttonIsLoading => status == TaskStatus.Loading; + + @override + String get buttonLabel => MaterialLocalizations.of(context).saveButtonLabel; + + @override + List get inputs => [ + ...user.addPostMetaData, + for (var attribute in ComposableProduct().attrbiutes.whereType().where((element) => _attributeKeys.contains(element.key))) + attribute.metaData( + groupValue: selectedAttrbiutes[attribute.key], + onSelected: (option) { + if (option is AttributeWithValueNameMixin && mounted) { + setState(() { + selectedAttrbiutes[attribute.key] = option; + }); + } + }), + ]; + + @override + void start(BuildContext context) { + setState(() { + isError = false; + }); + super.start(context); + } + + @override + void error(BuildContext context, error) { + print(error); + setState(() { + isError = true; + }); + super.error(context, error); + } + + @override + String keyAfterFilter(String key, String input) { + return key; + } + + @override + String get title => 'firstStep'.translation; + + @override + String valueAfterFilter(String key, String input) { + return input; + } + + @override + Future Function() get asyncAction => () => ComposableProduct.getAttributes(context, widget.forEditing); + + @override + void onDataRecived(BuildContext context, data) { + if (mounted) { + setState(() {}); + launchControllers(true); + } + } + + @override + TaskStatus selector(BuildContext context, AppUserManager someManager) { + return someManager.getStatusByKey(_taskStatusKey); + } + + @override + void updateScreen() { + debugPrint('updateScreen'); + } + + @override + bool shouldUpdateListener(TaskStatus oldVal, TaskStatus newVal) { + return oldVal != newVal; + } + + @override + void updateListener() { + if (mounted) { + setState(() { + status = AppUserManager.of(context).getStatusByKey(_taskStatusKey); + if (status == TaskStatus.Success) { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => AddMoreInformationScreen( + forEditing: widget.forEditing, + ))); + } + }); + } + } +} + +const _taskStatusKey = 'compose_1'; +const _attributeKeys = ['category_id', 'market_type', 'country']; diff --git a/lib/screens/personalCabinet/addPost/step2.dart b/lib/screens/personalCabinet/addPost/step2.dart new file mode 100644 index 0000000..4438fce --- /dev/null +++ b/lib/screens/personalCabinet/addPost/step2.dart @@ -0,0 +1,358 @@ +import 'dart:io'; + +import 'package:birzha/components/abstractForm.dart'; +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/components/refreshButton.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/models/products/composableProduct.dart'; +import 'package:birzha/models/products/my_product.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/user/user.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/personalCabinet/my_products.dart'; +import 'package:birzha/services/streamFetchService.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class AddMoreInformationScreen extends StatefulWidget { + const AddMoreInformationScreen({Key? key, required this.forEditing}) : super(key: key); + + final MyProduct? forEditing; + + @override + State createState() => _AddBasicInformationScreenState(); +} + +class _AddBasicInformationScreenState extends State + with AbstractFormState, StreamControlledMixin, ManagerObserverMixin { + TaskStatus status = TaskStatus.None; + + late final User user; + + bool isError = false; + + Map selectedAttrbiutes = {}; + + Widget galleryBuilder(String title, List images) { + return Container( + margin: EdgeInsets.symmetric(vertical: 15.adaptedPx()), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: Theme.of(context).accentTextTheme.headline2, + ), + Container( + height: 100.adaptedPx(), + width: MediaQuery.of(context).size.width, + margin: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + child: ListView.builder( + itemCount: images.length, + scrollDirection: Axis.horizontal, + itemBuilder: (context, index) { + return LayoutBuilder( + builder: (context, constraints) { + var image = images[index]; + var iconSize = 25.adaptedPx(); + var imageBuilder = image is LocalImageModel + ? Image.file(File(image.primaryKey), + height: constraints.maxHeight - iconSize, width: constraints.maxHeight - iconSize, fit: BoxFit.cover) + : CachedNetworkImage( + imageUrl: image.primaryKey, + height: constraints.maxHeight - iconSize, + width: constraints.maxHeight - iconSize, + errorWidget: (context, url, error) { + return Container( + height: constraints.maxHeight - iconSize, + width: constraints.maxHeight - iconSize, + alignment: Alignment.center, + child: Icon(Icons.image), + ); + }, + placeholder: (context, url) => Container( + height: constraints.maxHeight - iconSize, + width: constraints.maxHeight - iconSize, + alignment: Alignment.center, + child: Icon(Icons.broken_image), + ), + fit: BoxFit.cover, + ); + return Stack( + children: [ + Container( + margin: EdgeInsets.only(top: iconSize / 2, right: iconSize / 2), + child: ClipRRect( + borderRadius: BorderRadius.circular(10.adaptedPx()), + child: imageBuilder, + ), + ), + Positioned( + top: 0, + right: 0, + child: GestureDetector( + onTap: () { + ComposableProduct().removeImage(context, image); + }, + child: Icon( + CupertinoIcons.clear_circled_solid, + color: Theme.of(context).accentColor, + size: iconSize, + ), + ), + ), + ], + ); + }, + ); + }, + )) + ], + ), + ); + } + + @override + body(BuildContext context) { + if (isLoading) + return Center( + child: Indicator( + size: 0.7.adaptedPx(), + ), + ); + else if (isError) + return Center( + child: Container( + height: 120.adaptedPx(), + child: RefreshButton( + onTap: () { + connect(context); + }, + ), + ), + ); + return super.body(context); + } + + @override + bool get shrinkWrap => isLoading; + + @override + void launchControllers([bool force = false]) { + if (force) { + var product = ComposableProduct(); + controllers = List.generate(inputs.length, (index) => TextEditingController(text: "")); + if (product.primaryKey != null) { + for (var i = 0; i < controllers.length; i++) { + var controller = controllers[i]; + var input = inputs[i]; + if (input.pickerMode == null) { + controller.text = product.jSON[input.key]?.toString() ?? ""; + } else if (product.getModelData(input.key) is AttributeWithValueNameMixin) { + var value = product.getModelData(input.key) as AttributeWithValueNameMixin; + selectedAttrbiutes[input.key] = value; + controller.text = value.label.toString(); + } + } + } + } else { + super.launchControllers(); + } + } + + @override + void initState() { + user = AppUserManager.of(context).dataSync.copy; + connect(context); + super.initState(); + } + + @override + void dispose() { + cancel(); + super.dispose(); + } + + @override + void updateScreen() { + debugPrint('updateScreen'); + } + + @override + void act() { + for (int i = 0; i < inputs.length; i++) { + ComposableProduct().setBasicTypeField(inputs[i].key, controllers[i].text); + } + for (var attributeKey in selectedAttrbiutes.keys) { + ComposableProduct().setModelField(attributeKey, selectedAttrbiutes[attributeKey]!); + } + + var product = ComposableProduct(); + + AppUserManager.of(context).composeStep2(context, [...inputs.map((el) => el.key), if (product.primaryKey != null) product.primaryKeyField.toString()]); + } + + @override + bool get buttonIsLoading => status == TaskStatus.Loading; + + @override + String get buttonLabel => MaterialLocalizations.of(context).saveButtonLabel; + + @override + List get inputs => [ + ...user.addMoreMetaData, + for (var attribute in ComposableProduct().attrbiutes.whereType().where((element) => _attributeKeys.contains(element.key))) + attribute.metaData( + groupValue: selectedAttrbiutes[attribute.key], + onSelected: (option) { + if (option is AttributeWithValueNameMixin && mounted) { + setState(() { + selectedAttrbiutes[attribute.key] = option; + }); + } + }), + ]; + + @override + void start(BuildContext context) { + setState(() { + isError = false; + }); + super.start(context); + } + + @override + void error(BuildContext context, error) { + print(error); + setState(() { + isError = true; + }); + super.error(context, error); + } + + @override + String keyAfterFilter(String key, String input) { + return key; + } + + @override + String get title => 'secondStep'.translation; + + @override + String valueAfterFilter(String key, String input) { + return input; + } + + @override + Future Function() get asyncAction => () => ComposableProduct.getAttributes(context, widget.forEditing); + + @override + void onDataRecived(BuildContext context, data) { + if (mounted) { + setState(() {}); + launchControllers(true); + } + } + + @override + TaskStatus selector(BuildContext context, AppUserManager someManager) { + return someManager.getStatusByKey(_taskStatusKey); + } + + @override + bool shouldUpdateListener(TaskStatus oldVal, TaskStatus newVal) { + return oldVal != newVal; + } + + @override + void updateListener() { + if (mounted) { + setState(() { + status = AppUserManager.of(context).getStatusByKey(_taskStatusKey); + if (status == TaskStatus.Success) { + Navigator.of(context).pushAndRemoveUntil(MaterialPageRoute(builder: (context) => MyProductsScreen()), (route) => route.isFirst); + } + }); + } + } + + @override + List get after => [ + GestureDetector( + onTap: ComposableProduct().pickImages, + child: Container( + margin: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + decoration: BoxDecoration( + color: Theme.of(context).backgroundColor, + border: Border.all(color: Theme.of(context).accentColor, width: 0.7.adaptedPx()), + borderRadius: BorderRadius.circular(10.adaptedPx())), + padding: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + alignment: Alignment.center, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.add, + size: 20.adaptedPx(), + color: Theme.of(context).accentColor, + ), + SizedBox( + width: 5.adaptedPx(), + ), + Text( + 'selectImages'.translation, + style: Theme.of(context).accentTextTheme.headline2, + ) + ], + ), + ), + ), + ), + Selector( + selector: (context, product) => product.localImages.length, + shouldRebuild: (previous, next) => previous != next, + builder: (context, value, child) { + if (value == 0) { + return Container(); + } else { + return galleryBuilder('localImages'.translation, ComposableProduct().localImages); + } + }, + ), + Selector( + selector: (_, manager) => manager.getStatusByKey('delete_image'), + shouldRebuild: (previous, next) => previous != next, + builder: (context, value, child) { + if (value == TaskStatus.Loading) { + return Container( + height: 100.adaptedPx(), + alignment: Alignment.center, + child: Indicator( + size: 0.7.adaptedPx(), + ), + ); + } + return Selector( + selector: (context, product) => product.remoteImages.length, + shouldRebuild: (previous, next) => previous != next, + builder: (context, value, child) { + if (value == 0) { + return Container(); + } else { + return galleryBuilder('loadedImages'.translation, ComposableProduct().remoteImages); + } + }, + ); + }, + ), + ]; +} + +const _taskStatusKey = 'compose_2'; +const _attributeKeys = ['measure_id', 'currency_id', 'payment_term_id', 'delivery_term_id', 'packaging']; diff --git a/lib/screens/personalCabinet/messages/messages.dart b/lib/screens/personalCabinet/messages/messages.dart new file mode 100644 index 0000000..a186426 --- /dev/null +++ b/lib/screens/personalCabinet/messages/messages.dart @@ -0,0 +1,97 @@ +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/postlist.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/models/chatroom/chatroom.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/screens/personalCabinet/messages/personalChat.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/core/lazyload/lazyload.dart'; +import 'package:provider/provider.dart'; + +class Messages extends StatefulWidget { + @override + _MessagesState createState() => _MessagesState(); +} + +class _MessagesState extends State { + ChatroomSerializer serializer = ChatroomSerializer(); + FetchController _fetchController = FetchController(); + + @override + Widget build(BuildContext context) { + return BaseWidget( + color: Theme.of(context).chipTheme.backgroundColor, + appBar: BaseAppBar( + title: 'message'.translation, + goBack: () { + Navigator.of(context).pop(); + }, + ), + body: PostList(category: serializer, fetchController: _fetchController)); + } +} + +class MessagesCard extends StatelessWidget { + final Chatroom chatroom; + + const MessagesCard({ + Key? key, + required this.chatroom, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider.value( + value: chatroom, + builder: (context, val) => Consumer( + builder: (context, room, __) => InkWell( + onTap: () { + Navigator.of(context, rootNavigator: true).push(MaterialPageRoute(builder: (_) => PersonalChat(chatroom: chatroom))); + }, + child: Container( + decoration: BoxDecoration(border: Border(bottom: BorderSide(width: 0.9.adaptedPx(), color: Theme.of(context).dividerColor))), + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context), vertical: 20.adaptedPx()), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + chatroom.title, + style: Theme.of(context).textTheme.headline1!.copyWith( + color: AppConstants.appColor, + fontWeight: FontWeight.bold, + ), + ), + if (chatroom.hasNewMessages) + Container( + child: Text( + chatroom.unread.toString(), + style: Theme.of(context).primaryTextTheme.headline3, + ), + width: 21.adaptedPx(), + height: 21.adaptedPx(), + alignment: Alignment.center, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20.adaptedPx()), + ), + ), + ], + ), + SizedBox(height: 10.adaptedPx()), + Text( + chatroom.subTitile, + style: + TextStyle(color: Theme.of(context).primaryTextTheme.headline2!.color, fontSize: Theme.of(context).primaryTextTheme.headline2!.fontSize), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/screens/personalCabinet/messages/personalChat.dart b/lib/screens/personalCabinet/messages/personalChat.dart new file mode 100644 index 0000000..e0ea198 --- /dev/null +++ b/lib/screens/personalCabinet/messages/personalChat.dart @@ -0,0 +1,244 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/components/TextInputCustom.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/icon.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/models/chatroom/chatroom.dart'; +import 'package:birzha/models/chatroom/message.dart'; +import 'package:birzha/services/helpers.dart'; +import 'package:birzha/services/textMetaData.dart'; +import 'package:birzha/services/validator.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:provider/provider.dart'; + +class PersonalChat extends StatefulWidget { + final Chatroom chatroom; + + PersonalChat({required this.chatroom}); + + @override + _PersonalChatState createState() => _PersonalChatState(); +} + +class _PersonalChatState extends State { + TextEditingController _textEditingController = TextEditingController(); + + ScrollController controller = ScrollController(); + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + widget.chatroom.refresh(context); + } + + @override + Widget build(BuildContext context) { + return ChangeNotifierProvider.value( + value: widget.chatroom, + child: BaseWidget( + appBar: BaseAppBar( + goBack: () { + Navigator.of(context, rootNavigator: false).pop(); + }, + title: widget.chatroom.title, + ), + body: Column( + children: [ + ManagerSelector( + selector: (context, manager) => manager.getStatusByKey('load'), + shouldRebuild: (prev, newValue) => prev != newValue, + onUpdate: () async { + setState(() {}); + }, + builder: (context, status) => status != TaskStatus.Loading + ? Container() + : SizedBox( + height: 3.adaptedPx(), + width: MediaQuery.of(context).size.width, + child: LinearProgressIndicator( + minHeight: 3.adaptedPx(), + )), + ), + Expanded( + child: Selector( + selector: (context, chatroom) => chatroom.lastIndexOfLocalMessages, + shouldRebuild: (prev, next) { + return prev != next; + }, + builder: (context, messages, __) => CustomScrollView( + controller: controller, + reverse: true, + slivers: [ + SliverList( + delegate: SliverChildListDelegate([for (var message in Chatroom.of(context).messages) _MessageBuilder(message: message)]), + ), + SliverToBoxAdapter( + child: Row(mainAxisAlignment: MainAxisAlignment.center, children: [ + ManagerSelector( + selector: (context, manager) => manager.getStatusByKey('load'), + shouldRebuild: (prev, newValue) => prev != newValue, + onUpdate: () async { + setState(() {}); + }, + builder: (context, status) => status == TaskStatus.Loading + ? Container() + : Padding( + padding: EdgeInsets.symmetric(vertical: 15.adaptedPx()), + child: GestureDetector( + onTap: () { + widget.chatroom.loadPastMessages(context, () async { + await Future.delayed(const Duration(milliseconds: 200)); + if (mounted) + controller.animateTo(controller.position.maxScrollExtent, + duration: const Duration(milliseconds: 200), curve: Curves.ease); + }); + }, + child: PhysicalModel( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(15.adaptedPx()), + elevation: 5.adaptedPx(), + shadowColor: Colors.black.withOpacity(0.3), + child: Container( + padding: EdgeInsets.symmetric(horizontal: 15.adaptedPx()), + alignment: Alignment.center, + height: 36.adaptedPx(), + child: Text( + 'tapToLoadMore'.translation, + style: TextStyle(fontWeight: FontWeight.w600), + ), + ), + ), + ), + ), + ), + ]), + ), + ], + ), + ), + ), + Container( + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context), vertical: 5.adaptedPx()).copyWith(bottom: 10.adaptedPx()), + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + ), + child: Row( + children: [ + Expanded( + child: TextInputCustom( + fieldStandard: + TextInputMetaData(hint: 'yourMessage'.translation, name: 'message', validation: Validation(conditions: []), key: 'message'), + controller: _textEditingController), + ), + SizedBox( + width: 15.adaptedPx(), + ), + PhysicalModel( + color: Theme.of(context).accentColor, + elevation: 3.adaptedPx(), + shape: BoxShape.circle, + child: SizedBox( + width: 45.adaptedPx(), + height: 45.adaptedPx(), + child: AppIconButton( + onTap: () { + widget.chatroom.textMessage(context, _textEditingController.text); + _textEditingController.clear(); + }, + icon: Icon( + Icons.send, + color: Colors.white, + ), + size: 20.adaptedPx()), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} + +class _MessageBuilder extends StatelessWidget { + const _MessageBuilder({Key? key, required this.message}) : super(key: key); + + final Message message; + + @override + Widget build(BuildContext context) { + return Selector( + selector: (context, chatroom) => chatroom.messages.lookup(message)?.status ?? MessagesStatus.none, + shouldRebuild: (prev, next) { + return prev != next; + }, + builder: (context, status, ___) => Container( + margin: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + padding: !message.isMyMessage(context) ? EdgeInsets.only(left: 10.adaptedPx()) : EdgeInsets.only(right: 10.adaptedPx()), + child: Row( + mainAxisAlignment: !message.isMyMessage(context) ? MainAxisAlignment.start : MainAxisAlignment.end, + children: [ + SizedBox( + width: MediaQuery.of(context).size.width * 0.8, + child: Material( + color: Colors.transparent, + child: Row( + mainAxisAlignment: !message.isMyMessage(context) ? MainAxisAlignment.start : MainAxisAlignment.end, + children: [ + if (status == MessagesStatus.sending) + Icon(Icons.arrow_circle_up, size: 22.adaptedPx(), color: Theme.of(context).accentColor) + else if (status == MessagesStatus.failed) + AppIconButton( + onTap: () { + Provider.of(context, listen: false).retextMessage(context, message); + }, + icon: Icon(Icons.warning, color: Colors.red), + size: 22.adaptedPx(), + ), + Flexible( + child: Column(crossAxisAlignment: !message.isMyMessage(context) ? CrossAxisAlignment.start : CrossAxisAlignment.end, children: [ + Container( + padding: EdgeInsets.symmetric(vertical: 11, horizontal: 16), + decoration: BoxDecoration( + color: message.isMyMessage(context) ? Theme.of(context).accentColor : Colors.green.shade600, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(21.adaptedPx()), + topRight: Radius.circular(21.adaptedPx()), + bottomLeft: !message.isMyMessage(context) ? Radius.circular(4.adaptedPx()) : Radius.circular(21.adaptedPx()), + bottomRight: !message.isMyMessage(context) ? Radius.circular(21.adaptedPx()) : Radius.circular(4.adaptedPx()), + ), + ), + child: Text( + message.text, + style: Theme.of(context).primaryTextTheme.bodyText2!.copyWith( + fontSize: 15, + color: Theme.of(context).backgroundColor, + ), + ), + ), + SizedBox(height: 5.adaptedPx()), + if (message.date != null) + Text( + safeValueDate(message.date), + style: TextStyle(fontSize: 11.99.adaptedPx()), + ) + ])), + ], + ), + ), + ), + ], + )), + ); + } +} diff --git a/lib/screens/personalCabinet/my_products.dart b/lib/screens/personalCabinet/my_products.dart new file mode 100644 index 0000000..21f06ef --- /dev/null +++ b/lib/screens/personalCabinet/my_products.dart @@ -0,0 +1,32 @@ +import 'package:birzha/models/categories/products/my_products.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/screens/productsScreen.dart'; +import 'package:flutter/material.dart'; + +import '../../components/baseWidget.dart'; + +class MyProductsScreen extends StatefulWidget { + const MyProductsScreen({Key? key}) : super(key: key); + + @override + State createState() => _MyProductsScreenState(); +} + +class _MyProductsScreenState extends State { + @override + Widget build(BuildContext context) { + return BaseWidget( + color: Theme.of(context).chipTheme.backgroundColor, + appBar: BaseAppBar( + title: 'myProducts'.translation, + goBack: () { + Navigator.of(context).pop(); + }, + ), + body: ProductsScreen(category: MyProducts(), route: 'auth'), + ); + } + // Widget build(BuildContext context) { + // return ProductsScreen(category: MyProducts(), route: 'auth'); + // } +} diff --git a/lib/screens/personalCabinet/personalCabinet.dart b/lib/screens/personalCabinet/personalCabinet.dart new file mode 100644 index 0000000..b64a1a2 --- /dev/null +++ b/lib/screens/personalCabinet/personalCabinet.dart @@ -0,0 +1,245 @@ +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/customCardWidget.dart'; +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/components/unauthenticatedWidget.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/core/manager/manager.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/user/userManager.dart'; +import 'package:birzha/screens/auth/smsVerification.dart'; +import 'package:birzha/screens/auth/update.dart'; +import 'package:birzha/screens/first_page.dart'; +import 'package:birzha/screens/personalCabinet/addPost/step1.dart'; +import 'package:birzha/screens/personalCabinet/messages/messages.dart'; +import 'package:birzha/screens/personalCabinet/my_products.dart'; +import 'package:birzha/screens/personalCabinet/topUp/topUpHistory.dart'; +import 'package:birzha/services/modals.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../../new/screens/top_up_balance/online_top_up_screen.dart'; + +class PersonalCabinet extends StatefulWidget { + @override + _PersonalCabinetState createState() => _PersonalCabinetState(); +} + +class _PersonalCabinetState extends State with AutomaticKeepAliveClientMixin { + @override + Widget build(BuildContext context) { + super.build(context); + return BaseWidget( + appBar: BaseAppBar( + goBack: () { + Tabnavigator.maybeOf(context)?.pop(context); + }, + title: 'personalCabinet'.translation, + ), + body: !AppUserManager.of(context, listen: true).dataSync.isRegistered + ? Center( + child: UnAuthenticated(), + ) + : Selector( + selector: (context, user) => + user.getStatusByKey('sync') == TaskStatus.Loading || + user.getStatusByKey('verify_mail') == TaskStatus.Loading || + user.getStatusByKey('send_sms') == TaskStatus.Loading, + shouldRebuild: (prev, next) => prev != next, + builder: (context, isLoading, __) => isLoading + ? Center( + child: Indicator( + size: 0.7.adaptedPx(), + ), + ) + : RefreshIndicator( + onRefresh: () { + AppUserManager.of(context).syncAccount(context); + return Future.value(null); + }, + child: ListView( + physics: AlwaysScrollableScrollPhysics(parent: BouncingScrollPhysics()), + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + vertical: AppConstants.verticalPadding(context), + ), + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(5.adaptedPx()), + child: Column( + children: [ + // personal data + CustomCardWidget( + name: 'personal_data'.translation, + onTap: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => UpdateScreen())); + }, + icon: Icon(Icons.person_outline), + borderRadius: BorderRadius.zero, + ), + Divider( + indent: 16.adaptedPx(), + endIndent: 15.adaptedPx(), + height: 0.adaptedPx(), + thickness: 0.9.adaptedPx(), + ), + + //top up history + CustomCardWidget( + onTap: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => TopUpHistory())); + }, + name: 'top_up_history'.translation, + icon: Icon(Icons.inbox_outlined, color: Theme.of(context).accentColor), + borderRadius: BorderRadius.zero, + ), + Divider( + indent: 16.adaptedPx(), + endIndent: 15.adaptedPx(), + height: 0.adaptedPx(), + thickness: 0.9.adaptedPx(), + ), + + //top up balance + CustomCardWidget( + onTap: () { + Navigator.of(context).push(MaterialPageRoute(builder: (_) => OnlineTopUpBalance())); + }, + name: 'topUpBalance'.translation, + icon: Icon( + Icons.account_balance_wallet_outlined, + color: Theme.of(context).accentColor, + ), + borderRadius: BorderRadius.zero, + ), + Divider( + indent: 16.adaptedPx(), + endIndent: 15.adaptedPx(), + height: 0.adaptedPx(), + thickness: 0.9.adaptedPx(), + ), + + // message + CustomCardWidget( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute( + builder: (_) => Messages(), + ), + ); + }, + name: 'message'.translation, + icon: Icon(Icons.message_outlined), + borderRadius: BorderRadius.zero, + ), + ], + ), + ), + + SizedBox(height: 20.adaptedPx()), + + ClipRRect( + borderRadius: BorderRadius.circular(5.adaptedPx()), + child: Column( + children: [ + // add product + CustomCardWidget( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => AddBasicInformationScreen(forEditing: null)), + ); + }, + name: 'addPosts'.translation, + icon: Icon(Icons.add), + borderRadius: BorderRadius.zero, + ), + + Divider( + indent: 16.adaptedPx(), + endIndent: 15.adaptedPx(), + height: 0.adaptedPx(), + thickness: 0.9.adaptedPx(), + ), + + // my products + CustomCardWidget( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => MyProductsScreen()), + ); + }, + name: 'myProducts'.translation, + icon: Icon(Icons.article_outlined), + borderRadius: BorderRadius.zero, + ), + ], + ), + ), + + SizedBox(height: 20.adaptedPx()), + + /* ClipRRect( + borderRadius: BorderRadius.circular(5.adaptedPx()), + child: Column( + children: [ + // verify mail + if (!AppUserManager.of(context).dataSync.isEmailVerified) ...[ + CustomCardWidget( + onTap: () { + AppUserManager.of(context).verifyMail(context); + }, + name: 'verifyMail'.translation, + icon: Icon(Icons.email_outlined), + borderRadius: BorderRadius.zero, + ), + Divider( + indent: 16.adaptedPx(), + endIndent: 15.adaptedPx(), + height: 0.adaptedPx(), + thickness: 0.9.adaptedPx(), + ) + ], + + // verify phone + if (!AppUserManager.of(context).dataSync.isPhoneVerified) + CustomCardWidget( + onTap: () { + var navContext = Navigator.of(context, rootNavigator: true).context; + AppUserManager.of(context).sendSmsCode(context, () { + Navigator.of(navContext).push(MaterialPageRoute(builder: (_) => SmsVerificationScreen())); + }); + }, + name: 'verifyPhone'.translation, + icon: Icon(Icons.smartphone_outlined), + borderRadius: BorderRadius.zero, + ), + ], + ), + ), */ + + SizedBox(height: 20.adaptedPx()), + // logout + CustomCardWidget( + onTap: () async { + var isSure = await yesOrNoDialog(context, content: 'sure_log_out'.translation); + var nav = Navigator.of(context, rootNavigator: true).context; + if (isSure && mounted) { + AppUserManager.of(context).logout(); + await Future.delayed(const Duration(milliseconds: 200)); + Navigator.of(nav, rootNavigator: true).pushAndRemoveUntil(MaterialPageRoute(builder: (_) => FirstPage()), (route) => false); + } + }, + name: 'logout'.translation, + icon: Icon(Icons.exit_to_app_outlined, color: Colors.red), + ), + ], + ), + ), + ), + ); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/screens/personalCabinet/topUp/topUpHistory.dart b/lib/screens/personalCabinet/topUp/topUpHistory.dart new file mode 100644 index 0000000..664326c --- /dev/null +++ b/lib/screens/personalCabinet/topUp/topUpHistory.dart @@ -0,0 +1,162 @@ +import 'package:badges/badges.dart'; +import 'package:birzha/components/actionIcons/searchicon.dart'; +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/postlist.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/core/lazyload/lazyload.dart'; +import 'package:birzha/models/products/post.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/transactions/serializer.dart'; +import 'package:birzha/models/transactions/transaction.dart'; +import 'package:flutter/material.dart'; + +class TopUpHistory extends StatefulWidget { + @override + _TopUpHistoryState createState() => _TopUpHistoryState(); +} + +class _TopUpHistoryState extends State { + TransactionSerializer serializer = TransactionSerializer(); + FetchController _fetchController = FetchController(); + + @override + void dispose() { + _fetchController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BaseWidget( + color: Theme.of(context).scaffoldBackgroundColor, + appBar: BaseAppBar( + title: 'top_up_history'.translation, + after: [SearchIcon()], + goBack: () { + Navigator.of(context, rootNavigator: false).pop(); + }, + ), + body: PostList( + category: serializer, + contentPadding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context), vertical: AppConstants.verticalPadding(context) / 2), + before: [ + SliverPadding( + padding: EdgeInsets.symmetric(vertical: 10.adaptedPx(), horizontal: AppConstants.horizontalPadding(context)), + sliver: SliverList( + delegate: SliverChildListDelegate.fixed( + [ + /* ManagerSelector( + onUpdate: () {}, + selector: (context, manager) => manager.getStatusByKey('balanceUp'), + shouldRebuild: (prev, next) => prev != next, + builder: (context, status) => MyButton( + text: 'payOnline'.translation, + inProgress: status == TaskStatus.Loading, + onTap: () async { + var amount = await showDialog( + context: context, + builder: (context) => AskQuantityDialog(initialQuantity: 1), + ); + if (amount is double) AppUserManager.of(context).balanceUp(context, amount); + }, + height: 40.adaptedPx(), + ), + ), + SizedBox(height: 12), + ManagerSelector( + onUpdate: () {}, + selector: (context, manager) => manager.getStatusByKey('uploadBill'), + shouldRebuild: (prev, next) => prev != next, + builder: (context, status) => MyButton( + text: 'uploadReceipt'.translation, + inProgress: status == TaskStatus.Loading, + onTap: () async { + AppUserManager.of(context).uploadBill(context); + }, + height: 40.adaptedPx(), + ), + ), + SizedBox(height: 12), */ + ], + ), + ), + ) + ], + fetchController: _fetchController), + ); + } +} + +class TopUpHistoryCard extends StatelessWidget { + final Transaction transaction; + + TopUpHistoryCard({Key? key, required this.transaction}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + margin: EdgeInsets.only(bottom: 15.adaptedPx()), + child: InkWell( + borderRadius: BorderRadius.circular(10.adaptedPx()), + child: Container( + decoration: BoxDecoration( + color: Theme.of(context).cardColor, + borderRadius: BorderRadius.circular(10.adaptedPx()), + ), + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + vertical: AppConstants.verticalPadding(context), + ), + child: Column( + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + '#' + transaction.primaryKey.toString(), + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + color: Theme.of(context).accentColor, + ), + ), + Text( + transaction.date, + style: Theme.of(context).primaryTextTheme.headline2, + ), + ], + ), + SizedBox( + height: 20.adaptedPx(), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Badge( + position: BadgePosition.topStart(top: 0, start: 0), + animationDuration: Duration(milliseconds: 300), + badgeColor: transaction.amountDouble > 0 ? Colors.green : Colors.red, + child: Row(children: [ + SizedBox(width: 20.adaptedPx()), + Text( + transaction.stateName, + style: Theme.of(context).primaryTextTheme.headline2, + ), + ]), + ), + Spacer(), + Text( + transaction.amount, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontWeight: FontWeight.bold, + color: Theme.of(context).accentColor, + ), + ), + ], + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/screens/photo.dart b/lib/screens/photo.dart new file mode 100644 index 0000000..0532b9d --- /dev/null +++ b/lib/screens/photo.dart @@ -0,0 +1,95 @@ +import 'dart:ui'; +import 'package:birzha/components/imagePlaceHolder.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:photo_view/photo_view.dart'; +import 'package:birzha/components/indicator.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; + +class PhotoScreen extends StatefulWidget{ + final String image; + PhotoScreen(this.image); + + @override + _PhotoScreenState createState()=> _PhotoScreenState(); + +} + +class _PhotoScreenState extends State{ + + @override + void initState() { + super.initState(); + } + + @override + void dispose() { + super.dispose(); + } + + @override + Widget build(BuildContext context) { + + final double paddingTop = MediaQueryData.fromWindow(window).padding.top; + final double verticalMarginTitle = + MediaQuery.of(context).size.width * (32 / 452); + + return Container( + color: Colors.white, + child: Stack( + children: [ + Hero( + tag: 'detailedPhoto', + child: Center( + child: PhotoView( + errorBuilder: (_, __, ___) => AppImagePlaceholder(), + loadingBuilder: (_, chunk) => Container( + color: Colors.white, + alignment: Alignment.center, + child: Container( + padding: EdgeInsets.symmetric( + vertical: verticalMarginTitle), + alignment: Alignment.center, + child: Indicator(size: 0.7.adaptedPx(),color: Theme.of(context).accentColor,) + )), + imageProvider: CachedNetworkImageProvider( + widget.image + ), + backgroundDecoration: BoxDecoration( + color: Colors.transparent + ), + ), + ), + ), + OrientationBuilder( + builder: (cntxt, orientation){ + + double height = (orientation == Orientation.portrait? + MediaQuery.of(context).size.height: MediaQuery.of(context).size.width)*0.049; + + return Container( + height: height, + alignment: Alignment.centerRight, + width: MediaQuery.of(context).size.width*0.98, + margin: EdgeInsets.only(top: paddingTop), + child: FittedBox( + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () => Navigator.of(cntxt).pop(), + child: Icon( + CupertinoIcons.clear_fill, + color: Theme.of(context).accentColor, + size:30.adaptedPx(), + ), + ), + ) + ) + ); + }, + ) + ], + )); + } +} \ No newline at end of file diff --git a/lib/screens/primal.dart b/lib/screens/primal.dart new file mode 100644 index 0000000..19cab4f --- /dev/null +++ b/lib/screens/primal.dart @@ -0,0 +1,53 @@ +import 'package:birzha/components/localizationOverride.dart'; +import 'package:birzha/components/tab_nav_icons.dart'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/screens/home/homeScreen.dart'; +import 'package:birzha/screens/masterCategoryScreen.dart'; +import 'package:birzha/screens/personalCabinet/personalCabinet.dart'; +import 'package:flutter/material.dart'; + +import '../new/screens/quotes/screen.dart'; + +class Primal extends StatelessWidget { + const Primal({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return LocalizationOverride( + builder: (context) { + return TabView( + items: [ + TabConfigs( + index: 0, + firstScreen: (_) => HomeScreen(), + routeLabel: 'home'.translation, + iconData: TabNavIcons.home, + initialRouteName: '/home', + ), + TabConfigs( + index: 1, + firstScreen: (_) => MasterCategoryScreen(), + routeLabel: 'category'.translation, + iconData: TabNavIcons.category, + initialRouteName: '/category'), + TabConfigs( + index: 2, + firstScreen: (_) => QuotesScreen(), + routeLabel: 'quotes'.translation, + iconData: TabNavIcons.news, + initialRouteName: '/quotations', + ), + TabConfigs( + index: 3, + firstScreen: (_) => PersonalCabinet(), + routeLabel: 'profile'.translation, + iconData: TabNavIcons.user, + initialRouteName: '/user', + ), + ], + ); + }, + ); + } +} diff --git a/lib/screens/productsScreen.dart b/lib/screens/productsScreen.dart new file mode 100644 index 0000000..5961928 --- /dev/null +++ b/lib/screens/productsScreen.dart @@ -0,0 +1,71 @@ +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/postlist.dart'; +import 'package:birzha/components/searchBar.dart'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/models/categories/category.dart'; +import 'package:birzha/new/themes/colors.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/lazyload/lazyload.dart'; +import 'package:birzha/models/products/post.dart'; + +class ProductsScreen extends StatefulWidget { + const ProductsScreen({Key? key, required this.category, required this.route, this.headerToolBar = const []}) : super(key: key); + + final RemoteCategory category; + final String route; + final List headerToolBar; + + @override + _ProductsScreenState createState() => _ProductsScreenState(); +} + +class _ProductsScreenState extends State { + FetchController controller = FetchController(); + + late RemoteCategory primal; + + @override + void initState() { + super.initState(); + primal = widget.category.copy; + } + + @override + void dispose() { + controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return BaseWidget( + appBar: BaseAppBar( + color: ThemeColor.white, + goBack: () { + Tabnavigator.backDispatcher(context); + }, + after: [...widget.headerToolBar], + customChild: primal is! SearchableMixin + ? null + : ActualSearchBar( + onSubmit: (word) { + (primal as SearchableMixin).search(word); + setState(() { + controller.refresh(); + }); + }, + route: Tabnavigator.currentRoute(context) + '/${widget.route}'), + title: primal.name, + ), + body: Container( + color: Theme.of(context).backgroundColor, + child: PostList( + contentPadding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context), vertical: AppConstants.verticalPadding(context)), + before: [], + category: primal, + fetchController: controller), + ), + ); + } +} diff --git a/lib/screens/settings/contact.dart b/lib/screens/settings/contact.dart new file mode 100644 index 0000000..41653fa --- /dev/null +++ b/lib/screens/settings/contact.dart @@ -0,0 +1,137 @@ +import 'package:birzha/constants.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; + +class ContactScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BaseWidget( + color: Theme.of(context).chipTheme.backgroundColor, + appBar: BaseAppBar( + after: [], + goBack: () { + Navigator.of(context).pop(); + }, + title: 'contact'.translation, + ), + body: ListView( + padding: EdgeInsets.symmetric(horizontal: AppConstants.horizontalPadding(context), vertical: AppConstants.verticalPadding(context)), + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox(height: 20.adaptedPx()), + Container( + alignment: Alignment.center, + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: Theme.of(context).accentColor), + width: 50.adaptedPx(), + height: 50.adaptedPx(), + child: Icon( + Icons.phone_in_talk_outlined, + size: 30.adaptedPx(), + color: Theme.of(context).accentIconTheme.color, + ), + ), + Padding( + padding: EdgeInsets.only(top: 20.adaptedPx(), bottom: 10.adaptedPx()), + child: Text( + 'telephone'.translation + ':', + style: Theme.of(context).accentTextTheme.headline2!.copyWith( + fontSize: AppConstants.h1FontSize, + fontWeight: FontWeight.bold, + ), + ), + ), + Text( + '+99312446015', + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontSize: AppConstants.h2FontSize, + fontWeight: FontWeight.w400, + ), + ), + Padding( + padding: EdgeInsets.only(top: 10.adaptedPx(), bottom: 30.adaptedPx()), + child: Text( + '+99312446016', + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontSize: AppConstants.h2FontSize, + fontWeight: FontWeight.w400, + ), + ), + ), + Container( + alignment: Alignment.center, + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: Theme.of(context).accentColor), + width: 50.adaptedPx(), + height: 50.adaptedPx(), + child: Icon( + Icons.mail_outline, + size: 30.adaptedPx(), + color: Theme.of(context).accentIconTheme.color, + ), + ), + Padding( + padding: EdgeInsets.only(top: 20.adaptedPx(), bottom: 10.adaptedPx()), + child: Text( + 'mail'.translation + ':', + style: Theme.of(context).accentTextTheme.headline2!.copyWith( + fontSize: AppConstants.h1FontSize, + fontWeight: FontWeight.bold, + ), + ), + ), + Text( + 'info@exchange.gov.tm', + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontSize: AppConstants.h2FontSize, + fontWeight: FontWeight.w400, + ), + ), + Padding( + padding: EdgeInsets.only(top: 10.adaptedPx(), bottom: 30.adaptedPx()), + child: Text( + 'brokers@exchange.gov.tm', + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontSize: AppConstants.h2FontSize, + fontWeight: FontWeight.w400, + ), + ), + ), + Container( + alignment: Alignment.center, + decoration: BoxDecoration(borderRadius: BorderRadius.circular(5), color: Theme.of(context).accentColor), + width: 50.adaptedPx(), + height: 50.adaptedPx(), + child: Icon( + Icons.map_outlined, + size: 30.adaptedPx(), + color: Theme.of(context).accentIconTheme.color, + ), + ), + Padding( + padding: EdgeInsets.only(top: 20.adaptedPx(), bottom: 10.adaptedPx()), + child: Text( + 'address'.translation + ':', + style: Theme.of(context).accentTextTheme.headline2!.copyWith( + fontSize: AppConstants.h1FontSize, + fontWeight: FontWeight.bold, + ), + ), + ), + Text( + 'realAddress'.translation, + textAlign: TextAlign.center, + style: Theme.of(context).primaryTextTheme.headline2!.copyWith( + fontSize: AppConstants.h2FontSize, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ], + ), + ); + } +} diff --git a/lib/screens/settings/feedback.dart b/lib/screens/settings/feedback.dart new file mode 100644 index 0000000..82f5ef8 --- /dev/null +++ b/lib/screens/settings/feedback.dart @@ -0,0 +1,59 @@ +// import 'package:birzha/components/abstractForm.dart'; +// import 'package:birzha/models/user/user.dart'; +// import 'package:birzha/services/textMetaData.dart'; +// import 'package:flutter/material.dart'; +// import 'package:manager/manager.dart'; +// import 'package:birzha/models/settings/settingsModel.dart'; + + +// class FeedbackScreen extends StatefulWidget { +// FeedbackScreen({Key? key}) : super(key: key); + +// @override +// _FeedbackScreenState createState() => _FeedbackScreenState(); +// } + +// class _FeedbackScreenState extends State +// with AbstractFormState { +// SampleUser sampleUser = SampleUser(data: {}); + +// TaskStatus status = TaskStatus.None; + +// @override +// List get before => []; + +// @override +// List get after => []; + +// @override +// List get inputs => sampleUser.feedbackMetaData; + +// @override +// String get title => 'feedback'.translation; + +// @override +// String get buttonLabel => 'sendMessage'.translation; + +// @override +// bool get buttonIsLoading => false; + +// @override +// String keyAfterFilter(String key, String input) { +// return key; +// } + +// @override +// String valueAfterFilter(String key, String input) { +// return input; +// } + +// @override +// void act() {} + +// @override +// void dispose() { +// super.dispose(); +// } +// } + +// // const _keyForTask = 'register'; diff --git a/lib/screens/settings/settingsScreen.dart b/lib/screens/settings/settingsScreen.dart new file mode 100644 index 0000000..55635a1 --- /dev/null +++ b/lib/screens/settings/settingsScreen.dart @@ -0,0 +1,109 @@ +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:birzha/components/baseWidget.dart'; +import 'package:birzha/components/customCardWidget.dart'; +import 'package:birzha/components/tabview.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/screens/primal.dart'; +import 'package:birzha/screens/settings/contact.dart'; +import 'package:birzha/services/helpers.dart'; +import 'package:birzha/services/modals.dart'; +import 'package:flutter/material.dart'; + +class SettingsScreen extends StatefulWidget { + @override + _SettingsScreenState createState() => _SettingsScreenState(); +} + +class _SettingsScreenState extends State with AutomaticKeepAliveClientMixin { + @override + bool get wantKeepAlive => true; + + @override + Widget build(BuildContext context) { + super.build(context); + return BaseWidget( + appBar: BaseAppBar( + title: 'settings'.translation, + goBack: () { + Tabnavigator.backDispatcher(context); + }, + ), + body: ListView( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context), + vertical: AppConstants.verticalPadding(context), + ), + children: [ + ClipRRect( + borderRadius: BorderRadius.circular(5.adaptedPx()), + child: Column( + children: [ + CustomCardWidget( + name: 'lang'.translation, + onTap: () async { + var a = await showLanguagePicker(context); + if (a != null) { + await SettingsModel.of(context).setLanguage(a); + Navigator.of(context, rootNavigator: true).pushAndRemoveUntil( + MaterialPageRoute(builder: (_) => Primal()), + (route) => false, + ); + } + }, + icon: Icon(Icons.language_outlined), + trailing: Container( + margin: EdgeInsets.only(right: 3.adaptedPx()), + child: Text( + 'localeLabel'.translation, + style: TextStyle(fontSize: AppConstants.b3FontSize, color: Theme.of(context).dividerColor.withOpacity(0.3)), + ), + ), + borderRadius: BorderRadius.zero, + ), + Divider( + indent: 16.adaptedPx(), + endIndent: 15.adaptedPx(), + height: 0.adaptedPx(), + thickness: 0.9.adaptedPx(), + ), + CustomCardWidget( + onTap: () { + linkLauncher('https://tmex.gov.tm/ru/politika-konfidencialnosti'); + }, + name: 'privacy_policy'.translation, + icon: Icon(Icons.policy_outlined, color: Theme.of(context).accentColor), + borderRadius: BorderRadius.zero, + ), + Divider( + indent: 16.adaptedPx(), + endIndent: 15.adaptedPx(), + height: 0.adaptedPx(), + thickness: 0.9.adaptedPx(), + ), + CustomCardWidget( + onTap: () { + linkLauncher('https://tmex.gov.tm/ru/contact-us'); + }, + name: 'feedback'.translation, + icon: Icon(Icons.feedback_outlined), + borderRadius: BorderRadius.zero, + ), + ], + ), + ), + SizedBox(height: 10.adaptedPx()), + CustomCardWidget( + onTap: () { + Navigator.of(context).push( + MaterialPageRoute(builder: (_) => ContactScreen()), + ); + }, + name: 'contact'.translation, + icon: Icon(Icons.contact_mail_outlined), + ), + ], + ), + ); + } +} diff --git a/lib/services/helpers.dart b/lib/services/helpers.dart new file mode 100644 index 0000000..fc5d80c --- /dev/null +++ b/lib/services/helpers.dart @@ -0,0 +1,45 @@ +import 'package:url_launcher/url_launcher.dart'; + +String priceFormatter(double price) { + return price.toStringAsFixed(2) + ' TMT'; +} + +String safeValueDate(DateTime? dateTime) { + if (dateTime == null) return ''; + final String year = dateTime.year.toString(), + month = dateTime.month.toString().length < 2 + ? '0${dateTime.month}' + : '${dateTime.month.toString()}', + day = dateTime.day.toString().length < 2 + ? '0${dateTime.day}' + : '${dateTime.day.toString()}', + hour = dateTime.hour.toString().length < 2 + ? '0${dateTime.hour}' + : '${dateTime.hour.toString()}', + minute = dateTime.minute.toString().length < 2 + ? '0${dateTime.minute}' + : '${dateTime.minute.toString()}', + processed = [year, month, day].reversed.join('/') + ' $hour:$minute'; + return processed; +} + +void linkLauncher(String link) async { + if (await canLaunch(link)) launch(link); +} + +bool boolParser(dynamic value) { + return value != null && + value != '0' && + value != false && + value != 0 && + value != 'false'; +} + +String caitalize(String word) { + if (word.length <= 1) { + return word.toUpperCase(); + } else { + var first = word[0]; + return first.toUpperCase() + word.substring(1, word.length); + } +} diff --git a/lib/services/imageUpload.dart b/lib/services/imageUpload.dart new file mode 100644 index 0000000..f6087de --- /dev/null +++ b/lib/services/imageUpload.dart @@ -0,0 +1,67 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:async/async.dart'; +import 'package:path/path.dart'; +import 'package:birzha/models/exceptions/exception.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/user/user.dart'; + +typedef void OnUploadProgressCallback(int sentBytes, int totalBytes); + +Future uploadImage(Uri uri, User user, PlatformFile image, String attributeName, Map body, + {required OnUploadProgressCallback onUploadProgressCallback}) async { + var multipartRequest = _MultipartRequest("POST", uri, onProgress: onUploadProgressCallback); + var stream = http.ByteStream(DelegatingStream(File(image.path!).openRead())); + var length = image.size; + var multipartFile = http.MultipartFile(attributeName, stream, length, filename: basename(image.path!)); + multipartRequest.files.add(multipartFile); + multipartRequest.fields.addAll({...body}); + multipartRequest.headers.addAll({'Authorization': 'Bearer ${user.token}', 'Accept': 'application/json'}); + try { + var request = await multipartRequest.send(); + var byteArray = await request.stream.toBytes(); + var stringBody = utf8.decode(byteArray); + var result = jsonDecode(stringBody); + debugPrint('stringBody $result'); + + if (result is String) return result; + return result['success']?['backendCode'.translation]; + } catch (error) { + if (error is MessageException) + throw error; + else + throw OtherException(); + } +} + +class _MultipartRequest extends http.MultipartRequest { + _MultipartRequest( + String method, + Uri url, { + required this.onProgress, + }) : super(method, url); + + final OnUploadProgressCallback onProgress; + http.ByteStream finalize() { + final byteStream = super.finalize(); + + final total = this.contentLength; + int bytes = 0; + + final t = StreamTransformer.fromHandlers(handleData: (List data, EventSink> sink) { + bytes += data.length; + onProgress(bytes, total); + sink.add(data); + }, handleDone: (sink) { + sink.close(); + }, handleError: (err, trace, sink) { + sink.close(); + }); + final stream = byteStream.transform(t); + return http.ByteStream(stream); + } +} diff --git a/lib/services/modals.dart b/lib/services/modals.dart new file mode 100644 index 0000000..1a253e3 --- /dev/null +++ b/lib/services/modals.dart @@ -0,0 +1,353 @@ +import 'package:birzha/components/localizationOverride.dart'; +import 'package:birzha/components/radio.dart'; +import 'package:birzha/constants.dart'; +import 'package:birzha/countryCodes.dart'; +import 'package:birzha/models/attributes/attribute.dart'; +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:flutter/material.dart'; +import 'package:birzha/core/adaptix/adaptix.dart'; +import 'package:flag/flag.dart'; + +Future showLanguagePicker(BuildContext context) async { + return showModalBottomSheet( + context: context, + builder: (BuildContext context) { + return Container( + padding: EdgeInsets.only(top: 10.adaptedPx()), + decoration: BoxDecoration( + color: Theme.of(context).backgroundColor, + ), + height: 130.adaptedPx(), + child: ListView( + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context)), + children: [ + Align( + alignment: Alignment.centerLeft, + child: Column( + children: [ + GestureDetector( + onTap: () { + Navigator.of(context).pop('tk'); + }, + child: Row( + children: [ + Flag.fromCode( + FlagsCode.TM, + height: 30.adaptedPx(), + width: 30.adaptedPx(), + // fit: BoxFit.contain, + ), + SizedBox(width: 10.adaptedPx()), + Text( + 'turkmen'.translation, + // style: TextStyle( + // fontSize: 15.adaptedPx(), color: Colors.black) + style: Theme.of(context).textTheme.headline2, + ), + ], + ), + ), + SizedBox(height: 10.adaptedPx()), + GestureDetector( + onTap: () { + Navigator.of(context).pop('ru'); + }, + child: Row( + children: [ + Flag.fromCode( + FlagsCode.RU, + height: 30.adaptedPx(), + width: 30.adaptedPx(), + // fit: BoxFit.contain, + ), + SizedBox(width: 10.adaptedPx()), + Text( + 'russian'.translation, + style: Theme.of(context).textTheme.headline2, + ), + ], + ), + ), + SizedBox(height: 10.adaptedPx()), + GestureDetector( + onTap: () { + Navigator.of(context).pop('en'); + }, + child: Row( + children: [ + Flag.fromCode( + FlagsCode.US, + height: 30.adaptedPx(), + width: 30.adaptedPx(), + // fit: BoxFit.contain, + ), + SizedBox(width: 10.adaptedPx()), + Text( + 'english'.translation, + style: Theme.of(context).textTheme.headline2, + ), + ], + ), + ), + ], + ), + ), + ], + ), + ); + }, + ); +} + +Future attributeSelector( + BuildContext context, + AttributeWithValueNameMixin? groupValue, + List options) { + var radios = [ + for (var method in options) + RadioItem( + name: method.value, value: method, groupValue: groupValue), + ]; + return _picker( + context: context, + borderRadius: BorderRadius.vertical(top: Radius.circular(20.adaptedPx())), + items: radios, + height: (radios.length * 41.adaptedPx()) + + AppConstants.horizontalPadding(context) + + 32.adaptedPx(), + padding: EdgeInsets.symmetric( + horizontal: AppConstants.horizontalPadding(context)) + .copyWith(top: 10.adaptedPx()), + itemBuilder: (cntxt, id, dismiss) { + return item(radios[id], context, (val) { + dismiss(val); + }); + }); +} + +Future _picker({ + required List items, + required double height, + required EdgeInsets padding, + required BorderRadius borderRadius, + required BuildContext context, + required Widget Function(BuildContext, int, void Function(T)) itemBuilder, +}) { + return showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + useRootNavigator: true, + builder: (context2) { + return SizedBox( + height: height, + child: Container( + decoration: BoxDecoration( + borderRadius: borderRadius, + color: Theme.of(context).dialogBackgroundColor, + ), + child: SingleChildScrollView( + padding: padding, + child: Column( + mainAxisSize: MainAxisSize.min, + children: List.generate( + items.length, + (index) => itemBuilder(context2, index, + (T val) => Navigator.of(context2).pop(val)))))), + ); + }); +} + +Widget item( + RadioItem radio, BuildContext context, void Function(T) onChange) { + final inputStyle = TextStyle( + fontSize: 14.adaptedPx(), + ); + return GestureDetector( + onTap: () { + onChange(radio.value); + }, + child: Container( + margin: EdgeInsets.symmetric(vertical: 7.adaptedPx()), + padding: EdgeInsets.symmetric(vertical: 3.5.adaptedPx()), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Container( + margin: + EdgeInsets.only(right: AppConstants.horizontalPadding(context)), + child: RadioButton( + size: 17.adaptedPx(), + borderColor: Colors.grey, + checkedColor: Theme.of(context).accentColor.withOpacity(0.8), + uncheckedColor: Colors.grey.withOpacity(0.1), + borderWidth: 0.3.adaptedPx(), + animationDuration: Duration(milliseconds: 100), + onChange: (v) => onChange(v), + value: radio.value, + groupValue: radio.groupValue, + ), + ), + Expanded( + child: Container( + child: Text( + '${radio.name}', + style: inputStyle, + ), + ), + ) + ], + ), + ), + ); +} + +Future showCountryCodesSheet(BuildContext context) { + return showModalBottomSheet( + context: context, + isScrollControlled: true, + isDismissible: true, + barrierColor: Colors.black.withOpacity(0.5), + backgroundColor: Colors.transparent, + builder: (BuildContext context) { + return DraggableScrollableSheet( + initialChildSize: 0.5, //set this as you want + minChildSize: 0.4, //set this as you want + expand: false, + builder: (context, controller) => PhysicalModel( + color: Theme.of(context).cardColor, + elevation: 4.adaptedPx(), + borderRadius: + BorderRadius.vertical(top: Radius.circular(10.adaptedPx())), + child: ListView.separated( + separatorBuilder: (context, index) { + return const Divider( + height: 0, + ); + }, + padding: EdgeInsets.symmetric(vertical: 10.adaptedPx()), + controller: controller, + itemCount: countryCodes.length, + itemBuilder: (context, index) { + var title = countryCodes[index]['country_name']!; + var code = countryCodes[index]['dial_code']!; + return Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(10.adaptedPx()), + onTap: () { + Navigator.of(context).pop('$title $code'); + }, + child: Padding( + padding: EdgeInsets.symmetric( + vertical: 20.adaptedPx(), + horizontal: AppConstants.horizontalPadding(context), + ), + child: Row( + children: [ + Expanded( + child: Text('$title $code'), + ) + ], + ), + ), + ), + ); + }, + ), + ), + ); + }, + ); +} + +void showSnackBar(BuildContext ctx, + {SnackBar Function(String? content)? snackBar, + String? content, + Color? textColor, + Color? backgroundColor, + Duration? duration}) { + ScaffoldMessenger.of(ctx).hideCurrentSnackBar(); + ScaffoldMessenger.of(ctx).showSnackBar(snackBar == null + ? SnackBar( + padding: EdgeInsets.symmetric( + vertical: 5.adaptedPx(), + horizontal: 7.adaptedPx() + AppConstants.horizontalPadding(ctx)), + duration: duration ?? const Duration(seconds: 3), + backgroundColor: backgroundColor, + content: Text( + '$content', + style: TextStyle(fontSize: 15.adaptedPx(), color: textColor), + ), + ) + : snackBar(content)); +} + +Future yesOrNoDialog(BuildContext context, + {String? content, Widget? widgetContent}) async { + return (await showDialog( + context: context, + builder: (ctx) { + return LocalizationOverride( + builder: (context) => AlertDialog( + title: Text(MaterialLocalizations.of(context).alertDialogLabel), + titleTextStyle: Theme.of(context).textTheme.bodyText1?.copyWith( + fontWeight: FontWeight.w500, fontSize: 15.adaptedPx()), + titlePadding: EdgeInsets.all(18.adaptedPx()), + actions: [ + Theme( + data: Theme.of(context).copyWith( + colorScheme: Theme.of(context) + .colorScheme + .copyWith(primary: Theme.of(context).accentColor)), + child: TextButton( + onPressed: () { + Navigator.of(ctx).pop(true); + }, + child: Text( + MaterialLocalizations.of(context).continueButtonLabel, + style: TextStyle(fontSize: 11.8.adaptedPx()), + )), + ), + Theme( + data: Theme.of(context).copyWith( + colorScheme: Theme.of(context) + .colorScheme + .copyWith(primary: Theme.of(context).accentColor)), + child: TextButton( + onPressed: () { + Navigator.of(ctx).pop(false); + }, + child: Text( + MaterialLocalizations.of(context).cancelButtonLabel, + style: TextStyle(fontSize: 11.8.adaptedPx()), + )), + ), + ], + contentTextStyle: Theme.of(context) + .textTheme + .bodyText1 + ?.copyWith(height: 1.5), + content: Container( + width: Resizer( + xSmall: 200, + small: 350, + medium: 430, + large: 450, + xlarge: 700, + totalWidth: MediaQuery.of(context).size.width, + ).value, + child: Row( + children: [ + if (widgetContent != null) + Expanded(child: widgetContent) + else + Expanded(child: Text(content ?? "")) + ], + ), + ), + ), + ); + }) ?? + false); +} diff --git a/lib/services/requests.dart b/lib/services/requests.dart new file mode 100644 index 0000000..02520c6 --- /dev/null +++ b/lib/services/requests.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; +import 'package:http/http.dart' as http; +import 'package:birzha/core/orm/orm.dart'; + +const kApiPath = 'api/v1'; + +Uri baseUrl({required String path, Map? queryParameters, String? query}) => Uri( + scheme: 'https', + host: 'tmex.gov.tm', + path: '/$path', + queryParameters: queryParameters == null ? null : {...queryParameters}, + query: query, + ); + +class FutureGetList { + late final Uri api; + late final T Function(Map)? constructor; + late final List Function(http.Response)? parser; + + List defaultParser(http.Response response) { + String output = response.body; + List list = jsonDecode(output); + return list.map((entity) => constructor!(entity)).toList(); + } + + Future> fetch([Map? headers]) async { + final response = await http.get(api, headers: {...?headers}); + if (constructor != null) { + return defaultParser(response); + } else if (parser != null) { + return parser!(response); + } else { + return []; + } + } + + FutureGetList(this.api, {this.constructor, this.parser}); +} diff --git a/lib/services/streamFetchService.dart b/lib/services/streamFetchService.dart new file mode 100644 index 0000000..4e85d8d --- /dev/null +++ b/lib/services/streamFetchService.dart @@ -0,0 +1,38 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; + +mixin StreamControlledMixin on State { + Future Function() get asyncAction; + StreamSubscription? channel; + bool isLoading = false; + void start(BuildContext context) {} + void done(BuildContext context) {} + void error(BuildContext context, dynamic error) {} + void onDataRecived(BuildContext context, D data) {} + + void cancel() { + channel?.cancel(); + } + + void connect(BuildContext ctx) { + cancel(); + this.setState(() { + start(ctx); + isLoading = true; + this.channel = asyncAction().asStream().listen((event) { + this.onDataRecived(ctx, event); + }) + ..onDone(() { + done(ctx); + if (mounted) + this.setState(() { + isLoading = false; + }); + }) + ..onError((e) { + error(ctx, e); + }); + }); + } +} diff --git a/lib/services/textMetaData.dart b/lib/services/textMetaData.dart new file mode 100644 index 0000000..f9fbbb9 --- /dev/null +++ b/lib/services/textMetaData.dart @@ -0,0 +1,41 @@ +import 'dart:async'; + +import 'package:flutter/cupertino.dart'; +import 'package:flutter/services.dart'; +import 'package:birzha/services/validator.dart'; + +class TextInputMetaData { + final String key; + final String name; + final Validation validation; + final List? formatters; + final String? hint; + final String? label; + final Widget? bottomInfo; + final FutureOr Function(BuildContext)? pickerMode; + final TextInputType? type; + final bool autoFocus; + final bool password; + final Color? fillColor; + final bool filled; + final bool readOnly; + final bool showSuffix; + + TextInputMetaData({ + this.filled = false, + this.fillColor, + this.readOnly = false, + this.showSuffix = false, + required this.name, + this.password = false, + this.autoFocus = false, + this.type, + required this.validation, + required this.key, + this.formatters, + this.hint, + this.label, + this.bottomInfo, + this.pickerMode, + }); +} diff --git a/lib/services/translationServices.dart b/lib/services/translationServices.dart new file mode 100644 index 0000000..508d93e --- /dev/null +++ b/lib/services/translationServices.dart @@ -0,0 +1,24 @@ +import 'package:birzha/models/settings/settingsModel.dart'; +import 'package:birzha/models/translationModel.dart'; + +List translationsFromMap(Map data){ + var translationRaw = data['translations']; + if(translationRaw == null) + return []; + else{ + var realTranslations = (translationRaw as List).map((data) => TranslationModel(data)).toList(); + return realTranslations; + } +} + +TranslationModel? getTranslationAccordingToLocale( List translations){ + var backendCode = 'backendCode'.translation; + TranslationModel? needed; + for(var trans in translations){ + if(trans.primaryKey == backendCode){ + needed = trans; + break; + } + } + return needed; +} \ No newline at end of file diff --git a/lib/services/validator.dart b/lib/services/validator.dart new file mode 100644 index 0000000..dad4b57 --- /dev/null +++ b/lib/services/validator.dart @@ -0,0 +1,20 @@ +class Validation{ + + final List conditions; + + String? validate(String input){ + for(var condition in conditions){ + if(condition(input) != null){ + return condition(input); + } + } + return null; + } + + Validation({required this.conditions}); + + static bool phoneValidator(String input) => RegExp(r'86[1-5]\d{6}$').hasMatch('${input.trim()}'); + + static bool emailValidator(String input) => RegExp( r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$').hasMatch('${input.trim()}'); + +} \ No newline at end of file diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..db93402 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,871 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + animate_do: + dependency: "direct main" + description: + name: animate_do + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + archive: + dependency: transitive + description: + name: archive + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.0" + args: + dependency: transitive + description: + name: args + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.2" + badges: + dependency: "direct main" + description: + name: badges + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + cached_network_image: + dependency: "direct main" + description: + name: cached_network_image + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" + cached_network_image_platform_interface: + dependency: transitive + description: + name: cached_network_image_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + cached_network_image_web: + dependency: transitive + description: + name: cached_network_image_web + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + chewie: + dependency: transitive + description: + name: chewie + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.2" + chewie_audio: + dependency: transitive + description: + name: chewie_audio + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.16.0" + crypto: + dependency: transitive + description: + name: crypto + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" + csslib: + dependency: transitive + description: + name: csslib + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.1" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + dio: + dependency: "direct main" + description: + name: dio + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.6" + enum_to_string: + dependency: transitive + description: + name: enum_to_string + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + expandable: + dependency: "direct main" + description: + name: expandable + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.1" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + ffi: + dependency: transitive + description: + name: ffi + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" + file: + dependency: transitive + description: + name: file + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.2" + file_picker: + dependency: "direct main" + description: + name: file_picker + url: "https://pub.dartlang.org" + source: hosted + version: "4.5.1" + flag: + dependency: "direct main" + description: + name: flag + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.1" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_blurhash: + dependency: transitive + description: + name: flutter_blurhash + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.6" + flutter_cache_manager: + dependency: transitive + description: + name: flutter_cache_manager + url: "https://pub.dartlang.org" + source: hosted + version: "3.3.0" + flutter_html: + dependency: "direct main" + description: + name: flutter_html + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" + flutter_launcher_icons: + dependency: "direct dev" + description: + name: flutter_launcher_icons + url: "https://pub.dartlang.org" + source: hosted + version: "0.9.2" + flutter_layout_grid: + dependency: transitive + description: + name: flutter_layout_grid + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.6" + flutter_localizations: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_math_fork: + dependency: transitive + description: + name: flutter_math_fork + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.2+2" + flutter_native_splash: + dependency: "direct dev" + description: + name: flutter_native_splash + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.3" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + url: "https://pub.dartlang.org" + source: hosted + version: "0.22.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + get: + dependency: "direct main" + description: + name: get + url: "https://pub.dartlang.org" + source: hosted + version: "4.6.1" + google_nav_bar: + dependency: "direct main" + description: + name: google_nav_bar + url: "https://pub.dartlang.org" + source: hosted + version: "5.0.6" + html: + dependency: transitive + description: + name: html + url: "https://pub.dartlang.org" + source: hosted + version: "0.15.0" + http: + dependency: "direct main" + description: + name: http + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.4" + http_parser: + dependency: transitive + description: + name: http_parser + url: "https://pub.dartlang.org" + source: hosted + version: "4.0.0" + idb_shim: + dependency: transitive + description: + name: idb_shim + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" + image: + dependency: transitive + description: + name: image + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.3" + intl: + dependency: "direct main" + description: + name: intl + url: "https://pub.dartlang.org" + source: hosted + version: "0.17.0" + js: + dependency: transitive + description: + name: js + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.4" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + nested: + dependency: transitive + description: + name: nested + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + numerus: + dependency: transitive + description: + name: numerus + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" + octo_image: + dependency: transitive + description: + name: octo_image + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + path_drawing: + dependency: transitive + description: + name: path_drawing + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.1+1" + path_parsing: + dependency: transitive + description: + name: path_parsing + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.1" + path_provider: + dependency: "direct main" + description: + name: path_provider + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.12" + path_provider_ios: + dependency: transitive + description: + name: path_provider_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.8" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.5" + path_provider_macos: + dependency: transitive + description: + name: path_provider_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + pedantic: + dependency: transitive + description: + name: pedantic + url: "https://pub.dartlang.org" + source: hosted + version: "1.11.1" + petitparser: + dependency: transitive + description: + name: petitparser + url: "https://pub.dartlang.org" + source: hosted + version: "4.4.0" + photo_view: + dependency: "direct main" + description: + name: photo_view + url: "https://pub.dartlang.org" + source: hosted + version: "0.13.0" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + process: + dependency: transitive + description: + name: process + url: "https://pub.dartlang.org" + source: hosted + version: "4.2.4" + provider: + dependency: "direct main" + description: + name: provider + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.2" + quiver: + dependency: transitive + description: + name: quiver + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1+1" + rxdart: + dependency: transitive + description: + name: rxdart + url: "https://pub.dartlang.org" + source: hosted + version: "0.27.3" + sembast: + dependency: "direct main" + description: + name: sembast + url: "https://pub.dartlang.org" + source: hosted + version: "3.2.0" + sembast_web: + dependency: "direct main" + description: + name: sembast_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1+1" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.13" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.11" + shared_preferences_ios: + dependency: transitive + description: + name: shared_preferences_ios + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + shared_preferences_macos: + dependency: transitive + description: + name: shared_preferences_macos + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.2" + sqflite: + dependency: transitive + description: + name: sqflite + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2+1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1+1" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + synchronized: + dependency: transitive + description: + name: synchronized + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0+2" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.9" + tuple: + dependency: transitive + description: + name: tuple + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" + typed_data: + dependency: transitive + description: + name: typed_data + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + universal_io: + dependency: transitive + description: + name: universal_io + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.4" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.20" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.15" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + url: "https://pub.dartlang.org" + source: hosted + version: "6.0.15" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.5" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.9" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.0" + uuid: + dependency: transitive + description: + name: uuid + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.6" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" + very_good_analysis: + dependency: transitive + description: + name: very_good_analysis + url: "https://pub.dartlang.org" + source: hosted + version: "2.4.0" + video_player: + dependency: transitive + description: + name: video_player + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.0" + video_player_android: + dependency: transitive + description: + name: video_player_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.2" + video_player_avfoundation: + dependency: transitive + description: + name: video_player_avfoundation + url: "https://pub.dartlang.org" + source: hosted + version: "2.3.1" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "5.1.1" + video_player_web: + dependency: transitive + description: + name: video_player_web + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.7" + wakelock: + dependency: transitive + description: + name: wakelock + url: "https://pub.dartlang.org" + source: hosted + version: "0.6.1+2" + wakelock_macos: + dependency: transitive + description: + name: wakelock_macos + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.0" + wakelock_platform_interface: + dependency: transitive + description: + name: wakelock_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "0.3.0" + wakelock_web: + dependency: transitive + description: + name: wakelock_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.0" + wakelock_windows: + dependency: transitive + description: + name: wakelock_windows + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0" + webview_flutter: + dependency: transitive + description: + name: webview_flutter + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.0" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.5" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + url: "https://pub.dartlang.org" + source: hosted + version: "2.7.2" + win32: + dependency: transitive + description: + name: win32 + url: "https://pub.dartlang.org" + source: hosted + version: "2.5.1" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + url: "https://pub.dartlang.org" + source: hosted + version: "0.2.0+1" + xml: + dependency: transitive + description: + name: xml + url: "https://pub.dartlang.org" + source: hosted + version: "5.3.1" + yaml: + dependency: transitive + description: + name: yaml + url: "https://pub.dartlang.org" + source: hosted + version: "3.1.0" +sdks: + dart: ">=2.17.0-0 <3.0.0" + flutter: ">=2.10.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..4994b4e --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,120 @@ +name: birzha +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `pub publish`. This is preferred for private packages. +publish_to: "none" # Remove this line if you wish to publish to pub.dev + +version: 3.0.2+15 + +environment: + sdk: ">=2.12.0 <3.0.0" + +dependencies: + flutter_svg: ^0.22.0 + google_nav_bar: ^5.0.5 + provider: ^6.0.2 + file_picker: ^4.0.1 + flag: ^5.0.1 + flutter: + sdk: flutter + flutter_localizations: + sdk: flutter + intl: ^0.17.0 + shared_preferences: ^2.0.6 + http: ^0.13.3 + cached_network_image: ^3.0.0 + flutter_html: ^2.2.1 + photo_view: ^0.13.0 + url_launcher: ^6.0.9 + sembast: ^3.0.4 + path_provider: ^2.0.4 + sembast_web: ^2.0.1+1 + badges: ^2.0.2 + get: ^4.6.1 + dio: ^4.0.0 + animate_do: ^2.1.0 + # flutter_screenutil: ^5.4.0+1 + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + expandable: ^5.0.1 + +flutter_native_splash: + color: "#42a5f5" + image: "assets/images/Logo.png" + android_gravity: center + fullscreen: true + android: true + ios: true + +flutter_icons: + android: "launcher_icon" + ios: true + image_path: "assets/icon.jpg" + +dev_dependencies: + flutter_native_splash: ^1.2.0 + flutter_launcher_icons: ^0.9.2 + + # background_image: 'assets/' + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec +# The following section is specific to Flutter. +flutter: + generate: true + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + assets: + - assets/images/appBarIcon.svg + - assets/images/unauth.svg + + - assets/icons/profile_screen/cart.svg + - assets/icons/profile_screen/exit.svg + - assets/icons/profile_screen/message.svg + - assets/icons/profile_screen/popup_history.svg + - assets/icons/profile_screen/profile.svg + - assets/icons/profile_screen/phone_not_verified.svg + - assets/icons/profile_screen/phone_verified.svg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + fonts: + - family: SVGs_data + fonts: + - asset: assets/fonts/svgs.ttf + + - family: MyFlutterApp + fonts: + - asset: assets/fonts/AppBarIcons.ttf + + - family: Settings_Icons + fonts: + - asset: assets/fonts/Settings_Icons.ttf + - family: TabNavIcons + fonts: + - asset: assets/fonts/TabNavIcons.ttf + + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..ac576a6 --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,14 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility that Flutter provides. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + var a = 0; + expect(++a, 1); + }); +} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 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 MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..9528430 --- /dev/null +++ b/web/index.html @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + birzha + + + + + + + + \ No newline at end of file diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..52be736 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,23 @@ +{ + "name": "birzha", + "short_name": "birzha", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} diff --git a/web/splash/img/dark-1x.png b/web/splash/img/dark-1x.png new file mode 100644 index 0000000000000000000000000000000000000000..38482c2a174957fdfdcf5f65dd741dd9c6280db6 GIT binary patch literal 23588 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%0DNOLk8b4}RWOE} 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 literal 0 HcmV?d00001 diff --git a/web/splash/img/light-1x.png b/web/splash/img/light-1x.png new file mode 100644 index 0000000000000000000000000000000000000000..38482c2a174957fdfdcf5f65dd741dd9c6280db6 GIT binary patch literal 23588 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%0DNOLk8b4}RWOE} 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 literal 0 HcmV?d00001 diff --git a/web/splash/style.css b/web/splash/style.css new file mode 100644 index 0000000..d222ab6 --- /dev/null +++ b/web/splash/style.css @@ -0,0 +1,43 @@ +body, html { + margin:0; + height:100%; + background: #42a5f5; + background-image: url("img/light-background.png"); + background-size: 100% 100%; +} + +.center { + margin: 0; + position: absolute; + top: 50%; + left: 50%; + -ms-transform: translate(-50%, -50%); + transform: translate(-50%, -50%); +} + +.contain { + display:block; + width:100%; height:100%; + object-fit: contain; +} + +.stretch { + display:block; + width:100%; height:100%; +} + +.cover { + display:block; + width:100%; height:100%; + object-fit: cover; +} + +@media (prefers-color-scheme: dark) { + body { + margin:0; + height:100%; + background: #42a5f5; + background-image: url("img/dark-background.png"); + background-size: 100% 100%; + } +} diff --git a/windows/.gitignore b/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt new file mode 100644 index 0000000..8815dd6 --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,95 @@ +cmake_minimum_required(VERSION 3.14) +project(birzha LANGUAGES CXX) + +set(BINARY_NAME "birzha") + +cmake_policy(SET CMP0063 NEW) + +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Configure build options. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() + +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") + +# Flutter library and tool build rules. +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build +add_subdirectory("runner") + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..b2e4bd8 --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,103 @@ +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + windows-x64 $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..4f78848 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..88b22e5 --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..de2d891 --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) +apply_standard_settings(${BINARY_NAME}) +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc new file mode 100644 index 0000000..2aca545 --- /dev/null +++ b/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#ifdef FLUTTER_BUILD_NUMBER +#define VERSION_AS_NUMBER FLUTTER_BUILD_NUMBER +#else +#define VERSION_AS_NUMBER 1,0,0 +#endif + +#ifdef FLUTTER_BUILD_NAME +#define VERSION_AS_STRING #FLUTTER_BUILD_NAME +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.tpsadvertising.digital" "\0" + VALUE "FileDescription", "birzha" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "birzha" "\0" + VALUE "LegalCopyright", "Copyright (C) 2022 com.tpsadvertising.digital. All rights reserved." "\0" + VALUE "OriginalFilename", "birzha.exe" "\0" + VALUE "ProductName", "birzha" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..b43b909 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,61 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp new file mode 100644 index 0000000..a8fd971 --- /dev/null +++ b/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.CreateAndShow(L"birzha", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/windows/runner/resource.h b/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 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 literal 0 HcmV?d00001 diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..c977c4a --- /dev/null +++ b/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000..d19bdbb --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,64 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr); + if (target_length == 0) { + return std::string(); + } + std::string utf8_string; + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, utf8_string.data(), + target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/windows/runner/utils.h b/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp new file mode 100644 index 0000000..c10f08d --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,245 @@ +#include "win32_window.h" + +#include + +#include "resource.h" + +namespace { + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + FreeLibrary(user32_module); + } +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW | WS_VISIBLE, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + return OnCreate(); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000..17ba431 --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,98 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates and shows a win32 window with |title| and position and size using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size to will treat the width height passed in to this function + // as logical pixels and scale to appropriate for the default monitor. Returns + // true if the window was created successfully. + bool CreateAndShow(const std::wstring& title, + const Point& origin, + const Size& size); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responsponds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_