39 Commits

Author SHA1 Message Date
3a74b8017d Scooter order payment screen fix 2026-09-15 21:28:33 +03:00
153a763b6f Registration pipeline chenged - fill profile step added. Order payment fixed 2026-09-14 19:20:31 +03:00
7460408784 Finish screen - attention message added 2026-09-14 08:42:25 +03:00
5f57af2ad2 bug fixes 2026-09-04 13:41:57 +03:00
cf5b56e365 Tariff subsriptionId fix 2026-08-31 10:37:08 +03:00
b0c9f6dc17 fix qr 2026-08-31 09:57:40 +03:00
ece8e7ba79 bug fixes 2026-08-31 09:53:29 +03:00
02b3e5caa8 Tariff description fix, iOS payment card binding fix 2026-08-31 09:18:33 +03:00
a556dc5736 bug fixes 2026-08-29 00:00:09 +03:00
6513a004d9 fix profile 2026-08-18 15:09:53 +03:00
80a95ece5b fix to prod 2026-08-14 13:47:11 +03:00
f53fea576e add page company detail 2026-08-13 09:34:06 +03:00
182be1049b some fix
# Conflicts:
#	lib/presentation/navigation/app_router.dart
#	pubspec.yaml
2026-08-11 00:23:16 +03:00
c9b8d143d1 fixing the app launch bug 2026-07-27 11:06:04 +03:00
d5f70ee9c4 change package name 2026-07-19 20:27:26 +03:00
99d2875b56 Merge pull request 'map fix' (#8) from fix/ios-fix into main
Reviewed-on: #8
2026-07-16 11:16:14 +00:00
46cd22c287 fix merge conflict 2026-07-16 14:14:22 +03:00
0a6c40181a Merge pull request 'add test block' (#7) from fix/bug-fix into main
Reviewed-on: #7
2026-07-16 07:26:56 +00:00
fcb23e0d5f fix merge conflict 2026-07-16 10:15:10 +03:00
7a2c214ff5 map fix 2026-07-15 22:58:33 +03:00
11c00ad2cc add test block 2026-07-15 22:46:42 +03:00
419b54d5dd Merge pull request 'fix payment card change. fix adding a new payment card' (#6) from fix/bug-fix into main
Reviewed-on: #6
2026-07-13 12:47:55 +00:00
a6e8b9d070 fix payment card change. fix adding a new payment card 2026-07-13 15:46:34 +03:00
4a919a5bcc Merge pull request 'fix add new card in bottomsheet' (#5) from fix/bug-fix into main
Reviewed-on: #5
2026-07-13 08:50:59 +00:00
e91f373258 fix add new card in bottomsheet 2026-07-13 11:49:00 +03:00
902c6d27a4 Merge pull request 'fix/bug-fix' (#4) from fix/bug-fix into main
Reviewed-on: #4
2026-07-12 22:53:19 +00:00
98c5a7a1d1 fix 2026-07-13 01:38:13 +03:00
9eda119527 fix 2026-07-08 13:09:20 +03:00
939b5be7d8 Merge pull request 'fix/ios-launch' (#3) from fix/ios-launch into main
Reviewed-on: #3
2026-06-01 15:02:16 +00:00
10c21e4ae3 resolved merge conflicts 2026-06-01 18:00:44 +03:00
406b2bc2dc Merge pull request 'fix/bug-fix' (#1) from fix/bug-fix into main
Reviewed-on: #1
2026-06-01 14:29:39 +00:00
b9da1d3064 fix styles on the add card page, move the parser to a separate file, change the styles of the page of one news item, add a parser for the subscription page, add the input field for the qr code 2026-06-01 17:15:08 +03:00
0b6757e26f create promocode page 2026-06-01 14:35:46 +03:00
134ffdde60 fix functional bugs 2026-05-29 11:40:55 +03:00
bb49bbd0f7 docs(ios): update README for simulator setup and build instructions
- Translated and reorganized instructions for running the app on the iOS simulator.
- Added specific commands for terminal usage and emphasized the importance of executing commands from the correct project directory.
- Removed outdated sections and streamlined the content for clarity and relevance.

This update enhances the documentation for developers working with the iOS simulator.
2026-05-25 15:33:37 +03:00
7779803ccc chore: update dependencies and configurations for iOS build
- Updated mobile_scanner dependency version to 7.0.0 in pubspec.yaml.
- Adjusted versions of several packages in pubspec.lock.
- Added exclusion of arm64 architecture for iOS simulator in Podfile and xcconfig files to support Apple Silicon.
- Cleaned up Podfile.lock by removing unused dependencies.

This update ensures compatibility with the latest mobile_scanner and improves build stability on M1/M4 devices.
2026-05-25 15:23:13 +03:00
591265a7fc fix order history, add CheckUser check before starting the trip, fix dialog for cancel the order, add dialog for finish the order 2026-05-21 18:00:26 +03:00
c996d0847f add notification, fix appbar,fix style subscription 2026-05-21 12:19:06 +03:00
713cc2520b fix(ios): запуск на iOS — MapKit, ключ из xcconfig, CocoaPods
- AppDelegate: YMKMapKit до super, регистрация плагинов по шаблону Flutter 3.41
- Info.plist: YandexMapKitApiKey из $(YANDEX_MAPKIT_API_KEY)
- Debug/Release/Profile.xcconfig: ключ, include Pods и опциональный Secrets
- Podfile, workspace, pbxproj; .gitignore для Secrets.xcconfig, пример Secrets
- ios/README.md

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 10:32:18 +03:00
388 changed files with 27136 additions and 21591 deletions

View File

@@ -15,7 +15,7 @@ plugins {
} }
android { android {
namespace = "com.sparkit.be_happy" namespace = "com.behappybel.behappy"
compileSdk = flutter.compileSdkVersion compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973" ndkVersion = "27.0.12077973"
@@ -44,7 +44,7 @@ android {
defaultConfig { defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.sparkit.be_happy" applicationId = "com.behappybel.behappy"
// You can update the following values to match your application needs. // You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config. // For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 26 minSdk = 26

View File

@@ -8,6 +8,7 @@
<queries> <queries>
<intent> <intent>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" /> <data android:scheme="https" />
</intent> </intent>
<intent> <intent>
@@ -25,7 +26,7 @@
<meta-data <meta-data
android:name="com.yandex.runtime.API_KEY" android:name="com.yandex.runtime.API_KEY"
android:value="a0ef1404-2650-4f28-9891-c965ecc09174" /> android:value="45fe500d-b549-4444-9e4b-3b2acd78ee2c" />
<activity <activity
android:name=".MainActivity" android:name=".MainActivity"
@@ -49,6 +50,14 @@
<action android:name="android.intent.action.MAIN"/> <action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/> <category android:name="android.intent.category.LAUNCHER"/>
</intent-filter> </intent-filter>
<intent-filter android:label="card_binding_deep_link">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="com.behappy.app" android:host="card-result" />
</intent-filter>
</activity> </activity>
<!-- Don't delete the meta-data below. <!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java --> This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->

View File

@@ -1,4 +1,4 @@
package com.sparkit.be_happy package com.behappybel.behappy
import android.os.Bundle import android.os.Bundle
import com.yandex.mapkit.MapKitFactory import com.yandex.mapkit.MapKitFactory
@@ -6,7 +6,7 @@ import io.flutter.embedding.android.FlutterActivity
class MainActivity : FlutterActivity() { class MainActivity : FlutterActivity() {
override protected fun onCreate(savedInstanceState: Bundle?) { override protected fun onCreate(savedInstanceState: Bundle?) {
MapKitFactory.setApiKey("a0ef1404-2650-4f28-9891-c965ecc09174") MapKitFactory.setApiKey("45fe500d-b549-4444-9e4b-3b2acd78ee2c")
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

View File

@@ -1,12 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" /> <item>
<bitmap android:gravity="fill" android:src="@drawable/background"/>
<!-- You can insert your own image assets here --> </item>
<!-- <item> <item>
<bitmap <bitmap android:gravity="center" android:src="@drawable/splash"/>
android:gravity="center" </item>
android:src="@mipmap/launch_image" />
</item> -->
</layer-list> </layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

View File

@@ -1,12 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" /> <item>
<bitmap android:gravity="fill" android:src="@drawable/background"/>
<!-- You can insert your own image assets here --> </item>
<!-- <item> <item>
<bitmap <bitmap android:gravity="center" android:src="@drawable/splash"/>
android:gravity="center" </item>
android:src="@mipmap/launch_image" />
</item> -->
</layer-list> </layer-list>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 442 B

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 721 B

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -5,6 +5,10 @@
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowBackground">?android:colorBackground</item>
</style>
</resources>

View File

@@ -5,6 +5,10 @@
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screen on the activity. Automatically removed when
the Flutter engine draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
<item name="android:forceDarkAllowed">false</item>
<item name="android:windowFullscreen">false</item>
<item name="android:windowDrawsSystemBarBackgrounds">false</item>
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style> </style>
<!-- Theme applied to the Android Window as soon as the process has started. <!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your This theme determines the color of the Android Window while your

View File

@@ -2,3 +2,8 @@ org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
yandexMapkit.variant=full yandexMapkit.variant=full
# This builtInKotlin flag was added automatically by Flutter migrator
android.builtInKotlin=false
kotlin.incremental=false
# This newDsl flag was added automatically by Flutter migrator
android.newDsl=false

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

BIN
assets/icons/failed.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

BIN
assets/icons/fine.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
assets/icons/success.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

BIN
assets/icons/timer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
assets/news_def.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

BIN
assets/payment_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
assets/rules_alpha.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
assets/rules_apple_pay.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
assets/rules_belcard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
assets/rules_mastercard.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
assets/rules_visa.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
assets/splash_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
assets/splash_map.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

BIN
assets/tech_works.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

3
devtools_options.yaml Normal file
View File

@@ -0,0 +1,3 @@
description: This file stores settings for Dart & Flutter DevTools.
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
extensions:

View File

@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>MinimumOSVersion</key>
<string>13.0</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>en</string> <string>en</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
@@ -20,7 +22,5 @@
<string>????</string> <string>????</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key>
<string>12.0</string>
</dict> </dict>
</plist> </plist>

View File

@@ -1 +1,6 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"
#include? "Secrets.xcconfig"
YANDEX_MAPKIT_API_KEY=45fe500d-b549-4444-9e4b-3b2acd78ee2c
// Переопределение Pods/ML Kit: arm64 для симулятора на Apple Silicon (M1/M4)
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386

View File

@@ -0,0 +1,5 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"
#include "Generated.xcconfig"
#include? "Secrets.xcconfig"
YANDEX_MAPKIT_API_KEY=45fe500d-b549-4444-9e4b-3b2acd78ee2c
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386

View File

@@ -1 +1,5 @@
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig" #include "Generated.xcconfig"
#include? "Secrets.xcconfig"
YANDEX_MAPKIT_API_KEY=45fe500d-b549-4444-9e4b-3b2acd78ee2c
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386

View File

@@ -0,0 +1,2 @@
// Локальные переопределения (опционально). Не задавайте YANDEX_MAPKIT_API_KEY плейсхолдером —
// рабочий ключ задаётся в конце Debug/Release/Profile.xcconfig после этого include.

View File

@@ -0,0 +1,3 @@
// Скопируй в ios/Flutter/Secrets.xcconfig (файл в .gitignore) для своих локальных xcconfig-переменных.
// Ключ MapKit задаётся в конце Debug/Release/Profile.xcconfig — не подставляйте туда тестовый плейсхолдер вместо реального ключа.
// https://developer.tech.yandex.ru/

50
ios/Podfile Normal file
View File

@@ -0,0 +1,50 @@
# image_picker_ios и др. требуют минимум iOS 13
platform :ios, '15.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
ENV['YANDEX_MAPKIT_VARIANT'] = 'full'
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!
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config|
# ML Kit исключает arm64 для симулятора → сборка только x86_64.
# На M1 это ещё могло работать через Rosetta; на M4 симулятор только arm64.
config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'i386'
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0'
end
end
end

80
ios/Podfile.lock Normal file
View File

@@ -0,0 +1,80 @@
PODS:
- device_info_plus (0.0.1):
- Flutter
- Flutter (1.0.0)
- flutter_native_splash (2.4.3):
- Flutter
- flutter_secure_storage (6.0.0):
- Flutter
- geolocator_apple (1.2.0):
- Flutter
- FlutterMacOS
- image_picker_ios (0.0.1):
- Flutter
- mobile_scanner (7.0.0):
- Flutter
- FlutterMacOS
- shared_preferences_foundation (0.0.1):
- Flutter
- FlutterMacOS
- url_launcher_ios (0.0.1):
- Flutter
- yandex_mapkit (0.0.1):
- Flutter
- YandexMapsMobile (= 4.22.0-full)
- YandexMapsMobile (4.22.0-full)
DEPENDENCIES:
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- Flutter (from `Flutter`)
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
- geolocator_apple (from `.symlinks/plugins/geolocator_apple/darwin`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- yandex_mapkit (from `.symlinks/plugins/yandex_mapkit/ios`)
SPEC REPOS:
trunk:
- YandexMapsMobile
EXTERNAL SOURCES:
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
Flutter:
:path: Flutter
flutter_native_splash:
:path: ".symlinks/plugins/flutter_native_splash/ios"
flutter_secure_storage:
:path: ".symlinks/plugins/flutter_secure_storage/ios"
geolocator_apple:
:path: ".symlinks/plugins/geolocator_apple/darwin"
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
mobile_scanner:
:path: ".symlinks/plugins/mobile_scanner/darwin"
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
yandex_mapkit:
:path: ".symlinks/plugins/yandex_mapkit/ios"
SPEC CHECKSUMS:
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
yandex_mapkit: b0468cf6fdc2e5ef315e08c081cb48763db1edee
YandexMapsMobile: 27e6e45425bb61f0be2dbc2bf02d4e64926691a9
PODFILE CHECKSUM: 4db91eb18e4c468b9b75ce0a1fbe33194b57f06a
COCOAPODS: 1.16.2

23
ios/README.md Normal file
View File

@@ -0,0 +1,23 @@
# Запуск на симуляторе (Mac)
**Терминал** (⌘ + `):
```bash
cd /Users/commercesparkit.by/Desktop/projekt/be_happy_public
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
open -a Simulator
flutter run
```
Первый раз или после обновления кода:
```bash
cd /Users/commercesparkit.by/Desktop/projekt/be_happy_public
export LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8
flutter pub get
cd ios && pod install && cd ..
open -a Simulator
flutter run
```
Важно: команды только из папки `be_happy_public`, не из `~`.

View File

@@ -10,7 +10,9 @@
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
719658A7EA74BCF79744189C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 815E41E9A67B82F3B5893FB0 /* Pods_Runner.framework */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
947230899A63DCC5FC354559 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A5825CAAC7BEAFA8756F6D22 /* Pods_RunnerTests.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
@@ -40,28 +42,46 @@
/* End PBXCopyFilesBuildPhase section */ /* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
12F1F4F8ABC8CE708CB9918F /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; }; 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; }; 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; }; 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; }; 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
4AADFAE03DF1A02E1E799949 /* 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 = "<group>"; };
53B78B2283B7ADCE0208F756 /* 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 = "<group>"; };
673086666704B99027FC010B /* 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 = "<group>"; };
6EC6FEDB5882EB1ECF391D95 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
7AFC7F9B8515A109C72DDF1B /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
815E41E9A67B82F3B5893FB0 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; }; 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
9740EEB41CF90195004384FC /* Profile.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Profile.xcconfig; path = Flutter/Profile.xcconfig; sourceTree = "<group>"; };
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; 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 = "<group>"; }; 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A5825CAAC7BEAFA8756F6D22 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
83F4E53737A5B4793588BFEB /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
947230899A63DCC5FC354559 /* Pods_RunnerTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
97C146EB1CF9000F007C117D /* Frameworks */ = { 97C146EB1CF9000F007C117D /* Frameworks */ = {
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
719658A7EA74BCF79744189C /* Pods_Runner.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -76,12 +96,22 @@
path = RunnerTests; path = RunnerTests;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
4E47A3B8F8440AE11EF826D6 /* Frameworks */ = {
isa = PBXGroup;
children = (
815E41E9A67B82F3B5893FB0 /* Pods_Runner.framework */,
A5825CAAC7BEAFA8756F6D22 /* Pods_RunnerTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = { 9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
9740EEB21CF90195004384FC /* Debug.xcconfig */, 9740EEB21CF90195004384FC /* Debug.xcconfig */,
7AFA3C8E1D35360C0083082E /* Release.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
9740EEB41CF90195004384FC /* Profile.xcconfig */,
9740EEB31CF90195004384FC /* Generated.xcconfig */, 9740EEB31CF90195004384FC /* Generated.xcconfig */,
); );
name = Flutter; name = Flutter;
@@ -94,6 +124,8 @@
97C146F01CF9000F007C117D /* Runner */, 97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */, 97C146EF1CF9000F007C117D /* Products */,
331C8082294A63A400263BE5 /* RunnerTests */, 331C8082294A63A400263BE5 /* RunnerTests */,
BBAC3160211F77BA6C1CDBEB /* Pods */,
4E47A3B8F8440AE11EF826D6 /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@@ -121,6 +153,19 @@
path = Runner; path = Runner;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
BBAC3160211F77BA6C1CDBEB /* Pods */ = {
isa = PBXGroup;
children = (
4AADFAE03DF1A02E1E799949 /* Pods-Runner.debug.xcconfig */,
673086666704B99027FC010B /* Pods-Runner.release.xcconfig */,
53B78B2283B7ADCE0208F756 /* Pods-Runner.profile.xcconfig */,
7AFC7F9B8515A109C72DDF1B /* Pods-RunnerTests.debug.xcconfig */,
12F1F4F8ABC8CE708CB9918F /* Pods-RunnerTests.release.xcconfig */,
6EC6FEDB5882EB1ECF391D95 /* Pods-RunnerTests.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@@ -128,8 +173,10 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
buildPhases = ( buildPhases = (
8320BCAEA155F95875F06656 /* [CP] Check Pods Manifest.lock */,
331C807D294A63A400263BE5 /* Sources */, 331C807D294A63A400263BE5 /* Sources */,
331C807F294A63A400263BE5 /* Resources */, 331C807F294A63A400263BE5 /* Resources */,
83F4E53737A5B4793588BFEB /* Frameworks */,
); );
buildRules = ( buildRules = (
); );
@@ -145,12 +192,15 @@
isa = PBXNativeTarget; isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = ( buildPhases = (
C59C8F9337F753AC74343087 /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */, 9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */, 97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */, 97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */, 97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */, 9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
FB90C79E7B88832806AD3371 /* [CP] Embed Pods Frameworks */,
81264E30AB9A7C4C10AB44BA /* [CP] Copy Pods Resources */,
); );
buildRules = ( buildRules = (
); );
@@ -238,6 +288,45 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
}; };
81264E30AB9A7C4C10AB44BA /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
8320BCAEA155F95875F06656 /* [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-RunnerTests-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 */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1; alwaysOutOfDate = 1;
@@ -253,6 +342,45 @@
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
}; };
C59C8F9337F753AC74343087 /* [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;
};
FB90C79E7B88832806AD3371 /* [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 */ /* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
@@ -346,30 +474,34 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = Profile; name = Profile;
}; };
249021D4217E4FDB00AE95B9 /* Profile */ = { 249021D4217E4FDB00AE95B9 /* Profile */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; baseConfigurationReference = 9740EEB41CF90195004384FC /* Profile.xcconfig */;
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = J463CU8H5F;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy; PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";
@@ -378,13 +510,14 @@
}; };
331C8088294A63A400263BE5 /* Debug */ = { 331C8088294A63A400263BE5 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 7AFC7F9B8515A109C72DDF1B /* Pods-RunnerTests.debug.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
@@ -395,13 +528,14 @@
}; };
331C8089294A63A400263BE5 /* Release */ = { 331C8089294A63A400263BE5 /* Release */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 12F1F4F8ABC8CE708CB9918F /* Pods-RunnerTests.release.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -410,13 +544,14 @@
}; };
331C808A294A63A400263BE5 /* Profile */ = { 331C808A294A63A400263BE5 /* Profile */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
baseConfigurationReference = 6EC6FEDB5882EB1ECF391D95 /* Pods-RunnerTests.profile.xcconfig */;
buildSettings = { buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)"; BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1; CURRENT_PROJECT_VERSION = 1;
GENERATE_INFOPLIST_FILE = YES; GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0; MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy.RunnerTests; PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy.RunnerTests;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
@@ -427,7 +562,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
@@ -472,11 +607,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1";
}; };
name = Debug; name = Debug;
}; };
@@ -484,7 +619,7 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++"; CLANG_CXX_LIBRARY = "libc++";
@@ -523,13 +658,13 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 12.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule; SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O"; SWIFT_OPTIMIZATION_LEVEL = "-O";
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
}; };
name = Release; name = Release;
@@ -540,15 +675,19 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = J463CU8H5F;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy; PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
@@ -562,15 +701,19 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = J463CU8H5F;
ENABLE_BITCODE = NO; ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy; PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
VERSIONING_SYSTEM = "apple-generic"; VERSIONING_SYSTEM = "apple-generic";

View File

@@ -4,4 +4,7 @@
<FileRef <FileRef
location = "group:Runner.xcodeproj"> location = "group:Runner.xcodeproj">
</FileRef> </FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace> </Workspace>

View File

@@ -1,13 +1,29 @@
import Flutter import Flutter
import UIKit import UIKit
import YandexMapsMobile
@main @main
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
override func application( override func application(
_ application: UIApplication, _ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool { ) -> Bool {
GeneratedPluginRegistrant.register(with: self) let apiKey =
(Bundle.main.object(forInfoDictionaryKey: "YandexMapKitApiKey") as? String ?? "")
.trimmingCharacters(in: .whitespacesAndNewlines)
#if DEBUG
if apiKey.isEmpty || apiKey.contains("$(") {
assertionFailure(
"YandexMapKitApiKey пустой или не подставился из xcconfig — проверь YANDEX_MAPKIT_API_KEY в ios/Flutter/*.xcconfig"
)
}
#endif
YMKMapKit.setLocale(Locale.current.identifier)
YMKMapKit.setApiKey(apiKey)
return super.application(application, didFinishLaunchingWithOptions: launchOptions) return super.application(application, didFinishLaunchingWithOptions: launchOptions)
} }
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
}
} }

View File

@@ -1,122 +1 @@
{ {"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":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"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":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@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"}}
"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"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 B

After

Width:  |  Height:  |  Size: 986 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 B

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 704 B

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 B

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 586 B

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 862 B

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "background.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 B

View File

@@ -1,23 +1,23 @@
{ {
"images" : [ "images" : [
{ {
"idiom" : "universal",
"filename" : "LaunchImage.png", "filename" : "LaunchImage.png",
"idiom" : "universal",
"scale" : "1x" "scale" : "1x"
}, },
{ {
"idiom" : "universal",
"filename" : "LaunchImage@2x.png", "filename" : "LaunchImage@2x.png",
"idiom" : "universal",
"scale" : "2x" "scale" : "2x"
}, },
{ {
"idiom" : "universal",
"filename" : "LaunchImage@3x.png", "filename" : "LaunchImage@3x.png",
"idiom" : "universal",
"scale" : "3x" "scale" : "3x"
} }
], ],
"info" : { "info" : {
"version" : 1, "author" : "xcode",
"author" : "xcode" "version" : 1
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 B

After

Width:  |  Height:  |  Size: 11 KiB

View File

@@ -16,13 +16,19 @@
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3"> <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="tWc-Dq-wcI"/>
</imageView> <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"></imageView>
</subviews> </subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/> <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints> <constraints>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/> <constraint firstItem="YRO-k0-Ey4" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="3T2-ad-Qdv"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/> <constraint firstItem="tWc-Dq-wcI" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="RPx-PI-7Xg"/>
<constraint firstItem="tWc-Dq-wcI" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="SdS-ul-q2q"/>
<constraint firstAttribute="trailing" secondItem="tWc-Dq-wcI" secondAttribute="trailing" id="Swv-Gf-Rwn"/>
<constraint firstAttribute="trailing" secondItem="YRO-k0-Ey4" secondAttribute="trailing" id="TQA-XW-tRk"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="bottom" secondItem="Ze5-6b-2t3" secondAttribute="bottom" id="duK-uY-Gun"/>
<constraint firstItem="tWc-Dq-wcI" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="kV7-tw-vXt"/>
<constraint firstItem="YRO-k0-Ey4" firstAttribute="top" secondItem="Ze5-6b-2t3" secondAttribute="top" id="xPn-NY-SIU"/>
</constraints> </constraints>
</view> </view>
</viewController> </viewController>
@@ -32,6 +38,7 @@
</scene> </scene>
</scenes> </scenes>
<resources> <resources>
<image name="LaunchImage" width="168" height="185"/> <image name="LaunchImage" width="130" height="130"/>
<image name="LaunchBackground" width="1" height="1"/>
</resources> </resources>
</document> </document>

View File

@@ -1,7 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
@@ -24,6 +26,29 @@
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneClassName</key>
<string>UIWindowScene</string>
<key>UISceneConfigurationName</key>
<string>flutter</string>
<key>UISceneDelegateClassName</key>
<string>FlutterSceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key> <key>UIMainStoryboardFile</key>
@@ -41,9 +66,30 @@
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>CADisableMinimumFrameDurationOnPhone</key> <key>YandexMapKitApiKey</key>
<true/> <string>$(YANDEX_MAPKIT_API_KEY)</string>
<key>UIApplicationSupportsIndirectInputEvents</key> <key>NSLocationWhenInUseUsageDescription</key>
<true/> <string>Данные о местоположении необходимы для поиска ближайших самокатов и отображения их на карте.</string>
</dict> <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Данные о местоположении необходимы для отслеживания поездки на самокате в фоновом режиме.</string>
<key>NSCameraUsageDescription</key>
<string>Приложению нужен доступ к камере для сканирования QR-кодов самокатов</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Приложению нужен доступ к галерее для выбора фото профиля и подтверждения поездки</string>
<key>UIStatusBarHidden</key>
<false/>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.behappy.app</string>
<key>CFBundleURLSchemes</key>
<array>
<string>com.behappy.app</string>
</array>
</dict>
</array>
</dict>
</plist> </plist>

BIN
lib.rar

Binary file not shown.

View File

@@ -1,5 +1,4 @@
import 'dart:convert'; import 'dart:convert';
import '../../domain/entities/client_notification.dart'; import '../../domain/entities/client_notification.dart';
class ClientNotificationDto { class ClientNotificationDto {
@@ -43,12 +42,19 @@ class ClientNotificationDto {
clientId: clientId, clientId: clientId,
type: _parseType(type), type: _parseType(type),
category: _parseCategory(category), category: _parseCategory(category),
createdAt: DateTime.parse(createdAt), createdAt: _parseUtcDate(createdAt),
canceledAt: canceledAt != null ? DateTime.parse(canceledAt!) : null, canceledAt: canceledAt != null ? _parseUtcDate(canceledAt!) : null,
readAt: readAt != null ? DateTime.parse(readAt!) : null, readAt: readAt != null ? _parseUtcDate(readAt!) : null,
); );
} }
DateTime _parseUtcDate(String dateString) {
if (dateString.endsWith('Z') || dateString.contains('+') || dateString.contains('-')) {
return DateTime.parse(dateString).toLocal();
}
return DateTime.parse('${dateString}Z').toLocal();
}
NotificationType _parseType(String type) { NotificationType _parseType(String type) {
switch (type.toLowerCase()) { switch (type.toLowerCase()) {
case 'info': case 'info':

View File

@@ -2,7 +2,7 @@ import '../../domain/entities/payment_card.dart';
class PaymentCardResponseDto { class PaymentCardResponseDto {
final int id; final int id;
final int clientId; final String bindingId;
final int expirationMonth; final int expirationMonth;
final int expirationYear; final int expirationYear;
final String cardHolder; final String cardHolder;
@@ -12,7 +12,7 @@ class PaymentCardResponseDto {
PaymentCardResponseDto({ PaymentCardResponseDto({
required this.id, required this.id,
required this.clientId, required this.bindingId,
required this.expirationMonth, required this.expirationMonth,
required this.expirationYear, required this.expirationYear,
required this.cardHolder, required this.cardHolder,
@@ -24,7 +24,7 @@ class PaymentCardResponseDto {
factory PaymentCardResponseDto.fromJson(Map<String, dynamic> json) { factory PaymentCardResponseDto.fromJson(Map<String, dynamic> json) {
return PaymentCardResponseDto( return PaymentCardResponseDto(
id: json['id'] as int, id: json['id'] as int,
clientId: json['clientId'] as int, bindingId: json['bindingId'] as String,
expirationMonth: json['expirationMonth'] as int, expirationMonth: json['expirationMonth'] as int,
expirationYear: json['expirationYear'] as int, expirationYear: json['expirationYear'] as int,
cardHolder: json['cardHolder'] as String, cardHolder: json['cardHolder'] as String,
@@ -37,13 +37,9 @@ class PaymentCardResponseDto {
PaymentCard toEntity(String? fullCardNumber) { PaymentCard toEntity(String? fullCardNumber) {
return PaymentCard( return PaymentCard(
id: id, id: id,
clientId: clientId, bindingId: bindingId,
expirationMonth: expirationMonth,
expirationYear: expirationYear,
cardHolder: cardHolder,
cardLastNumber: cardLastNumber, cardLastNumber: cardLastNumber,
isMain: isMain, isMain: isMain,
type: type,
); );
} }
} }

View File

@@ -0,0 +1,25 @@
import '../../domain/entities/promo_code_result.dart';
class PromoCodeResponseDto {
final bool success;
final double balance;
PromoCodeResponseDto({
required this.success,
required this.balance,
});
factory PromoCodeResponseDto.fromJson(Map<String, dynamic> json) {
return PromoCodeResponseDto(
success: json['success'] as bool,
balance: (json['balance'] as num).toDouble(),
);
}
PromoCodeResult toEntity() {
return PromoCodeResult(
success: success,
balance: balance,
);
}
}

View File

@@ -20,6 +20,8 @@ import 'package:path/path.dart';
import 'package:flutter_client_sse/constants/sse_request_type_enum.dart'; import 'package:flutter_client_sse/constants/sse_request_type_enum.dart';
import 'package:flutter_client_sse/flutter_client_sse.dart'; import 'package:flutter_client_sse/flutter_client_sse.dart';
import '../../domain/entities/client_subscription.dart';
import '../../domain/entities/fine.dart';
import '../../domain/entities/point.dart'; import '../../domain/entities/point.dart';
import '../../domain/entities/user_profile.dart'; import '../../domain/entities/user_profile.dart';
import '../../domain/entities/payment_card.dart'; import '../../domain/entities/payment_card.dart';
@@ -34,8 +36,11 @@ import '../models/subscriptions_response.dart';
import '../models/user_check_response_dto.dart'; import '../models/user_check_response_dto.dart';
class ApiService { class ApiService {
static const String baseUrl = "https://sharing-api.sparkit.by/api/v1"; static const String baseUrl = "https://api.behappybel.by/api/v1";
static const String fileBaseUrl = "https://sharing-api.sparkit.by"; static const String fileBaseUrl = "https://api.behappybel.by/";
/*static const String baseUrl = "https://sharing-api.sparkit.by/api/v1";
static const String fileBaseUrl = "https://sharing-api.sparkit.by";*/
final SecurityService _securityService; final SecurityService _securityService;
final Dio _dio; final Dio _dio;
@@ -51,7 +56,11 @@ class ApiService {
try { try {
final response = await _dio.post( final response = await _dio.post(
"$baseUrl/auth/client/login", "$baseUrl/auth/client/login",
data: {"phone": phone, "model": model, "systemId": systemId}, data: {
"phone": phone,
"model": model,
"systemId": systemId
},
); );
if (response.statusCode == 200 || response.statusCode == 201) { if (response.statusCode == 200 || response.statusCode == 201) {
@@ -137,15 +146,17 @@ class ApiService {
if (avatarId != null && profileData["avatar"] != null) { if (avatarId != null && profileData["avatar"] != null) {
final String? avatarPath = profileData["avatar"]["path"]; final String? avatarPath = profileData["avatar"]["path"];
if (avatarPath != null && avatarPath.isNotEmpty) { if (avatarPath != null && avatarPath.isNotEmpty) {
avatarUrl = Uri.parse(fileBaseUrl).resolve(avatarPath).toString(); } avatarUrl = Uri.parse(fileBaseUrl).resolve(avatarPath).toString();
}
} }
dynamic balanceRaw = profileData["balance"]; dynamic balanceRaw = profileData["balance"];
int? balance; double? balance;
if (balanceRaw is int) {
balance = balanceRaw; if (balanceRaw is num) {
balance = balanceRaw.toDouble();
} else if (balanceRaw is String) { } else if (balanceRaw is String) {
balance = int.tryParse(balanceRaw); balance = double.tryParse(balanceRaw);
} }
return UserProfile( return UserProfile(
@@ -164,6 +175,53 @@ class ApiService {
} }
} }
Future<void> deleteProfile() async {
try {
final response = await _dio.delete(
"$baseUrl/client/me",
options: await _getAuthOptions(),
);
if (response.statusCode == 200) {
final data = response.data;
final profileData = data["profile"];
if (profileData == null) return null;
String? parsedDate;
if (profileData["dob"] != null) {
try {
parsedDate = DateFormat(
'dd.MM.yyyy',
).format(DateTime.parse(profileData["dob"]));
} catch (_) {}
}
final int? avatarId = profileData["avatarId"];
String? avatarUrl;
if (avatarId != null && profileData["avatar"] != null) {
final String? avatarPath = profileData["avatar"]["path"];
if (avatarPath != null && avatarPath.isNotEmpty) {
avatarUrl = Uri.parse(fileBaseUrl).resolve(avatarPath).toString();
}
}
dynamic balanceRaw = profileData["balance"];
double? balance;
if (balanceRaw is num) {
balance = balanceRaw.toDouble();
} else if (balanceRaw is String) {
balance = double.tryParse(balanceRaw);
}
}
return null;
} catch (e) {
return null;
}
}
Future<List<PaymentCard>> getPaymentCards() async { Future<List<PaymentCard>> getPaymentCards() async {
final response = await _dio.get( final response = await _dio.get(
"$baseUrl/client/me", "$baseUrl/client/me",
@@ -175,13 +233,9 @@ class ApiService {
cardsJson.map((cardJson) async { cardsJson.map((cardJson) async {
return PaymentCard( return PaymentCard(
id: cardJson['id'], id: cardJson['id'],
clientId: cardJson['clientId'], bindingId: cardJson['bindingId'],
expirationMonth: cardJson['expirationMonth'],
expirationYear: cardJson['expirationYear'],
cardHolder: cardJson['cardHolder'],
cardLastNumber: cardJson['cardLastNumber'], cardLastNumber: cardJson['cardLastNumber'],
isMain: cardJson['isMain'], isMain: cardJson['isMain'],
type: cardJson['cardType'],
); );
}), }),
); );
@@ -236,11 +290,11 @@ class ApiService {
} }
dynamic balanceRaw = data["balance"]; dynamic balanceRaw = data["balance"];
int? balance; double? balance;
if (balanceRaw is int) { if (balanceRaw is double) {
balance = balanceRaw; balance = balanceRaw;
} else if (balanceRaw is String) { } else if (balanceRaw is String) {
balance = int.tryParse(balanceRaw); balance = double.tryParse(balanceRaw);
} }
return UserProfile( return UserProfile(
@@ -394,10 +448,7 @@ class ApiService {
final url = "$baseUrl/scooter/$title/code"; final url = "$baseUrl/scooter/$title/code";
try { try {
final response = await _dio.get( final response = await _dio.get(url, options: await _getAuthOptions());
url,
options: await _getAuthOptions(),
);
if (response.statusCode == 200 || response.statusCode == 201) { if (response.statusCode == 200 || response.statusCode == 201) {
return Scooter.fromJson(response.data); return Scooter.fromJson(response.data);
@@ -421,7 +472,7 @@ class ApiService {
int page = 1, int page = 1,
int pageSize = 500, int pageSize = 500,
}) async { }) async {
const path = "$baseUrl/zone/available"; const path = "$baseUrl/zone/available2";
final queryParams = { final queryParams = {
'readAll': 'true', 'readAll': 'true',
@@ -447,6 +498,35 @@ class ApiService {
} }
} }
Future<ZonesResponse?> getAllZones({
int page = 1,
int pageSize = 500,
}) async {
const path = "$baseUrl/zone/available2";
final queryParams = {
'readAll': 'true',
'page': page,
'pageSize': pageSize,
};
try {
final response = await _dio.get(
path,
queryParameters: queryParams,
options: await _getAuthOptions(),
);
if (response.statusCode == 200) {
return ZonesResponse.fromJson(response.data);
}
return null;
} catch (e) {
print("ERROR: getZones failed: $e");
return null;
}
}
Future<TariffsResponse?> getAvailableTariffs({required int scooterId}) async { Future<TariffsResponse?> getAvailableTariffs({required int scooterId}) async {
final url = "$baseUrl/scooterplan/$scooterId/available"; final url = "$baseUrl/scooterplan/$scooterId/available";
@@ -463,7 +543,7 @@ class ApiService {
} }
} }
Future<List<Subscription>> getClientSubscriptions() async { Future<List<ClientSubscription>> getClientSubscriptions() async {
const url = "$baseUrl/scootersubscription/client"; const url = "$baseUrl/scootersubscription/client";
try { try {
@@ -474,14 +554,7 @@ class ApiService {
final List<dynamic> items = responseData['data'] ?? []; final List<dynamic> items = responseData['data'] ?? [];
return items.map((item) { return items.map((item) {
final Map<String, dynamic> subscriptionMap = return ClientSubscription.fromJson(item);
Map<String, dynamic>.from(item['subscription'] ?? {});
if (item['expiredAt'] != null) {
subscriptionMap['activeTo'] = item['expiredAt'];
}
return Subscription.fromJson(subscriptionMap);
}).toList(); }).toList();
} }
return []; return [];
@@ -525,13 +598,13 @@ class ApiService {
} }
} }
Future<bool> activateSubscription({required int optionId}) async { Future<bool> activateSubscription({required int optionId, required int cardId}) async {
const url = "$baseUrl/scootersubscription/client"; const url = "$baseUrl/scootersubscription/client";
try { try {
final response = await _dio.post( final response = await _dio.post(
url, url,
data: {"optionId": optionId}, data: {"optionId": optionId, "cardId": cardId},
options: await _getAuthOptions(), options: await _getAuthOptions(),
); );
@@ -547,32 +620,27 @@ class ApiService {
} }
} }
Future<int> addPaymentCard({ Future<Map<String, dynamic>> addPaymentCard() async {
required String cardNumber,
required String cardHolder,
required int expirationMonth,
required int expirationYear,
required String cvv,
}) async {
const url = "$baseUrl/client/card"; const url = "$baseUrl/client/card";
final cleanCardNumber = cardNumber.replaceAll(' ', ''); /*final cleanCardNumber = cardNumber.replaceAll(' ', '');*/
try { try {
final response = await _dio.post( final response = await _dio.post(
url, url,
data: { /*data: {
"cardNumber": cleanCardNumber, "cardNumber": cleanCardNumber,
"cardHolder": cardHolder, "cardHolder": cardHolder,
"expirationMonth": expirationMonth, "expirationMonth": expirationMonth,
"expirationYear": expirationYear, "expirationYear": expirationYear,
"cvv": cvv, "cvv": cvv,
}, },*/
options: await _getAuthOptions(), options: await _getAuthOptions(),
); );
if (response.statusCode == 200 || response.statusCode == 201) { if (response.statusCode == 200 || response.statusCode == 201) {
return response.data['id'] as int; return response.data;
} }
throw AuthException('Непредвиденный статус: ${response.statusCode}', 0); throw AuthException('Непредвиденный статус: ${response.statusCode}', 0);
} on DioException catch (e) { } on DioException catch (e) {
final data = e.response?.data; final data = e.response?.data;
@@ -674,7 +742,9 @@ class ApiService {
final firstError = data['message'][0]['message'].toString(); final firstError = data['message'][0]['message'].toString();
if (firstError.contains("Wrong start zone")) { if (firstError.contains("Wrong start zone")) {
throw WrongZoneException(message: "Некорректная зона для начала поездки."); throw WrongZoneException(
message: "Некорректная зона для начала поездки.",
);
} }
} }
@@ -705,7 +775,9 @@ class ApiService {
final firstError = data['message'][0]['message'].toString(); final firstError = data['message'][0]['message'].toString();
if (firstError.contains("Wrong start zone")) { if (firstError.contains("Wrong start zone")) {
throw WrongZoneException(message: "Некорректная зона для начала поездки."); throw WrongZoneException(
message: "Некорректная зона для начала поездки.",
);
} }
} }
@@ -717,17 +789,13 @@ class ApiService {
} }
} }
Future<ScooterOrder?> cancelRide(int orderId) async { Future<void> cancelRide(int orderId) async {
try { try {
final response = await _dio.put( final response = await _dio.put(
"$baseUrl/scooterorder/$orderId/cancel", "$baseUrl/scooterorder/$orderId/cancel",
options: await _getAuthOptions(), options: await _getAuthOptions(),
); );
if (response.statusCode == 200 || response.statusCode == 201) {
return ScooterOrder.fromJson(response.data);
}
return null;
} on DioException catch (e) { } on DioException catch (e) {
_handleDioError(e); _handleDioError(e);
return null; return null;
@@ -768,7 +836,7 @@ class ApiService {
} }
} }
Future<ScooterOrder?> finishRide({ Future<void> finishRide({
required int orderId, required int orderId,
required List<int> filesId, required List<int> filesId,
}) async { }) async {
@@ -779,10 +847,6 @@ class ApiService {
options: await _getAuthOptions(), options: await _getAuthOptions(),
); );
if (response.statusCode == 200 || response.statusCode == 201) {
return ScooterOrder.fromJson(response.data);
}
return null;
} on DioException catch (e) { } on DioException catch (e) {
if (e.response?.statusCode == 400) { if (e.response?.statusCode == 400) {
final data = e.response?.data; final data = e.response?.data;
@@ -791,7 +855,9 @@ class ApiService {
final firstError = data['message'][0]['message'].toString(); final firstError = data['message'][0]['message'].toString();
if (firstError.contains("Wrong start zone")) { if (firstError.contains("Wrong start zone")) {
throw WrongZoneException(message: "Некорректная зона для завершения поездки."); throw WrongZoneException(
message: "Некорректная зона для завершения поездки.",
);
} }
} }
@@ -803,7 +869,7 @@ class ApiService {
} }
} }
Future<ScooterOrder?> payRide(int orderId) async { Future<void> payRide(int orderId) async {
try { try {
final response = await _dio.put( final response = await _dio.put(
"$baseUrl/scooterorder/$orderId/pay", "$baseUrl/scooterorder/$orderId/pay",
@@ -811,12 +877,12 @@ class ApiService {
); );
if (response.statusCode == 200 || response.statusCode == 201) { if (response.statusCode == 200 || response.statusCode == 201) {
return ScooterOrder.fromJson(response.data); // return ScooterOrder.fromJson(response.data);
return;
} }
return null;
} on DioException catch (e) { } on DioException catch (e) {
_handleDioError(e); _handleDioError(e);
return null; return;
} }
} }
@@ -878,7 +944,7 @@ class ApiService {
} }
} }
Future<ScooterOrder?> payScooterOrderWithPhotos({ Future<void> payScooterOrderWithPhotos({
required int orderId, required int orderId,
required int? cardId, required int? cardId,
required bool isBalance, required bool isBalance,
@@ -891,12 +957,10 @@ class ApiService {
); );
if (response.statusCode == 200 || response.statusCode == 201) { if (response.statusCode == 200 || response.statusCode == 201) {
return ScooterOrder.fromJson(response.data); return;
} }
return null;
} on DioException catch (e) { } on DioException catch (e) {
_handleDioError(e); _handleDioError(e);
return null;
} }
} }
@@ -918,7 +982,6 @@ class ApiService {
} }
} }
Future<List<Point>> getScooterOrderRouteHistory({required int id}) async { Future<List<Point>> getScooterOrderRouteHistory({required int id}) async {
try { try {
final response = await _dio.get( final response = await _dio.get(
@@ -930,13 +993,19 @@ class ApiService {
final String routeString = response.data['route'] ?? '[]'; final String routeString = response.data['route'] ?? '[]';
final List<dynamic> routeList = json.decode(routeString); final List<dynamic> routeList = json.decode(routeString);
return routeList.map((item) => Point( return routeList
.map(
(item) => Point(
(item[1] as num).toDouble(), (item[1] as num).toDouble(),
(item[0] as num).toDouble(), (item[0] as num).toDouble(),
)).toList(); ),
)
.toList();
} }
throw RouteHistoryNotFoundException(message: "История маршрута не найдена"); throw RouteHistoryNotFoundException(
message: "История маршрута не найдена",
);
} on DioException catch (e) { } on DioException catch (e) {
if (e.response?.statusCode == 401) throw UnauthorizedException(); if (e.response?.statusCode == 401) throw UnauthorizedException();
if (e.response?.statusCode == 403) throw AuthBlockException(); if (e.response?.statusCode == 403) throw AuthBlockException();
@@ -945,6 +1014,64 @@ class ApiService {
} }
} }
/// GET /scooterorder/fines/client
Future<List<Fine>> getClientFines() async {
try {
final response = await _dio.get(
"$baseUrl/scooterorder/fines/client",
options: await _getAuthOptions(),
);
if (response.statusCode == 200 && response.data is Map) {
final List<dynamic> dataList = response.data['data'] ?? [];
return dataList.map((json) => Fine.fromJson(json)).toList();
}
return [];
} on DioException catch (e) {
_handleDioError(e);
return [];
}
}
/// GET /scooterorder/{id}/fine
Future<Fine?> getFineDetails(int orderId) async {
try {
final response = await _dio.get(
"$baseUrl/scooterorder/fines/client/$orderId",
options: await _getAuthOptions(),
);
if (response.statusCode == 200 && response.data != null) {
return Fine.fromJson(response.data);
}
return null;
} on DioException catch (e) {
_handleDioError(e);
return null;
}
}
/// PUT /scooterorder/fines/client/{id}
/// {id} — это id штрафа (Fine.id), а не id заказа (Fine.orderId)
Future<void> payFine({
required int orderId,
int? cardId,
required bool isBalance,
}) async {
try {
await _dio.put(
"$baseUrl/scooterorder/fines/client/$orderId",
data: {
"cardId": cardId ?? 0,
"isBalance": isBalance,
},
options: await _getAuthOptions(),
);
} on DioException catch (e) {
_handleDioError(e);
}
}
Future<Map<String, dynamic>> getNews() async { Future<Map<String, dynamic>> getNews() async {
try { try {
final response = await _dio.get( final response = await _dio.get(
@@ -1017,10 +1144,10 @@ class ApiService {
if (event.data != null && event.data!.isNotEmpty) { if (event.data != null && event.data!.isNotEmpty) {
try { try {
final Map<String, dynamic> jsonData = jsonDecode(event.data!); final Map<String, dynamic> jsonData = jsonDecode(event.data!);
print("✅ [SSE] Parsed JSON: $jsonData"); print("[SSE] Parsed JSON: $jsonData");
controller.add(jsonData); controller.add(jsonData);
} catch (e) { } catch (e) {
print("❌ [SSE] JSON Parse Error: $e | Raw: ${event.data}"); print("[SSE] JSON Parse Error: $e | Raw: ${event.data}");
} }
} }
}, },
@@ -1038,6 +1165,42 @@ class ApiService {
return controller.stream; return controller.stream;
} }
Future<Map<String, dynamic>> getNotifications({
int page = 1,
int pageSize = 10,
}) async {
final url = Uri.parse('$baseUrl/notification/client').replace(
queryParameters: {
'page': page.toString(),
'pageSize': pageSize.toString(),
},
);
final accessToken = await _securityService.getAccessToken();
if (accessToken == null) throw UnauthorizedException();
final response = await http.get(
url,
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer $accessToken",
},
);
if (response.statusCode == 200) {
final data = jsonDecode(utf8.decode(response.bodyBytes));
if (data is Map<String, dynamic>) {
return data;
}
throw Exception('Expected Map with data and pagination');
} else if (response.statusCode == 401) {
throw UnauthorizedException();
} else if (response.statusCode == 403) {
throw AuthBlockException();
}
throw Exception('Ошибка сервера: ${response.statusCode}');
}
Future<List<Certificate>> getCertificates() async { Future<List<Certificate>> getCertificates() async {
try { try {
final response = await _dio.get( final response = await _dio.get(
@@ -1097,4 +1260,32 @@ class ApiService {
} }
return null; return null;
} }
Future<Map<String, dynamic>> applyPromoCode(String code) async {
final token = await _securityService.getAccessToken();
if (token == null) throw Exception('No access token');
final response = await _dio.post(
'$baseUrl/promocode/apply',
data: {'code': code},
options: Options(
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $token',
},
),
);
if (response.statusCode == 201 || response.statusCode == 200) {
return response.data;
} else if (response.statusCode == 404) {
throw PromoCodeNotFoundException();
} else {
throw Exception('API Error: ${response.statusCode}');
}
}
} }
class PromoCodeNotFoundException implements Exception {}

View File

@@ -1,7 +1,9 @@
import 'package:be_happy/domain/entities/client_notification.dart'; import 'package:be_happy/domain/entities/client_notification.dart';
import '../../data/network/api_service.dart'; import '../../data/network/api_service.dart';
import '../../domain/entities/pagination_meta.dart';
import '../../domain/repositories/notification_repository.dart'; import '../../domain/repositories/notification_repository.dart';
import '../../domain/usecase/get_notifications_usecase.dart';
import '../models/client_notification_dto.dart'; import '../models/client_notification_dto.dart';
class NotificationRepositoryImpl implements NotificationRepository { class NotificationRepositoryImpl implements NotificationRepository {
@@ -33,4 +35,30 @@ class NotificationRepositoryImpl implements NotificationRepository {
void closeStream() { void closeStream() {
// соединение закрывается автоматически при отписке от stream // соединение закрывается автоматически при отписке от stream
} }
@override
Future<NotificationsResult> getNotifications({
int page = 1,
int pageSize = 10,
}) async {
try {
final response = await _apiService.getNotifications(
page: page,
pageSize: pageSize,
);
final notifications = (response['data'] as List)
.map((json) => ClientNotificationDto.fromJson(json).toEntity())
.toList();
final pagination = PaginationMeta.fromJson(response['pagination']);
return NotificationsResult(
notifications: notifications,
pagination: pagination,
);
} catch (e, stackTrace) {
throw Exception('Не удалось загрузить уведомления: $e');
}
}
} }

View File

@@ -32,26 +32,25 @@ class PaymentRepositoryImpl implements PaymentRepository {
} }
@override @override
Future<Result<void>> addPaymentCard({ Future<Result<Map<String, dynamic>>> addPaymentCard(
required String cardNumber, /*required String cardNumber,
required String cardHolder, required String cardHolder,
required String expiryMonth, required String expiryMonth,
required String expiryYear, required String expiryYear,
required String cvv, required String cvv,*/
}) async { ) async {
try { try {
final cardId = await apiService.addPaymentCard( final result = await apiService.addPaymentCard(
cardNumber: cardNumber, /*cardNumber: cardNumber,
cardHolder: cardHolder, cardHolder: cardHolder,
expirationMonth: int.parse(expiryMonth), expirationMonth: int.parse(expiryMonth),
expirationYear: int.parse(expiryYear), expirationYear: int.parse(expiryYear),
cvv: cvv, cvv: cvv,*/
); );
// Сохраняем полный номер карты локально // await securityService.saveCardFullNumber(cardId, cardNumber);
await securityService.saveCardFullNumber(cardId, cardNumber);
return Success(null); return Success(result);
} on AuthException catch (e) { } on AuthException catch (e) {
return Failure(AuthFailure(e.attemptsLeft)); return Failure(AuthFailure(e.attemptsLeft));
} on AuthBlockException catch (_) { } on AuthBlockException catch (_) {
@@ -99,9 +98,9 @@ class PaymentRepositoryImpl implements PaymentRepository {
} }
@override @override
Future<Result<bool>> activateSubscription(int optionId) async { Future<Result<bool>> activateSubscription(int optionId, int cardId) async {
try { try {
final success = await apiService.activateSubscription(optionId: optionId); final success = await apiService.activateSubscription(optionId: optionId, cardId: cardId);
return Success(success); return Success(success);
} on AuthException catch (e) { } on AuthException catch (e) {
return Failure(AuthFailure(e.attemptsLeft)); return Failure(AuthFailure(e.attemptsLeft));

View File

@@ -27,6 +27,11 @@ class UserProfileRepositoryImpl implements UserProfileRepository {
return await _apiService.getProfile() ?? _cachedProfile; return await _apiService.getProfile() ?? _cachedProfile;
} }
@override
Future<void> deleteProfile() async {
return await _apiService.deleteProfile();
}
@override @override
Future<UserProfile?> updateProfile(UserProfile profile) async { Future<UserProfile?> updateProfile(UserProfile profile) async {
//await Future.delayed(const Duration(milliseconds: 300)); //await Future.delayed(const Duration(milliseconds: 300));

View File

@@ -0,0 +1,23 @@
import '../../domain/entities/promo_code_result.dart';
import '../../domain/repositories/promo_code_repository.dart';
import '../models/promo_code_response_dto.dart';
import '../network/api_service.dart';
class PromoCodeRepositoryImpl implements PromoCodeRepository {
final ApiService apiService;
PromoCodeRepositoryImpl(this.apiService);
@override
Future<PromoCodeResult> applyPromoCode(String code) async {
try {
final data = await apiService.applyPromoCode(code);
final dto = PromoCodeResponseDto.fromJson(data);
return dto.toEntity();
} on PromoCodeNotFoundException {
throw Exception('Промокод не найден');
} catch (e) {
throw Exception('Ошибка активации промокода: $e');
}
}
}

View File

@@ -1,20 +1,22 @@
import 'dart:io'; import 'dart:io';
import 'package:be_happy/data/exceptions/auth_block_exception.dart';
import 'package:be_happy/data/exceptions/route_history_not_found_exception.dart';
import 'package:be_happy/data/exceptions/scooter_not_found_exception.dart';
import 'package:be_happy/data/exceptions/unauthorized_exception.dart';
import 'package:be_happy/data/exceptions/wrong_zone_exception.dart';
import 'package:be_happy/domain/entities/point.dart';
import 'package:be_happy/domain/repositories/scooter_repository.dart';
import '../../core/failures.dart'; import '../../core/failures.dart';
import '../../core/result.dart'; import '../../core/result.dart';
import '../../domain/entities/active_scooter_order.dart'; import '../../domain/entities/active_scooter_order.dart';
import '../../domain/entities/client_subscription.dart';
import '../../domain/entities/fine.dart';
import '../../domain/entities/point.dart';
import '../../domain/entities/scooter.dart'; import '../../domain/entities/scooter.dart';
import '../../domain/entities/tariff.dart'; import '../../domain/entities/tariff.dart';
import '../../domain/entities/subscription.dart'; import '../../domain/entities/subscription.dart';
import '../../domain/entities/scooter_order.dart'; import '../../domain/entities/scooter_order.dart';
import '../../domain/repositories/scooter_repository.dart';
import '../exceptions/auth_block_exception.dart';
import '../exceptions/auth_exception.dart'; import '../exceptions/auth_exception.dart';
import '../exceptions/route_history_not_found_exception.dart';
import '../exceptions/scooter_not_found_exception.dart';
import '../exceptions/unauthorized_exception.dart';
import '../exceptions/wrong_zone_exception.dart';
import '../network/api_service.dart'; import '../network/api_service.dart';
class ScooterRepositoryImpl extends ScooterRepository { class ScooterRepositoryImpl extends ScooterRepository {
@@ -127,8 +129,8 @@ class ScooterRepositoryImpl extends ScooterRepository {
} }
@override @override
Future<Result<List<Subscription>>> getClientSubscriptions() async { Future<Result<List<ClientSubscription>>> getClientSubscriptions() async {
late final Result<List<Subscription>> result; late final Result<List<ClientSubscription>> result;
try { try {
final subscriptions = await _apiService.getClientSubscriptions(); final subscriptions = await _apiService.getClientSubscriptions();
result = Success(subscriptions); result = Success(subscriptions);
@@ -191,15 +193,11 @@ class ScooterRepositoryImpl extends ScooterRepository {
} }
@override @override
Future<Result<ScooterOrder>> cancelRide(int orderId) async { Future<Result<void>> cancelRide(int orderId) async {
late final Result<ScooterOrder> result; late final Result<void> result;
try { try {
final order = await _apiService.cancelRide(orderId); await _apiService.cancelRide(orderId);
if (order != null) { result = Success(null);
result = Success(order);
} else {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
} on AuthException catch (e) { } on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft)); result = Failure(AuthFailure(e.attemptsLeft));
} catch (e) { } catch (e) {
@@ -245,18 +243,11 @@ class ScooterRepositoryImpl extends ScooterRepository {
} }
@override @override
Future<Result<ScooterOrder>> finishRide(int orderId, List<int> files) async { Future<Result<void>> finishRide(int orderId, List<int> files) async {
late final Result<ScooterOrder> result; late final Result<ScooterOrder> result;
try { try {
final order = await _apiService.finishRide( await _apiService.finishRide(orderId: orderId, filesId: files);
orderId: orderId, result = Success(null);
filesId: files,
);
if (order != null) {
result = Success(order);
} else {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
} on AuthException catch (e) { } on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft)); result = Failure(AuthFailure(e.attemptsLeft));
} on WrongZoneException catch (e) { } on WrongZoneException catch (e) {
@@ -268,15 +259,11 @@ class ScooterRepositoryImpl extends ScooterRepository {
} }
@override @override
Future<Result<ScooterOrder>> payRide(int orderId) async { Future<Result<void>> payRide(int orderId) async {
late final Result<ScooterOrder> result; late final Result<void> result;
try { try {
final order = await _apiService.payRide(orderId); await _apiService.payRide(orderId);
if (order != null) { result = Success(null);
result = Success(order);
} else {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
} on AuthException catch (e) { } on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft)); result = Failure(AuthFailure(e.attemptsLeft));
} catch (e) { } catch (e) {
@@ -335,23 +322,19 @@ class ScooterRepositoryImpl extends ScooterRepository {
} }
@override @override
Future<Result<ScooterOrder>> payScooterOrderWithPhotos({ Future<Result<void>> payScooterOrderWithPhotos({
required int orderId, required int orderId,
required int? cardId, required int? cardId,
required bool isBalance, required bool isBalance,
}) async { }) async {
late final Result<ScooterOrder> result; late final Result<void> result;
try { try {
final order = await _apiService.payScooterOrderWithPhotos( final order = await _apiService.payScooterOrderWithPhotos(
orderId: orderId, orderId: orderId,
cardId: cardId, cardId: cardId,
isBalance: isBalance, isBalance: isBalance,
); );
if (order != null) { result = Success(null);
result = Success(order);
} else {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
} on AuthException catch (e) { } on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft)); result = Failure(AuthFailure(e.attemptsLeft));
} catch (e) { } catch (e) {
@@ -443,4 +426,70 @@ class ScooterRepositoryImpl extends ScooterRepository {
} }
return result; return result;
} }
@override
Future<Result<Fine>> getFineDetails(int orderId) async {
late final Result<Fine> result;
try {
final fine = await _apiService.getFineDetails(orderId);
if (fine != null) {
result = Success(fine);
} else {
result = Failure(UnknownFailure("Не удалось получить данные о штрафе"));
}
} on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft));
} on UnauthorizedException catch (e) {
result = Failure(AuthFailure(0, message: e.toString()));
} on AuthBlockException catch (e) {
result = Failure(AuthBlockFailure(e.toString()));
} catch (e) {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
return result;
}
@override
Future<Result<List<Fine>>> getClientFines() async {
late final Result<List<Fine>> result;
try {
final fines = await _apiService.getClientFines();
result = Success(fines);
} on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft));
} on UnauthorizedException catch (e) {
result = Failure(AuthFailure(0, message: e.toString()));
} on AuthBlockException catch (e) {
result = Failure(AuthBlockFailure(e.toString()));
} catch (e) {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
return result;
}
@override
Future<Result<void>> payFine({
required int orderId,
int? cardId,
required bool isBalance,
}) async {
late final Result<void> result;
try {
await _apiService.payFine(
orderId: orderId,
cardId: cardId,
isBalance: isBalance,
);
result = Success(null);
} on AuthException catch (e) {
result = Failure(AuthFailure(e.attemptsLeft));
} on UnauthorizedException catch (e) {
result = Failure(AuthFailure(0, message: e.toString()));
} on AuthBlockException catch (e) {
result = Failure(AuthBlockFailure(e.toString()));
} catch (e) {
result = Failure(UnknownFailure("Неизвестная ошибка"));
}
return result;
}
} }

View File

@@ -10,60 +10,60 @@ class ZoneRepositoryImpl extends ZoneRepository {
ZoneRepositoryImpl(this._apiService); ZoneRepositoryImpl(this._apiService);
@override @override
Future<List<Zone>> getZones(List<double> area, Future<List<Zone>> getZones(List<double> area, int page, int pageSize) async {
int page,
int pageSize,) async {
final List<Point> list = []; final List<Point> list = [];
final List<Point> list2 = []; final List<Point> list2 = [];
/*list.add(Point(55.182372,30.203347));
list.add(Point(55.173746,30.200257));
list.add(Point(55.172153,30.212531));
list.add(Point(55.179946,30.215964));
list2.add(Point(55.178304,30.227380));
list2.add(Point(55.178059,30.229654));
list2.add(Point(55.191339,30.234718));
list2.add(Point(55.194352,30.234890));
list2.add(Point(55.194377,30.231972));
list2.add(Point(55.192123,30.232744));
final zone = Zone(id: 123,
title: "Zone 01",
description: "description",
type: "Finish",
isActive: true,
shapeType: "polygon",
points: list,
speedLimit: "speedLimit");
final zone2 = Zone(id: 124,
title: "Zone 02",
description: "description",
type: "NotDrive",
isActive: true,
shapeType: "polygon",
points: list2,
speedLimit: "speedLimit");
*/
final responce = await _apiService.getZones( final responce = await _apiService.getZones(
area: area, area: area,
page: page, page: page,
pageSize: pageSize, pageSize: pageSize,
); );
final List<Zone>? zones = responce?.zones; if (responce == null) {
// zones?.add(zone); throw Exception(
// zones?.add(zone2); 'Failed to load zones for area: empty response from server',
);
print("Scooters: ${zones?.first.title}");
if (responce != null) {
return zones ?? List.empty();
} }
return List.empty(); final zones = responce.zones;
print("Zones: ${zones.length}");
return zones;
}
@override
Future<List<Zone>> getAllZones(int page, int pageSize) async {
final List<Point> list = [];
final List<Point> list2 = [];
final responce = await _apiService.getAllZones(
page: page,
pageSize: pageSize,
);
// apiService.getAllZones ловит свои ошибки (сеть/401/5xx) и в этом
// случае возвращает null. Раньше это тихо превращалось в "зон нет" —
// из-за чего сбой запроса выглядел как легитимный пустой ответ и
// (в связке с кешем на уровне MapBloc) навсегда "прятал" зоны на
// время сессии. Бросаем исключение, чтобы вызывающий код (usecase/bloc)
// мог отличить реальный сбой от честного "зон действительно нет"
// и, при необходимости, повторить запрос.
if (responce == null) {
throw Exception('Failed to load zones: empty response from server');
}
final zones = responce.zones;
print(zones.map((z) => '${z.type}:${z.id}'));
for (final z in zones) {
print("Zone ${z.type}:${z.id} geometry.length=${z.geometry.length}");
}
print("Zones: ${zones.length}");
return zones;
} }
} }

View File

@@ -10,6 +10,6 @@ class AppSettingsService {
} }
bool getMapSettingsFlag(String key) { bool getMapSettingsFlag(String key) {
return sharedPreferences.getBool(key) ?? false; return sharedPreferences.getBool(key) ?? true;
} }
} }

View File

@@ -17,6 +17,8 @@ import 'package:be_happy/domain/repositories/scooter_repository.dart';
import 'package:be_happy/domain/repositories/zone_repository.dart'; import 'package:be_happy/domain/repositories/zone_repository.dart';
import 'package:be_happy/domain/service/security_service.dart'; import 'package:be_happy/domain/service/security_service.dart';
import 'package:be_happy/domain/usecase/add_payment_card_usecase.dart'; // ← новый import 'package:be_happy/domain/usecase/add_payment_card_usecase.dart'; // ← новый
import 'package:be_happy/domain/usecase/delete_profile_usecase.dart';
import 'package:be_happy/domain/usecase/get_all_zones_usecase.dart';
import 'package:be_happy/domain/usecase/get_certificates_usecase.dart'; import 'package:be_happy/domain/usecase/get_certificates_usecase.dart';
import 'package:be_happy/domain/usecase/get_scooter_order_route_history_usecase.dart'; import 'package:be_happy/domain/usecase/get_scooter_order_route_history_usecase.dart';
import 'package:be_happy/domain/usecase/is_pin_set_usecase.dart'; import 'package:be_happy/domain/usecase/is_pin_set_usecase.dart';
@@ -54,6 +56,7 @@ import 'package:be_happy/domain/usecase/finish_ride_usecase.dart';
import 'package:be_happy/domain/usecase/pause_ride_usecase.dart'; import 'package:be_happy/domain/usecase/pause_ride_usecase.dart';
import 'package:be_happy/domain/usecase/resume_ride_usecase.dart'; import 'package:be_happy/domain/usecase/resume_ride_usecase.dart';
import 'package:be_happy/domain/usecase/verify_pin_usecase.dart'; import 'package:be_happy/domain/usecase/verify_pin_usecase.dart';
import 'package:be_happy/presentation/event/profile_event.dart';
import 'package:be_happy/presentation/viewmodel/active_ride_bloc.dart'; import 'package:be_happy/presentation/viewmodel/active_ride_bloc.dart';
import 'package:be_happy/presentation/viewmodel/add_card_bloc.dart'; // ← новый import 'package:be_happy/presentation/viewmodel/add_card_bloc.dart'; // ← новый
import 'package:be_happy/presentation/viewmodel/current_rides_bloc.dart'; import 'package:be_happy/presentation/viewmodel/current_rides_bloc.dart';
@@ -85,22 +88,32 @@ import '../data/repositories/auth_repository_impl.dart';
import '../data/repositories/news_repository_impl.dart'; import '../data/repositories/news_repository_impl.dart';
import '../data/repositories/pin_repository_impl.dart'; import '../data/repositories/pin_repository_impl.dart';
import '../data/repositories/profile_repository_impl.dart'; import '../data/repositories/profile_repository_impl.dart';
import '../data/repositories/promo_code_repository_impl.dart';
import '../data/service/news_api_service.dart'; import '../data/service/news_api_service.dart';
import '../domain/repositories/auth_repository.dart'; import '../domain/repositories/auth_repository.dart';
import '../domain/repositories/news_repository.dart'; import '../domain/repositories/news_repository.dart';
import '../domain/repositories/promo_code_repository.dart';
import '../domain/service/device_info_service.dart'; import '../domain/service/device_info_service.dart';
import '../domain/usecase/activate_subscription_usecase.dart'; import '../domain/usecase/activate_subscription_usecase.dart';
import '../domain/usecase/apply_promo_code_usecase.dart';
import '../domain/usecase/get_client_subscriptions_usecase.dart'; import '../domain/usecase/get_client_subscriptions_usecase.dart';
import '../domain/usecase/get_fine_details_usecase.dart';
import '../domain/usecase/get_fines_usecase.dart';
import '../domain/usecase/get_news_by_id_usecase.dart'; import '../domain/usecase/get_news_by_id_usecase.dart';
import '../domain/usecase/get_notifications_usecase.dart';
import '../domain/usecase/get_scooter_by_title_usecase.dart'; import '../domain/usecase/get_scooter_by_title_usecase.dart';
import '../domain/usecase/get_scooter_order_history_usecase.dart'; import '../domain/usecase/get_scooter_order_history_usecase.dart';
import '../domain/usecase/pay_fine_usecase.dart';
import '../domain/usecase/remove_payment_card_usecase.dart'; import '../domain/usecase/remove_payment_card_usecase.dart';
import '../domain/usecase/set_main_payment_card_usecase.dart'; import '../domain/usecase/set_main_payment_card_usecase.dart';
import '../presentation/viewmodel/auth_bloc.dart'; import '../presentation/viewmodel/auth_bloc.dart';
import '../presentation/viewmodel/edit_profile_bloc.dart'; import '../presentation/viewmodel/edit_profile_bloc.dart';
import '../presentation/viewmodel/fine_list_bloc.dart';
import '../presentation/viewmodel/map_bloc.dart'; import '../presentation/viewmodel/map_bloc.dart';
import '../presentation/viewmodel/news_bloc.dart'; import '../presentation/viewmodel/news_bloc.dart';
import '../presentation/viewmodel/notifications_bloc.dart';
import '../presentation/viewmodel/order_history_bloc.dart'; import '../presentation/viewmodel/order_history_bloc.dart';
import '../presentation/viewmodel/promo_code_bloc.dart';
import '../presentation/viewmodel/scooter_detail_modal_bloc.dart'; import '../presentation/viewmodel/scooter_detail_modal_bloc.dart';
import '../presentation/viewmodel/subscription_list_bloc.dart'; import '../presentation/viewmodel/subscription_list_bloc.dart';
import '../presentation/viewmodel/verify_code_bloc.dart'; import '../presentation/viewmodel/verify_code_bloc.dart';
@@ -110,7 +123,13 @@ final getIt = GetIt.instance;
Future<void> setupDependencies() async { Future<void> setupDependencies() async {
final sharedPreferences = await SharedPreferences.getInstance(); final sharedPreferences = await SharedPreferences.getInstance();
final dio = Dio(); final dio = Dio();
dio.interceptors.add(LogInterceptor(responseBody: true, requestBody: true)); dio.interceptors.add(
LogInterceptor(
/*requestHeader: false, responseHeader:false, */
responseBody: true,
requestBody: true,
),
);
dio.interceptors.add(AuthInterceptor()); dio.interceptors.add(AuthInterceptor());
// HTTP // HTTP
getIt.registerSingleton<http.Client>(http.Client()); getIt.registerSingleton<http.Client>(http.Client());
@@ -189,6 +208,8 @@ Future<void> setupDependencies() async {
getIt.registerSingleton<GetProfileUseCase>(GetProfileUseCase(getIt())); getIt.registerSingleton<GetProfileUseCase>(GetProfileUseCase(getIt()));
getIt.registerSingleton<DeleteProfileUsecase>(DeleteProfileUsecase(getIt(), getIt(), getIt()));
getIt.registerSingleton<UpdateProfileUseCase>(UpdateProfileUseCase(getIt())); getIt.registerSingleton<UpdateProfileUseCase>(UpdateProfileUseCase(getIt()));
getIt.registerSingleton<UploadProfilePhotoUsecase>( getIt.registerSingleton<UploadProfilePhotoUsecase>(
@@ -219,6 +240,9 @@ Future<void> setupDependencies() async {
getIt.registerSingleton<GetAvailableZonesUsecase>( getIt.registerSingleton<GetAvailableZonesUsecase>(
GetAvailableZonesUsecase(getIt()), GetAvailableZonesUsecase(getIt()),
); );
getIt.registerSingleton<GetAllZonesUsecase>(
GetAllZonesUsecase(getIt()),
);
getIt.registerSingleton<GetMapSettingsUsecase>( getIt.registerSingleton<GetMapSettingsUsecase>(
GetMapSettingsUsecase(getIt()), GetMapSettingsUsecase(getIt()),
); );
@@ -286,15 +310,25 @@ Future<void> setupDependencies() async {
getIt.registerSingleton<GetScooterByTitleUsecase>( getIt.registerSingleton<GetScooterByTitleUsecase>(
GetScooterByTitleUsecase(getIt()), GetScooterByTitleUsecase(getIt()),
); );
getIt.registerSingleton<GetNotificationsUsecase>(
GetNotificationsUsecase(getIt<NotificationRepository>()),
);
getIt.registerFactory<NotificationsBloc>(
() => NotificationsBloc(getIt<GetNotificationsUsecase>()),
);
// Blocs // Blocs
getIt.registerLazySingleton<SplashBloc>(() => SplashBloc(getIt())); getIt.registerLazySingleton<SplashBloc>(() => SplashBloc(getIt()));
getIt.registerFactory<PhoneAuthBloc>(() => PhoneAuthBloc(getIt())); getIt.registerFactory<PhoneAuthBloc>(() => PhoneAuthBloc(getIt()));
getIt.registerFactory<VerifyCodeBloc>(() => VerifyCodeBloc(getIt())); getIt.registerFactory<VerifyCodeBloc>(
() => VerifyCodeBloc(getIt(), getIt(), getIt()),
);
getIt.registerFactory<ProfileBloc>(() => ProfileBloc(getIt(), getIt(), getIt())); getIt.registerLazySingleton<ProfileBloc>(
() => ProfileBloc(getIt(), getIt(), getIt(), getIt(), getIt(), getIt()),
);
getIt.registerFactory<EditProfileBloc>( getIt.registerFactory<EditProfileBloc>(
() => EditProfileBloc(getIt(), getIt()), () => EditProfileBloc(getIt(), getIt()),
@@ -310,6 +344,7 @@ Future<void> setupDependencies() async {
getIt(), getIt(),
getIt(), getIt(),
getIt(), getIt(),
getIt(),
), ),
); );
@@ -321,9 +356,8 @@ Future<void> setupDependencies() async {
getIt.registerFactory<AddCardBloc>(() => AddCardBloc(getIt())); getIt.registerFactory<AddCardBloc>(() => AddCardBloc(getIt()));
getIt.registerFactory<PaymentMethodSheetBloc>( getIt.registerFactory<PaymentMethodSheetBloc>(
() => PaymentMethodSheetBloc(getIt()), () => PaymentMethodSheetBloc(getIt(), getIt(), getIt(), getIt()),
); );
getIt.registerFactory<CurrentRidesBloc>(() => CurrentRidesBloc(getIt())); getIt.registerFactory<CurrentRidesBloc>(() => CurrentRidesBloc(getIt()));
@@ -338,7 +372,6 @@ Future<void> setupDependencies() async {
getIt.registerFactory<NewsBloc>(() => NewsBloc(getIt<NewsRepository>())); getIt.registerFactory<NewsBloc>(() => NewsBloc(getIt<NewsRepository>()));
getIt.registerFactory<SendPhotoBloc>(() => SendPhotoBloc(getIt(), getIt())); getIt.registerFactory<SendPhotoBloc>(() => SendPhotoBloc(getIt(), getIt()));
getIt.registerFactory<SubscriptionListBloc>( getIt.registerFactory<SubscriptionListBloc>(
@@ -370,7 +403,34 @@ Future<void> setupDependencies() async {
() => OrderHistoryBloc(getIt<GetScooterOrderHistoryUsecase>()), () => OrderHistoryBloc(getIt<GetScooterOrderHistoryUsecase>()),
); );
getIt.registerFactory<FineListBloc>(() => FineListBloc(getIt()));
getIt.registerFactory<ScooterCodeBloc>( getIt.registerFactory<ScooterCodeBloc>(
() => ScooterCodeBloc(getScooterByTitleUsecase: getIt<GetScooterByTitleUsecase>()), () => ScooterCodeBloc(
getScooterByTitleUsecase: getIt<GetScooterByTitleUsecase>(),
getAddressUsecase: getIt<GetAddressByPointUsecase>(),
getPedestrianRoutesUsecase: getIt<GetPedestrianRoutesUsecase>()
),
);
// Repository
getIt.registerSingleton<PromoCodeRepository>(
PromoCodeRepositoryImpl(getIt<ApiService>()),
);
// UseCase
getIt.registerSingleton<ApplyPromoCodeUsecase>(
ApplyPromoCodeUsecase(getIt<PromoCodeRepository>()),
);
getIt.registerFactory<GetFinesUsecase>(() => GetFinesUsecase(getIt()));
getIt.registerFactory<GetFineDetailsUsecase>(() => GetFineDetailsUsecase(getIt()));
getIt.registerFactory<PayFineUsecase>(() => PayFineUsecase(getIt()));
// Bloc (factory, т.к. экран создаёт новый экземпляр)
getIt.registerFactory<PromoCodeBloc>(
() => PromoCodeBloc(getIt<ApplyPromoCodeUsecase>()),
); );
} }

View File

@@ -32,7 +32,7 @@ class ClientNotification {
required this.createdAt, required this.createdAt,
this.canceledAt, this.canceledAt,
this.readAt, this.readAt,
}); }) ;
ClientNotification copyWith({ ClientNotification copyWith({
int? id, int? id,

Some files were not shown because too many files have changed in this diff Show More