Compare commits
18 Commits
0a6c40181a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 3a74b8017d | |||
| 153a763b6f | |||
| 7460408784 | |||
| 5f57af2ad2 | |||
| cf5b56e365 | |||
| b0c9f6dc17 | |||
| ece8e7ba79 | |||
| 02b3e5caa8 | |||
| a556dc5736 | |||
| 6513a004d9 | |||
| 80a95ece5b | |||
| f53fea576e | |||
| 182be1049b | |||
| c9b8d143d1 | |||
| d5f70ee9c4 | |||
| 99d2875b56 | |||
| 46cd22c287 | |||
| 7a2c214ff5 |
@@ -15,7 +15,7 @@ plugins {
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.sparkit.be_happy"
|
||||
namespace = "com.behappybel.behappy"
|
||||
compileSdk = flutter.compileSdkVersion
|
||||
ndkVersion = "27.0.12077973"
|
||||
|
||||
@@ -44,7 +44,7 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||
applicationId = "com.sparkit.behappy"
|
||||
applicationId = "com.behappybel.behappy"
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||
minSdk = 26
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<meta-data
|
||||
android:name="com.yandex.runtime.API_KEY"
|
||||
android:value="a0ef1404-2650-4f28-9891-c965ecc09174" />
|
||||
android:value="45fe500d-b549-4444-9e4b-3b2acd78ee2c" />
|
||||
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.sparkit.be_happy
|
||||
package com.behappybel.behappy
|
||||
|
||||
import android.os.Bundle
|
||||
import com.yandex.mapkit.MapKitFactory
|
||||
@@ -6,7 +6,7 @@ import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
class MainActivity : FlutterActivity() {
|
||||
override protected fun onCreate(savedInstanceState: Bundle?) {
|
||||
MapKitFactory.setApiKey("a0ef1404-2650-4f28-9891-c965ecc09174")
|
||||
MapKitFactory.setApiKey("45fe500d-b549-4444-9e4b-3b2acd78ee2c")
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
}
|
||||
BIN
android/app/src/main/res/drawable-hdpi/splash.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
android/app/src/main/res/drawable-mdpi/splash.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |
BIN
android/app/src/main/res/drawable-v21/background.png
Normal file
|
After Width: | Height: | Size: 69 B |
@@ -1,12 +1,9 @@
|
||||
<?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">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
<item>
|
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||
</item>
|
||||
<item>
|
||||
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
||||
BIN
android/app/src/main/res/drawable-xhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
android/app/src/main/res/drawable-xxhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
android/app/src/main/res/drawable-xxxhdpi/splash.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
android/app/src/main/res/drawable/background.png
Normal file
|
After Width: | Height: | Size: 69 B |
@@ -1,12 +1,9 @@
|
||||
<?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">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
<!-- You can insert your own image assets here -->
|
||||
<!-- <item>
|
||||
<bitmap
|
||||
android:gravity="center"
|
||||
android:src="@mipmap/launch_image" />
|
||||
</item> -->
|
||||
<item>
|
||||
<bitmap android:gravity="fill" android:src="@drawable/background"/>
|
||||
</item>
|
||||
<item>
|
||||
<bitmap android:gravity="center" android:src="@drawable/splash"/>
|
||||
</item>
|
||||
</layer-list>
|
||||
|
||||
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 9.0 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
19
android/app/src/main/res/values-night-v31/styles.xml
Normal 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>
|
||||
@@ -5,6 +5,10 @@
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<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>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
|
||||
19
android/app/src/main/res/values-v31/styles.xml
Normal 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>
|
||||
@@ -5,6 +5,10 @@
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<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>
|
||||
<!-- Theme applied to the Android Window as soon as the process has started.
|
||||
This theme determines the color of the Android Window while your
|
||||
|
||||
@@ -4,5 +4,6 @@ android.enableJetifier=true
|
||||
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
|
||||
|
||||
BIN
assets/icons/fine.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
assets/payment_logo.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
assets/rules_alpha.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
assets/rules_apple_pay.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
assets/rules_belcard.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
assets/rules_mastercard.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
assets/rules_mastercard_id.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
assets/rules_samsung_pay.png
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
assets/rules_visa.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
assets/rules_visa_secure.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
assets/tech_works.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
@@ -2,6 +2,8 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>13.0</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
#include? "Secrets.xcconfig"
|
||||
YANDEX_MAPKIT_API_KEY=a0ef1404-2650-4f28-9891-c965ecc09174
|
||||
YANDEX_MAPKIT_API_KEY=45fe500d-b549-4444-9e4b-3b2acd78ee2c
|
||||
// Переопределение Pods/ML Kit: arm64 для симулятора на Apple Silicon (M1/M4)
|
||||
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
#include? "Secrets.xcconfig"
|
||||
YANDEX_MAPKIT_API_KEY=a0ef1404-2650-4f28-9891-c965ecc09174
|
||||
YANDEX_MAPKIT_API_KEY=45fe500d-b549-4444-9e4b-3b2acd78ee2c
|
||||
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
|
||||
#include "Generated.xcconfig"
|
||||
#include? "Secrets.xcconfig"
|
||||
YANDEX_MAPKIT_API_KEY=a0ef1404-2650-4f28-9891-c965ecc09174
|
||||
YANDEX_MAPKIT_API_KEY=45fe500d-b549-4444-9e4b-3b2acd78ee2c
|
||||
EXCLUDED_ARCHS[sdk=iphonesimulator*]=i386
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
# image_picker_ios и др. требуют минимум iOS 13
|
||||
platform :ios, '13.0'
|
||||
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,
|
||||
@@ -43,6 +44,7 @@ post_install do |installer|
|
||||
# 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
|
||||
|
||||
@@ -2,6 +2,8 @@ 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):
|
||||
@@ -12,9 +14,6 @@ PODS:
|
||||
- mobile_scanner (7.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- path_provider_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -22,17 +21,17 @@ PODS:
|
||||
- Flutter
|
||||
- yandex_mapkit (0.0.1):
|
||||
- Flutter
|
||||
- YandexMapsMobile (= 4.22.0-lite)
|
||||
- YandexMapsMobile (4.22.0-lite)
|
||||
- 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`)
|
||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/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`)
|
||||
@@ -46,6 +45,8 @@ EXTERNAL SOURCES:
|
||||
: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:
|
||||
@@ -54,8 +55,6 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||
mobile_scanner:
|
||||
:path: ".symlinks/plugins/mobile_scanner/darwin"
|
||||
path_provider_foundation:
|
||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||
shared_preferences_foundation:
|
||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||
url_launcher_ios:
|
||||
@@ -66,16 +65,16 @@ EXTERNAL SOURCES:
|
||||
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
|
||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||
yandex_mapkit: bac34ca1bdf97e87252a8c6d09a95b1fe39ba103
|
||||
YandexMapsMobile: c73844c6096bbb240d1491adc511c2ef4a88d88d
|
||||
yandex_mapkit: b0468cf6fdc2e5ef315e08c081cb48763db1edee
|
||||
YandexMapsMobile: 27e6e45425bb61f0be2dbc2bf02d4e64926691a9
|
||||
|
||||
PODFILE CHECKSUM: 715b1068ab8815ca4115a24e305e836709652b69
|
||||
PODFILE CHECKSUM: 4db91eb18e4c468b9b75ce0a1fbe33194b57f06a
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -10,12 +10,12 @@
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
6D33173F8CCB65895D564988 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4BB22D9E6003D7254B27B141 /* Pods_RunnerTests.framework */; };
|
||||
719658A7EA74BCF79744189C /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 815E41E9A67B82F3B5893FB0 /* Pods_Runner.framework */; };
|
||||
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 */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
FB3C1019114E649A3758FC7D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 151F40E0A8A0B88D7F9715D8 /* Pods_Runner.framework */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@@ -42,30 +42,30 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0EB91AA8815BC4C23E9C769C /* 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>"; };
|
||||
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>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
151F40E0A8A0B88D7F9715D8 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
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; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
4BB22D9E6003D7254B27B141 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
4D0302F803C0949E93DDCE44 /* 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>"; };
|
||||
525F1415727A8E2A6F5CA828 /* 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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
9740EEB41CF90195004384FC /* Profile.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Profile.xcconfig; path = Flutter/Profile.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>"; };
|
||||
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; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
BAF1C86965EF66AE2F0839BD /* 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>"; };
|
||||
BE9A8C77364E79EA4C6EE36B /* 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>"; };
|
||||
D24CB1920C4748F67C854B22 /* 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>"; };
|
||||
A5825CAAC7BEAFA8756F6D22 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -73,7 +73,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
6D33173F8CCB65895D564988 /* Pods_RunnerTests.framework in Frameworks */,
|
||||
947230899A63DCC5FC354559 /* Pods_RunnerTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -81,7 +81,7 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
FB3C1019114E649A3758FC7D /* Pods_Runner.framework in Frameworks */,
|
||||
719658A7EA74BCF79744189C /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -96,6 +96,15 @@
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4E47A3B8F8440AE11EF826D6 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
815E41E9A67B82F3B5893FB0 /* Pods_Runner.framework */,
|
||||
A5825CAAC7BEAFA8756F6D22 /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -115,8 +124,8 @@
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
991E98147265C7C44D711731 /* Pods */,
|
||||
E94B50B8FA90842D98EF918A /* Frameworks */,
|
||||
BBAC3160211F77BA6C1CDBEB /* Pods */,
|
||||
4E47A3B8F8440AE11EF826D6 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -144,29 +153,19 @@
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
991E98147265C7C44D711731 /* Pods */ = {
|
||||
BBAC3160211F77BA6C1CDBEB /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4D0302F803C0949E93DDCE44 /* Pods-Runner.debug.xcconfig */,
|
||||
0EB91AA8815BC4C23E9C769C /* Pods-Runner.release.xcconfig */,
|
||||
525F1415727A8E2A6F5CA828 /* Pods-Runner.profile.xcconfig */,
|
||||
BAF1C86965EF66AE2F0839BD /* Pods-RunnerTests.debug.xcconfig */,
|
||||
D24CB1920C4748F67C854B22 /* Pods-RunnerTests.release.xcconfig */,
|
||||
BE9A8C77364E79EA4C6EE36B /* Pods-RunnerTests.profile.xcconfig */,
|
||||
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 */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E94B50B8FA90842D98EF918A /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
151F40E0A8A0B88D7F9715D8 /* Pods_Runner.framework */,
|
||||
4BB22D9E6003D7254B27B141 /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -174,7 +173,7 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
1D742F73AAFC432DF3836D7E /* [CP] Check Pods Manifest.lock */,
|
||||
8320BCAEA155F95875F06656 /* [CP] Check Pods Manifest.lock */,
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
83F4E53737A5B4793588BFEB /* Frameworks */,
|
||||
@@ -193,15 +192,15 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
8734FCBECF65F25CB259DF82 /* [CP] Check Pods Manifest.lock */,
|
||||
C59C8F9337F753AC74343087 /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
25F6FF3856E913FFAF963081 /* [CP] Embed Pods Frameworks */,
|
||||
FF12327738E91E5AA87207B8 /* [CP] Copy Pods Resources */,
|
||||
FB90C79E7B88832806AD3371 /* [CP] Embed Pods Frameworks */,
|
||||
81264E30AB9A7C4C10AB44BA /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -273,7 +272,40 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
1D742F73AAFC432DF3836D7E /* [CP] Check Pods Manifest.lock */ = {
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
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 = (
|
||||
@@ -295,40 +327,22 @@
|
||||
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;
|
||||
};
|
||||
25F6FF3856E913FFAF963081 /* [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;
|
||||
};
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||
);
|
||||
name = "Thin Binary";
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
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\" build";
|
||||
};
|
||||
8734FCBECF65F25CB259DF82 /* [CP] Check Pods Manifest.lock */ = {
|
||||
C59C8F9337F753AC74343087 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
@@ -350,36 +364,21 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "Run Script";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
FF12327738E91E5AA87207B8 /* [CP] Copy Pods Resources */ = {
|
||||
FB90C79E7B88832806AD3371 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
"${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-resources.sh\"\n";
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
@@ -479,7 +478,7 @@
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TARGETED_DEVICE_FAMILY = "1";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Profile;
|
||||
@@ -490,15 +489,19 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = J463CU8H5F;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
@@ -507,14 +510,14 @@
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = BAF1C86965EF66AE2F0839BD /* Pods-RunnerTests.debug.xcconfig */;
|
||||
baseConfigurationReference = 7AFC7F9B8515A109C72DDF1B /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -525,14 +528,14 @@
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = D24CB1920C4748F67C854B22 /* Pods-RunnerTests.release.xcconfig */;
|
||||
baseConfigurationReference = 12F1F4F8ABC8CE708CB9918F /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
@@ -541,14 +544,14 @@
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = BE9A8C77364E79EA4C6EE36B /* Pods-RunnerTests.profile.xcconfig */;
|
||||
baseConfigurationReference = 6EC6FEDB5882EB1ECF391D95 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy.RunnerTests;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
@@ -608,7 +611,7 @@
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TARGETED_DEVICE_FAMILY = "1";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -661,7 +664,7 @@
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
SWIFT_COMPILATION_MODE = wholemodule;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
TARGETED_DEVICE_FAMILY = "1";
|
||||
VALIDATE_PRODUCT = YES;
|
||||
};
|
||||
name = Release;
|
||||
@@ -672,15 +675,19 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = J463CU8H5F;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -694,15 +701,19 @@
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = J463CU8H5F;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.sparkit.beHappy;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.behappybel.behappy;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
|
||||
|
Before Width: | Height: | Size: 351 KiB After Width: | Height: | Size: 322 KiB |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 986 B |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
21
ios/Runner/Assets.xcassets/LaunchBackground.imageset/Contents.json
vendored
Normal 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
|
||||
}
|
||||
}
|
||||
BIN
ios/Runner/Assets.xcassets/LaunchBackground.imageset/background.png
vendored
Normal file
|
After Width: | Height: | Size: 69 B |
@@ -1,23 +1,23 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"filename" : "LaunchImage@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"version" : 1,
|
||||
"author" : "xcode"
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 68 B After Width: | Height: | Size: 11 KiB |
@@ -16,13 +16,19 @@
|
||||
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
||||
</imageView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" image="LaunchBackground" translatesAutoresizingMaskIntoConstraints="NO" id="tWc-Dq-wcI"/>
|
||||
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4"></imageView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
||||
<constraint firstItem="YRO-k0-Ey4" firstAttribute="leading" secondItem="Ze5-6b-2t3" secondAttribute="leading" id="3T2-ad-Qdv"/>
|
||||
<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>
|
||||
</view>
|
||||
</viewController>
|
||||
@@ -32,6 +38,7 @@
|
||||
</scene>
|
||||
</scenes>
|
||||
<resources>
|
||||
<image name="LaunchImage" width="168" height="185"/>
|
||||
<image name="LaunchImage" width="130" height="130"/>
|
||||
<image name="LaunchBackground" width="1" height="1"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
||||
@@ -1,72 +1,95 @@
|
||||
<?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">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Be Happy</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>be_happy</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Be Happy</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>be_happy</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>UIApplicationSceneManifest</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>
|
||||
<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>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>YandexMapKitApiKey</key>
|
||||
<string>$(YANDEX_MAPKIT_API_KEY)</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Данные о местоположении необходимы для поиска ближайших самокатов и отображения их на карте.</string>
|
||||
<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>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>YandexMapKitApiKey</key>
|
||||
<string>$(YANDEX_MAPKIT_API_KEY)</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -21,6 +21,7 @@ import 'package:flutter_client_sse/constants/sse_request_type_enum.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/user_profile.dart';
|
||||
import '../../domain/entities/payment_card.dart';
|
||||
@@ -35,8 +36,11 @@ import '../models/subscriptions_response.dart';
|
||||
import '../models/user_check_response_dto.dart';
|
||||
|
||||
class ApiService {
|
||||
static const String baseUrl = "https://sharing-api.sparkit.by/api/v1";
|
||||
static const String fileBaseUrl = "https://sharing-api.sparkit.by";
|
||||
static const String baseUrl = "https://api.behappybel.by/api/v1";
|
||||
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 Dio _dio;
|
||||
@@ -171,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 {
|
||||
final response = await _dio.get(
|
||||
"$baseUrl/client/me",
|
||||
@@ -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 {
|
||||
final url = "$baseUrl/scooterplan/$scooterId/available";
|
||||
|
||||
@@ -934,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 {
|
||||
try {
|
||||
final response = await _dio.get(
|
||||
@@ -1148,5 +1286,6 @@ class ApiService {
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ Добавь исключение (можно в отдельный файл)
|
||||
|
||||
|
||||
class PromoCodeNotFoundException implements Exception {}
|
||||
|
||||
@@ -27,6 +27,11 @@ class UserProfileRepositoryImpl implements UserProfileRepository {
|
||||
return await _apiService.getProfile() ?? _cachedProfile;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteProfile() async {
|
||||
return await _apiService.deleteProfile();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<UserProfile?> updateProfile(UserProfile profile) async {
|
||||
//await Future.delayed(const Duration(milliseconds: 300));
|
||||
|
||||
@@ -1,21 +1,22 @@
|
||||
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/result.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/tariff.dart';
|
||||
import '../../domain/entities/subscription.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/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';
|
||||
|
||||
class ScooterRepositoryImpl extends ScooterRepository {
|
||||
@@ -425,4 +426,70 @@ class ScooterRepositoryImpl extends ScooterRepository {
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,60 +10,60 @@ class ZoneRepositoryImpl extends ZoneRepository {
|
||||
ZoneRepositoryImpl(this._apiService);
|
||||
|
||||
@override
|
||||
Future<List<Zone>> getZones(List<double> area,
|
||||
int page,
|
||||
int pageSize,) async {
|
||||
|
||||
Future<List<Zone>> getZones(List<double> area, int page, int pageSize) async {
|
||||
final List<Point> list = [];
|
||||
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(
|
||||
area: area,
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
);
|
||||
|
||||
final List<Zone>? zones = responce?.zones;
|
||||
// zones?.add(zone);
|
||||
// zones?.add(zone2);
|
||||
|
||||
print("Scooters: ${zones?.first.title}");
|
||||
|
||||
if (responce != null) {
|
||||
return zones ?? List.empty();
|
||||
if (responce == null) {
|
||||
throw Exception(
|
||||
'Failed to load zones for area: empty response from server',
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,6 @@ class AppSettingsService {
|
||||
}
|
||||
|
||||
bool getMapSettingsFlag(String key) {
|
||||
return sharedPreferences.getBool(key) ?? false;
|
||||
return sharedPreferences.getBool(key) ?? true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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/service/security_service.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_scooter_order_route_history_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/resume_ride_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/add_card_bloc.dart'; // ← новый
|
||||
import 'package:be_happy/presentation/viewmodel/current_rides_bloc.dart';
|
||||
@@ -94,14 +97,18 @@ import '../domain/service/device_info_service.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_fine_details_usecase.dart';
|
||||
import '../domain/usecase/get_fines_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_order_history_usecase.dart';
|
||||
import '../domain/usecase/pay_fine_usecase.dart';
|
||||
import '../domain/usecase/remove_payment_card_usecase.dart';
|
||||
import '../domain/usecase/set_main_payment_card_usecase.dart';
|
||||
import '../presentation/viewmodel/auth_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/news_bloc.dart';
|
||||
import '../presentation/viewmodel/notifications_bloc.dart';
|
||||
@@ -116,7 +123,13 @@ final getIt = GetIt.instance;
|
||||
Future<void> setupDependencies() async {
|
||||
final sharedPreferences = await SharedPreferences.getInstance();
|
||||
final dio = Dio();
|
||||
dio.interceptors.add(LogInterceptor(/*requestHeader: false, responseHeader:false, */responseBody: true, requestBody: true));
|
||||
dio.interceptors.add(
|
||||
LogInterceptor(
|
||||
/*requestHeader: false, responseHeader:false, */
|
||||
responseBody: true,
|
||||
requestBody: true,
|
||||
),
|
||||
);
|
||||
dio.interceptors.add(AuthInterceptor());
|
||||
// HTTP
|
||||
getIt.registerSingleton<http.Client>(http.Client());
|
||||
@@ -140,7 +153,7 @@ Future<void> setupDependencies() async {
|
||||
getIt.registerSingleton<AppSettingsService>(AppSettingsService(getIt()));
|
||||
|
||||
getIt.registerLazySingleton<NewsApiService>(
|
||||
() => NewsApiService(getIt<ApiService>()),
|
||||
() => NewsApiService(getIt<ApiService>()),
|
||||
);
|
||||
|
||||
// Repository
|
||||
@@ -171,7 +184,7 @@ Future<void> setupDependencies() async {
|
||||
);
|
||||
|
||||
getIt.registerLazySingleton<NewsRepository>(
|
||||
() => NewsRepositoryImpl(getIt<NewsApiService>()),
|
||||
() => NewsRepositoryImpl(getIt<NewsApiService>()),
|
||||
);
|
||||
|
||||
getIt.registerSingleton<NotificationRepository>(
|
||||
@@ -195,6 +208,8 @@ Future<void> setupDependencies() async {
|
||||
|
||||
getIt.registerSingleton<GetProfileUseCase>(GetProfileUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<DeleteProfileUsecase>(DeleteProfileUsecase(getIt(), getIt(), getIt()));
|
||||
|
||||
getIt.registerSingleton<UpdateProfileUseCase>(UpdateProfileUseCase(getIt()));
|
||||
|
||||
getIt.registerSingleton<UploadProfilePhotoUsecase>(
|
||||
@@ -225,6 +240,9 @@ Future<void> setupDependencies() async {
|
||||
getIt.registerSingleton<GetAvailableZonesUsecase>(
|
||||
GetAvailableZonesUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetAllZonesUsecase>(
|
||||
GetAllZonesUsecase(getIt()),
|
||||
);
|
||||
getIt.registerSingleton<GetMapSettingsUsecase>(
|
||||
GetMapSettingsUsecase(getIt()),
|
||||
);
|
||||
@@ -296,25 +314,28 @@ Future<void> setupDependencies() async {
|
||||
GetNotificationsUsecase(getIt<NotificationRepository>()),
|
||||
);
|
||||
getIt.registerFactory<NotificationsBloc>(
|
||||
() => NotificationsBloc(getIt<GetNotificationsUsecase>()),
|
||||
() => NotificationsBloc(getIt<GetNotificationsUsecase>()),
|
||||
);
|
||||
|
||||
|
||||
// Blocs
|
||||
getIt.registerLazySingleton<SplashBloc>(() => SplashBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<PhoneAuthBloc>(() => PhoneAuthBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<VerifyCodeBloc>(() => VerifyCodeBloc(getIt(), getIt(), getIt()));
|
||||
getIt.registerFactory<VerifyCodeBloc>(
|
||||
() => VerifyCodeBloc(getIt(), getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerLazySingleton<ProfileBloc>(() => ProfileBloc(getIt(), getIt(), getIt()));
|
||||
getIt.registerLazySingleton<ProfileBloc>(
|
||||
() => ProfileBloc(getIt(), getIt(), getIt(), getIt(), getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<EditProfileBloc>(
|
||||
() => EditProfileBloc(getIt(), getIt()),
|
||||
() => EditProfileBloc(getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<MapBloc>(
|
||||
() => MapBloc(
|
||||
() => MapBloc(
|
||||
getIt(),
|
||||
getIt(),
|
||||
getIt(),
|
||||
@@ -330,33 +351,31 @@ Future<void> setupDependencies() async {
|
||||
getIt.registerFactory<ScooterDetailBloc>(() => ScooterDetailBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<MapSettingsModalBloc>(
|
||||
() => MapSettingsModalBloc(getIt(), getIt()),
|
||||
() => MapSettingsModalBloc(getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<AddCardBloc>(() => AddCardBloc(getIt()));
|
||||
|
||||
|
||||
getIt.registerFactory<PaymentMethodSheetBloc>(
|
||||
() => PaymentMethodSheetBloc(getIt(), getIt(), getIt(), getIt()),
|
||||
() => PaymentMethodSheetBloc(getIt(), getIt(), getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<CurrentRidesBloc>(() => CurrentRidesBloc(getIt()));
|
||||
|
||||
getIt.registerFactory<ActiveRideBloc>(
|
||||
() => ActiveRideBloc(getIt(), getIt(), getIt(), getIt(), getIt()),
|
||||
() => ActiveRideBloc(getIt(), getIt(), getIt(), getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<ReservedRideBloc>(
|
||||
() => ReservedRideBloc(getIt(), getIt()),
|
||||
() => ReservedRideBloc(getIt(), getIt()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<NewsBloc>(() => NewsBloc(getIt<NewsRepository>()));
|
||||
|
||||
|
||||
getIt.registerFactory<SendPhotoBloc>(() => SendPhotoBloc(getIt(), getIt()));
|
||||
|
||||
getIt.registerFactory<SubscriptionListBloc>(
|
||||
() => SubscriptionListBloc(
|
||||
() => SubscriptionListBloc(
|
||||
getAvailableSubscriptionsUsecase: getIt(),
|
||||
getClientSubscriptionsUsecase: getIt(),
|
||||
),
|
||||
@@ -381,26 +400,37 @@ Future<void> setupDependencies() async {
|
||||
|
||||
// Bloc
|
||||
getIt.registerFactory<OrderHistoryBloc>(
|
||||
() => OrderHistoryBloc(getIt<GetScooterOrderHistoryUsecase>()),
|
||||
() => OrderHistoryBloc(getIt<GetScooterOrderHistoryUsecase>()),
|
||||
);
|
||||
|
||||
getIt.registerFactory<FineListBloc>(() => FineListBloc(getIt()));
|
||||
|
||||
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
|
||||
// UseCase
|
||||
getIt.registerSingleton<ApplyPromoCodeUsecase>(
|
||||
ApplyPromoCodeUsecase(getIt<PromoCodeRepository>()),
|
||||
);
|
||||
|
||||
// Bloc (factory, т.к. экран создаёт новый экземпляр)
|
||||
getIt.registerFactory<GetFinesUsecase>(() => GetFinesUsecase(getIt()));
|
||||
|
||||
getIt.registerFactory<GetFineDetailsUsecase>(() => GetFineDetailsUsecase(getIt()));
|
||||
|
||||
getIt.registerFactory<PayFineUsecase>(() => PayFineUsecase(getIt()));
|
||||
|
||||
// Bloc (factory, т.к. экран создаёт новый экземпляр)
|
||||
getIt.registerFactory<PromoCodeBloc>(
|
||||
() => PromoCodeBloc(getIt<ApplyPromoCodeUsecase>()),
|
||||
() => PromoCodeBloc(getIt<ApplyPromoCodeUsecase>()),
|
||||
);
|
||||
}
|
||||
|
||||
62
lib/domain/entities/fine.dart
Normal file
@@ -0,0 +1,62 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
|
||||
class Fine extends Equatable {
|
||||
final int id;
|
||||
final int orderId; // ← добавлено
|
||||
final String scooterNumber; // можно оставить для совместимости, но не использовать в UI
|
||||
final DateTime createdAtDateTime; // ← новое поле
|
||||
final String description;
|
||||
final double amount;
|
||||
final String amountPrint;
|
||||
final List<String> photoUrls;
|
||||
final bool isPaid;
|
||||
|
||||
const Fine({
|
||||
required this.id,
|
||||
required this.orderId,
|
||||
required this.scooterNumber,
|
||||
required this.createdAtDateTime,
|
||||
required this.description,
|
||||
required this.amount,
|
||||
required this.amountPrint,
|
||||
required this.photoUrls,
|
||||
required this.isPaid,
|
||||
});
|
||||
|
||||
factory Fine.fromJson(Map<String, dynamic> json, {String? scooterNumber}) {
|
||||
final List<dynamic> filesJson = json['files'] ?? [];
|
||||
final List<String> photos = filesJson
|
||||
.map((file) => file['path'] as String? ?? file['filename'] as String? ?? '')
|
||||
.where((path) => path.isNotEmpty)
|
||||
.toList();
|
||||
|
||||
// Парсим createdAt как DateTime
|
||||
final createdAtDateTime = DateTime.tryParse(json['createdAt'].toString()) ??
|
||||
DateTime.now(); // fallback
|
||||
|
||||
return Fine(
|
||||
id: json['id'] as int? ?? 0,
|
||||
orderId: json['orderId'] as int? ?? 0,
|
||||
scooterNumber: scooterNumber ?? '',
|
||||
createdAtDateTime: createdAtDateTime,
|
||||
description: json['description'] as String? ?? '',
|
||||
amount: (json['value'] as num?)?.toDouble() ?? 0.0,
|
||||
amountPrint: json['valuePrint'] as String? ?? '0,00 BYN',
|
||||
photoUrls: photos,
|
||||
isPaid: json['isPaid'] as bool? ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [
|
||||
id,
|
||||
orderId,
|
||||
scooterNumber,
|
||||
createdAtDateTime,
|
||||
description,
|
||||
amount,
|
||||
amountPrint,
|
||||
photoUrls,
|
||||
isPaid,
|
||||
];
|
||||
}
|
||||
@@ -6,10 +6,10 @@ class MapSettings {
|
||||
final bool restricted_driving_zones;
|
||||
|
||||
MapSettings({
|
||||
required this.all_placemarks,
|
||||
required this.all_zones,
|
||||
required this.parking_zones,
|
||||
required this.restricted_parking_zones,
|
||||
required this.restricted_driving_zones,
|
||||
this.all_placemarks = true,
|
||||
this.all_zones = true,
|
||||
this.parking_zones = true,
|
||||
this.restricted_parking_zones = true,
|
||||
this.restricted_driving_zones = true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -27,11 +27,12 @@ class ScooterOrder {
|
||||
final DateTime? expiresAt;
|
||||
final DateTime? cancelAt;
|
||||
final String? cancelDescription;
|
||||
final double mileage; //эту
|
||||
final double avgSpeed; //эту и снизу еще 4 есть
|
||||
final double mileage;
|
||||
final double avgSpeed;
|
||||
final String payTotalPricePrint;
|
||||
final String unpayTotalPricePrint;
|
||||
final String totalOrderPricePrint;
|
||||
final bool hasFine;
|
||||
|
||||
ScooterOrder({
|
||||
required this.id,
|
||||
@@ -65,6 +66,7 @@ class ScooterOrder {
|
||||
required this.payTotalPricePrint, // оплачено
|
||||
required this.unpayTotalPricePrint, //неоплачено
|
||||
required this.totalOrderPricePrint, //общая
|
||||
required this.hasFine,
|
||||
});
|
||||
|
||||
factory ScooterOrder.fromJson(Map<String, dynamic> json) {
|
||||
@@ -114,6 +116,7 @@ class ScooterOrder {
|
||||
payTotalPricePrint: paymentInfo?['payTotalPricePrint'] ?? '',
|
||||
unpayTotalPricePrint: paymentInfo?['unpayTotalPricePrint'] ?? '',
|
||||
totalOrderPricePrint: paymentInfo?['totalOrderPricePrint'] ?? '',
|
||||
hasFine: paymentInfo?['hasFine'] ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ class Tariff {
|
||||
final double startPrice; // Старт цена
|
||||
final double cashback; // Процент кэшбэка
|
||||
final double insurance; // Страховка
|
||||
final int subscriptionId;
|
||||
|
||||
Tariff({
|
||||
required this.id,
|
||||
@@ -23,6 +24,7 @@ class Tariff {
|
||||
required this.startPrice,
|
||||
required this.cashback,
|
||||
required this.insurance,
|
||||
required this.subscriptionId,
|
||||
});
|
||||
|
||||
factory Tariff.fromJson(Map<String, dynamic> json) {
|
||||
@@ -41,6 +43,7 @@ class Tariff {
|
||||
startPrice: (planPrice['start'] as num?)?.toDouble() ?? 0.0,
|
||||
cashback: (planPrice['cashback'] as num?)?.toDouble() ?? 0.0,
|
||||
insurance: (planPrice['insurance'] as num?)?.toDouble() ?? 0.0,
|
||||
subscriptionId: json.containsKey('subscriptionId') ? json['subscriptionId'] : 0,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:be_happy/domain/entities/point.dart';
|
||||
|
||||
class Zone {
|
||||
@@ -8,9 +10,6 @@ class Zone {
|
||||
final String type;
|
||||
final bool isActive;
|
||||
final String shapeType;
|
||||
// Трехмерная структура для поддержки MultiPolygon и дыр (holes):
|
||||
// geometry[индекс_полигона][индекс_кольца][индекс_точки]
|
||||
// индекс_кольца == 0 — внешняя граница, > 0 — внутренние вырезы (дыры)
|
||||
final List<List<List<Point>>> geometry;
|
||||
final String speedLimit;
|
||||
|
||||
@@ -25,7 +24,6 @@ class Zone {
|
||||
required this.speedLimit,
|
||||
});
|
||||
|
||||
// Геттер для обратной совместимости (возвращает внешнее кольцо первого полигона)
|
||||
List<Point> get points {
|
||||
if (geometry.isNotEmpty && geometry[0].isNotEmpty) {
|
||||
return geometry[0][0];
|
||||
@@ -45,77 +43,64 @@ class Zone {
|
||||
|
||||
if (decoded is List && decoded.isNotEmpty) {
|
||||
if (shapeType == 'Polygon') {
|
||||
// Структура: [[[lon, lat], [lon, lat], ...], [hole1], ...]
|
||||
List<List<Point>> polygonRings = [];
|
||||
for (var ring in decoded) {
|
||||
if (ring is List) {
|
||||
List<Point> ringPoints = [];
|
||||
for (var coord in ring) {
|
||||
if (coord is List && coord.length >= 2) {
|
||||
// В GeoJSON сначала идет Longitude, затем Latitude
|
||||
ringPoints.add(Point(
|
||||
(coord[1] as num).toDouble(),
|
||||
(coord[0] as num).toDouble(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if (ringPoints.isNotEmpty) polygonRings.add(ringPoints);
|
||||
}
|
||||
}
|
||||
final polygonRings = _parseRings(decoded);
|
||||
if (polygonRings.isNotEmpty) parsedGeometry.add(polygonRings);
|
||||
|
||||
} else if (shapeType == 'MultiPolygon') {
|
||||
// Структура: [[[[lon, lat], ...]], [[[lon, lat], ...]]]
|
||||
for (var poly in decoded) {
|
||||
if (poly is List) {
|
||||
List<List<Point>> polygonRings = [];
|
||||
for (var ring in poly) {
|
||||
if (ring is List) {
|
||||
List<Point> ringPoints = [];
|
||||
for (var coord in ring) {
|
||||
if (coord is List && coord.length >= 2) {
|
||||
ringPoints.add(Point(
|
||||
(coord[1] as num).toDouble(),
|
||||
(coord[0] as num).toDouble(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if (ringPoints.isNotEmpty) polygonRings.add(ringPoints);
|
||||
}
|
||||
}
|
||||
final polygonRings = _parseRings(poly);
|
||||
if (polygonRings.isNotEmpty) parsedGeometry.add(polygonRings);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Fallback для LineString или плоских списков
|
||||
List<Point> ringPoints = [];
|
||||
for (var coord in decoded) {
|
||||
if (coord is List && coord.length >= 2) {
|
||||
ringPoints.add(Point(
|
||||
(coord[1] as num).toDouble(),
|
||||
(coord[0] as num).toDouble(),
|
||||
));
|
||||
}
|
||||
}
|
||||
if (ringPoints.isNotEmpty) parsedGeometry.add([ringPoints]);
|
||||
final singleRing = _parseCoordinateList(decoded);
|
||||
if (singleRing.isNotEmpty) parsedGeometry.add([singleRing]);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
print("PARSE ERROR for Zone ID ${json['id']}: $e");
|
||||
} catch (e, stackTrace) {
|
||||
// Replace with your project logger (e.g., debugPrint or Logger)
|
||||
assert(() {
|
||||
print("PARSE ERROR for Zone ID ${json['id']}: $e\n$stackTrace");
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
|
||||
return Zone(
|
||||
id: json['id'] ?? 0,
|
||||
title: json['title'] ?? 'Unknown',
|
||||
description: json['description'] ?? '',
|
||||
type: json['type'] ?? '',
|
||||
isActive: json['isActive'] ?? false,
|
||||
speedLimit: json['speedLimit'] ?? '',
|
||||
id: json['id'] as int? ?? 0,
|
||||
title: json['title'] as String? ?? 'Unknown',
|
||||
description: json['description'] as String? ?? '',
|
||||
type: json['type'] as String? ?? '',
|
||||
isActive: json['isActive'] as bool? ?? false,
|
||||
speedLimit: json['speedLimit'] as String? ?? '',
|
||||
shapeType: shapeType,
|
||||
geometry: parsedGeometry,
|
||||
);
|
||||
}
|
||||
|
||||
static List<List<Point>> _parseRings(List rawRings) {
|
||||
List<List<Point>> polygonRings = [];
|
||||
for (var ring in rawRings) {
|
||||
if (ring is List) {
|
||||
final ringPoints = _parseCoordinateList(ring);
|
||||
if (ringPoints.isNotEmpty) polygonRings.add(ringPoints);
|
||||
}
|
||||
}
|
||||
return polygonRings;
|
||||
}
|
||||
|
||||
static List<Point> _parseCoordinateList(List rawCoords) {
|
||||
List<Point> ringPoints = [];
|
||||
for (var coord in rawCoords) {
|
||||
if (coord is List && coord.length >= 2) {
|
||||
ringPoints.add(Point(
|
||||
(coord[1] as num).toDouble(),
|
||||
(coord[0] as num).toDouble(),
|
||||
));
|
||||
}
|
||||
}
|
||||
return ringPoints;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Zone{id: $id, title: $title, type: $type, polygonsCount: ${geometry.length}}';
|
||||
|
||||
@@ -5,6 +5,7 @@ import '../entities/user_profile.dart';
|
||||
|
||||
abstract class UserProfileRepository {
|
||||
Future<UserProfile> getProfile();
|
||||
Future<void> deleteProfile();
|
||||
Future<UserProfile?> updateProfile(UserProfile profile);
|
||||
Future<int?> uploadProfilePhoto(File imageFile);
|
||||
Future<UserCheckFlags?> checkUser();
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:be_happy/domain/entities/active_scooter_order.dart';
|
||||
|
||||
import '../../core/result.dart';
|
||||
import '../entities/client_subscription.dart';
|
||||
import '../entities/fine.dart';
|
||||
import '../entities/point.dart';
|
||||
import '../entities/scooter.dart';
|
||||
import '../entities/subscription.dart';
|
||||
@@ -53,4 +54,14 @@ abstract class ScooterRepository {
|
||||
|
||||
Future<Result<List<Point>>> getScooterOrderRouteHistory(int id);
|
||||
|
||||
Future<Result<Fine>> getFineDetails(int orderId);
|
||||
|
||||
Future<Result<void>> payFine({
|
||||
required int orderId,
|
||||
int? cardId,
|
||||
required bool isBalance,
|
||||
});
|
||||
|
||||
Future<Result<List<Fine>>> getClientFines();
|
||||
|
||||
}
|
||||
|
||||
@@ -2,5 +2,6 @@ import '../entities/zone.dart';
|
||||
|
||||
abstract class ZoneRepository {
|
||||
Future<List<Zone>> getZones(List<double> area, int page, int pageSize);
|
||||
Future<List<Zone>> getAllZones(int page, int pageSize);
|
||||
}
|
||||
|
||||
|
||||
21
lib/domain/usecase/delete_profile_usecase.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import '../entities/user_profile.dart';
|
||||
import '../repositories/auth_repository.dart';
|
||||
import '../repositories/pin_repository.dart';
|
||||
import '../repositories/profile_repository.dart';
|
||||
|
||||
class DeleteProfileUsecase {
|
||||
final UserProfileRepository repository;
|
||||
final PinRepository _pinRepository;
|
||||
final AuthRepository _authRepository;
|
||||
|
||||
|
||||
|
||||
DeleteProfileUsecase(this.repository, this._pinRepository, this._authRepository);
|
||||
|
||||
Future<void> call() {
|
||||
_pinRepository.removePin();
|
||||
repository.deleteProfile();
|
||||
return _authRepository.logout();
|
||||
}
|
||||
}
|
||||
|
||||
30
lib/domain/usecase/get_all_zones_usecase.dart
Normal file
@@ -0,0 +1,30 @@
|
||||
import '../entities/zone.dart';
|
||||
import '../repositories/zone_repository.dart';
|
||||
|
||||
class GetAllZonesUsecase {
|
||||
final ZoneRepository repository;
|
||||
|
||||
GetAllZonesUsecase(this.repository);
|
||||
|
||||
static const int _pageSize = 100;
|
||||
|
||||
Future<List<Zone>> call() async {
|
||||
final List<Zone> allZones = [];
|
||||
int page = 0;
|
||||
|
||||
while (true) {
|
||||
final zones = await repository.getAllZones(page, _pageSize);
|
||||
|
||||
if (zones == null || zones.isEmpty) break;
|
||||
|
||||
allZones.addAll(zones);
|
||||
|
||||
// если пришло меньше, чем размер страницы — это последняя страница
|
||||
if (zones.length < _pageSize) break;
|
||||
|
||||
page++;
|
||||
}
|
||||
|
||||
return allZones;
|
||||
}
|
||||
}
|
||||
14
lib/domain/usecase/get_fine_details_usecase.dart
Normal file
@@ -0,0 +1,14 @@
|
||||
import 'package:be_happy/core/result.dart';
|
||||
import '../entities/fine.dart';
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
|
||||
class GetFineDetailsUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetFineDetailsUsecase(this.repository);
|
||||
|
||||
Future<Result<Fine>> call(int orderId) {
|
||||
return repository.getFineDetails(orderId);
|
||||
}
|
||||
}
|
||||
13
lib/domain/usecase/get_fines_usecase.dart
Normal file
@@ -0,0 +1,13 @@
|
||||
import '../../core/result.dart';
|
||||
import '../entities/fine.dart';
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class GetFinesUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
GetFinesUsecase(this.repository);
|
||||
|
||||
Future<Result<List<Fine>>> call() {
|
||||
return repository.getClientFines();
|
||||
}
|
||||
}
|
||||
21
lib/domain/usecase/pay_fine_usecase.dart
Normal file
@@ -0,0 +1,21 @@
|
||||
import '../../core/result.dart';
|
||||
import '../entities/fine.dart';
|
||||
import '../repositories/scooter_repository.dart';
|
||||
|
||||
class PayFineUsecase {
|
||||
final ScooterRepository repository;
|
||||
|
||||
PayFineUsecase(this.repository);
|
||||
|
||||
Future<Result<void>> call({
|
||||
required int orderId,
|
||||
int? cardId,
|
||||
required bool isBalance,
|
||||
}) {
|
||||
return repository.payFine(
|
||||
orderId: orderId,
|
||||
cardId: cardId,
|
||||
isBalance: isBalance,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import 'package:be_happy/domain/entities/map_settings.dart';
|
||||
|
||||
import '../repositories/app_settings_repository.dart';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart'; // 🔹 1. Добавлен импорт
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:bot_toast/bot_toast.dart';
|
||||
import 'package:be_happy/presentation/event/edit_profile_event.dart';
|
||||
import 'package:be_happy/presentation/event/profile_event.dart';
|
||||
@@ -69,6 +70,14 @@ class MyApp extends StatelessWidget {
|
||||
title: 'BeHappy',
|
||||
debugShowCheckedModeBanner: false,
|
||||
theme: ThemeData.dark(),
|
||||
localizationsDelegates: const [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: const [
|
||||
Locale('ru', 'RU'),
|
||||
],
|
||||
builder: BotToastInit(),
|
||||
routerConfig: appRouter.router,
|
||||
),
|
||||
|
||||
@@ -2,13 +2,15 @@ import 'package:flutter/material.dart';
|
||||
|
||||
class CustomAppBar extends StatelessWidget {
|
||||
final String title;
|
||||
final showBackButton;
|
||||
|
||||
const CustomAppBar({super.key, required this.title});
|
||||
const CustomAppBar({super.key, required this.title, this.showBackButton = true});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
if (showBackButton)
|
||||
InkWell(
|
||||
onTap: () => Navigator.pop(context),
|
||||
child: Row(
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class DeleteAccountDialog extends StatelessWidget {
|
||||
const DeleteAccountDialog({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
insetPadding: const EdgeInsets.symmetric(horizontal: 40),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(24),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF2E3253).withOpacity(0.95),
|
||||
borderRadius: BorderRadius.circular(28),
|
||||
),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
"Удалить\nучётную запись?",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.2,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
const Text(
|
||||
"Это действие необратимо. Все ваши\nданные будут удалены безвозвратно",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white70,
|
||||
fontSize: 14,
|
||||
height: 1.4,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
Container(
|
||||
width: double.infinity,
|
||||
height: 52,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(26),
|
||||
gradient: const LinearGradient(
|
||||
colors: [Color(0xFFFF8E8E), Color(0xFFFE5F86)],
|
||||
),
|
||||
),
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Navigator.pop(context, true),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(26),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
"Удалить",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 52,
|
||||
child: ElevatedButton(
|
||||
onPressed: () => Navigator.pop(context, false),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF0D1024),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(26),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
"Отмена",
|
||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
60
lib/presentation/components/full_screen_image_viewer.dart
Normal file
@@ -0,0 +1,60 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FullScreenImageViewer extends StatefulWidget {
|
||||
final List<String> photoUrls;
|
||||
final int initialIndex;
|
||||
|
||||
const FullScreenImageViewer({
|
||||
super.key,
|
||||
required this.photoUrls,
|
||||
required this.initialIndex,
|
||||
});
|
||||
|
||||
@override
|
||||
State<FullScreenImageViewer> createState() => _FullScreenImageViewerState();
|
||||
}
|
||||
|
||||
class _FullScreenImageViewerState extends State<FullScreenImageViewer> {
|
||||
late PageController _pageController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_pageController = PageController(initialPage: widget.initialIndex);
|
||||
}
|
||||
|
||||
String _resolveImageUrl(String path) {
|
||||
if (path.startsWith('http://') || path.startsWith('https://')) return path;
|
||||
return 'https://sharing-api.sparkit.by/$path';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: Colors.black,
|
||||
appBar: AppBar(
|
||||
backgroundColor: Colors.transparent,
|
||||
iconTheme: const IconThemeData(color: Colors.white),
|
||||
),
|
||||
body: PageView.builder(
|
||||
controller: _pageController,
|
||||
itemCount: widget.photoUrls.length,
|
||||
itemBuilder: (context, index) {
|
||||
final photo = widget.photoUrls[index];
|
||||
final imageUrl = _resolveImageUrl(photo);
|
||||
return InteractiveViewer(
|
||||
child: Center(
|
||||
child: Image.network(
|
||||
imageUrl,
|
||||
fit: BoxFit.contain,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return const Icon(Icons.error, color: Colors.white, size: 64);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,6 @@ class _ScooterBottomSheetState extends State<ScooterBottomSheet> {
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// PageView с динамическим списком
|
||||
SizedBox(
|
||||
height: 220,
|
||||
child: PageView.builder(
|
||||
@@ -115,8 +114,6 @@ class _ScooterBottomSheetState extends State<ScooterBottomSheet> {
|
||||
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 250),
|
||||
// 2. Добавляем левый отступ ТОЛЬКО для первого элемента,
|
||||
// чтобы он совпадал с заголовком
|
||||
margin: EdgeInsets.only(
|
||||
left: index == 0 ? 20 : 0,
|
||||
right: 16,
|
||||
@@ -243,7 +240,7 @@ class _ScooterCard extends StatelessWidget {
|
||||
showArrows: true,
|
||||
height: 32,
|
||||
width: double.infinity,
|
||||
fontSize: 12,
|
||||
fontSize: 11,
|
||||
onTap: () {
|
||||
context.go('/home/scooter/${scooter.id}', extra: [address, scooter.distance]);
|
||||
},
|
||||
|
||||
@@ -73,7 +73,6 @@ class MapSettingsSheet extends StatelessWidget {
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.read<MapSettingsModalBloc>().add(ApllyButtonClick());
|
||||
context.read<MapBloc>().add(UpdateMap());
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: const Text(
|
||||
|
||||
@@ -3,8 +3,10 @@ import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../../di/service_locator.dart';
|
||||
import '../../event/map_event.dart';
|
||||
import '../../event/reserved_ride_event.dart';
|
||||
import '../../state/reserved_ride_state.dart';
|
||||
import '../../viewmodel/map_bloc.dart';
|
||||
import '../../viewmodel/reserved_ride_bloc.dart';
|
||||
import '../dialog/cancel_booking_dialog.dart';
|
||||
import '../gradient_button.dart';
|
||||
@@ -125,7 +127,6 @@ class _ReservedRideSheetState extends State<ReservedRideSheet> {
|
||||
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// ТАЙМЕР + ИНФО О САМОКАТЕ (КОМПАКТНЫЙ)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Row(
|
||||
@@ -227,6 +228,7 @@ class _ReservedRideSheetState extends State<ReservedRideSheet> {
|
||||
listener: (context, state) {
|
||||
if (state.rideStarted) {
|
||||
Navigator.pop(context);
|
||||
context.read<MapBloc>().add(FetchActiveOrders());
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
|
||||
@@ -57,7 +57,7 @@ class _ScooterBottomSheetState extends State<ScooterBottomSheet> {
|
||||
if (state.status == ScooterDetailModalStatus.success) {
|
||||
return Dismissible(
|
||||
key: const Key('scooter-modal'),
|
||||
direction: DismissDirection.down, // Закрытие только вниз
|
||||
direction: DismissDirection.down,
|
||||
onDismissed: (_) => context.pop(),
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
@@ -79,7 +79,6 @@ class _ScooterBottomSheetState extends State<ScooterBottomSheet> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header с адресом (без изменений)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Row(
|
||||
@@ -123,13 +122,11 @@ class _ScooterBottomSheetState extends State<ScooterBottomSheet> {
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// PageView с динамическим списком
|
||||
SizedBox(
|
||||
height: 220,
|
||||
child: PageView.builder(
|
||||
controller: _pageController,
|
||||
padEnds: false,
|
||||
// Оставляем false, чтобы первый элемент прилипал к левому краю
|
||||
itemCount: state.scooters!.length,
|
||||
itemBuilder: (context, index) {
|
||||
final scooter = state.scooters![index];
|
||||
|
||||
@@ -3,6 +3,8 @@ import 'package:be_happy/domain/entities/tariff.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import '../content_parser.dart';
|
||||
|
||||
class TariffInfoSheet extends StatefulWidget {
|
||||
final Tariff tariff;
|
||||
final bool isInsurance;
|
||||
@@ -42,7 +44,6 @@ class _TariffInfoSheetState extends State<TariffInfoSheet> {
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Полоска сверху (Handle)
|
||||
const SizedBox(height: 12),
|
||||
Container(
|
||||
width: 40,
|
||||
@@ -81,9 +82,9 @@ class _TariffInfoSheetState extends State<TariffInfoSheet> {
|
||||
const SizedBox(height: 30),
|
||||
|
||||
// Таблица цен
|
||||
_buildPriceRow('Старт поездки', '${widget.tariff.startPrice} BYN'),
|
||||
_buildPriceRow('Последующая минута', '${widget.tariff.drivePrice} BYN'),
|
||||
_buildPriceRow('Пауза', '${widget.tariff.pausePrice} BYN/мин'),
|
||||
_buildPriceRow('Старт поездки', '${widget.tariff.startPrice} руб.'),
|
||||
_buildPriceRow('Последующая минута', '${widget.tariff.drivePrice} руб.'),
|
||||
_buildPriceRow('Пауза', '${widget.tariff.pausePrice} руб./мин'),
|
||||
_buildPriceRow('КЕШБЭК', '${widget.tariff.cashback * 100}%', isAccent: true),
|
||||
|
||||
const Divider(color: Colors.white24, height: 40),
|
||||
@@ -98,7 +99,7 @@ class _TariffInfoSheetState extends State<TariffInfoSheet> {
|
||||
Image.asset('assets/icons/info_icon.png', width: 18, height: 18),
|
||||
const Spacer(),
|
||||
Text(
|
||||
'${widget.tariff.insurance} BYN',
|
||||
'${widget.tariff.insurance} руб.',
|
||||
style: TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
@@ -118,10 +119,13 @@ class _TariffInfoSheetState extends State<TariffInfoSheet> {
|
||||
|
||||
const Divider(color: Colors.white24, height: 40),
|
||||
|
||||
_buildInfoBullet('Оплата страховки осуществляется только по банковской карте отдельным платежом'),
|
||||
_buildInfoBullet('В режиме паузы время тарифа приостанавливается'),
|
||||
_buildInfoBullet('При старте заказа будет заблокирована сумма в размере 7 рублей для проверки платежеспособности. Сумма разблокируется по факту списания средств за поездку.'),
|
||||
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: ContentParser.parseContent(
|
||||
text: widget.tariff.description,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -15,9 +15,11 @@ import '../../../domain/usecase/add_payment_card_usecase.dart';
|
||||
import '../../../domain/usecase/get_payment_cards_usecase.dart';
|
||||
import '../../../domain/usecase/get_profile_usecase.dart';
|
||||
import '../../../domain/usecase/set_main_payment_card_usecase.dart';
|
||||
import '../../event/map_event.dart';
|
||||
import '../../event/payment_method_sheet_event.dart';
|
||||
import '../../event/tariff_sheet_event.dart';
|
||||
import '../../state/tariff_sheet_state.dart';
|
||||
import '../../viewmodel/map_bloc.dart';
|
||||
import '../../viewmodel/tariff_sheet_bloc.dart';
|
||||
import '../gradient_button.dart';
|
||||
import '../scooter/mini_battery_indicator.dart';
|
||||
@@ -62,6 +64,14 @@ class _TariffSheetState extends State<TariffSheet> {
|
||||
}
|
||||
return BlocConsumer<TariffSheetBloc, TariffSheetState>(
|
||||
listener: (context, state) {
|
||||
if (state.status == TariffSheetStatus.success &&
|
||||
state.tariffs.isNotEmpty &&
|
||||
_selectedTariffIndex == null) {
|
||||
setState(() {
|
||||
_selectedTariffIndex = 0;
|
||||
});
|
||||
}
|
||||
|
||||
if (state.status == TariffSheetStatus.failure && state.errorMessage != null) {
|
||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@@ -82,6 +92,8 @@ class _TariffSheetState extends State<TariffSheet> {
|
||||
}
|
||||
},
|
||||
builder: (context, state) {
|
||||
final selectedIndex = _selectedTariffIndex ?? (state.tariffs.isNotEmpty ? 0 : null);
|
||||
|
||||
if (state.status == TariffSheetStatus.loading) {
|
||||
return Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
@@ -265,7 +277,7 @@ class _TariffSheetState extends State<TariffSheet> {
|
||||
const SizedBox(height: 20),
|
||||
|
||||
SizedBox(
|
||||
height: 150,
|
||||
height: 160,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
padding: const EdgeInsets.only(left: 20),
|
||||
@@ -281,9 +293,9 @@ class _TariffSheetState extends State<TariffSheet> {
|
||||
subtitle: 'Старт поездки',
|
||||
details: [
|
||||
'Далее ${tariff.drivePrice.toStringAsFixed(2)} ${tariff.currency}/мин.',
|
||||
'Минута на паузе ${tariff.pausePrice.toStringAsFixed(0)} ${tariff.currency}',
|
||||
'Минута на паузе ${tariff.pausePrice.toStringAsFixed(2)} ${tariff.currency}',
|
||||
],
|
||||
isSelected: _selectedTariffIndex == index,
|
||||
isSelected: selectedIndex == index,
|
||||
isInsurance: state.isInsurance,
|
||||
tariff: tariff,
|
||||
onTap: () {
|
||||
@@ -412,19 +424,20 @@ class _TariffSheetState extends State<TariffSheet> {
|
||||
height: 56,
|
||||
width: double.infinity,
|
||||
fontSize: 16,
|
||||
enabled: _selectedTariffIndex != null && (state.selectedCard != null || state.useBalance),
|
||||
onTap: (_selectedTariffIndex != null && (state.selectedCard != null || state.useBalance))
|
||||
enabled: selectedIndex != null && (state.selectedCard != null || state.useBalance),
|
||||
onTap: (selectedIndex != null && (state.selectedCard != null || state.useBalance))
|
||||
? () {
|
||||
context.read<TariffSheetBloc>().add(
|
||||
BookScooterPressed(
|
||||
widget.scooter.id,
|
||||
state.tariffs[_selectedTariffIndex!].id,
|
||||
0,
|
||||
state.tariffs[selectedIndex].id,
|
||||
state.tariffs[selectedIndex].subscriptionId,
|
||||
state.useBalance ? null : state.selectedCard?.id,
|
||||
state.useBalance,
|
||||
state.isInsurance
|
||||
)
|
||||
);
|
||||
context.read<MapBloc>().add(FetchActiveOrders());
|
||||
context.pushReplacement('/home/current-rides-sheet');
|
||||
}
|
||||
: null,
|
||||
|
||||