From a6d27c5f2146c563c57558b27f924af75efb8c93 Mon Sep 17 00:00:00 2001 From: Filip Rojek Date: Tue, 16 Sep 2025 21:48:33 +0200 Subject: [PATCH] Release version 1.0.0 --- .gitea/workflows/build.yaml | 62 ++ .github/workflows/build-profile.yml | 43 ++ .gitignore | 45 ++ .metadata | 45 ++ README.md | 38 + analysis_options.yaml | 28 + android/.gitignore | 14 + android/app/build.gradle.kts | 46 ++ android/app/src/debug/AndroidManifest.xml | 7 + android/app/src/main/AndroidManifest.xml | 30 + .../cz/filiprojek/fuelstats/MainActivity.kt | 5 + .../drawable-hdpi/ic_launcher_foreground.png | Bin 0 -> 4816 bytes .../drawable-mdpi/ic_launcher_foreground.png | Bin 0 -> 3318 bytes .../res/drawable-v21/launch_background.xml | 12 + .../drawable-xhdpi/ic_launcher_foreground.png | Bin 0 -> 6601 bytes .../ic_launcher_foreground.png | Bin 0 -> 9756 bytes .../ic_launcher_foreground.png | Bin 0 -> 13349 bytes .../main/res/drawable/launch_background.xml | 12 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 9 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2239 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1429 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3011 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 4404 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 5762 bytes .../app/src/main/res/values-night/styles.xml | 18 + android/app/src/main/res/values/colors.xml | 4 + android/app/src/main/res/values/styles.xml | 18 + android/app/src/profile/AndroidManifest.xml | 7 + android/build.gradle.kts | 21 + android/gradle.properties | 3 + .../gradle/wrapper/gradle-wrapper.properties | 5 + android/settings.gradle.kts | 25 + assets/icon/app_icon.png | Bin 0 -> 41375 bytes assets/icon/app_icon.png.old | Bin 0 -> 41814 bytes assets/icon/app_icon.svg | 1 + ios/.gitignore | 34 + ios/Flutter/AppFrameworkInfo.plist | 26 + ios/Flutter/Debug.xcconfig | 1 + ios/Flutter/Release.xcconfig | 1 + ios/Runner.xcodeproj/project.pbxproj | 616 +++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 99 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + ios/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 1 + .../Icon-App-1024x1024@1x.png | Bin 0 -> 33466 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 0 -> 586 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 0 -> 1195 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 0 -> 1886 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 0 -> 837 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 0 -> 1765 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 0 -> 2715 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 0 -> 1195 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 0 -> 2461 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 0 -> 3689 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 0 -> 1532 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 0 -> 3129 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 0 -> 1642 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 0 -> 3400 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 0 -> 3689 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 0 -> 5470 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 0 -> 2239 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 0 -> 4404 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 0 -> 2389 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 0 -> 4620 bytes .../Icon-App-83.5x83.5@2x.png | Bin 0 -> 5004 bytes .../LaunchImage.imageset/Contents.json | 23 + .../LaunchImage.imageset/LaunchImage.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@2x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/LaunchImage@3x.png | Bin 0 -> 68 bytes .../LaunchImage.imageset/README.md | 5 + ios/Runner/Base.lproj/LaunchScreen.storyboard | 37 + ios/Runner/Base.lproj/Main.storyboard | 26 + ios/Runner/Info.plist | 49 ++ ios/Runner/Runner-Bridging-Header.h | 1 + ios/RunnerTests/RunnerTests.swift | 12 + lib/config.dart | 2 + lib/main.dart | 164 ++++ lib/main.dart.old2 | 20 + lib/models/refuel.dart | 113 +++ lib/models/service.dart | 235 ++++++ lib/models/vehicle.dart | 104 +++ lib/screens/add_screen.dart | 279 +++++++ lib/screens/add_service_screen.dart | 371 +++++++++ lib/screens/history_screen.dart | 428 +++++++++++ lib/screens/home_screen.dart | 196 +++++ lib/screens/login.dart | 152 ++++ lib/screens/signup.dart | 186 +++++ lib/screens/user_settings.dart | 71 ++ lib/screens/vehicles_screen.dart | 201 +++++ lib/services/session_manager.dart | 342 +++++++++ lib/widgets/consumption_chart.dart | 98 +++ lib/widgets/data_section.dart | 19 + lib/widgets/gas_price_chart.dart | 93 +++ lib/widgets/stat_card.dart | 29 + linux/.gitignore | 1 + linux/CMakeLists.txt | 128 ++++ linux/flutter/CMakeLists.txt | 88 +++ linux/flutter/generated_plugin_registrant.cc | 15 + linux/flutter/generated_plugin_registrant.h | 15 + linux/flutter/generated_plugins.cmake | 24 + linux/runner/CMakeLists.txt | 26 + linux/runner/main.cc | 6 + linux/runner/my_application.cc | 130 ++++ linux/runner/my_application.h | 18 + macos/.gitignore | 7 + macos/Flutter/Flutter-Debug.xcconfig | 1 + macos/Flutter/Flutter-Release.xcconfig | 1 + macos/Flutter/GeneratedPluginRegistrant.swift | 16 + macos/Runner.xcodeproj/project.pbxproj | 705 ++++++++++++++++++ .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/xcschemes/Runner.xcscheme | 99 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + macos/Runner/AppDelegate.swift | 13 + .../AppIcon.appiconset/Contents.json | 68 ++ .../AppIcon.appiconset/app_icon_1024.png | Bin 0 -> 102994 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 0 -> 5680 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 0 -> 520 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 0 -> 14142 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 0 -> 1066 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 0 -> 36406 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 0 -> 2218 bytes macos/Runner/Base.lproj/MainMenu.xib | 343 +++++++++ macos/Runner/Configs/AppInfo.xcconfig | 14 + macos/Runner/Configs/Debug.xcconfig | 2 + macos/Runner/Configs/Release.xcconfig | 2 + macos/Runner/Configs/Warnings.xcconfig | 13 + macos/Runner/DebugProfile.entitlements | 12 + macos/Runner/Info.plist | 32 + macos/Runner/MainFlutterWindow.swift | 15 + macos/Runner/Release.entitlements | 8 + macos/RunnerTests/RunnerTests.swift | 12 + pubspec.lock | 658 ++++++++++++++++ pubspec.yaml | 108 +++ test/widget_test.dart | 19 + web/favicon.png | Bin 0 -> 917 bytes web/icons/Icon-192.png | Bin 0 -> 5292 bytes web/icons/Icon-512.png | Bin 0 -> 8252 bytes web/icons/Icon-maskable-192.png | Bin 0 -> 5594 bytes web/icons/Icon-maskable-512.png | Bin 0 -> 20998 bytes web/index.html | 38 + web/manifest.json | 35 + windows/.gitignore | 17 + windows/CMakeLists.txt | 108 +++ windows/flutter/CMakeLists.txt | 109 +++ .../flutter/generated_plugin_registrant.cc | 14 + windows/flutter/generated_plugin_registrant.h | 15 + windows/flutter/generated_plugins.cmake | 24 + windows/runner/CMakeLists.txt | 40 + windows/runner/Runner.rc | 121 +++ windows/runner/flutter_window.cpp | 71 ++ windows/runner/flutter_window.h | 33 + windows/runner/main.cpp | 43 ++ windows/runner/resource.h | 16 + windows/runner/resources/app_icon.ico | Bin 0 -> 33772 bytes windows/runner/runner.exe.manifest | 14 + windows/runner/utils.cpp | 65 ++ windows/runner/utils.h | 19 + windows/runner/win32_window.cpp | 288 +++++++ windows/runner/win32_window.h | 102 +++ 165 files changed, 8385 insertions(+) create mode 100644 .gitea/workflows/build.yaml create mode 100644 .github/workflows/build-profile.yml create mode 100644 .gitignore create mode 100644 .metadata create mode 100644 README.md create mode 100644 analysis_options.yaml create mode 100644 android/.gitignore create mode 100644 android/app/build.gradle.kts create mode 100644 android/app/src/debug/AndroidManifest.xml create mode 100644 android/app/src/main/AndroidManifest.xml create mode 100644 android/app/src/main/kotlin/cz/filiprojek/fuelstats/MainActivity.kt create mode 100644 android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png create mode 100644 android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png create mode 100644 android/app/src/main/res/drawable-v21/launch_background.xml create mode 100644 android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png create mode 100644 android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png create mode 100644 android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png create mode 100644 android/app/src/main/res/drawable/launch_background.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/app/src/main/res/mipmap-hdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-mdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 android/app/src/main/res/values-night/styles.xml create mode 100644 android/app/src/main/res/values/colors.xml create mode 100644 android/app/src/main/res/values/styles.xml create mode 100644 android/app/src/profile/AndroidManifest.xml create mode 100644 android/build.gradle.kts create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100644 android/settings.gradle.kts create mode 100644 assets/icon/app_icon.png create mode 100644 assets/icon/app_icon.png.old create mode 100644 assets/icon/app_icon.svg create mode 100644 ios/.gitignore create mode 100644 ios/Flutter/AppFrameworkInfo.plist create mode 100644 ios/Flutter/Debug.xcconfig create mode 100644 ios/Flutter/Release.xcconfig create mode 100644 ios/Runner.xcodeproj/project.pbxproj create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 ios/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 ios/Runner/AppDelegate.swift create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png create mode 100644 ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md create mode 100644 ios/Runner/Base.lproj/LaunchScreen.storyboard create mode 100644 ios/Runner/Base.lproj/Main.storyboard create mode 100644 ios/Runner/Info.plist create mode 100644 ios/Runner/Runner-Bridging-Header.h create mode 100644 ios/RunnerTests/RunnerTests.swift create mode 100644 lib/config.dart create mode 100644 lib/main.dart create mode 100644 lib/main.dart.old2 create mode 100644 lib/models/refuel.dart create mode 100644 lib/models/service.dart create mode 100644 lib/models/vehicle.dart create mode 100644 lib/screens/add_screen.dart create mode 100644 lib/screens/add_service_screen.dart create mode 100644 lib/screens/history_screen.dart create mode 100644 lib/screens/home_screen.dart create mode 100644 lib/screens/login.dart create mode 100644 lib/screens/signup.dart create mode 100644 lib/screens/user_settings.dart create mode 100644 lib/screens/vehicles_screen.dart create mode 100644 lib/services/session_manager.dart create mode 100644 lib/widgets/consumption_chart.dart create mode 100644 lib/widgets/data_section.dart create mode 100644 lib/widgets/gas_price_chart.dart create mode 100644 lib/widgets/stat_card.dart create mode 100644 linux/.gitignore create mode 100644 linux/CMakeLists.txt create mode 100644 linux/flutter/CMakeLists.txt create mode 100644 linux/flutter/generated_plugin_registrant.cc create mode 100644 linux/flutter/generated_plugin_registrant.h create mode 100644 linux/flutter/generated_plugins.cmake create mode 100644 linux/runner/CMakeLists.txt create mode 100644 linux/runner/main.cc create mode 100644 linux/runner/my_application.cc create mode 100644 linux/runner/my_application.h create mode 100644 macos/.gitignore create mode 100644 macos/Flutter/Flutter-Debug.xcconfig create mode 100644 macos/Flutter/Flutter-Release.xcconfig create mode 100644 macos/Flutter/GeneratedPluginRegistrant.swift create mode 100644 macos/Runner.xcodeproj/project.pbxproj create mode 100644 macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme create mode 100644 macos/Runner.xcworkspace/contents.xcworkspacedata create mode 100644 macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 macos/Runner/AppDelegate.swift create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png create mode 100644 macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png create mode 100644 macos/Runner/Base.lproj/MainMenu.xib create mode 100644 macos/Runner/Configs/AppInfo.xcconfig create mode 100644 macos/Runner/Configs/Debug.xcconfig create mode 100644 macos/Runner/Configs/Release.xcconfig create mode 100644 macos/Runner/Configs/Warnings.xcconfig create mode 100644 macos/Runner/DebugProfile.entitlements create mode 100644 macos/Runner/Info.plist create mode 100644 macos/Runner/MainFlutterWindow.swift create mode 100644 macos/Runner/Release.entitlements create mode 100644 macos/RunnerTests/RunnerTests.swift create mode 100644 pubspec.lock create mode 100644 pubspec.yaml create mode 100644 test/widget_test.dart create mode 100644 web/favicon.png create mode 100644 web/icons/Icon-192.png create mode 100644 web/icons/Icon-512.png create mode 100644 web/icons/Icon-maskable-192.png create mode 100644 web/icons/Icon-maskable-512.png create mode 100644 web/index.html create mode 100644 web/manifest.json create mode 100644 windows/.gitignore create mode 100644 windows/CMakeLists.txt create mode 100644 windows/flutter/CMakeLists.txt create mode 100644 windows/flutter/generated_plugin_registrant.cc create mode 100644 windows/flutter/generated_plugin_registrant.h create mode 100644 windows/flutter/generated_plugins.cmake create mode 100644 windows/runner/CMakeLists.txt create mode 100644 windows/runner/Runner.rc create mode 100644 windows/runner/flutter_window.cpp create mode 100644 windows/runner/flutter_window.h create mode 100644 windows/runner/main.cpp create mode 100644 windows/runner/resource.h create mode 100644 windows/runner/resources/app_icon.ico create mode 100644 windows/runner/runner.exe.manifest create mode 100644 windows/runner/utils.cpp create mode 100644 windows/runner/utils.h create mode 100644 windows/runner/win32_window.cpp create mode 100644 windows/runner/win32_window.h diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..cf7c901 --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -0,0 +1,62 @@ +name: Build and Release APK + +on: + push: + tags: + - "v*.*.*" # Runs only when a version tag is pushed + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Install jq + run: apt-get update && apt-get install -y jq + + - name: Set up Flutter + uses: subosito/flutter-action@v2 + with: + flutter-version: "3.29.3" + + - name: Mark Flutter SDK as safe + run: | + git config --global --add safe.directory /opt/hostedtoolcache/flutter/stable-3.29.3-x64 + + - name: Install dependencies + run: flutter pub get + + - name: Build APK + run: flutter build apk --release + + - name: Create Gitea release + env: + TOKEN_GITEA: ${{ secrets.TOKEN_GITEA }} + TAG_NAME: ${{ github.ref_name }} + run: | + curl -X POST https://git.filiprojek.cz/api/v1/repos/fr/android_fuelstats/releases \ + -H "Authorization: token $TOKEN_GITEA" \ + -H "Content-Type: application/json" \ + -d '{ + "tag_name": "'"$TAG_NAME"'", + "name": "'"$TAG_NAME"'", + "body": "Automated release for version '"$TAG_NAME"'", + "draft": false, + "prerelease": false + }' + + - name: Upload APK to release + env: + TOKEN_GITEA: ${{ secrets.TOKEN_GITEA }} + TAG_NAME: ${{ github.ref_name }} + run: | + # Get release ID + RELEASE_ID=$(curl -s -H "Authorization: token $TOKEN_GITEA" \ + https://git.filiprojek.cz/api/v1/repos/fr/android_fuelstats/releases/tags/$TAG_NAME \ + | jq -r '.id') + + curl -X POST \ + -H "Authorization: token $TOKEN_GITEA" \ + -F "attachment=@build/app/outputs/flutter-apk/app-release.apk" \ + https://git.filiprojek.cz/api/v1/repos/fr/android_fuelstats/releases/$RELEASE_ID/assets diff --git a/.github/workflows/build-profile.yml b/.github/workflows/build-profile.yml new file mode 100644 index 0000000..b984af7 --- /dev/null +++ b/.github/workflows/build-profile.yml @@ -0,0 +1,43 @@ +name: Build Profile APK + +on: + push: + branches: ["dev"] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Java + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '17' + + - name: Setup Flutter + uses: subosito/flutter-action@v2 + with: + channel: stable + + - name: Determine version + run: | + VERSION_NAME=$(grep '^version:' pubspec.yaml | sed 's/version: //') + BUILD_NUMBER=$(git rev-list --count HEAD) + echo "VERSION_NAME=$VERSION_NAME" >> $GITHUB_ENV + echo "BUILD_NUMBER=$BUILD_NUMBER" >> $GITHUB_ENV + + - name: Install dependencies + run: flutter pub get + + - name: Build profile APK + run: flutter build apk --profile --build-name="$VERSION_NAME" --build-number="$BUILD_NUMBER" + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: profile-apk + path: build/app/outputs/flutter-apk/app-profile.apk diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79c113f --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..e8f7bf9 --- /dev/null +++ b/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "ea121f8859e4b13e47a8f845e4586164519588bc" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + - platform: android + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + - platform: ios + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + - platform: linux + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + - platform: macos + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + - platform: web + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + - platform: windows + create_revision: ea121f8859e4b13e47a8f845e4586164519588bc + base_revision: ea121f8859e4b13e47a8f845e4586164519588bc + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/README.md b/README.md new file mode 100644 index 0000000..ccfcf7f --- /dev/null +++ b/README.md @@ -0,0 +1,38 @@ +# Fuel Stats + +Fuel Stats is a Flutter application for tracking vehicle fuel consumption and service history. It lets you record refuels and maintenance, manage multiple vehicles, and visualise trends in cost and efficiency. + +## Features +- Email-based authentication with login and sign-up flows +- Manage vehicles and choose a default one +- Log refuels with liters, price, mileage and notes +- Record maintenance/service events, including cost and optional photos +- Stats dashboard with consumption figures and kilometers driven +- Charts for gas price and fuel consumption trends + +## Platform Support +The app is tested only on Android. A web build should also work, but iOS, macOS, Windows, and Linux have not been tested. + +## Configuration +The app communicates with a Node.js backend maintained in a separate project: [Fuel Stats Server](https://github.com/filiprojek/fuelstats-server). +Provide the server's base URL at build time using a compile-time define: + +```bash +flutter run --dart-define=API_BASE_URL=https://api.example.com +``` + +## Getting Started +1. Install [Flutter](https://flutter.dev) (3.7 or later). +2. Fetch dependencies: + ```bash + flutter pub get + ``` +3. Launch the application: + ```bash + flutter run --dart-define=API_BASE_URL=http://localhost:6060 + ``` + +## CI/CD +A GitHub Actions workflow builds a profile APK on each push to the `dev` branch. The workflow reads the version from `pubspec.yaml`, uses the repository commit count as the build number, and uploads the APK as an artifact. + + diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..0d29021 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..be3943c --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts new file mode 100644 index 0000000..3292303 --- /dev/null +++ b/android/app/build.gradle.kts @@ -0,0 +1,46 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "cz.filiprojek.fuelstats" + compileSdk = flutter.compileSdkVersion + //ndkVersion = flutter.ndkVersion + ndkVersion = "27.0.12077973" + + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_11.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "cz.filiprojek.fuelstats" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..0e9586c --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/cz/filiprojek/fuelstats/MainActivity.kt b/android/app/src/main/kotlin/cz/filiprojek/fuelstats/MainActivity.kt new file mode 100644 index 0000000..377ad4a --- /dev/null +++ b/android/app/src/main/kotlin/cz/filiprojek/fuelstats/MainActivity.kt @@ -0,0 +1,5 @@ +package cz.filiprojek.fuelstats + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..641c6cafc87e1af0636bcc324536a93c6a1ab595 GIT binary patch literal 4816 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..71de4da2ef262b52f70f94be10a86d28294a336f GIT binary patch literal 3318 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 ZlAWWHnUb-#FaEP + + + + + + + diff --git a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..35e25c0b3335bc97a2e53fee546ee8324ae6a7fb GIT binary patch literal 6601 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 TP7r_pK~j=a2Up8{{QSQFUh)L& literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..c79c58a --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7c00f3d92ca1f8bcf646b51de57430878f0d8cdd GIT binary patch literal 2239 zcmV;w2tfCVP)Mz)6@m&4ht8I5Ut;|LD7A+BBWgrlm7Y z+K~RyHfg8Rq)nko3TZRs!4Q%VXwm}p0~>;og=J$Kzv7o3);)B$t$ae3?X#jg+iKM6 z`;YH-Z-2L++u#0vyDO7qegph3iu`YPV5JlTi#El;qD?WdXj2R<+7tteHiZJqNKekq zOh-tHJq%-$jw{w)jPcStw-kwkY1FExzWdlcTPu(>EWd0$1K)V^*B^KFE~vo-0v^k; zDOKWNKl%2)d$-*o+h~5a<;BC_Y1sSt*rX%4{OBG>sl{9J3lr^KaW)aKH8~mg-Bkqu zZ5>yx*{)+=no}j2O`of(FdO6d?QZzl^REQTvyI#X>uCZ(vYzjsQY=U3LrDZ|TXh*i z$llxc=BamOSiIiT%kkXyx|;gx@?fxs%P0atOFtO_Dsix^j5J^W>^-uLT5a9i>uRzr zseuxNa8tPl0G>aum2Fm%M8K4!?~AftuWX|%>uXDr3WSgl9_tI391}n3L9euFme%2L zB{`2JB_$Q)=ZjWR6xG_+CR(+B69oW&ZqrP&kqC)$z(|tR>-C~l1VJp;sy2`LkCVS} zF+#%?xs`{I4tpmf5jF(E zqtpKVr~d!|zwvyc1FUelA-s<*0QjZwT_Ob`QWa7nU?6y&?5j zCdq8d$;t$PV{e@upKvs>F3#&wVqZ?D0d_O47gYvE)=`QiiGYnyI-h#(#$!s#3 zO-6Zkn>(zpzHtTsa(HhaQfP8B0fEhaGl%yo0W&MV014O)bd+rtcvIeCevETUR; z7QX)W`@gUFi#(&(aH%oj{zrDz7Zqgw>G-?J<^%wkbhs8ii4dyUl$T?fU1vF5)X5J! zVOrjsXSFDpn?V>$8?Au4`X|S94zn?SbLm>0R{e3;4d1q4WMbiy#rbK$Q~(ekr>QK- zfztzWUL2%F!8nYjSyPzk|BBfUzFyE|#bvfe))JME$9n#v92%<0h8nQ;piL7@0Jf41CMx*29 z6sLK^1#`(CF+vFO|GLx_DC9Wa-ZykxLFTG7vurR#fI{W(6|2voj2i=0@#;A#clm<{ z#{*BOwHn_B{^sylaMjqj?+4C!gHDE7zZPHP&8u1dIW}jU=dN40nW;sr{AO%LM$ADY z55=&oSE(eEOz}gbvuj^-qQOV*_Q>k0G%Y`v(5i26G&eJSQ_0#B@BC9J*QiwmxfTHE zANoXYZzX8?!30-qX}9HOrq^#NqiCk}vW*~!#_g3FwaVd~w%?E)5+x{ff|e8Rg_(Ko z!sUwcqKx#U#vPT7J1PUUZ@qV6SvJU@s!(7P9yud6;qiSAub2Df3$H)=P(yz9Dxn-> zeCmVdbLTJ1?W#11fEg1EbyX$8mZDubO-Q73rjonv^=;#<-Tlx0_O;xs^z4jO47k(Q zH#j^V{G`d4U|F?Fh|@eEhs$lTScEFY=2B0AFE{Y{IWRm*YqXx)Dj|oGa*Vm*$`DDn0#ysK0%>Dz9vU)-Tw4E=35TwRx*Ufkj4LJpEBUC96Uk~KEeP1 N002ovPDHLkV1lt7M0@}M literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..1dccc0d1d1dd4401bc1aa167061666b549471258 GIT binary patch literal 1429 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 literal 0 HcmV?d00001 diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 0000000..89176ef --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,21 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = rootProject.layout.buildDirectory.dir("../../build").get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..f018a61 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true +android.enableJetifier=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..afa1e8e --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts new file mode 100644 index 0000000..a439442 --- /dev/null +++ b/android/settings.gradle.kts @@ -0,0 +1,25 @@ +pluginManagement { + val flutterSdkPath = run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.7.0" apply false + id("org.jetbrains.kotlin.android") version "1.8.22" apply false +} + +include(":app") diff --git a/assets/icon/app_icon.png b/assets/icon/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4ecbc9cea2d777e568ad8e8e1d909c00a79bf046 GIT binary patch literal 41375 zcmeFZ^;?ut^FMwQ3WAgh2+~MMibzPVN~omLAfSMBNXG)ZC?F{+AYGz#NJ+COB_$xz zu{206wM(;~dl7tm-haXO`d-fuUWfHGiQU zT;}pQ@B@Iz5+8pk{_o>|5J3J1!T%rt{{IC5{CNx|^T^^)1%5%RUsLbS-aqFk)Psq& zGzc4`VYDk5$tx}=XcH7G{5<%Z$4xwxv7qMQ0}{h{09M#7ElFvgHb6kF`xw3pBElm*HN0BmGN^-VIH%pwvo8PNq+$+8ekc_Hl)eIp%c4H|X9jMq z_LSB3SVq;7rrPoL+g*{KEV-B|{7euZfWM~%(oBnDnU~RpicA&!0-_2S0f_(eN@G&tSxcNsDvKJG-P&D` z8}dAU!60KQS-vB;%JN+PyAjG4C1-P`(Fx;vfO8B==(0G_@A)RB=C+w@LY zyW(=-No*&wbahI^RJk{T;UQvIqhj|3RH`oEq zZcvSlmFcOU6@51%td}Jr#3x9hD|eeF9}2Z>o)wW|AErk7W=l5Hi_gPK#l~);$`{=G zQN>VH(FQ^B%#SK>_iE2wx6OKcn{?*p&bwXmaXseZ)wHU^B zA#_~i=k+X+n+ABmuRDNd(3rV_)FJw;YYqrEB-_kv-fc;ihn-gk!#24TU$rWKxOrh^ z{^%FBrbecrVRPEzh=JdW7l4Nl!%220`kt1%)aZl2v^{BmjYQF5s+Re`{W{EN=!Mco zq1D271?E0QJF;Q$fFKAEWgJnkf~3E75BI+9DA%UUfy-O)ebp9)RceapO?URYb1iB^ z-%ucwSBT+GIR+(*KjTb4tcVVU0^Gs~ByxIE$9K$G9mDqYDn~P7DLC)f;3J=nd6c*B z-Ij>R3JL&-2d8<}WNUQ8RC#(&1XTFcM9>qu=fwjES%J3cCMqB1g&uj3J07#$Z3AXH5hD!E(=?@v13!s2d1Ne>w|m%QT6Db0 z0SGsKYKMTmrbTO*5U2&IFNjhYs_i!mi_70Q^nPCEwf5Aa>)XknVZT*#=?w6V9#7re z7-~fGCxL zD+Tdu!_RR#*x8QykthO-UgkH;*~!Fqxn*?gLS1rX>s0`N*q9JPr<=}aGgqULZk@9% z4`gu)BC>oUT1Y}))}TcnX@zbxUWt3Ai5@{4WO5V?c3u1luz;rb?0RXJo!a?T4$zo* z5=7m17tW=$j^BA5BSHIm@#9ANn`SKK;nfs;eE4;c9c}ARjb)q7O>!e3tPmfuE#IlZ zV3#2S|M;HE;(L#^(S(R9(*dTS#T%dARSDw(JZ!*&rJ=O#^EKNvpa_&xxzCnT=r)6w z`S0W}$rl7H8e$KX+=_}8bECDGNda|IJawLRN1+5-)zT4s~B_;-f3G(vQMx+AEt=a<}DrYX>GK)d$aa=VzSUxQk3*5izPGl@pt zQ*EEN0|3elV)%q@e^w_c7iVKjn-L)#q8d}Z!q~7us#!;MEB&o|us&>S8wR;}Al?zt;(hq^rHl#9{M`|N6J zx?N5{XyjqJrqH%7wF(CLv24JLirqlbNF%6bTaTpM%C6&P|ELr?r3cTy#DAwEx6pQM zqgW}O?}D$t)JA@`Gi@Q+VI`|5s%~^O=3M2G!MAy_K}BtIe%ny*NALAjrIM7Y1vym8r^8*g?-_U znAb{FB8-6gQ^NXyt6WXkQpOYJvr_Bw>uKQ(1b?DsI`66CQ!scuGu8QZ#efcrR4%PDJdE>DF}UbN~|` zki~*O!5lERDQm^0<|8qmd++cwUTT$*yNk`}=eh+A5|U6sl*Aw^q7)&79V=MKHy|{^ z^7ky(&KUl#!9S1lOwWC_9=#LgPvqWc{4E%Q%A!3-GGTh<0aqG z(x;o+X^Ozx9QhI@``X_MX^P9kuo(;y2tHe*Ii{_8+sO~%z~^+ux<p21 z-NCtq6*U^KmKr;;=DQSXbw@=NyJ=VV_E0~1=h~5KRAS6PDjWWUl+6A_<(HUHFQmF- zk?GV79aEuVw>Ly5kZd_6mSr(}6UHFp=*;YgIDbCwi|gpptB~5G{qJIqDF=;cW1#yi zNWqN{dsRmD7oxS_ZnWlUFU{=+yxPi*4H`rH1s2N+BnpwYc~>>2etRykIf}`X;xX&m zUSYdU)&|J{3=bkq40rC!*F#rVP7{)Cd(<#{OZEMp`ig~1@X@pfu~H1>Y2V(2${e&| z3}M9dO!TZ3N0L6dKHUS4v1foz7T|}gQcJF^hih!=^N6CEp|;8d8Yz3DGp42iC;bKdiN_`5Fibped~j@HLX4PI zn=(}-UJ`U-HMz`Mn^wpZ&wVq zm(nE<(1`>1kTlj_do(DpW#rkYGHY)okrg#X+soXAuYOs|0MEp&0dq zsfg7}AZ&ryt9IgS#n%A&18$YGH&~;1kyx^ygl7CCd-xBpCzEhCvkE4z~11L>^>p<+bD%` z%?HnmeJ!h_weCF|TF0|rDRgkxTGGymIGkP!PS}@92gmnQwAvf!fLfM*D?`EIQ%C{@ zKp6t4>x!?S%~ck&W!xI(@J&PzOWYp4>@WUh9Zjc1f}&y}I6ABq>X8cZMI&xz=4<*%6PXU&PA zo*%P6(@;naJuJs8{K_-IVXjRDkjQ#V*C}YBnQf#|2~98t2~beLB3G+qkHCFf(bj*L;YcqMx$AukC=G1p-;~MOyj}P7%R?9EJ5JElHD=d76#pF zuka0d<+E!sgA1`#cbP8;?dFUGJ~N*WiOnmZe2n$6lJAHuTSVC60hA92;V)8w9kb@; zFg_!K^Fhx_hLRaXbsJ}FP~KZxbVW$r+^H1<5+(;O(2*e>vi23)e&d%^umb=q1mLCw z;BLRA0KSa+^?6|p(=$d`!335_27X%4P3ipG=u@8)yF&DTtx%0E49&1d@-O^P~HN47(UP~ zz<3t^H<+(ruiIx|%*c+$sf|C=3H=730)1g#%%{l+TWjI=O-B+ZFBN#8K9=_>z~{|U zzSLyzxG5YOR;HNgbqGQY54v+QIX{rowEtQr=Gl#NQYNE&3l=esIOfSth?fH%lg-~~ z9WHr*p<9z_B!!tCI57Z52!9sC0*_K$^wBaJiGIbGBy*oej2U1dJsFz|R8(d=JHkM@ z_J7>pF(Cq791A{ZFNE+pIlcTC5gSe@>A^s`az&+5k*;@CnT1{tFzk z8=xNq=b!{8UjoE&7KMUdD|2jVipNWR8ONL@IUc19FJ%`@_OpLLt6dQyC zz6b|A#F-er2Ih(sGMfu#2{!zhgeKZ|)L^e^ya)jZ8&39a27DH8FmbcqRO=}nPg-+i zFe9qz`RN8u#utBN{4>8_)MYHF>ggT$5j&QVhdlu}`0s%>PYJ}|1^g-SSqPIYjknBo zK$r|_V`_Mla9p(h%LN!c-v}_mj=eXxl6;GMI{DAjp#C&J8#D_zn)yh=cTpP$ng6jN zb+Q8Ai11j3^Qt#j?XO|>9Kr{9XrVZtNA((~9XG+`6f+@+f++SkEvP+7#Z5A1xP6Fa z;~xPi7mJoc#w)eJHU4rj^2;YZT$D>pLx1^nM#{J$x@UI2Es zEcW4oxWQhx|AQWcp$D(~sNthZ3r?{Aev*c_rkJt&&K>te;#lENCS(Agpqd;n`i9}o zS(JhQ!pSZG9KR3liKiv7DWCZj2l_OSHSc8e=sEn<70KI|7bJd z2p(s_B+!4fH|Q=nM)SYqzz4II|EllQ|5(9?F#LZ371JW!#a{(r67@hwfB0N^3%?^? z5)q`Q71Cq%GV}U`>t#M61)CbyfxhtNYv z8%LmoSo}MBtm#>Bc~kG=)CjPQAty*((0tOB2bo-Ffk|Z-O@4re^+b0?;(@xhKzZV` z%K`E0NSL=BUEs}{PW8;qO5_q)JN-+e0DofQLw%8!U-1vC(O%u$+No_^3HI;s6hOT4 z+Go_}4cIm|v;8cchTuNpEDNa1uW)(^Zf8k^kjdcs{&M_4Cts|?b$Pl1`e&tF*g`x| zdAnJ0Mgs2e6nGQcXTH=?ajO<~mo}aa)MgLkIFFm=!U>nJ0P*4u*p319S<&BCSwlw% zNFC;yBG)8Z0k`EpQeh8Kkr;pNN>FdS_e7K=zvs1DrSI7Y-hVu%Wm!&L3nm2 zSfA}?|1&x76v0Gh&(TzGPN#C+V7EzD@IOeiNdj(|uHgfHPv%2sBZa&Bj?KRYcyUvU z{Q+6WjHsT1@dhjZlwrMku9oZbW`wvC(}^eB5Lae@4E zK$Fx%mjA~kp>zC9zNi6%8fXXvsYWffOAree}tpOQz!pN5#)g=0+5=-vGaku z$y)=u_Q07xJ2Mv!W@Yk(~t7W!jZ!PkMCV$3eYYdE>X!Vh4XI?;@`mw-Y^r{SG| z(Y@Nw{G20M3lGv{X^(?moDu0X64nzGyx6aiXO&!KDB&wAv0X1#1%ol*k7iQS;XRM* zlJ1Y=Uyt1JefiX1de^-~Yn%iCj>8I|yMUM&6ca1UTC=mS_T#b&!3Pb)$HZshxIi8k z49Y_QsiltJ+;aiO&&s+lNVmS{22;Us$`c#zCrB;o5^kjvz^1Ozoj*+1P)p#$m2I*j zaGM7h-g*Hwv)}D!-9u$QZS}{lI1ELCS-TIiphe*(E(&&E?t4 z9&WHU0=GVK4dG`Y7HaDntKPR8wAMdL?}{0nKMzp({~cd5@!e{kA~Xhe7%9jv6lr(v zn10~Nb2ESte>1eJkq-Y(VD3y%j}&)CF<9{da!z!%^fD0colMa%w}PO3?%*=39H|GE z6#&;0+4axEnO48uPQF7G*@w2*{N`j6h8w+jqBr2^LW$x+OtrkS_JEV~Ry9TrOrQh5 zjsp?6o0Sk?PLq^vzZMD}mueN-O@*?LnR|J{++&>jKWq98o&mo;y*|!lp!M(E@ucvx zGF`CJ=L9=yqXcK+L8nv&fMF;@`lu&3Y=+L@lQEwtZc@#YQx8#hr%t3~{5gIlOAZ-Tm+&SN}70I^&Rz^`uBWOy8~uVW;#C zECxW%oVp5@OL)MF^~C1Yvj?Jg>uHE}m5!{h>yr5z)ISj-Y`fWFbG<6;Z28xj8&L;k zGqP6<&zdIpxO`{euylq{{_%OCxKlq|yOHo9{9yc@!`_vs1CfdB`EC6(DY_fw>rYL8 zv6jrf>3MX4fJm9Alhs|0 z<17Jd)YubkBL>ol0sm+kqXEY8soYwD5(VFyRnp6%adxD6MToctVXaibf6#zGe}dkZ z+-E3vxU=(v$ZnP2NLNV=_ONS99wVrMz_{JfC7PT^AC9 zUJqvRKRG`Cfhp?UVVzjgEwq_zk8C3*fiHbI+9~{i2P_T$@iO3ngAllrk=C^tD9qJ5 z5mOsP7^l#?iFxo!Wt0T2`!6cpmP@WOsJ6b%^o=AA?DNkYhh{}!P4sQpAG10ZfD)gv z_O-=hPj8ZOhwC*@l^$CJzpo``qxom$Af;|ttOd4)VM$Hq<)jKd@a@Ftk6H2O*(vgWtF7rqyNH)8LIJ}@=$a3SeB8*m(;gMrYo8s>za+mUrN(>}Mb?umUCZGV$2 zOx2aXlAY|-Egf^HNkd%oyQA{4B#iW4`H(HN$LKzWCg@~KpvA*klk3>Dz%uGuRBb@B za&Sn3MR;WG88*CsF_4eh9W_lF@=pAecW}008Z%RCE{))(J9Ti!8k5B_j!KyP9wtU; zCivn0t+Ug2d$P}PG9~zv{HuUj&pz{F1ssaN8v3%0Qb)@d!XX35$iKMc+*{u_zjec7 z)k5BbEU>O8T6mWO;DP_MYN;U>Nw*k%1cnSOnP9RXUi@ct-6W)`4-Ms%+$m3!I4hsY zFxmHn8?0{P0>fjghcwl$e7Da|!X{8S%O>P?$#b=j)WBht_W=3c6HANH-Zo{^sk1u<;NrUv)MI30=dR6i}x=& zXhVknRgbp(i0agcOtAD$Wn->6YHO3Y%%3WBvd>ol6|lyIj%BI77V_uRk7u^CWcn`? z$C8Gq$jiU~U_#w;0pKo=YohBTkO5`LyQtudjcqF~hc}ap0 z=Y6Du@}6UEYyP(lLZB_Ps7tyv`$(|+`IlEK*IsqhTsr^kWK*F6=ASu9@a7w()L8qR z0mE1B6u*LlWFrw6T>v7%G&spT6l~@wJ=vAn009;r>5{g@GeWOkM?vxN;2Xq*bJP}B z=?;pwgPvQ2W$c^gdez_KbwEj!)*I1MznwIa-qQ&B;Pq2MX!S@~LEh2RsPAQmz?Sos|ckr677D z=t{1&-4sfCYbBZbOt`wl-}k)A#<5rT){1T%Qh|i~`ZR8SGh~61GSXS7=u%O$LrEQ7w$vy$+OP&XyUUEMRU%)*#buze<4n1?#= zzq+W|Qvdg0P}9kb=naksdtLKI(!M@FWRMuq^vGfMvGb=!lGp3AGfcmo%D*mYJ-gLsDpboyAW_busI@}XI2Na*V>U$ z`39*o#pU7=@xrp7#Sn7Q4}Yvks-5?E9Q|;S-XYwWo|^X$)yeYcNK?~aFyH>LuK6T! zSN-Fhek`S|?GqSPqz<;CZ)r0)mM^At(spNg>3DfQ4U8Cy*K2S?LlHs=^tMO+mJjEr zh43P_yG6<`*F4=;3sn0sRae{$w!7fO-LYE#_=^N~a}8w<+wFX7+5$FwOxR|(w!Yj) z3Yu(epcCZ7q6K)^bH|rZ(Ho)XfG8tb_pi0dY#^TP;~PKYds}kFudf^_KCa%*7FVY} zISQ3Sz&!t@I_yU6a33#Nc*zY=!Z3;-S7UPZYV{FNXtqp0YP)dsvpl+Jvfg*ia)p93 z=9vDty3P^fXYYQ4@TCDw zpXHy?Hg3zK`Nzec(a*OFCGE9*@>-S*N*r?+O&e}c?Wt(h8R`E~2Q_hLhmBj$92^T~ zCJA_?Jt9H~oMm?T_S5Nj$Tgd8gdX}FY0F;+OCn;C#&*7r1br<>pRL;W!r$&vftlV? zd(WZHBzv$t);oK2l(~`3qXF?;!Y>-t>aUVwVK1iusVv=L^OOx zo^ws*S`1kss7{QK8%Q7Aw7<$(^T5 zg*f_X#agRt+$$<7pe}9)vR9YME;A)+Iq!Ku+m*B!76vg(t$u1*AovE#{SSLui~oS1 zQFAy$Hc$$p1Fot$tP+CL9k&*KF=MZXV1aFp_L3bRI-*siG2Si5KHHeUmIY9!LES0_ zJ%Sks&M;EBygxU83bOr`y#*@u5ybw$JjCmU1lWZ|><+TOkV!P^lK_vP6gQma^f@kd zT^Yq5{W3$tR$V!HEucHn3+YolU4~JmMdxD@K+PF%X`(|DJl*#0sA`uf*DU-n1yLJr zH67c_0eL41n@bZ~l>I?S1)k(C_oH67FfX#2Z1}5X%*O2LtN?9oCPK2CgY0aa%+j7- zC_nHIB{P@mD`DOZGuIlrEOGQR<>~s)KcxlGb^F74i;;Ccba9GRqo530i8tf-sQ_Y- zbOqR1IPUBFIjGfGK(`pnqK1D)E?cA8JjKX8IJO4WUDRO3C9nKG>!9^X)Wbc;|=Y1KA!|XG+zckO%v(T;2Y&+k_S4EZOzNSx*g&-%wt!2^ zgvUaQ2Tuk20HpW7*Ak$pTr=l;D~%Z=Dq4a8CyvGz3g%zN-D{;=VTSwUB=k%--Y<_@ z3(qSs-!gj33gR09ya@#$>R=l~)z~2BFeX4srKZuL8Y5s-^q~7WB*os+y;H=lfbyny zmtRARY6jTIfZt!Lu|DE<)o#=}XHDene~C`EsA-Je)xF(NYlLcS?F|iKd@)Dhh3nmA zlwujSr@e`7e`cd*5mZ%ejGPaqUC(nV>~fQ6@Y-|P`fA!QOlPfP`0O>44Xu+b$=g?_ zta&c$ON$KKU%YwHlJdm|@iaYk5;|*2=sUf%47XMe1ih&$_#xOv+^$jB@+wIF{^EQv|~t^fO+)yyNB;CTqGnzx-WPP)ODSs zH<~(Uv8p1IS+TnqZxbA6eG!eYmb;7(5x@s-gTbE=*wsbgMS5V|K4&*FkT=3&FOz!F z4(wSgIxL%-gH^hWl{hHVh{1w*3#)a6nTZprsP`*zU7293%P9@V29bQw3;9><`XXR$ zd4e}?lr%Ep$<^#sRIpND!b6IKB&UK0j!K>c)N8})wVtPx-y8LIRS5|(whRZmfx+d3R%oW5L<@3{Oup3< zt(GX9J76>nKG%!zge?x-iO8DWRCczWONWn{3Ae09Zjg#oL`hP%m zwyxc(tkjTASaPzOy9I}cd#u%s_vLC)`#gyFDu^xKhj+6p`_+G#a#1-@KMd<}fhpsH z9pO_t2kCvrVfn_@RSOzFRg>dIwrvnd!95n18>4+-FQ*E9u*|2_&lR(sFXd7mO{GtD z1mZamljo%VNoj)ds5vFz1bW60U`Me_#tBsqtqPn-MY^F3YrM6H$?;1IG^%Y1?RzB% ziTL%)*4K4p&VRkFcFS4PW>O0{qHPS}P@jtWyuVeOR&EWQ6#v;=Do= z*y0^!P`03VFrG0gjXsB)U_&W*j5zUEclOXVzXMwK{Ff_6YYse-d~M&`$cKUH1KQ%8k#h%Of6kUq3mEDa_J!8WE7&8EG;Ok3jG`syK# zUm?BptC4A=8gDdezexs4*d1~fz376NHLo6HYP%~rwmI{5I&B~G2~j=4q^66Y@Td{- zwYr1?6zEQIC!R_dVy`MiurYI3-!;;O?j~NpWzi1v5tE zMechmimQJenkjzcuBS=d&iOziAuSRQ0-){1iLF2=#f%2_rp1_JoVH#kRg2k<$Hx@< zk-mV3OqrOD7!6fvg_@@w%#Ii-C>Vpd)6MYh0M=r?^gLJV0o&n$O2e5UJqfeM-6DRKDj z$?~#PaEI=;IB=_`^PiNK!=tn5T;3V|rSUST+=9g6$wO~7*A-Fu zS`(!%X`1$2a+eG;F<}JVO1QOZ&m2 zZ^NF`CSW3kGFW2k@>@6kq*v==Tb?pb=GiwMq_37_n#XcTeWM0j9{zYw2%Xg6{@na4 zq~LKcxw!KrG!mg{GpzAr^oQ5sIyPla*Ccaj3cMx}_jeY*R)kpNEyYXRzzs@W76%Vj;9>{vqi;>=zl~8E%bA3|xr8+nhuW6B+U0@Efx{Z)vFV`O zxB5GaBC=Wnv9&`0CgRmuQ7XIEQ(#=b>aiLGk;Gf+rzY+ zK@qq!!B7IZ-W}=(Z!32-#Xs6@vQSP8PMapq$dykE4?vfzeCp)dP|ZsM*qu%oc=m+Eh0{x} zga#nb(fd|cFHouZrB24L6^mGzMj2vg-UOdc6;QJ~S`Xe_0^920H+G)3|M127Dvf#@ zuw1VdXYZS!b(a$d743ZReQ*c8`d80bd)!7|Tq_jKY03Qx*nRJ4t^S1i{tiJRJxd?4 z`OLkboBdn=^p}}2n%rf67P?cwLvr4|EA`l0_%$O3ibee4^I(tZ8ZV4NmGrBg&*&K+ zDS1|L?!2%P&b*)yFkdlqI$i3EX0(kDdR^&{NvuWG7$IvL6tOkVuy5qrhw>qdBPzk`ksALPWDKvcF}5$k<87ljZ1M$}tJ zC%a-ZWT5%IU2Q9yZ$b=krt!fx%z;IZGpA~nmFHf*q$n#5M-l)}rw+4?)nbprm-%@X zlW2+LNBUr;Kf*kD%U6lVJ`pbvoeGL}Mf|QRNqnsmxv(U0 zpPq5q*TJ#plTKk}Y2;5TV8U*&-vn5Ck_lc#d`#N2LrtP(SBBjuDwbW_1g{C%ZwVjD zDf>cy)}(X&2>N&MgYqjQ;DMYSv;!CGE@s8oNqY!~+ds@^eG%&e%;l?Sui6XcJSqBp z8Yx$N%Y#}4UmxD&{dVtSrtz|qr?$gjozs}$BsMMe^}v^krT1=N_a-kl({3}aqY{izMUSIg zRwvh7rE!ndGzpO$@OoDeM712+#r&$vY&Hr_@!tDljYnUG$_OT8@B#mrgt5;i8F(%i zUD2Goa&az8hUPjYP<$LY5i^E1Nu|0E;4bZna_WPZ_CBsvZ~Sz#zcshLdpMiycthF- zbAWoypr+#}NR9sOINcXx{BdtkdOt!nzDO5c1P3GCaNO|(lJ)5-hm`czYV}dy>sS8x z)R&SfS$Ds~e4jtAmhH}Yk$&Kdb-w~Ltl7xCejwL9{c_b-voLVcR190=-alZY$xM2g z7#KQ^FTeNXSsg|sSJx`Aqha|J3w~u!V4v7EY&|6(9BtCWB3=g0<%D&%wWi#1==++U zsTr5?ejwSG<<>PLbP;d=VU1-IXJ5+)aEFdr7wPkV;Vv1|-p~o{(X2|L zJagVYV&FHXa@44NWNB|xwpwavx5++2ZEcnI&Z!~AXM#<4mCy%9NzhOY$;)BpLrXwB zWzdiD#OG5=2IB>YqughHGFE=gJjq2*+gA%??4DP@lzPBzMp%2+V|>bWNpuBln8r4m z2xW3MUFB+y@0f)7rft?*=6Xt z6MNub@`#6{W>3?YDv}FU=iO2Oc6d)S++W8?^zrm%Cu`oirP}{WmNe8*QEiq%GTND^ zq+Y#>>zNkesij!$eQ{G>*@dBaNMb)Qw%Ubg6uN3w-FWgky5cgWOqfij^!9x0a(Itk zg7WycP2Wx_?AqhI&!{pB^$|FC#Ksw8G<{Y?LCPgFsCD{ivoGyBcOtR22uFb``W9jS4tT6D%%PnmgrN!`6|=(;QK10~)i zH~nQG?6mO%shLHYo_0T}tusMWjW`pvkNvTPMoA|gjWB0E7C;NuT|C)D-(>u`m-oUq zPO>hTt14OYOC4860TS#@Z6Q>~z=!6+p^W~(G`iEc>gl1HlZ*gNDO1!?vh1OcEeqvk%)!;Zmc_&# zOH2L22d(8tjzaOfuSy2yk?uPk4*O~nnw`LD%>MJSR!hlK%Q&O~;RJ)mq2SK>hac32 ziuNb+3j4(k?R$ul(jB_46k2~eQUZ#dH;p~^H9*os^61=BOMQ0HVIJsPr@h0qIAaXh zcZ+wrgMYNrAF5tDXO+SWu)XYhlDr7JcGF^ZhQ|9~s2B`P?l_O8B-8&aFAchCOSTX}mlXsu?vhJ$A6vL(o#fBNOs>3ALuZtV?y!9FK~b2W)pZ%v!>sj;Uh>NAvf;927gu#pG%-=SnKv&CL+eznRUtYL%SkKBYXq zmqKxi2Q#St7lEt8hjD@yVAS0GWfZblQ=iT%AY}Gb1001owD*LK3U8erZ*M!#Ucjp3x?P%Jqkx8 zTq^c%P(>=%-I5kW+-scquD!tztL`VG?*oIUdkZtv;_tB)h2I~3nKwQS5Z_o0AWGu3 zuWhPn0|&EDQitLpf|ZiX!|rBn^X=031%y(VZblXQUypF<=PT<|ia8PC9yBG{&Lf{JX={Jka;)4f{_agY|v0F4>w=3xX;7Z?S5-AW#u5oO%$*|Bb= zun{}b|H^uIZ~W)-hrOI-=htGKKU5^+SWTQ}taK$mHBgg1bD%PMo!D`-nn^%=M1N{S zH^PrE4YaR4J_F3_PNN*VyB~vfp(5{2s$Eq`C0@;Pb-t1g_Ns}~)yW3g zPmX>R_^StNLKh{>n&ev90Nk|A!JbLE{avgr zNAjJU`BZ5Dxy70e>{qTKI-6BmetE*BD%ryoyxc|AV0!~oSNUlyBOIGfLc}Y&D*4uT zRSmo@d}6l0K2%wZm=Xf&sse?Rm|3whJ0C}MPAk~A6MZqWWIRO*F-Y|hPr`6u@khZx zi0%{Y*V1(jFh$QGBw(kzk~4R(gE;@Qgyj9vN(^x7Ud^m=J4&!EcmmarHhPjLvWK7r z76%I4>=Kj=#2l_Jm@U)#T5pQa}rM+m3MS{P|5ksCYSz622A;!hDpv*$**FygGtfN7BM-ih#ITP9Z`Dv=*-kn{g4%m1i&-V)YjZ+PiwpBL+*nQ^ z{ZI)fT_qLBih58n_pV~X=;2fA;Iwn`q?-D=@$nC*LO7ola96&28muIcc6K$0dta1~ zpkeLjNF{ev;?udx7&_mSO`~~Mt4)FP^(4)3*#d>OZsk!fj z$)x)SWzn?xe4VfA2Av_O*UAcyG=`^_%aE(NC3uO9cJJ%N0=nzkWk%jchhCxhrE>Mg zWmK=8wZK#9AXSOy64$t}DbD;i5H`kn;07_Z8k;Ce- zCXSk^G!Vg3K6C@s9$u?q= zYSZ0c@vW@suf2_om#8t7WYb9-RlaYCK(m1K8!A|n@;=EG)L0YeOBG_5)HCI<$hZ_BPQJo6G%fqt^xR==9nA{_%24Fr8dmliT{J zEuI1y^`?@D;|JjTnnuOWc(DmJFE24^udjL#fK3v51w0`Ie;t4oxU3YPGQFzV>O}%1 zUGn_lg7M{bWwJ8op_42%MkcS^kND`9Q2uDZVHbI2(@tO1a~oacFS=(9wf&j0P0U}g zWVE`}|7$1^eW^-C56oomY?Cw@BYG(RVt&rAGP!`HFMOd=25P4hi9xUh~d z<3+vppbZ^{)t=i+jEXtfhOC(V8mZ5cX@=v*yWwr@#Ppn|>_yn1Rgz!yp&^#VS;sB@Y$(^b$^`V3q(zE+Js&az<0IoJ45ZTrg4 zg7DnW?2f!Q_P+Nmx$CKYWq<4E2g=OZ9GFMcbJ5WPtK7vW_m?%h%Z8V`uiycx=dgzF zg$7E!XkiPX(yz!CuhE1C&<7jr;Mc>fmMw4n%4J--w$&0|O*da41Nl2VV887}t&*lJ zIgl)5Uyc5HWjJ|cxJo_}eyw4r=6;s?PhqET15>1c>*n&za2mA{|GA8hr3cj&y#Ep9 z32N#&(xhJlSok>ku)pO|DH+_lUz-N+s6qdxbHDF3nI^2;%KlvoUA3>-!FQ`;6XHK7 z-zj7ek1mx=YFX-}1OO3AAnc6Cd)v$G$AD}MTPDQvbj0bI6j^S>#_YKabSd4g3zqSk z-DB+6So{8?&2}sGbzWw-7y{{Cy7!Z#U*i`Z*x*cnS08Jf`E#LFJ}(pKzRyJE)~cs~ zFEEJgH9ZKz3k=-DM8nVUvMIH(>{h>JfTo2$@A`o6V7!)XGjRFxU+%lJ4-fSr>qLe z7l)dXMrkfZ#prYxGwEq*HF;4o-5S;p+gh#nB02np*~=G*aVSon0#m7QdeG4%eu}nA zyM=>QnogcA=DFg}>hnI?^Fd#eKf1HdJN-;@aA$l5f-zhnv4t9c2ZEY?e>f6veO^y( z{U#v*Ap@Ole@5H#v!P=et#N@&HkOYwkhwM^zo$J97zBe%$6o zqDuCAEJM%KpkHGlf4!RGiZ+j)+C$PmD|tCtzwnLZZo?kR$5w$ukY-;WufRy4G~JS#DnyZ^gC0_<>m|DGyIQMm5awA}{j ze+bu>zTvY_@|LGa^(8kFqbq;8$T(_9FWKR_Ld____5|5e!sT1p0WudX|A8(YTAciW zT(n=?uTX_HSk7AJ=vQ0`!f;}Ja7^Z0Ogs|S=oO;>N91LW&Mrsysnz;Rz>lWK(L1Ow z88z9FFFT=lruiS|qPF`weyWwv&#a?q_+*#!JB>YCU!pI$E`ZlP+z~R1vPX^z=D$># zD7Y#2wZ%2#1VP)-w6{h_MjYvFC z0)40Lk}GiM-09A{Q-d`mh4yfFd&3qG@ut_GZ>v-l~Ahb+SC! z{TKOq%#1e*wD*Zee+q&H0xw&nW1}NzL2faHUY$35loaIcSLJ7_$E3MF_duOgvQUo? zw(eb@n9Te=_KoRDX`!XXFL3n96+=}P6I%RBM;YMq4{3F~j}fAzw40kb6HPg>2}DS9 za{g7B`+N-_?sl&uJpa%{Q1AG_{e^br%*+T)KZRsmfsvpXbzsj~j(acrd%POOdv-Qk zBD~-chQ;n{Si?fa6C;{0&^dRQR(nEXaj7O zMp|7P9e(>OImq~P-Ee{LX_~)Red?yC&Tid3=^dAOrp7$KD&MnFhI4~~n`agssc7S) zZZubK8^G=Uo))PY!81qh@FMZsM+Yc+?NTL}pM;y-e0}FP^zUR{*)bUz3MyN(ta@mc zo0sT`E<3uuQh1EI`f%&U$;s1a+@eLrzvW6ishX>E1=zG3AJy`wye0c0k%XwS2Nipb zDtdamw|^Z{*!nr;czR-M6PqhKI}a%Es!Kl%-*!E*<1m&rshrJpI!lkCU~f^GsZ)V8>Gc&|9Ydhy$rZ%=?@A(Rwaq3f=ik47vG}Gl@hhch=g|C2 zUhEVF(jD*eX)@xYZm9szt_P1W7hCs!p0!S%YBpV2X)@VMnmN)o<83psC%bPT!bO0S zHRvR|9xHZDu(LeAtEw_ng5{Bq#gF&NW=2T!f}Mnd9wu#=tYa&bCVr`FYCj4VUK1-`Lo}#qGHtxtztgeHYp# z=h-xBG1Gb9tu?_$tnrNE+;0B{9~wm9DCTWgoDiYv{`~B{?aL$7;IXaC`iugBVd2&` z7*ED;L3e=Ry+HuCWkkRT$ohmfIni%ZM-D5-@i2M!Zpz-Ua%v!#K6or!qiRcf`zftD z3=Ite4F)A7Ji`Ks!6o~NCl@A_;fcW$-hpQ+hPt}PtE7paxoiz{owoy%-76eoeheH7 zLvkL_bKq0~bT0k~hx|Xf9T%Z!-Y{K0K8fJ1PYZb=QSP}8M8TP@t&Ft;s~tZW^>cXv ztNPk4NaYa%$1{&=MU0IqAt3ivYsIOm5#X6jZp`!>EVHsGl})&=KbV45WZ2E$K=nXH zg8=rDyM$8hm2|+pDiaDftQ$e|QbubDoIf^=A=XmXc>5bLddQ}6*|n!x#2P4% zte#O>mt!!n*}xWw*);!qf#lQ8L1+KI?_Pps7BMO$sCim;S1&6vCw9tlJn~*z%x6Xz zy@_LVlRB&Ie>W1=@UvU4QXRDLgeL~KWV=Kbdz8{?#km&!R@hg z?QBuUX@Cy42ciJ~KVSRnl#CoihG>j#0RN9;_>EQv%P2xZCHDAh&+9lh{#|Qf0g@{y zf+(mSgord~vNmORv!eGh;(Z#m%WV4Z;4mhsdt9r6Peu028=Mgli)9tH-v` z1Nbs)UQd56djL?JX174>>CTkxz%y3Q^9ofn_B7~PNGk}rV{&o~uT)l>f%~&v>vI|q z(FTZKST)i`wZ0=^N`AoeJ4kTS2NPd3dyinfMi_v4%#gw4*eTsgukkc3oqQBpb0gLa-$^*}gr+h8;#!8Pq z>|DEYUKPtz_Njw+FriY)d;QI(i6DnM?H(F72NKb}XRj@xBx+|~)6$tp7%DN~+4b(+ zD%XXG!svf(6wX1T+;CUmlW1*6+_7tI)-oObso!R1=3poopyNlR=jHDUN0F@z@SyJD zIVjz@@*Tw9v+b4c8uw*iknl(t7|d>RbOX9u2F91m=QsDb=lG_5vIOFr5$X76V*@~g zefw&c>kdxm48MWQQE4+K-}dufUhEr&^Jhnl%*PR5Y_|TEx2FzlhUHlk_R?4d*zMaK zrn&tCMgSb+G5&eqat0qo(PhNf{&NS{L2<+3^z*ceEammc4E^D#g`WG|ut#^!Tc|^h zy~$|`&MaJ4P$;d4(x;h*I&Km93e8K~+087JHUE@+5SQ=l&IhCa_j_02p2S+%aSdCL zG;dG*HbMJv2dlndQFo>5aED-R8n&}Mg#l1Z^nW%-`h*yLn;D)};yA20x2}Y@UB>}V zOOuGbVMqnnV)ST1yh9Xb2ZZwP_x}0=2m!8C&;_eQbYez|lJW)<>4vFtioFRcJUi`H zcx`uUu}wyD-kd*rs-dz6qeZ}aAfD$AAv-zOE~Sr+6uj8&Xj4ux+iT!Dl8|U6>WF=A zEVh{RD`BdKCcQ{eVc|gf$9W&4)wZIHe^0&<4oN2qx;gLlNBkIQeDaP0UAmy)n+Td6VAk5CE8{I*9ap$4zGh9l z`q-hhO^E;=LQK#yQ-~gKh+>sTs@vE^i8xJ+boy*KiH7S-7y9=788f|idvCiyVy#sS z&(F7a+c}{x&4m3ZlOm4KQoV+AuIR#bFU8GwA@zQrf{O!3Nn!--7i zz=h?C*YR9NsrH>K z^clgr3PywVuX$_KlF?i6xE_Dh(i}@QD|*rN3ov5Ova3eQoXb+D(YqsO+|=fhN%j7| zs2(-m#0KNQ`GUkD=llj|%`2}*+XlTK;@ahNhev5;if(}`g6?KYVYTbh1%ZH zoOUef30J)<1uI!}0z<_sU0W2wTO*i3-J)4qRgy+5QOJ|J$_GjLhp;(^w8ON2w#1Ix zK8#9DOY@No%Q$G@I}Nx5Q!Rc6O?tuIcdH@%`B~pccU43=ps(NPzL682#2VpM2p5^m!Tj}4u<~lxH#H;`{2e_ zgeh&Pga)w!m}3{!*NMb;$tIgD!GGot;`GxI^Zj_OI`nSmuh*ULZ#4hFTH^aO_ndb( zmd}2XHl`v4>DeBCgg#!USKbe4qlh1wf1O15VS@h-zvWoS&aKf$kR>$}b?dNv(`8bR zTs`{6y2O`@%d<1j33x1WzfgX)56rd3QgS2DOi_SkIX-zeMYASt^*xV@U$Fq(jE#HS zP9cpeB1;fqfsc=%h2ad{qqnsKIOW>wiQm?;#OBC9&V^1Xymr3@J$U7;V`r^iaY%@D zs~8ajLYSK)_YSWYg-I_iE1J~}2y@Akr<^%NY0C^*PtLP>yLS!yf*Tv)fjs{bC zwzXmFFqE~bBJg{zeu77Z(tC@k*e_?E(4-hVzR>Zfnn6NTosk{mveRa3TACv=6tZi| zN3%)16RSLG6Gqamww7z=X5wvIA+-rpz^ySd?95|aLxwmK43F4~jkAogaGEWgsYH(| zu;fp85wOLU>C6IXACy)3sAVLah}oX~05%|x#nwZ5k}0KC36M%{f|ItXskwRS%hPLE z)+FIYtAR&5`;im$FGVnr50AQ7?MMDqJCF${1kNL{N*!R;*Xerr<^1+-)(f;!ek?=+w@Q)%z*j~~%qZfHXd5rpfujNqXa_UjBICUfAn{N_d z^#ycNp313|zigLzl$FNC7J65kHMF+qwXcsPv6lsH1r|_AxYefIfJ~ndwJ$15I9=~h zR3IteFEGl_*orxt)f z06s0yx@|Z`gjW2X{jtKt37=J`t=+*_>;+jgl8m>7(T`_bqqvfB zV0~FM-l4GkZ)?W(f3}!r==@?4qT75e70bH{Jx6)V&h`hr`d*TO& zspVjKiskC-?s&10O^FJgvwdzL^9^|1#NWS&;t^|gDX;V6r8C+Jb;)qY>_8%y;j>rB zsvEUZ?0s{&xYZT0jAIM?XK^Ag4_|LHiy%*QGa6#$NRznS^1?hli90ZBpQ>j0q%I7= zKd}Cw*G#i?sGu;}38vFOGNPS^C{g1xVMR?nH)2}OJ)>c%GFGj}c}x?eUCpUP)cWQd z2`NEU1cz?#co|{Tf!-q=3u*_Cke+_!{_NOsWYZ8aY_ zfOScD5rVEJd}npU@%Y2(8(gl~v5jCEF**{HnWt=StnG=?X*W;h7OQ;16YqRP=YkL3BT6xI@T&*Z!KF^nXD& z$(-ph1VqA-{M%s*MBng(3D;y3EhW1e;$G6<>FXyAM~X<^2)gc*?iLq5GG6lOl&{pF z;nG$pT~bE!EgZ0ZqZbBh#y9{T?T5m16XFL@W8lrnvE<Vm@4Ep>qPK?OG^z@x(KBH4Waac8m4UH{2UP#HLaVc9 zq=W-Gc2Sv)={az*V$JnM76;;-_1w8_cNx6=>vcDL_L7Iyf?WwDmE;d=M4w80l^F-K zSMUrm)aXL>xQ64J=gZLpQE4mpD8Eq?kV@s^K`yDtROeViiUYJ@=qBF~Xm6~pEmBUt z=?sbu+UhP{OEVr5n8-^%%HI$cTf^Vc9Q|rKTCu9|+Xr`|3l?YJ9U`?j8x#)jT*)$8 z*aEl9L6yz5_h}A~tGJ*{WE+&R&%};1jL|b0s~}1uePB&ox-+3rv!KD6j?+wJSL3_- z9=YpA`@;lvJS3`ad4}@bEUoSdqwqYv+}l)xA`M*D?7YGbA|(91y_xq7Tv3J_T3?JRlTo=`*lkP zfZ%l+O4h+%#To$XWgf?}#Z+iVKoR$Mzdq#uiIp27F;XdDb-Ed6v+E=Qdh_G!bVtIK z`BLOJ3sqD5ay%bjMHC?p?4i5Y<&HO4H7hh()cXbcM;{ire-vG0z8XRa?c?(@b~gFf zjJ$<-bZpBV#iAkmLI5eWDxatA!cwMpPqsU6yC>x-#|VwbjMj@cTgV8QZmq_-olO&U zGoiglxG@Q7D1tB47`-fGv{a#%en5c#f5J4OE&cu^<%vUi>enZ=hA zo@d%*qo5GKGWfI!q{DIgIefp$M2Ytz-SjOmLR{#~#^z2$ituhCrNe>3S|+MuJ9s1^EsepZf50V%hwwU5$*V3@%W2qJJeAR7BrD?!LX>cPA8>s*Tp8$mSO%p1D4a&QI9Ev)?50K(TtGb}&ya>Yo|63Ru+%H>2dX z_$I>DaZVi>Lp!t>yjY@jgg2j0W<YO}ptG2DAiv7Q3K>e?zu^HIPM9Hb?jpU*8n z@pvfS!M?4c2g-S`fhg{0Ixo&`z-$07?sp-a&IO3WxZ^8;lC zRxBL#4C(ld#d{p^=NA9aGy27Q1ld}{^G(`;<&rGvo5YoDkA@tVwxzebft=-r#4fPW z?QbtEKQTXfc1d}cT>Ms1C1_2;>w=LB3n4k|p#JGJyKSZyXJMu)OGyoE1yQND>LwQ) zLsZn>p|EZcuARn`*LG}WIOE2-?Dpd(*>|h-HsbisOHmiOJ<{2jk}dqGt}TcZuM1b# zAxzndIllU|CiJe3Ifd;DJ&M9w@O{Chu`_s*!C*d3!5q-%@H4 z)ppxkxHo7~UO~*7W$W8GGjQf`5}Ut$_Z1B5BGO6{iljts?-=oWRYqPj+o_`f%}%^4 z;L+`7ghj+upbvm3ui5u4m$;S|eZFu0@%t7ZtVoi}ewAO`iI~ZDwd;Ph`}L9?+gTCN zm4yQop6vViY)#mL7Yk1_hMnJU&x<_=Likg_pA6#U(#3Lu^@nBozm1uvpPeO?RI&&T zU3Xg!5Tica_lyjaw-$m;xJPU(Do+roX&|K_bzNP_(KShVFa6isSXXRN2_*Iok|%21 z*|`8^P$OEwy_4R^+>dIXPnO$-Z)4%bs`-g(^1Zr4?A;{^^AoRMpA8zm&I}NvA&i2c z&>UTJZlUw*(s9?^Gh-Z3yuXdr8e;60Xbn}^&Sh=Hi%E~W-q?8+7mi^^>=NtFc;~Lx z;iBDR1DbBlw>|kmCsQTC&6!ntYd@^R%|EGY;~~yVs`v`K@fHKB2j)B>P6>_Erjai+ zDWfJ9mPf-pcERCi&b8@ZPovNThiY#W4(Q8TP3)d{Z-t*xmwJ5%6)^MVj2}((OU0Hn zj;3u^LcYJx>C&Dzy7b}V4_}4x^6i3lmOUv@VFPy|+JBmxFXmlrJo*5!BYVT38Tqrk zYkQ2V@nb~t6D66`O%C348-|hhR~9&b7O{M3*uwG^F0Q(92PuQGaYEH1{2b6|Zy#nE zvkB-UP5~7V%lWC%=niQB^JIPbjCh=@6kX#u9NTd*VL&kPFw0VnM7n5 zcQ=*>KgcN*uhhg;>$P9k)Ei`~s#|SDC433h<3qL^Ta0u3c-6ao0KR14J!i&%HFSrc zOAcEfiw`w_+$QoBP~R*S5n3lu*K|2Lv#>S{Fd1nK?V3{84bYz9^+A}|0$WbTQWK2H zV`d+`xqqckBbf8H*EO0wC{_fd4G&&qVR30EWY@gisPnqG zacq^@*)Nf)wNjfMckIrr)!s&2%KZIEYxiaDeYP(R7ZLSk!8o&#H0C_VD<1b@%#mcu z=?BlP9JPA4f<@3J5^le^m8{Zd{55tI6BDI6WLv{KDgguf75S@(i}?C+-(6JoEmMEU888>+Pb-%72^AWyKty@%Pa_B)0J6oOU=y zw^TYZ_-ePaKOR&UM-ge%L_jKPEv@v^h;S=HWycGe?0DDhg;L=tAc^TwiO2+Zusqfu zvzcWq?R|MvvCQkVTh9{yBUAQg`JiZ7feqN)v4M7L>%j>t0m9ZF?s+HBo)jOU3WhfC z>r4ovCpd+8JMOaJxMxvweQHD({dw%7Oks`&Kc)H)wIy1hiHpc30;zks-Y82ywF zYIyy|+qv$>HvTYPmcePRt3`OwC?YuwN1PQRq>1&pA4{I_1d_@u^_vwCRB4RcZ{IE1 zq5qzjqj7^TrfVvi!ru>$Oa!%y_CyAlN{-Oty9|WfdF90~OtNhgU%V~Rzbla_-Hq14 zfF4ATRYZL?aVwhvLL1b}TmiEK=pI2qzX0Qoot=8;>Hba#25AvFRsI9%I`kcqhaZ|H ze=YG`RxJqq`>M`YL8)Z+C?C6D_>Z8TXk#8^5MeGoX1W*04Edhhut(8 zfQYC;QMk0O(7N)7UhrwTsJW|26o;J#yAkS_24dH1iqzBFZ=N9h^5LQT-TR+j5krAa zPn0E=PQ()x)%@B|EZ{rwuZryG_06jWr-Dcy;bm9I9?>;g8h0^UkmMJ=vP;b_uJ!2Y zLYmoIqGT4`MbdBIcJ^O+9XfP?7zh0RVfmnsh;Aine2d`m_lc*ThjF~-u_t+Talfda z^fY!%(6H%cfPe__x;=VfNE{~U;`2$vi>oQl;+^G#Ps$3YY&}~OlUc|gx&?GiZCCJ{ zy%ilHqE-svcRX$Wu|=&kK#p)(2D;N}uT6`~9#;tU+^Lwi!;UqU-!@82Cpjf})KLSY zowgeSUriI^i?nD!{^B?Ky`W4i zBLitREp0ciIJq}ZP(n&%_jz2iY6!4rBc)mJ_*x&c5%>BXW)$i1dqLoQtiqJOdCkGC zh6Q)CK2w=H^w0_AH_c#AzXJsibG9?@dA6|lvQ;VQ{t z3ko#0m;gT$vnh(tm^aI1GFd%NCZ2KJzgs8nK2DdD8-|Dock`CS}2tn zMDabNw?DB>s_r$;R55?P^`%r>Y#RQWVG2Xl&x(N8;c*+m_)6WWV9Ze|w`&;Dz0XxU zLVDB+Xbs{SZAxpaE8hZ0MRaE=0;BmOEhFn&z>Q^~w;$h@llQs_2Hb#moyT(Fmni;0 zjv7FCK+`G5M1k~^y!5%%0aiLiH15?i)me&+=Z;TDrZ4$lMFd51^1iY9;fMO;)cA~a z(N&esXD{#>O)nw5^8F@ebn(EKw2y^!`pq9VFgZL!=5O4!T5E)`-9dU(|Z3O$_ zV|+IK*%=n!A#q&;a+jQACVVa#>B`_j^DVcU@c!Q>f(h~9L4p#0_+8*S*XJZQDw)ta zDfjc|aWd3~51cm|vnXVPR3b63CL$+)ij0wFrm?WmxpRm2BaabC4ittzB2vjrI7#fL zDwzd2KAqxxP@a+B%e8^%`YR*40dZBIq`*q>N^Rv0zP?)hTf864bkVDUT50Zew*6kvLsw9cavLh5p)mmV4rr8c z#r?gR?IhHyjzhadE6A*EoX%g0UHO1DNG#ucc0@O4y$W>;OP?~m@N(r{0Umqf8A)>T*lP~UEiEAxMAHcHCwlAmZ?-O;9n07 znvb72HC@GLv`z?0T=}$jjL^HGB!RUc6;*J12PjE`1bYE^FZw?XLQ8#Qvd2I%H(okC zs+#@r`sDfs;B>KkREZ>LYNw-&p%S_VZZ72xVWA2;wn{sM_J>nnrsvVLl_dXJ z4}xH@@JmM+BH4n|XH7CTb&yG7GgjG0MfI(n4b1QE&H`Q8UcT#9L;HMKNW#GHbr`7a z^|Vj>0>VJ`)j-U$nY;Z>3J3lq55C)r*4SsuDO8qiGuDL9w!?y5%Isb;?dOIEuey}M zQYKqXerqyvKMmQ>UTo{5LDd3C+5rOvr|DGd7;nK8al%77> z`fXHN{fNo_J<9F#XM{+`;OtwE+dXm^B|WwuV?Kwgpei`q{t;#D z$vDmx>>~Vfm~q zcdgXq^Z$CnABKWfGa-79T!Gu9+i{H)qhtZjm8@_IU3YHR-L%Qp&BjDC-=buHJeOfm z;47mr$9GX>LevWX)4B(ejJ-nEaOwIY0z@KD;OKfcFE#py!_{QTL33bsv?=9oKkp&KRhWSkQHP104YB&cqSbz2uJDmo5qp5tor0EuASk63u-}7uKfB z*_;Y2x^`{DwwUs~`F*^5_gTW>w|NM=7LmXdGEmSG`Bq)QqP|z1`+-cA`_NsF`S$I^ z0>*KwoXz)fE6p9VFkC#Oi$f~L9e5Kg*9UkKjRy{6`lC3cp}1`K*)_^G&G0YWJ$dOY zV@~NE>X>J45dY=NI?JsG$C$_@^|ylFdEpjN_KXJ9Rg3Wu3@NqQIw?Q@huShT*vnl& zzc1?pKhka_d7({88co}-|Byd*Q5Co&BoC(r>5k%kt*v>u9zoDC4U+Q;HWG9_`(Rxf z|AM8%C0@$6tBE8zi|@-)Wr2nLWATp=JPDUE4qT5=B;f&UfGyOea2p$J;8b7ok&Y*( zM<7vqej)xtP*6a0YX8?ma`HA^M&Z<}YOjwEeET=jv_n4~p*~?X*N+sH38+ zJI(|attDesW`KJp;rK-u>Us@9ZxBr+O*oH$8R0t>$e5bI2J7s+ zr2X1ODcK*So!2(Eg}MOFzKH7apXf)GiIz2M;osj!CImot$j}PsU={Y{mfJkyM?NK4okj_L5Q11=Lz4uk9?uY6vnN2_1_&O6H&5X4{kw8^iB9(>N>eWUD53y9 z`@PcpN^>1^hT~jPU2@CatC!EKp4@kPt6~e!Vi=}}1cE*4-|sj>+&Xcelj!uyN_HWI z%;8q$Wb3PiEdz_Fh?E^sO%}N4e`gK#c|f;7;~S*=vY3zzV!WXD77jV8+z&VjLNYUa z=k0j)siE>{DD|qAW{}_lNm}5*irY5z`~P7&n42&K68;jv41zR_D_T|`#j2rvpE_CG zEev~u`<-KM$cvHw4NEJf5XyJ`ox)LvmQ~;aNsjmQS6$DgPtMBdHcmA8IpISf>5A!;uk5N8eax1 z3ILWgTl^`ujv^CNk;}#TXx+fEcjyQ6_Sg?KS4Bc^FAhXGR}dM_@n#m)g76}m zz)9}T_$)zkd&w)jY)=ZTtqEP;O`H{1INC=8Z}!dBmv-%=m|ZvZXgy2674}*+#`(%ME+AfPhs?~nN3<8D&lYg}%CiQjDveaf=u==j{eCcGm2a3)V$0JAdV zH;hEuNG`nb|4Wt~wdJu%}l|C0sciBMiY=_|MdK*pZmwmR6UsgsExH#F^5x5M4 zp4^jFK5%INETp;Rl(qGzUmmFuBxirO!NDOUGYWTg^oxPV87sb?%f?Dz(dxHgl}L)M z36jBPe{dH$O0+|?a88%c)BvVvC zbb7s@jt)OCw)EEjT+Ck(*@$S^TYR1KBwNl1XNi!|_1g*$E^>7TF(R7v-n~vkhz9^;d?0xU~3IzUb*Hi@+NTO!ELUWE6m`qMI{HHJhG^e z(4EaLY@$7J46JVf9C$cUTeGnOwBvtkrHxP*7^uKDB-9 zHO}c+6}v(g=;&SFlFnJ5^st3GC-)z3mYYCFxNjQ<&ros@9+U_SIe>aszT+2qZ*eNl z6HBh0OCXS}FMT*=*utYONa-oHx#ogsY5LyI@f9BBb|UNyJ4t za3EWDm*$>0m>{d!%myq&eBZqOG{@-!3;YsSh9Y}eWQy`z#+P@QarXMRf<;jjNN&D3 z*&1^~6TD4VMzbbE%if0cxA`tPnt>dqqQ=dbKBJwTQSe*NJ$*jD<}181E> z@Xl0DngBHnrqlr@%Bl#A3xY2xyYYPz)HNtH?7Tiap2_VUnpk&Z<3CSyKcf1)jWVc+H8Gi~Ee%H18;ayMBuCnE3Af`2lQ zSvcM7J}N}Q6V7^cB~qs%_C7KneLJU`>!fa8sdeHxT<8yrj!eX4dg#32B=je@LIRK0 zCTVisbU?C&{KSRHW_%7$BuGcAU=d$VFx#z{=OqE9%fD+%O5sdZ@yt6&g`0!l6kvzH z1qWmT5|(WGSm-%9fFCNK7y(8f7cd$5uh7~wnN2zp&T{!oDQ@-RwL;5xnYR2LYDyEs zzFc-E4nDvT&O7qvSN00j7iV*UNWQ+252}0Bboj7!sM)d|3^}{v7XJ*WpzG8u6*snO ziQ=-o9J?ZFys?H;fA%Rt#MtT|P^ph_p9oMX|0JlHrhFVl&I~cx*gfODB<31YVj_Iy zO9MSAZ=2~yWnv*;_rw0ZJqklSHI08#2h~4wS)nw9Roa|y;@{{^+ z750u!28lV}y?V_unJzIswD_Uy(;^|{`(F-=l(QtfazF{iKaxb^%Nhb_8>_fQE|GOd zlhMkv{jKJTnSta)Ur`uWb99u(iq=waC+CTvvDM1?U|IhI^on=NP4cofd0f`mY4}8|W4PA=0v1ub2KP zCgY6ax8E4`mL|Q*jk9cVL)DS7YDiJ>Yx>z+P^p=z@W`1Nm;eN|of(Xofx&-tSOdX) zlF5$07=LRnt=_$;z_62ys|`k@t8H;IlI5D*p;i3I2J6*$EN5+^8J3VQW2oXIMk+w| z$IQ(BCmAk&Tdg6h3>ffGgg2tF9%|URGC9s?c_^kc?d0ygb)SelZ&?e8c^N z?d7TS&8mM~*A${)4vy^C?=J2}uXY??e!3_l%6w{YhbCqpvTTu{?ou*48CN9lZTWdnO& zJMhW5xbR^FPW3NZ)zrFjD`c>;Xw>b8)O7M^2|oeN&37tN$6UHjPdcKq_rk(LgU7|3 zPn?~lZq7>E_+lx`7dGC!UF!AkmTFxMYQ|~cSfCN%j@vK9t4;a^k&Q-SadcXbg1%Bi z(Gdef@##Qi=+}eXgJ(4OdI@DNd5o(P`1UMM;t+&`|KL)Q&G(l-K>vze1L=_SRlg_` z?=4aXqMa6nlm!l0aLcKtCgo|m-XQUraMoMK%JToPnjojZta4TL%jC&v!}$!|>JMG% zd828fnQoerh4SZ!>)Dqh4ZyMSuaR&)ldl?fRbZaqC_6%;DUL%hgK@2yGbBr-V%XqHC_ z>D>Ouf7Bnqd#M`rAR-$glXW%bp7G3stiy1|aZaW4 z@}HRnKVCDzP+WD|^iPh^@yE-yJ-BOq=T7hLUZj}*_xld-G7H{e_`G=XMegSQV$n0B z?4Hql83L^v532KS$5gnL*;vny2ixrS{9|&_f4pr(&^w-HLe%4j&Z*krR&^Em+R2sX z-;&IaP92_F(Vt|VaUvU2@r7f=6U$|`YgY?az}>O%M!|2)J6K}X(BOy(8OOsRFW%gI zMr!@cbOT$eE8+fxe#2J*a&fWpXemc+XWn!G@U)Dd?8XY5g&_(8q~KxaqY>WxYKqw9 z7BJ`vks@ZAYH%{hxJKbrp0{e5m4M0V?o+i5Yk=7l!g>>9CYn(~Jm(h{ecuPhC6*-q zgJY)t^hBTEMtWVj^kFs0I-(9d6An1{H|FT1GktI^iNAw3|1p?7esZ{-b!smJ6KF~Z zOz_d?u{HDw&K%6~RDX)pTs4A4X zIM8Asc9yl0deiy%E*bc}YjCH---M9_4u;JvJaOWKku=y##m{exj?k->_>TW0*1!G9*P(Q6%F%cap)03n zoCnVuaj0@$30rgRh`+_DJh1?n8TCK)?LrPvY3xix+cL;`S0P^vFzjlu)%cdk;(^Wf ziu(mLh!7L{?UUdAxmWoVQ&;4?cfuHR+*N-U}8OJ^OjR?)r`xQw5$* z1Ti*swOrmkL^dwGq73jn)-r$M1s~oC-nm9{9&8$8!ug$u7T#;*$kfaL*Zun%d`1a* ziPfUm?0DYcXQQVT>nzDgn)L5Pz!(z_QZx4s;vuJMxFcj3?lt@TV1y}}|4S(v@SpB2 zt&Bp-7L3f@zi{c0jTmH-MuN&G$>|pa2a~VKP0g|&(vm{`;9`dxyluYQ%uaLfhqPtl zD!>4E=J|>*JAyKTaC7JgSLt`><+TT{`WSn2*EoA{f7ADOuKoOHbJzQ|D(%%!;F@X) zCsKA7KWI|W%>}K(fZc&>yFIpmBTN`43fpcFa6gakj1iLyLXe;^HJl-N=j6V1ZjtJK zfVSo1V0R{mCciz7o;miV^@Pv}Y4sRso z2~acsDT#ajAu{F@hWOkJlZ0iqBjAuf4EdJok_mzFt_0MH# z)wfd1g>pba2)8#+1(yoh6#T7`=y0mWJIDi_4mm-UKK7fat5jzFI5p#E{>eJ%k7i(8 z1yrZM{>&Sc9EGM07oeL+92oWs$_`jK)1BzJf-zZdk1^#gE(OLN*Uwv+1cDEt2#3~b z2>!dDMVo+&T(*vTcn(Kv2A3s>14!^XBoa{($F4uXDar4*ySjsE9-( z;H|iTD!;wq$y@0Bdgqq@k6FUcc8%Xg#r60x!SBFc{?n|Wu|5hF@e6?)4nwwop?B)2 zrfqMsbJ@mi^aa?gAczg0?QS}L8om`kE_x1{-MKNCv&?%Y1Sm#wv!|&iV>g9?FRbZk ze6<-tJW^m~!2h8dT&NN-ZeN;^@MYBEAC<2Eqte@VLealb1}G{Xk2@z@zYojC*~`uA z4z{?sJnqi(>llm$%KfuZU9+?{t#@@EUr_$A$@;;BQ`NC9E`c6dCDnqClTx3(0Qg<< zJo2}ki1zbuO^f{l`sH3BL4QWFoG-w6*C#3~N(;eyX=P|N4mQM4Ve~`iixUgnH$HO3 z8^DqI9b})&fd4T+`>R~iUHQ%|^2~bORkx#o#h?DpAY0rKSE{QhJYU?7#}Gvk^qi_{ zy+237@*Ya*?Cx+{_sFU!E!}c?DhI~yZqpH1Ow2DB+#ooAEd0d;ci8Xn5B$_}ZCf*4 zm}k3pZ?!vBx+<0o+?!&^FUd5|LKn9`yC*99N(Hy};`yDD!{;#(Yae#x7cP^SEUu_2+9y1z_8@0}6b*-aQMtxbc{L?@hVamk(9qEEkROr~GmmpW zy${SIynL}P#}+w4fJ6e=zNXLUvbD&y_<4p@U_C28P$mxmpsdm=4YE8vTsaC<=|tT= z=W4p-z}5`Gr2j}FKMV|h$AdY2(n9ij8g}gZ36$rC=FFjL5faq+1kVV>cdDd@$Y+)K zy$xkEQsfjE7`@1zI1d~=#&-nLI;AYk$8(XUkrlY-_Z6MUUln)bZqUNeDf7QRI?}BrV8M0~ve7r3Z;0h{KMtQz#ZBNwt9Cb8 z8*q6#iB^7yVQid6`ut?z!n|A64<|gl0I|L*<@d_(v8yHB!SAdZ%ADf9cNZ^q7>iHy z*}1#(4)8tw3vAkZxTI-lGcZsfbOy#y--oBW-2~B<$+)GqFITu;#hVhi7QZBh8~|9c z?)(zRLbo_nkcjC~>eUw6S5pBuZjVT?5zr`BSe!iKS+~fRB{`I@Vg}hF#BUE)S+soM zy>o5H143#Aw_VqL*5;T0zZ z^wd0kVHquOUyz_?%+CtE<6X2Im3k*U@bQqAG+C|&jS8#qom-urP|8{85nPHDk2~gw1a)c|i$j0N~8@U=& zR-!Iks2}SN)D8X|)?!CS+u5JS;HC*Wu(BG9BiqF;cq_0v2vA_(X8Z)bCArLJWnsRC zvT*WI_1W7@|4J*yP%wEf4E1exC#W)ML<4#abn^#G$VKK;;B?}DHu)NIG~rr8la2oB zxZqv|UH->ocu+wGu5(jIBit=j2LW368Fw6LBr7b8|6scF{3g%=$i(}@sPm%QWf=Vu zIBA2UpU-a#gTMws+FI^sTc3IWFT8rIEt0!bcFzvJ`jlC~c&!@E1$(m zA!xOnp!6YE73d1B$6dj0(01QsHb1=pmDAHRIa_!CY>}XWJ&Fa23vPyhI)xxh9PP7< zkhyEFPG`aA(U?o%)&KpE`M}$7jJ-8@gU*8|8aVtrr>ivn=lkQRKj-Mo=su2af)neGPCaVzt6bGBxG6T!_1yJk$V*a~)hn)mg9GUD)Y~ zjokpZo)lp~);M%d4{c!>@a%i@=S}NvH62c4K7w#z94D7Zav9DOeTQE-BgljaK@LQy z9!4u8#qT<{;InSk?w8d`U8j{8z`Y8OAn+8(16;iBz*(I)t^Q0D$Q+s!aJ^A*Rx|#@fvWQW0jAC#Jk5F^2U`1Y{eFH|irlZl z*?b)wP0 zE#3fEVL6bX#)G?fAU-UV>Z*d)3uG&qh(|~s21j4i2}0Z^_V)v-1X|>yRip?7fUbACvQXOw&5>(*09tlheofzbauPIls%~IquTm-1QOe0VnS;FxCw`Ngj0t4v6sY zNyV@=r^A2`hYJzAV{UB91IQ+NggLftj z<_W?55#;CAWT^Xc88&u87*}a%h(C}Ad1%oyg;Majtu`-i5fWY=$OFZM{|-4GBO_@J zWKlPV$_Oe6A?W8bhEOB?vmw`8m10V@PDIjwPtmEaAT>DKK9D?S^efSWI}pT9$;e!0 z$#Jl-i1i{cPo)!t%m0i{u=9h+RAJ`lou#Sqyl14m>Wl-^;8*NZPMIt>)LOh4e{h-e zXB<}9tr&0w-MUh3TokUfbsEUSM#3^?#b}NyOtl{)Y=-6Lqt=H}(3VX;?|#Vx@If4C zq4A;ovDLj^9WJunUbmu?IgBsuh83FG1F-(NN*(^w?T=M2RKs9qC0g?%D|RvAj&3!= z^Q@gmI>StL<|>?Zn@1PQ>us+KteM`FsdI2?5G{DY?;^F;WOxwquFg)?-@1V2mBYqXK_!iGV+XAHW|Ey#M>)|B2`Sl;ZzK cQ#e4y)KlXQewN4yUJ8jnmJ!Jkdj97B0k%ksMgRZ+ literal 0 HcmV?d00001 diff --git a/assets/icon/app_icon.png.old b/assets/icon/app_icon.png.old new file mode 100644 index 0000000000000000000000000000000000000000..660afee38dd5636fb5f112ea996dc4661d029abf GIT binary patch literal 41814 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 z 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 \ No newline at end of file diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..7c56964 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + MinimumOSVersion + 12.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..b9fb836 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,616 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 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 */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 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 = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + 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"; + }; + 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"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = cz.filiprojek.fuelstats; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = cz.filiprojek.fuelstats.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = cz.filiprojek.fuelstats.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = cz.filiprojek.fuelstats.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = cz.filiprojek.fuelstats; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = cz.filiprojek.fuelstats; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..15cada4 --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..6266644 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + GeneratedPluginRegistrant.register(with: self) + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d0d98aa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1 @@ +{"images":[{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"20x20","idiom":"iphone","filename":"Icon-App-20x20@3x.png","scale":"3x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"29x29","idiom":"iphone","filename":"Icon-App-29x29@3x.png","scale":"3x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"40x40","idiom":"iphone","filename":"Icon-App-40x40@3x.png","scale":"3x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@1x.png","scale":"1x"},{"size":"57x57","idiom":"iphone","filename":"Icon-App-57x57@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@2x.png","scale":"2x"},{"size":"60x60","idiom":"iphone","filename":"Icon-App-60x60@3x.png","scale":"3x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@1x.png","scale":"1x"},{"size":"20x20","idiom":"ipad","filename":"Icon-App-20x20@2x.png","scale":"2x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@1x.png","scale":"1x"},{"size":"29x29","idiom":"ipad","filename":"Icon-App-29x29@2x.png","scale":"2x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@1x.png","scale":"1x"},{"size":"40x40","idiom":"ipad","filename":"Icon-App-40x40@2x.png","scale":"2x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@1x.png","scale":"1x"},{"size":"50x50","idiom":"ipad","filename":"Icon-App-50x50@2x.png","scale":"2x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@1x.png","scale":"1x"},{"size":"72x72","idiom":"ipad","filename":"Icon-App-72x72@2x.png","scale":"2x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@1x.png","scale":"1x"},{"size":"76x76","idiom":"ipad","filename":"Icon-App-76x76@2x.png","scale":"2x"},{"size":"83.5x83.5","idiom":"ipad","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"}],"info":{"version":1,"author":"xcode"}} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ee8c20b7e3e3f701fbd15dab8b2c88e58406bdc GIT binary patch literal 33466 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 A9RL6T literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..d066e5be570412b563811fc9da2f3230c8bf9ed0 GIT binary patch literal 586 zcmV-Q0=4~#P)`av8B;lezfBjyy<-pf(KiFCR|NO&R8UY*Rz`+_f#KHe+Y(ZW5e7e2USKEeY^ZC0 z{(SrPEdv9?pFe*X7#JAu|9kSDnOM!=zyQvbz423zmF)}*)N->wKcxTv-O9rCi;)qb z`QN|)OibvZqNOJPIw^u>$yNxL_5c4yrXO4?ieGO&-Nnj<(0t?WBW1-19Zd~HfUz-6 znZMQa?3v$SE*mQ|`=7sT>|7iM+FUoEpg8;6_n)U$R5ZGMg^Par$t)xq`@qNT?1Ih0 z0$f2Z24CKOU^spOyPrS*L~-_q@BcULI*}Rg!@#uu5#t-b-1h)-{0q-nEo>` zV%PlTC!>?K!QwT0ZOwJ=-g}5FRbczgGU)H*LyRR`c(H5#{FCwb-@mu-KQ+)%Msup7 z_`h!=cA8=ba60?*PeyJoc1vT;A3uIFU;~VBKMM=;nb?`1Wk;y{D8>Bj(A&TN{_Qw$ z*2z+rmycgfP3FbqSjxsPX>|tPFc=i!w?TMSee*gLR?>|WM+xMT>?>LIpc?=8;H}5{VdG`rcsevmD Y0QA7t+I}u6{Qv*}07*qoM6N<$g3`h-rT_o{ literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..e32b54943935002c6111db70fb70ce6a997db173 GIT binary patch literal 1195 zcmV;c1XTNpP)=tk6pL{0qI z;>;q`NZfGx&j?0bG`ft0IU^#Y7(juI@>L3b{d({9y?0GnS3cI)4(2xh;QV#ZJ?Gxv zx#ymDZXQMD-VZlIs2f6E1}}rJ8~Blm4KF-uw2UKb(JGRP82tXqo^( zR|U?or`Od!*?G?C^9R(tGi~V~?0p{qeki6Gg=Oo3IlbvlcnPTdnU0poSM`KD+@-n1~2IJDGNx-2{h$Lq-DM?anOdt?B z?B$7T0zTK>t!5%axb02MXmIdaq&k5-7z$tsDuuvjjN!V1%~*-tG?wF9izI%x$QiLR zNKkLFCKnNhvJ~)^(gO1>Y3_g@zCV4rmB4t9;57mUg2+{*ouY4_#+(Q&h+&px6C(+N zpefpJvm%2g7zpClw#$7iSTO=-avok*!GacA5ij|K0i8?#IhYiu~%G%bscT zOmqA8fAV_3ZCAn`g3)0mfacY9R3Rxukuxez0`BQQ|L&o$UfETNNtIrWF%mr=9sOAZ z_|9UrRBk-}MRWL4RWmec)N6u#7y_aA%hkXD&~U8fkrKPawao6pwv8I~FC#MrENjE8_>jjz8V^X&+ZLHiOG<9m?r#cZ>Kx^09jyInIfGMwk zblkH#IeEqzdrHH-T4mA7d+C`D$B}Dzoc1~m1KowSwvB?*(e)yVpxg{R-hn40%%2r zrjb!b29$jz*-dVnB^i7Bq6xHwXGrKJEc z<{E?d>!tvPA|V5C0J{9V3SN8mK!_J-!8CnEZ!KQuhfvP@LRcy1A0RESIC z@ky^3mgb$f`DAI@$a+@UIzb{@-ICp#4T?JS%m-q002ov JPDHLkV1ficJJ0|C literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..39f4536624cea15d09c6ae5c0b0605a16a18ab41 GIT binary patch literal 1886 zcmV-k2ch_hP)8NXsDc1#?cS4kiw@dkq+kR=IFD4`^UY@rXWv@Jq?K-*oZr9#?%Xm?j# zZTBHnRa>d;2U=C^eyR{Htw3y1pcGnCoTOwMh#i`gq)8wowc~gkduBW{cQu*BB#sl0 zy_0lXKRa*ZC1s>dZ2FeUtf4aql{RVDB{5{8OxtH>?l0CcXe%-Jw3SD2u+0(@vKJ}+L4s_{?0sv@j`z9$b*F4vE zZr>`8mG#*AFvf7?vR)<5X^MrGHy;;?voHvPm}$i0l7?^*twtjob2EgxGOnqYY9G`r z1oUju>-C#zYG&GddV9ONx?+s`)-e6LAdI7ViPLvw3IK4*t(y<$^P60FalSk& zg=SgS<#NTbbKFd$&kY@(c|%qXjWG_;w8GB(e}vmSq#MN1czgGMm-@?NwZK;MEC4*s z1zyryRrfzH(8VH;#v3aIUP*ro7Akqx1UL++mDCLpiSv>A&;*`r08Y>qpiJQY#*7#z zdvXA;=qycCf|R5tw85aQTw7`v*Z|K^K0kE#CK!P6b8Nsk<=M0VhuAnps2!SQTwEy890C0P}V9k2rFLMvc#NrApEg>??n(^Q+`eY+Na4QqU6=I~5)FuHP zphMC+Gn+^Je&xhkjV8@t81nl2ZVp?pn1uz+kQWKU+@s7e5f-(@Mb@YHM|%5%1GfMm z11FfeSm?`F+!>ci7tynf`^{e0-RoD>}U5NX8X z7*Y`R<7XUVQEoO#@a-ddEm$x6yv!k$PuY(X)Se zJEkK+pruxmRzopdWXKm(4H^Ij27hQi{&MX-A?031vDIWe^xTts{{30Y$;QjJC1!sh zmdTW+tKU?XZk(v1e4`=Hg{u%&2^s)scCLssQ~krCPp`JrZeCY^&xVZjG<&wS<9cko zt8^Abi2=ZBPFw59gRcgEG-z*7_~gu2o!$KhAHA<;LpcC+-MAUkCqLUPtq_FD9cAqu zZU9(fPx1Ju4z%3Av%CMDqbCm?*ozSIjs&K5&`<Gp*BV9^ADFW8Bqqb7fK9 zjxFm>pKDGHi$HiwQ6$eSjB)6Ex7N>0n?yCC@7rFPX-;oybss-<@lS{M)oxzNLqS4aXjJMb;02+n#VuRLLQLPS;euRSvcyvTWSnUD z3lC&5w@JDKA;>Z&f*#|Lh=EW{PP1s4#pLw`81_z$<@E&$^Ox#%+NnlGn*3gj5T2}} zrozOB7BLEOU{V}LX%>khCdp}gT#kJ>^%8wn%~}%CEMd|qy#}CJDVvlm&(AQW1%eYr zOP+m6D9o^|qN~@WGzT=wQS60gk^9^4%Zdwrvv=FkV~t^ktz28W)Rx(Hty?Y7shSH~ zxfhy6ovv$JHaeY-qJO;jc$ndgX?jr<8!uc@iF2A}h4zM&W^#G^eH?cuL9Aa>vfAlH2vHQ}>F#x|S|#mNj03h@DOg#}bXN~sy+J5mF5Qmj06885 znD4ze#9BiCOX;$~*?)DgEk1Nrg=1w=p4|2+e)N?^(x+ahId#tE9}W6Pr=0+_8tR#S z4RVzyofzn#%{CFgx$JDY5e|+)ey;SE5A(8u5r9IOaqq8IUHH0Z$m@>-jpn>?NTm2< zBRoGi?90zdCDBAR8W@YlrC8_-m)kqL`%?282*y7=VGMtK^=M&%otQo&asVf$Ul@ph z#$QsQ7wsmBsPEQrG)c|8Lhz(UJhvD&;^|6pE@tXy^pEZTxfY=pN{i47rA6q4(oYil Yzpca4lnZe(wEzGB07*qoM6N<$f~M|~{Qv*} literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..cb118084252b34baba1097fa130104c2fe9fb570 GIT binary patch literal 837 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 Hu0mjf45eRk literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..493f3e8a9d5d352068557a61f207493a67fb9f08 GIT binary patch literal 2715 zcmV;M3S{+(P)$C1AX4y3qyR(; zUWpWdNWm+S0uU*9B~k$4DP*LjzO;E=X;ChQVbK{t2;DY4IN8`daPMJsEyO{yQFykx z;ty~AI7ulNZf4&%>)-tS2S-nx<-M9jvJ?X;1`0P6okCK`&P;rfLx0KmW~*4Rx7>4tD6GJ+zur_`Nf?}!Y(pa^$;|G*AHDIZ=0eDoR{JTU6 zB4m;Hcp*A1bGv>W7ry(a&>i8XOGe8bVbDSz zJaokK00J>zbvrPC7zqI(WEfV%Fm<%!s6^>}+MY*@j@x#>`s>5L+Fy{T6>f&6T&J5p zvpGDu)|)uFRhbC@_{|%86msd==4&TTUleXah-RCReFKC04;(oEiwa6v5N&|x@dgsd zz5C`-rDF4IKWz9%W6Rm*>z-La5^|YmFF9_thx(>MCRtjRo12*;B?-i$F`LuS_psOW zDB7NcR2a8pbGVh}vr56M1cR1y>*d!st41>3@frX{{0Dx6h&m^l9J$?7MOQ!q$j8|6X z`w;|aacQ<~U=W!3*+r*t6sXulO+9zV-fjBl>SbjO_3H=%Us#g=j6M$l@MvUw%xZhQ zzKkStGE#V(f)MHpG{F2ICLQAxhJu3zZWa)NQCO$ORLd2^nANs-*Jgsixu~?$$iInD zC(C_Lh9HD5ZrRk)+1+LIP6S4+6564e3LCCKn+vAOh2}_oGt1CpdjI%;zSB_0QMf-!Yj~T3S4Rd}6{!fg)p^q6;6iO~itN)#)Ejw@pKCH$#%1l1;VM*E)J_c4tt1 z7!W>j$AKjXi*Z;nCkn#NSe^bxUf8&rB)x9$3pcs*h1$b^JuTdX5XFnabR!G&c~up~ z0Dy<)QMa4P$x5#*D_T@mc*D>y+{)uBPIp&m-6R1foUrY##BAsHaN#M~VmB5r3~t*} z!;S5eXD-?%oj=+8B82eyudIkUg;W{)UW0Y>0)HZsX29G3Q@qire0;Yx2MSaSC~yPn z+3IqwM*YR4XgA!x+2zRvT)kmjR#}pxO)o3f8H^_3hNgv%?6lUEP=Q4f9K5!E@{t{T zr&$qHJ5DoV+=&qc{S8oH=)S!ZyiWGF!&m4Y!w+>&r@Xq=ca8C{yx5 zdajiA4SNJ7j3gPSEZq4#1*+E37y4(cwec7WQ!T)X1%=%Hy7}_0z^hlbg~nxFmhQ zDPeydh@W3*yWU;1vI2u}-|pu>KHJu5G$Dklmn>Mbd?5hf?x5K+8uHD^C#`ryO&o=O z)6nNPdzV(|l?vJREj2-P&U|`VpcNqsPr)j9EcjYDa^hV2ykuQYMo@+3wvH#Xr<|k0 zQy86ulN3-0$nFeIzh~fdQNKHUqION?^2Mc@8Z`u9$UJ)f(v9ZUj_6yDh4?8bT0e6#;~JRRopQo$+25K004JGJzHPL6<$t*`1Fd*+LD>Bo-Vi($myv^m?(Go zNUEV}EZ{jvi2p|v>xy()zEfuE6SbsLz`eSqRLGVr)Stb0&C_WnWRp9#KDV-JVPJ{V zML`Txsr*S-Ce@#zcGFXVh9=!tG9#xD15cmE_nKO+7|M!u@JT+uKL6Q`z*Bw-R@#ysv>R>*mh)5SG@5?-&e5>leR47w zO)*Wth0)VEBjPWS0uU*9B~kz)1+PR3K&0T6NCAixyb>t@k%Ctu1t3!JN~GY?{{dVp Vx%=lAYUuy~002ovPDHLkV1hDoF){!E literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..e32b54943935002c6111db70fb70ce6a997db173 GIT binary patch literal 1195 zcmV;c1XTNpP)=tk6pL{0qI z;>;q`NZfGx&j?0bG`ft0IU^#Y7(juI@>L3b{d({9y?0GnS3cI)4(2xh;QV#ZJ?Gxv zx#ymDZXQMD-VZlIs2f6E1}}rJ8~Blm4KF-uw2UKb(JGRP82tXqo^( zR|U?or`Od!*?G?C^9R(tGi~V~?0p{qeki6Gg=Oo3IlbvlcnPTdnU0poSM`KD+@-n1~2IJDGNx-2{h$Lq-DM?anOdt?B z?B$7T0zTK>t!5%axb02MXmIdaq&k5-7z$tsDuuvjjN!V1%~*-tG?wF9izI%x$QiLR zNKkLFCKnNhvJ~)^(gO1>Y3_g@zCV4rmB4t9;57mUg2+{*ouY4_#+(Q&h+&px6C(+N zpefpJvm%2g7zpClw#$7iSTO=-avok*!GacA5ij|K0i8?#IhYiu~%G%bscT zOmqA8fAV_3ZCAn`g3)0mfacY9R3Rxukuxez0`BQQ|L&o$UfETNNtIrWF%mr=9sOAZ z_|9UrRBk-}MRWL4RWmec)N6u#7y_aA%hkXD&~U8fkrKPawao6pwv8I~FC#MrENjE8_>jjz8V^X&+ZLHiOG<9m?r#cZ>Kx^09jyInIfGMwk zblkH#IeEqzdrHH-T4mA7d+C`D$B}Dzoc1~m1KowSwvB?*(e)yVpxg{R-hn40%%2r zrjb!b29$jz*-dVnB^i7Bq6xHwXGrKJEc z<{E?d>!tvPA|V5C0J{9V3SN8mK!_J-!8CnEZ!KQuhfvP@LRcy1A0RESIC z@ky^3mgb$f`DAI@$a+@UIzb{@-ICp#4T?JS%m-q002ov JPDHLkV1ficJJ0|C literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..93a9480a0f80ebccb745b9a8113ae3bd59718249 GIT binary patch literal 2461 zcmV;O31aq%P)e256+Z9jX}4wB$d)ayvSl#X7|dqOn&KEj*lJ)39R`|&Nl25H2_-+6X{OU<_|YWO zDU*_fX{JraZ4$yX0b15Flr<272^cJlH@qQZW6RQ$tmUn(BwLnc$+Dgn6II{Ho_Cjb z?)`MPbH5`D)2xR7Ct#D^foLO6IMxv-9P5Y^j&;Nd$2#JKV;ynAv5xTwFDozIxn*^c zCWnWj!P;d3jJWyi<=TUv938aSLhEEW;g@jrswMBdwF^NI&Zbl3iMzI~t(ZGw>ubNW z6QozEI)z@GNBr%U2!MMN9N?RY8r}Y-} zWP>pDRwfSLgtt{!O2i_DVNRX<&s}W;P177qCnqJXe|}|_Dr5V`sy}^v)Mh8#Ma%Qa z;&g{iG^(QuehDv`Kl6XH`p!M=?Ys4yO%E82$4{R9>CPPqQgK3IMcsc7YzKgvS`k4Fwq4B58r|{>Y+yV8txArb9%u zzv?st#gM>|pkk;#9&Z9~gc(sKEM(a|cBAY0mp0>eNh%QzcReUXmGD%COoE}AoD9rV zhP=mnI$X;LLBz7-Bm*LYp+4FDa^B>zcY?*0Q4e_g^d^XZW<2oVZdngZvw1O=$1tRIC)m}VFN;PHZ% zvc`hvJbT#D%axpx!t#S~EwdTQeS%4UusHn>zp>S6AN^#vD<_wwCT_|%;og3OA|)v! zU8#N0G;v#FA(cpEi3tGkptZA8*DGV0LdMZK$^9mjAXuSvf_6MbAXJv<{GZ^?5e2jN z`6m4B?S>hJxpPWqHa53*KJx2A1~83b&s9Eyq9{R<`wx7In=Sb?`Jt`fT|tk8GJ`lC z;Jyj}{ph)E)z1n9{Owyd8H_mNoZ-PDK`Idn9b@y==_|O|GMBQyM&RslPg#Js?1lqE zSsm{w5b;{tyWjcn@V?i7j37v|JSmh0+Pivw|H0<~@C4=6@`TNalCqKl0J!|kJ(^+r zkZ60Ces}4QK0j$T4ZOX3H7Usj4&7o|gdRltZ#T6IH>|4o$B8Q)7TfzmS+P1dYx6pi zq~5#bR}#rkB+6xC6hUkRrR&A5c5h8P6pVK)ojrfGX6dm|tn1k{iv3x6Sy7=n^H9x+ zuI@fXvdkgw;lA&Wd>aU>|3xm?={9gjolh9|}&Y$6br4a#rx#(;$}Gu8yD zI7Obg=ar3zYEERSQk}QU0iX33mgai0b;^n8vbp)KdIN+hTr(bFl1A(lh(eHJS{~uQ z{y|GlnlBpt_6TW8PM$|3<)kgXV-&*Pybh3U}8@v!hh08b0IBO*Tc zo4U!4SZ%~7NB-UOWMFMoxlq6t3LM|x{pOCbl@-ZSbT|@`p-juq%enf^O;=K&2x;T= zL?FU8G%bOop&MDCdg@SDxSG@cFkuVB*7|O1i zN=#Q$7z%xZ=;;T7E~5|kA>bMg1K|XTXv3;S0MMt$4>4812af>~SbvG279y5)Ge^(KPer zsVnaMn|B&Fty#jyu%g18&%<`#(E`AlQf^XJy9rN`dS7fKKBdzXasX&<^L7k%J^e+R z>=bzrf}>xI+Gh~(&=tmtR1w~^><%{r04!E-jnb7P5JX!ij=1ANIByGLk#~eaGC0?`{x*{amsETvbe>z+7ZG;y}i4G~vg!v!r4AI1R!jq93K&62~ZtROh&g>~fh2 zH&X=R&ao&E{jgMmlR}HxtVf5626;5VDACh5;k~bHF33~4o?D$CE|>;yOaoV7Y5#kl zX&c+Sdv5rvTRJ`e7cXxV2u4JY`^|0h=FW8|jTIF`4*Tv%RLGg5Cl;wRsjelAQe|G$WjUcl!QXPxYQ^8_KBCQCpUS|dizzj##P}IAWVi1BP z&s?lEng-pOz6tNz7eur=ETAa*$iFT{p`oW`grkNy;aEqUaI7OvIMxv-9P5Y^j&;Nd b$2$HCk-2`eAFoN600000NkvXXu0mjf(lD{V literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..280cb4926ae23aeefbc82662594a9536f1b6ab1c GIT binary patch literal 3689 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..e6c188d3a6a094f202ad596091c94d5d39226d15 GIT binary patch literal 1532 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..72d10759e2c6a4d603d84a8fbb5175d14c508218 GIT binary patch literal 3400 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..693dca5b629ae83924b3d605386fc039c395708f GIT binary patch literal 5470 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..7c00f3d92ca1f8bcf646b51de57430878f0d8cdd GIT binary patch literal 2239 zcmV;w2tfCVP)Mz)6@m&4ht8I5Ut;|LD7A+BBWgrlm7Y z+K~RyHfg8Rq)nko3TZRs!4Q%VXwm}p0~>;og=J$Kzv7o3);)B$t$ae3?X#jg+iKM6 z`;YH-Z-2L++u#0vyDO7qegph3iu`YPV5JlTi#El;qD?WdXj2R<+7tteHiZJqNKekq zOh-tHJq%-$jw{w)jPcStw-kwkY1FExzWdlcTPu(>EWd0$1K)V^*B^KFE~vo-0v^k; zDOKWNKl%2)d$-*o+h~5a<;BC_Y1sSt*rX%4{OBG>sl{9J3lr^KaW)aKH8~mg-Bkqu zZ5>yx*{)+=no}j2O`of(FdO6d?QZzl^REQTvyI#X>uCZ(vYzjsQY=U3LrDZ|TXh*i z$llxc=BamOSiIiT%kkXyx|;gx@?fxs%P0atOFtO_Dsix^j5J^W>^-uLT5a9i>uRzr zseuxNa8tPl0G>aum2Fm%M8K4!?~AftuWX|%>uXDr3WSgl9_tI391}n3L9euFme%2L zB{`2JB_$Q)=ZjWR6xG_+CR(+B69oW&ZqrP&kqC)$z(|tR>-C~l1VJp;sy2`LkCVS} zF+#%?xs`{I4tpmf5jF(E zqtpKVr~d!|zwvyc1FUelA-s<*0QjZwT_Ob`QWa7nU?6y&?5j zCdq8d$;t$PV{e@upKvs>F3#&wVqZ?D0d_O47gYvE)=`QiiGYnyI-h#(#$!s#3 zO-6Zkn>(zpzHtTsa(HhaQfP8B0fEhaGl%yo0W&MV014O)bd+rtcvIeCevETUR; z7QX)W`@gUFi#(&(aH%oj{zrDz7Zqgw>G-?J<^%wkbhs8ii4dyUl$T?fU1vF5)X5J! zVOrjsXSFDpn?V>$8?Au4`X|S94zn?SbLm>0R{e3;4d1q4WMbiy#rbK$Q~(ekr>QK- zfztzWUL2%F!8nYjSyPzk|BBfUzFyE|#bvfe))JME$9n#v92%<0h8nQ;piL7@0Jf41CMx*29 z6sLK^1#`(CF+vFO|GLx_DC9Wa-ZykxLFTG7vurR#fI{W(6|2voj2i=0@#;A#clm<{ z#{*BOwHn_B{^sylaMjqj?+4C!gHDE7zZPHP&8u1dIW}jU=dN40nW;sr{AO%LM$ADY z55=&oSE(eEOz}gbvuj^-qQOV*_Q>k0G%Y`v(5i26G&eJSQ_0#B@BC9J*QiwmxfTHE zANoXYZzX8?!30-qX}9HOrq^#NqiCk}vW*~!#_g3FwaVd~w%?E)5+x{ff|e8Rg_(Ko z!sUwcqKx#U#vPT7J1PUUZ@qV6SvJU@s!(7P9yud6;qiSAub2Df3$H)=P(yz9Dxn-> zeCmVdbLTJ1?W#11fEg1EbyX$8mZDubO-Q73rjonv^=;#<-Tlx0_O;xs^z4jO47k(Q zH#j^V{G`d4U|F?Fh|@eEhs$lTScEFY=2B0AFE{Y{IWRm*YqXx)Dj|oGa*Vm*$`DDn0#ysK0%>Dz9vU)-Tw4E=35TwRx*Ufkj4LJpEBUC96Uk~KEeP1 N002ovPDHLkV1lt7M0@}M literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..f7b577ef2d2604ee6e7eccea057b9404150ef288 GIT binary patch literal 4404 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 Hu0mjfFIasY literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8431331ad23f1b6b790c4c5066dd9f928ca25e62 GIT binary patch literal 4620 zcmb`L=RX?&6USrkS+lCOslE58AWf(dl-ebVpth*SL|EnEF;dA z()2PH6Op^8_ftm~P8Yg=HS1Tg9aq?BHqs1E@e?WGF}$bWEUu>duxe&Z#`!i*vRvPhoGdQ<$f}n3~~Jjj8#IW zUa?}sgt#J#?vMA%8NUmuK@A_Jgd}Civg8PO;5{`~=5L+9u!l;0UUM$%{WKZB5{fz|wm%@9cF3s^5+-=x(a+cQsuyEH%F^+*;LCQ{1fG>mvJ{-%rkc ztEPcXgm+|3Xq-=E9-dNz_YU)ol)R>3%jP4Vi`Qx#ewAPvT@R3fc@YNaE)!UdvePF9 z0PM%-YR&FyTB58SAl5zMw`T2e#;L6{v%x|^UQeffM)%Y}aKlKmGV*#JUzyb~nOH|i7i+sFcadx6(BHYaf|J0S(Y3Nhjp$G8q@mb z^x)*W#772?(RT(lO?-Il80MMzOGBPL4pb7tGd&@g%uYQ7XWeblGCrFUPGLJ{W+faWkL)1w^Qu zQxz6~fczWcr(*ZZj?*Xk;#tuHAoHPMJv1tHUv9Xk)&wM{&36(`+dJkdNKJ~G>O&sh zDZaVaFDn0er{Bv{nqTyh+0i!e;p-SCT~1+Wd(wF~kF9heUf^yc&I(_H6fJH}qADf< zH%ftI3fC@r&;-(UhO^nh_>5X6rrA0M`My^SxJiSAMQWongKU~)rm9(^ngYO zANm8#2J>>=Y(6^(`9&Dt1RaI5<~`jU;z8(|Mv®QTQzzO4!6(0s$rS(fb)Za762 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 t?z3?(!hDk0W&}wvFA{sWHJ@x}lE literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..ee6f1efad7a0444767782eba30c1436c72dae5ff GIT binary patch literal 5004 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..9da19eacad3b03bb08bbddbbf4ac48dd78b3d838 GIT binary patch literal 68 zcmeAS@N?(olHy`uVBq!ia0vp^j3CUx0wlM}@Gt=>Zci7-kcv6Uzs@r-FtIZ-&5|)J Q1PU{Fy85}Sb4q9e0B4a5jsO4v literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..b3bda92 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Fuel Stats + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + Fuel Stats + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + CADisableMinimumFrameDurationOnPhone + + UIApplicationSupportsIndirectInputEvents + + + \ No newline at end of file diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/lib/config.dart b/lib/config.dart new file mode 100644 index 0000000..983f791 --- /dev/null +++ b/lib/config.dart @@ -0,0 +1,2 @@ +const String apiBaseUrl = + String.fromEnvironment('API_BASE_URL', defaultValue: 'https://fuelstats.filiprojek.cz'); diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..4254193 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,164 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'services/session_manager.dart'; +import 'screens/home_screen.dart'; +import 'screens/add_screen.dart'; +import 'screens/vehicles_screen.dart'; +import 'screens/history_screen.dart'; +import 'screens/user_settings.dart'; +import 'screens/login.dart'; +import 'screens/signup.dart'; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await SessionManager().init(); + + runApp( + ChangeNotifierProvider( + create: (_) => SessionManager(), + child: FuelStatsApp(), + ), + ); +} + +class FuelStatsApp extends StatelessWidget { + @override + Widget build(BuildContext context) { + return MaterialApp( + theme: ThemeData.dark(), + themeMode: ThemeMode.dark, + debugShowCheckedModeBanner: false, + home: MainNavigation(), + ); + } +} + +class MainNavigation extends StatefulWidget { + const MainNavigation({super.key}); + + @override + _MainNavigationState createState() => _MainNavigationState(); +} + +class _MainNavigationState extends State { + int _currentIndex = 0; + + bool get isAuthScreen => _currentIndex == 5 || _currentIndex == 6; + + Widget get currentTitle { + switch (_currentIndex) { + case 0: + return Text("Fuel Stats"); + case 1: + return Text("Add record"); + case 2: + return Text("Vehicles"); + case 3: + return Text("History"); + case 4: + return Text("Settings"); + case 5: + return Text(""); // Empty title on login + case 6: + return Text(""); // Empty title on signup + default: + return Text("Fuel Stats"); + } + } + + @override + Widget build(BuildContext context) { + final session = Provider.of(context); + + // Auto-redirect to login if not logged in and not already on auth screens + Future.delayed(Duration(milliseconds: 100), () { + if (!session.isLoggedIn && !isAuthScreen) { + setState(() => _currentIndex = 5); + } + }); + + final screens = [ + HomeScreen(), + AddScreen( + onSaved: () { + setState(() => _currentIndex = 0); + }, + ), + VehiclesScreen(), + HistoryScreen(), + UserSettingsScreen( + onLogout: () { + setState(() => _currentIndex = 5); // Go to login + }, + ), + LoginScreen( + onSwitchToSignup: () { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() => _currentIndex = 6); + }); + }, + onLoginSuccess: () { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() => _currentIndex = 0); // Go to Home + }); + }, + ), + SignupScreen( + onSwitchToLogin: () { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() => _currentIndex = 5); + }); + }, + onSignupSuccess: () { + WidgetsBinding.instance.addPostFrameCallback((_) { + setState(() => _currentIndex = 0); // Go to Home + }); + }, + ), + ]; + + return Scaffold( + appBar: AppBar( + title: currentTitle, + actions: !isAuthScreen + ? [ + IconButton( + icon: const Icon(Icons.person), + tooltip: "User settings", + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => UserSettingsScreen( + onLogout: () { + Navigator.pop(context); // Close settings + setState(() => _currentIndex = 5); // Go to Login + }, + ), + ), + ); + }, + ), + ] + : null, + ), + body: screens[_currentIndex], + bottomNavigationBar: !isAuthScreen + ? BottomNavigationBar( + currentIndex: _currentIndex <= 3 ? _currentIndex : 0, + onTap: (index) => setState(() => _currentIndex = index), + backgroundColor: Colors.grey[900], + selectedItemColor: Colors.white, + unselectedItemColor: Colors.grey, + items: const [ + BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'), + BottomNavigationBarItem(icon: Icon(Icons.add), label: 'Add'), + BottomNavigationBarItem(icon: Icon(Icons.directions_car), label: 'Vehicles'), + BottomNavigationBarItem(icon: Icon(Icons.history), label: 'History'), + ], + ) + : null, + ); + } +} + diff --git a/lib/main.dart.old2 b/lib/main.dart.old2 new file mode 100644 index 0000000..b29a234 --- /dev/null +++ b/lib/main.dart.old2 @@ -0,0 +1,20 @@ +import 'package:flutter/material.dart'; + +void main() { + runApp(MaterialApp(home: Home())); +} + +class Home extends StatelessWidget { + const Home({super.key}); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: Text("Fuel Stats"), + backgroundColor: Colors.blue[700], + ), + body: Column(children: [Text("vim")]), + ); + } +} diff --git a/lib/models/refuel.dart b/lib/models/refuel.dart new file mode 100644 index 0000000..acc071d --- /dev/null +++ b/lib/models/refuel.dart @@ -0,0 +1,113 @@ +import 'dart:convert'; + +import 'vehicle.dart'; + +class Refuel { + final String? id; + final String vehicleId; + final FuelType fuelType; + final double liters; + final double pricePerLiter; + final double totalPrice; + final int mileage; + final String? note; + final DateTime? createdAt; + + Refuel({ + this.id, + required this.vehicleId, + required this.fuelType, + required this.liters, + required this.pricePerLiter, + required this.totalPrice, + required this.mileage, + this.note, + this.createdAt, + }); + + Refuel copyWith({ + String? id, + String? vehicleId, + FuelType? fuelType, + double? liters, + double? pricePerLiter, + double? totalPrice, + int? mileage, + String? note, + DateTime? createdAt, + }) { + return Refuel( + id: id ?? this.id, + vehicleId: vehicleId ?? this.vehicleId, + fuelType: fuelType ?? this.fuelType, + liters: liters ?? this.liters, + pricePerLiter: pricePerLiter ?? this.pricePerLiter, + totalPrice: totalPrice ?? this.totalPrice, + mileage: mileage ?? this.mileage, + note: note ?? this.note, + createdAt: createdAt ?? this.createdAt, + ); + } + + Map toApiMap() { + return { + 'vehicleId': vehicleId, + 'fuelType': fuelType.name, + 'note': note, + 'liters': liters, + 'pricePerLiter': pricePerLiter, + 'totalPrice': totalPrice, + 'mileage': mileage, + }; + } + + factory Refuel.fromApi(Map map) { + return Refuel( + id: map['id'] as String?, + vehicleId: map['vehicleId'] as String, + fuelType: + FuelType.values.firstWhere((e) => e.name == map['fuelType'] as String), + note: map['note'] as String?, + liters: (map['liters'] as num).toDouble(), + pricePerLiter: (map['pricePerLiter'] as num).toDouble(), + totalPrice: (map['totalPrice'] as num).toDouble(), + mileage: (map['mileage'] as num).toInt(), + createdAt: map['createdAt'] != null + ? DateTime.tryParse(map['createdAt'] as String) + : null, + ); + } + + Map toMap() => { + 'id': id, + 'vehicleId': vehicleId, + 'fuelType': fuelType.name, + 'note': note, + 'liters': liters, + 'pricePerLiter': pricePerLiter, + 'totalPrice': totalPrice, + 'mileage': mileage, + 'createdAt': createdAt?.toIso8601String(), + }; + + factory Refuel.fromMap(Map map) { + return Refuel( + id: map['id'] as String?, + vehicleId: map['vehicleId'] as String, + fuelType: + FuelType.values.firstWhere((e) => e.name == map['fuelType'] as String), + note: map['note'] as String?, + liters: (map['liters'] as num).toDouble(), + pricePerLiter: (map['pricePerLiter'] as num).toDouble(), + totalPrice: (map['totalPrice'] as num).toDouble(), + mileage: (map['mileage'] as num).toInt(), + createdAt: map['createdAt'] != null + ? DateTime.tryParse(map['createdAt'] as String) + : null, + ); + } + + String toJson() => jsonEncode(toMap()); + factory Refuel.fromJson(String source) => + Refuel.fromMap(jsonDecode(source) as Map); +} diff --git a/lib/models/service.dart b/lib/models/service.dart new file mode 100644 index 0000000..8738925 --- /dev/null +++ b/lib/models/service.dart @@ -0,0 +1,235 @@ +import 'dart:convert'; + +class ServiceRecord { + final String? id; + final String vehicleId; + final ServiceType serviceType; + final String? customType; + final String? itemName; + final double cost; + final int mileage; + final String? shop; + final bool selfService; + final String? note; + final List photos; + final DateTime? date; + final DateTime? createdAt; + + ServiceRecord({ + this.id, + required this.vehicleId, + required this.serviceType, + this.customType, + this.itemName, + required this.cost, + required this.mileage, + this.shop, + this.selfService = false, + this.note, + List? photos, + this.date, + this.createdAt, + }) : photos = photos ?? []; + + String get displayType => + serviceType == ServiceType.other && customType != null && customType!.isNotEmpty + ? customType! + : serviceType.label; + + ServiceRecord copyWith({ + String? id, + String? vehicleId, + ServiceType? serviceType, + String? customType, + String? itemName, + double? cost, + int? mileage, + String? shop, + bool? selfService, + String? note, + List? photos, + DateTime? date, + DateTime? createdAt, + }) { + return ServiceRecord( + id: id ?? this.id, + vehicleId: vehicleId ?? this.vehicleId, + serviceType: serviceType ?? this.serviceType, + customType: customType ?? this.customType, + itemName: itemName ?? this.itemName, + cost: cost ?? this.cost, + mileage: mileage ?? this.mileage, + shop: shop ?? this.shop, + selfService: selfService ?? this.selfService, + note: note ?? this.note, + photos: photos ?? List.of(this.photos), + date: date ?? this.date, + createdAt: createdAt ?? this.createdAt, + ); + } + + Map toApiMap() { + return { + 'vehicleId': vehicleId, + 'serviceType': serviceType.apiValue, + if (customType != null && customType!.isNotEmpty) 'customType': customType, + if (itemName != null) 'itemName': itemName, + 'cost': cost, + 'mileage': mileage, + if (shop != null && shop!.isNotEmpty) 'shop': shop, + if (selfService) 'selfService': true, + if (note != null) 'note': note, + 'photos': photos, + if (date != null) 'date': date!.toUtc().toIso8601String(), + }; + } + + factory ServiceRecord.fromApi(Map map) { + return ServiceRecord( + id: map['id'] as String?, + vehicleId: map['vehicleId'] as String, + serviceType: ServiceTypeX.fromApi(map['serviceType'] as String), + customType: map['customType'] as String?, + itemName: map['itemName'] as String?, + cost: (map['cost'] as num).toDouble(), + mileage: (map['mileage'] as num).toInt(), + shop: map['shop'] as String?, + selfService: map['selfService'] as bool? ?? false, + note: map['note'] as String?, + photos: map['photos'] != null + ? List.from(map['photos'] as List) + : [], + date: map['date'] != null + ? DateTime.tryParse(map['date'] as String) + : null, + createdAt: map['createdAt'] != null + ? DateTime.tryParse(map['createdAt'] as String) + : null, + ); + } + + Map toMap() => { + 'id': id, + 'vehicleId': vehicleId, + 'serviceType': serviceType.apiValue, + 'customType': customType, + 'itemName': itemName, + 'cost': cost, + 'mileage': mileage, + 'shop': shop, + 'selfService': selfService, + 'note': note, + 'photos': photos, + 'date': date?.toIso8601String(), + 'createdAt': createdAt?.toIso8601String(), + }; + + factory ServiceRecord.fromMap(Map map) { + return ServiceRecord( + id: map['id'] as String?, + vehicleId: map['vehicleId'] as String, + serviceType: ServiceTypeX.fromApi(map['serviceType'] as String), + customType: map['customType'] as String?, + itemName: map['itemName'] as String?, + cost: (map['cost'] as num).toDouble(), + mileage: (map['mileage'] as num).toInt(), + shop: map['shop'] as String?, + selfService: map['selfService'] as bool? ?? false, + note: map['note'] as String?, + photos: map['photos'] != null + ? List.from(map['photos'] as List) + : [], + date: map['date'] != null + ? DateTime.tryParse(map['date'] as String) + : null, + createdAt: map['createdAt'] != null + ? DateTime.tryParse(map['createdAt'] as String) + : null, + ); + } + + String toJson() => jsonEncode(toMap()); + factory ServiceRecord.fromJson(String source) => + ServiceRecord.fromMap(jsonDecode(source) as Map); +} + +enum ServiceType { + airFilter, + oilFilter, + fuelFilter, + cabinFilter, + motorOil, + brakePadFront, + brakePadRear, + sparkPlug, + coolant, + tireChange, + battery, + other, +} + +extension ServiceTypeX on ServiceType { + String get label { + switch (this) { + case ServiceType.airFilter: + return 'Air Filter'; + case ServiceType.oilFilter: + return 'Oil Filter'; + case ServiceType.fuelFilter: + return 'Fuel Filter'; + case ServiceType.cabinFilter: + return 'Cabin Filter'; + case ServiceType.motorOil: + return 'Motor Oil'; + case ServiceType.brakePadFront: + return 'Brake Pads (Front)'; + case ServiceType.brakePadRear: + return 'Brake Pads (Rear)'; + case ServiceType.sparkPlug: + return 'Spark Plugs'; + case ServiceType.coolant: + return 'Coolant'; + case ServiceType.tireChange: + return 'Tire Change'; + case ServiceType.battery: + return 'Battery'; + case ServiceType.other: + return 'Other'; + } + } + + String get apiValue { + switch (this) { + case ServiceType.airFilter: + return 'air_filter'; + case ServiceType.oilFilter: + return 'oil_filter'; + case ServiceType.fuelFilter: + return 'fuel_filter'; + case ServiceType.cabinFilter: + return 'cabin_filter'; + case ServiceType.motorOil: + return 'motor_oil'; + case ServiceType.brakePadFront: + return 'brake_pad_front'; + case ServiceType.brakePadRear: + return 'brake_pad_rear'; + case ServiceType.sparkPlug: + return 'spark_plug'; + case ServiceType.coolant: + return 'coolant'; + case ServiceType.tireChange: + return 'tire_change'; + case ServiceType.battery: + return 'battery'; + case ServiceType.other: + return 'other'; + } + } + + static ServiceType fromApi(String value) { + return ServiceType.values.firstWhere( + (e) => e.apiValue == value, + orElse: () => ServiceType.other); + } +} diff --git a/lib/models/vehicle.dart b/lib/models/vehicle.dart new file mode 100644 index 0000000..ee46c75 --- /dev/null +++ b/lib/models/vehicle.dart @@ -0,0 +1,104 @@ +import 'dart:convert'; + +enum FuelType { diesel, gasoline95, gasoline98, other } + +extension FuelTypeX on FuelType { + String get label { + switch (this) { + case FuelType.diesel: + return 'Diesel'; + case FuelType.gasoline95: + return 'Gasoline 95'; + case FuelType.gasoline98: + return 'Gasoline 98'; + case FuelType.other: + return 'Other'; + } + } + + static FuelType fromIndex(int index) => FuelType.values[index]; +} + +class Vehicle { + final String? id; + final String name; + final String registrationPlate; + final FuelType fuelType; + final String? note; + final bool isDefault; + + Vehicle({ + this.id, + required this.name, + required this.registrationPlate, + required this.fuelType, + this.note, + this.isDefault = false, + }); + + Vehicle copyWith({ + String? id, + String? name, + String? registrationPlate, + FuelType? fuelType, + String? note, + bool? isDefault, + }) { + return Vehicle( + id: id ?? this.id, + name: name ?? this.name, + registrationPlate: registrationPlate ?? this.registrationPlate, + fuelType: fuelType ?? this.fuelType, + note: note ?? this.note, + isDefault: isDefault ?? this.isDefault, + ); + } + + Map toApiMap() { + return { + 'name': name, + 'registrationPlate': registrationPlate, + 'fuelType': fuelType.name, + 'note': note, + 'isDefault': isDefault, + }; + } + + factory Vehicle.fromApi(Map map) { + return Vehicle( + id: map['id'] as String?, + name: map['name'] as String, + registrationPlate: map['registrationPlate'] as String, + fuelType: FuelType.values + .firstWhere((e) => e.name == map['fuelType'] as String), + note: map['note'] as String?, + isDefault: map['isDefault'] as bool? ?? false, + ); + } + + Map toMap() => { + 'id': id, + 'name': name, + 'registrationPlate': registrationPlate, + 'fuelType': fuelType.index, + 'note': note, + 'isDefault': isDefault, + }; + + factory Vehicle.fromMap(Map map) { + return Vehicle( + id: map['id'] as String?, + name: map['name'] as String, + registrationPlate: map['registrationPlate'] as String, + fuelType: map['fuelType'] is int + ? FuelTypeX.fromIndex(map['fuelType'] as int) + : FuelType.values + .firstWhere((e) => e.name == map['fuelType'] as String), + note: map['note'] as String?, + isDefault: map['isDefault'] as bool? ?? false, + ); + } + + String toJson() => jsonEncode(toMap()); + factory Vehicle.fromJson(String source) => Vehicle.fromMap(jsonDecode(source)); +} diff --git a/lib/screens/add_screen.dart b/lib/screens/add_screen.dart new file mode 100644 index 0000000..35451df --- /dev/null +++ b/lib/screens/add_screen.dart @@ -0,0 +1,279 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../models/vehicle.dart'; +import '../models/refuel.dart'; +import '../services/session_manager.dart'; +import 'add_service_screen.dart'; + +class AddScreen extends StatefulWidget { + final Refuel? refuel; + final VoidCallback? onSaved; + final bool standalone; + + AddScreen({this.refuel, this.onSaved, this.standalone = false}); + + @override + _AddScreenState createState() => _AddScreenState(); +} + +class _AddScreenState extends State { + final _formKey = GlobalKey(); + + String? _selectedVehicleId; + FuelType? _selectedFuelType; + final TextEditingController _litersController = TextEditingController(); + final TextEditingController _pricePerLiterController = + TextEditingController(); + final TextEditingController _totalPriceController = TextEditingController(); + final TextEditingController _mileageController = TextEditingController(); + final TextEditingController _noteController = TextEditingController(); + + final FocusNode _litersFocus = FocusNode(); + final FocusNode _pricePerLiterFocus = FocusNode(); + final FocusNode _totalPriceFocus = FocusNode(); + + bool _initialized = false; + bool _isRecalculating = false; + + @override + void initState() { + super.initState(); + _litersController.addListener(_recalculate); + _pricePerLiterController.addListener(_recalculate); + _totalPriceController.addListener(_recalculate); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + if (_initialized) return; + final session = Provider.of(context); + if (widget.refuel != null) { + final r = widget.refuel!; + _selectedVehicleId = r.vehicleId; + _selectedFuelType = r.fuelType; + _litersController.text = r.liters.toString(); + _pricePerLiterController.text = r.pricePerLiter.toString(); + _totalPriceController.text = r.totalPrice.toString(); + _mileageController.text = r.mileage.toString(); + if (r.note != null) _noteController.text = r.note!; + } else { + _selectedVehicleId = session.defaultVehicle?.id; + _selectedFuelType = session.defaultVehicle?.fuelType; + } + _initialized = true; + } + + @override + Widget build(BuildContext context) { + final session = Provider.of(context); + final vehicles = session.vehicles; + + final form = Padding( + padding: const EdgeInsets.all(16.0), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonFormField( + decoration: InputDecoration(labelText: 'Vehicle'), + value: _selectedVehicleId, + items: vehicles + .map( + (vehicle) => DropdownMenuItem( + value: vehicle.id, + child: Text(vehicle.name), + ), + ) + .toList(), + onChanged: (value) { + setState(() { + _selectedVehicleId = value; + final vehicle = vehicles.firstWhere((v) => v.id == value); + _selectedFuelType = vehicle.fuelType; + }); + }, + validator: + (value) => value == null ? 'Please select a vehicle' : null, + ), + SizedBox(height: 16), + DropdownButtonFormField( + decoration: InputDecoration(labelText: 'Fuel Type'), + value: _selectedFuelType, + items: FuelType.values + .map((fuel) => DropdownMenuItem( + value: fuel, + child: Text(fuel.label), + )) + .toList(), + onChanged: (value) => setState(() => _selectedFuelType = value), + validator: + (value) => value == null ? 'Please select a fuel type' : null, + ), + SizedBox(height: 16), + TextFormField( + controller: _litersController, + focusNode: _litersFocus, + decoration: InputDecoration(labelText: 'Liters'), + keyboardType: TextInputType.number, + validator: _numberValidator, + ), + SizedBox(height: 16), + TextFormField( + controller: _pricePerLiterController, + focusNode: _pricePerLiterFocus, + decoration: InputDecoration(labelText: 'Price per Liter'), + keyboardType: TextInputType.number, + validator: _numberValidator, + ), + SizedBox(height: 16), + TextFormField( + controller: _totalPriceController, + focusNode: _totalPriceFocus, + decoration: InputDecoration(labelText: 'Total Price'), + keyboardType: TextInputType.number, + validator: _numberValidator, + ), + SizedBox(height: 16), + TextFormField( + controller: _mileageController, + decoration: InputDecoration(labelText: 'Mileage'), + keyboardType: TextInputType.number, + validator: _numberValidator, + ), + SizedBox(height: 16), + TextFormField( + controller: _noteController, + decoration: InputDecoration(labelText: 'Note'), + keyboardType: TextInputType.text, + ), + SizedBox(height: 24), + ElevatedButton( + onPressed: _submitForm, + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + ), + child: Text(widget.refuel == null + ? 'Create Fuel Record' + : 'Update Fuel Record'), + ), + if (!widget.standalone) ...[ + SizedBox(height: 16), + ElevatedButton.icon( + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => AddServiceScreen(standalone: true), + ), + ); + }, + icon: Icon(Icons.build), + label: Text('Add Service Record'), + ), + ], + ], + ), + ), + ), + ); + + if (widget.standalone) { + return Scaffold( + appBar: AppBar( + title: Text(widget.refuel == null + ? 'Add Refuel Record' + : 'Edit Refuel Record'), + ), + body: form, + ); + } + + return form; + } + + String? _numberValidator(String? value) { + if (value == null || value.isEmpty) return 'This field cannot be empty'; + if (double.tryParse(value) == null) return 'Enter a valid number'; + return null; + } + + void _recalculate() { + if (_isRecalculating) return; + + final liters = double.tryParse(_litersController.text); + final price = double.tryParse(_pricePerLiterController.text); + final total = double.tryParse(_totalPriceController.text); + + _isRecalculating = true; + + if (!_totalPriceFocus.hasFocus && liters != null && price != null) { + _totalPriceController.text = (liters * price).toStringAsFixed(2); + } else if (!_pricePerLiterFocus.hasFocus && liters != null && total != null) { + _pricePerLiterController.text = (total / liters).toStringAsFixed(2); + } else if (!_litersFocus.hasFocus && price != null && total != null) { + _litersController.text = (total / price).toStringAsFixed(2); + } + + _isRecalculating = false; + } + + void _submitForm() async { + if (!(_formKey.currentState?.validate() ?? false)) return; + final session = Provider.of(context, listen: false); + final refuel = Refuel( + id: widget.refuel?.id, + vehicleId: _selectedVehicleId!, + fuelType: _selectedFuelType!, + liters: double.parse(_litersController.text), + pricePerLiter: double.parse(_pricePerLiterController.text), + totalPrice: double.parse(_totalPriceController.text), + mileage: int.parse(_mileageController.text), + note: _noteController.text.isEmpty ? null : _noteController.text, + ); + + if (widget.refuel == null) { + await session.addRefuel(refuel); + } else if (widget.refuel!.id != null) { + await session.updateRefuel(widget.refuel!.id!, refuel); + } + + if (!mounted) return; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Fuel record saved successfully!')), + ); + _formKey.currentState?.reset(); + setState(() { + _selectedVehicleId = session.defaultVehicle?.id; + _selectedFuelType = session.defaultVehicle?.fuelType; + }); + _litersController.clear(); + _pricePerLiterController.clear(); + _totalPriceController.clear(); + _mileageController.clear(); + _noteController.clear(); + + if (Navigator.canPop(context)) { + Navigator.pop(context); + } else { + widget.onSaved?.call(); + } + } + + @override + void dispose() { + _litersController.dispose(); + _pricePerLiterController.dispose(); + _totalPriceController.dispose(); + _mileageController.dispose(); + _noteController.dispose(); + _litersFocus.dispose(); + _pricePerLiterFocus.dispose(); + _totalPriceFocus.dispose(); + super.dispose(); + } +} diff --git a/lib/screens/add_service_screen.dart b/lib/screens/add_service_screen.dart new file mode 100644 index 0000000..fbc09ca --- /dev/null +++ b/lib/screens/add_service_screen.dart @@ -0,0 +1,371 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:image/image.dart' as img; +import 'package:image_picker/image_picker.dart'; +import 'package:provider/provider.dart'; + +import '../models/service.dart'; +import '../models/vehicle.dart'; +import '../services/session_manager.dart'; + +enum _ServicePerformer { shop, self } + +class AddServiceScreen extends StatefulWidget { + final ServiceRecord? service; + final VoidCallback? onSaved; + final bool standalone; + + AddServiceScreen({this.service, this.onSaved, this.standalone = false}); + + @override + _AddServiceScreenState createState() => _AddServiceScreenState(); +} + +class _AddServiceScreenState extends State { + final _formKey = GlobalKey(); + + String? _selectedVehicleId; + ServiceType? _selectedType; + final TextEditingController _customTypeController = TextEditingController(); + final TextEditingController _itemNameController = TextEditingController(); + final TextEditingController _costController = TextEditingController(); + final TextEditingController _mileageController = TextEditingController(); + final TextEditingController _shopController = TextEditingController(); + _ServicePerformer _performer = _ServicePerformer.shop; + final TextEditingController _noteController = TextEditingController(); + final List _photos = []; + DateTime? _selectedDate; + final TextEditingController _dateController = TextEditingController(); + + bool _initialized = false; + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + if (_initialized) return; + final session = Provider.of(context); + if (widget.service != null) { + final s = widget.service!; + _selectedVehicleId = s.vehicleId; + _selectedType = s.serviceType; + if (s.customType != null) _customTypeController.text = s.customType!; + if (s.itemName != null) _itemNameController.text = s.itemName!; + _costController.text = s.cost.toString(); + _mileageController.text = s.mileage.toString(); + if (s.selfService) { + _performer = _ServicePerformer.self; + } else { + _performer = _ServicePerformer.shop; + if (s.shop != null) _shopController.text = s.shop!; + } + if (s.note != null) _noteController.text = s.note!; + for (final p in s.photos) { + try { + final data = p.contains(',') ? p.split(',').last : p; + _photos.add(base64Decode(data)); + } catch (_) {} + } + _selectedDate = s.date; + if (s.date != null) { + _dateController.text = _formatDate(s.date!); + } + } else { + _selectedVehicleId = session.defaultVehicle?.id; + } + _initialized = true; + } + + String _formatDate(DateTime date) { + final d = date.toLocal(); + return '${d.year.toString().padLeft(4, '0')}-${d.month.toString().padLeft(2, '0')}-${d.day.toString().padLeft(2, '0')}'; + } + + @override + Widget build(BuildContext context) { + final session = Provider.of(context); + final vehicles = session.vehicles; + + final form = Padding( + padding: const EdgeInsets.all(16.0), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + DropdownButtonFormField( + decoration: InputDecoration(labelText: 'Vehicle'), + value: _selectedVehicleId, + items: vehicles + .map((vehicle) => DropdownMenuItem( + value: vehicle.id, + child: Text(vehicle.name), + )) + .toList(), + onChanged: (value) => setState(() => _selectedVehicleId = value), + validator: (value) => + value == null ? 'Please select a vehicle' : null, + ), + SizedBox(height: 16), + DropdownButtonFormField( + decoration: InputDecoration(labelText: 'Service Type'), + value: _selectedType, + items: ServiceType.values + .map((t) => DropdownMenuItem( + value: t, + child: Text(t.label), + )) + .toList(), + onChanged: (value) => setState(() => _selectedType = value), + validator: (value) => + value == null ? 'Please select a service type' : null, + ), + if (_selectedType == ServiceType.other) ...[ + SizedBox(height: 16), + TextFormField( + controller: _customTypeController, + decoration: InputDecoration(labelText: 'Custom Type'), + validator: (v) => + v == null || v.isEmpty ? 'Enter custom type' : null, + ), + ], + SizedBox(height: 16), + TextFormField( + controller: _itemNameController, + decoration: InputDecoration(labelText: 'Item Name'), + ), + SizedBox(height: 16), + TextFormField( + controller: _costController, + decoration: InputDecoration(labelText: 'Cost'), + keyboardType: TextInputType.number, + validator: _numberValidator, + ), + SizedBox(height: 16), + TextFormField( + controller: _mileageController, + decoration: InputDecoration(labelText: 'Mileage'), + keyboardType: TextInputType.number, + validator: _numberValidator, + ), + SizedBox(height: 16), + RadioListTile<_ServicePerformer>( + value: _ServicePerformer.shop, + groupValue: _performer, + title: Text('Performed at shop'), + onChanged: (v) => setState(() => _performer = v!), + ), + RadioListTile<_ServicePerformer>( + value: _ServicePerformer.self, + groupValue: _performer, + title: Text('Self Service'), + onChanged: (v) => setState(() { + _performer = v!; + _shopController.clear(); + }), + ), + if (_performer == _ServicePerformer.shop) ...[ + SizedBox(height: 16), + TextFormField( + controller: _shopController, + decoration: InputDecoration(labelText: 'Shop'), + validator: (v) => + v == null || v.isEmpty ? 'Enter shop name' : null, + ), + ], + SizedBox(height: 16), + TextFormField( + controller: _noteController, + decoration: InputDecoration(labelText: 'Note'), + ), + if (_photos.isNotEmpty) ...[ + SizedBox(height: 16), + Wrap( + spacing: 8, + runSpacing: 8, + children: List.generate(_photos.length, (i) { + return Stack( + children: [ + Image.memory( + _photos[i], + width: 80, + height: 80, + fit: BoxFit.cover, + ), + Positioned( + right: 0, + top: 0, + child: GestureDetector( + onTap: () => setState(() => _photos.removeAt(i)), + child: Container( + color: Colors.black54, + child: Icon(Icons.close, color: Colors.white, size: 20), + ), + ), + ), + ], + ); + }), + ), + ], + SizedBox(height: 16), + TextButton.icon( + onPressed: _pickPhoto, + icon: Icon(Icons.add_a_photo), + label: Text('Add Photo'), + ), + SizedBox(height: 16), + TextFormField( + controller: _dateController, + decoration: InputDecoration(labelText: 'Date'), + readOnly: true, + onTap: () async { + final now = DateTime.now(); + final picked = await showDatePicker( + context: context, + initialDate: _selectedDate ?? now, + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + if (picked != null) { + setState(() { + _selectedDate = picked; + _dateController.text = _formatDate(picked); + }); + } + }, + validator: (v) => _selectedDate == null ? 'Select a date' : null, + ), + SizedBox(height: 24), + ElevatedButton( + onPressed: _submitForm, + style: ElevatedButton.styleFrom(backgroundColor: Colors.green), + child: Text(widget.service == null + ? 'Create Service Record' + : 'Update Service Record'), + ), + ], + ), + ), + ), + ); + + if (widget.standalone) { + return Scaffold( + appBar: AppBar( + title: Text(widget.service == null + ? 'Add Service Record' + : 'Edit Service Record'), + ), + body: form, + ); + } + return form; + } + + Future _pickPhoto() async { + final picker = ImagePicker(); + final source = await showModalBottomSheet( + context: context, + builder: (context) => SafeArea( + child: Wrap( + children: [ + ListTile( + leading: Icon(Icons.camera_alt), + title: Text('Take Photo'), + onTap: () => Navigator.pop(context, ImageSource.camera), + ), + ListTile( + leading: Icon(Icons.photo_library), + title: Text('Choose from Gallery'), + onTap: () => Navigator.pop(context, ImageSource.gallery), + ), + ], + ), + ), + ); + if (source == null) return; + final file = await picker.pickImage(source: source); + if (file == null) return; + var bytes = await file.readAsBytes(); + final decoded = img.decodeImage(bytes); + if (decoded != null) { + const maxDim = 800; + img.Image resized; + if (decoded.width > decoded.height) { + resized = img.copyResize(decoded, width: maxDim); + } else { + resized = img.copyResize(decoded, height: maxDim); + } + bytes = Uint8List.fromList(img.encodeJpg(resized, quality: 70)); + } + setState(() => _photos.add(bytes)); + } + + String? _numberValidator(String? value) { + if (value == null || value.isEmpty) return 'This field cannot be empty'; + if (double.tryParse(value) == null) return 'Enter a valid number'; + return null; + } + + Future _submitForm() async { + if (!(_formKey.currentState?.validate() ?? false)) return; + final session = Provider.of(context, listen: false); + final service = ServiceRecord( + id: widget.service?.id, + vehicleId: _selectedVehicleId!, + serviceType: _selectedType!, + customType: _selectedType == ServiceType.other + ? _customTypeController.text + : null, + itemName: _itemNameController.text.isEmpty + ? null + : _itemNameController.text, + cost: double.parse(_costController.text), + mileage: int.parse(_mileageController.text), + shop: _performer == _ServicePerformer.shop ? _shopController.text : null, + selfService: _performer == _ServicePerformer.self, + note: _noteController.text.isEmpty ? null : _noteController.text, + photos: _photos.map((b) => base64Encode(b)).toList(), + date: _selectedDate, + ); + + bool success = false; + if (widget.service == null) { + success = await session.addService(service); + } else if (widget.service!.id != null) { + success = await session.updateService(widget.service!.id!, service); + } + + if (!mounted) return; + + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(success + ? 'Service record saved successfully!' + : 'Failed to save service record.')), + ); + + if (success) { + if (Navigator.canPop(context)) { + Navigator.pop(context); + } else { + widget.onSaved?.call(); + } + } + } + + @override + void dispose() { + _customTypeController.dispose(); + _itemNameController.dispose(); + _costController.dispose(); + _mileageController.dispose(); + _shopController.dispose(); + _noteController.dispose(); + _dateController.dispose(); + super.dispose(); + } +} diff --git a/lib/screens/history_screen.dart b/lib/screens/history_screen.dart new file mode 100644 index 0000000..d6055d9 --- /dev/null +++ b/lib/screens/history_screen.dart @@ -0,0 +1,428 @@ +import 'dart:ui'; +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../models/refuel.dart'; +import '../models/service.dart'; +import '../models/vehicle.dart'; +import '../services/session_manager.dart'; +import 'add_screen.dart'; +import 'add_service_screen.dart'; +import '../config.dart'; + +class HistoryScreen extends StatefulWidget { + @override + _HistoryScreenState createState() => _HistoryScreenState(); +} + +class _HistoryScreenState extends State { + final TextEditingController _searchController = TextEditingController(); + String _filter = 'all'; + String _search = ''; + + @override + void dispose() { + _searchController.dispose(); + super.dispose(); + } + + String _formatNumber(num value) { + if (value % 1 == 0) { + return value.toInt().toString(); + } + return value + .toStringAsFixed(2) + .replaceFirst(RegExp(r'0+$'), '') + .replaceFirst(RegExp(r'[.]$'), ''); + } + + String _formatCurrency(num value) => '${_formatNumber(value)},-'; + + String _formatDateTime(DateTime? date) { + if (date == null) return ''; + final d = date.toLocal(); + final day = d.day.toString().padLeft(2, '0'); + final month = d.month.toString().padLeft(2, '0'); + final hour = d.hour.toString().padLeft(2, '0'); + final minute = d.minute.toString().padLeft(2, '0'); + return '$day.$month.${d.year} $hour:$minute'; + } + + TableRow _detailRow(String label, String value) { + return TableRow( + children: [ + Padding( + padding: const EdgeInsets.only(top: 2, bottom: 2, right: 16), + child: Text(label, style: TextStyle(fontWeight: FontWeight.bold)), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 2), + child: Text(value), + ), + ], + ); + } + + void _showFullImage(BuildContext context, String p) { + Widget img; + if (p.startsWith('http') || p.startsWith('/')) { + final url = p.startsWith('http') ? p : '$apiBaseUrl$p'; + img = Image.network(url); + } else { + try { + img = Image.memory(base64Decode(p)); + } catch (_) { + return; + } + } + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => Scaffold( + backgroundColor: Colors.black, + body: GestureDetector( + onTap: () => Navigator.pop(context), + child: Center(child: InteractiveViewer(child: img)), + ), + ), + ), + ); + } + + bool _matchesSearch(Refuel? r, ServiceRecord? s) { + final q = _search.toLowerCase(); + if (q.isEmpty) return true; + if (r != null) { + return (r.note ?? '').toLowerCase().contains(q) || + r.fuelType.label.toLowerCase().contains(q); + } else if (s != null) { + return s.displayType.toLowerCase().contains(q) || + (s.note ?? '').toLowerCase().contains(q) || + (s.shop ?? '').toLowerCase().contains(q); + } + return false; + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, session, _) { + final items = <_HistoryItem>[]; + for (final r in session.refuels) { + items.add(_HistoryItem(date: r.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0), refuel: r)); + } + for (final s in session.services) { + items.add(_HistoryItem(date: s.date ?? s.createdAt ?? DateTime.fromMillisecondsSinceEpoch(0), service: s)); + } + items.sort((a, b) => b.date.compareTo(a.date)); + + final filtered = items.where((i) { + if (_filter == 'refuel' && i.refuel == null) return false; + if (_filter == 'service' && i.service == null) return false; + return _matchesSearch(i.refuel, i.service); + }).toList(); + + return Scaffold( + body: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: TextField( + controller: _searchController, + decoration: InputDecoration( + prefixIcon: Icon(Icons.search), + hintText: 'Search...', + ), + onChanged: (v) => setState(() => _search = v), + ), + ), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: Row( + children: [ + const SizedBox(width: 8), + ChoiceChip( + label: Text('All'), + selected: _filter == 'all', + onSelected: (_) => setState(() => _filter = 'all'), + ), + const SizedBox(width: 8), + ChoiceChip( + label: Text('Refuels'), + selected: _filter == 'refuel', + onSelected: (_) => setState(() => _filter = 'refuel'), + ), + const SizedBox(width: 8), + ChoiceChip( + label: Text('Services'), + selected: _filter == 'service', + onSelected: (_) => setState(() => _filter = 'service'), + ), + const SizedBox(width: 8), + ], + ), + ), + Expanded( + child: filtered.isEmpty + ? Center(child: Text('No history yet')) + : ListView.builder( + itemCount: filtered.length, + itemBuilder: (context, index) { + final item = filtered[index]; + if (item.refuel != null) { + final r = item.refuel!; + final textStyle = const TextStyle( + fontFeatures: [FontFeature.tabularFigures()]); + return ListTile( + leading: Icon(Icons.local_gas_station, color: Colors.green), + title: Row( + children: [ + Expanded( + child: Text( + '${_formatNumber(r.liters)} L', + style: textStyle, + ), + ), + Expanded( + child: Text( + '${_formatCurrency(r.pricePerLiter)}/L', + textAlign: TextAlign.center, + style: textStyle, + ), + ), + Expanded( + child: Text( + _formatCurrency(r.totalPrice), + textAlign: TextAlign.end, + style: textStyle, + ), + ), + ], + ), + subtitle: Text(_formatDateTime(r.createdAt), style: textStyle), + onTap: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Refuel Details'), + content: Table( + columnWidths: {0: IntrinsicColumnWidth()}, + children: [ + _detailRow('Total', _formatCurrency(r.totalPrice)), + _detailRow('Price/L', '${_formatCurrency(r.pricePerLiter)}'), + _detailRow('Liters', '${_formatNumber(r.liters)} L'), + _detailRow('Mileage', '${_formatNumber(r.mileage)} km'), + if (r.note != null && r.note!.isNotEmpty) + _detailRow('Note', r.note!), + _detailRow('Date', _formatDateTime(r.createdAt)), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text('Close'), + ), + ], + ), + ); + }, + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: Icon(Icons.edit, color: Colors.blue), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => AddScreen(refuel: r, standalone: true), + ), + ); + }, + ), + if (r.id != null) + IconButton( + icon: Icon(Icons.delete, color: Colors.red), + onPressed: () async { + final confirm = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Confirm Deletion'), + content: Text('Are you sure you want to delete this record?'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context, false), + child: Text('Cancel'), + ), + TextButton( + onPressed: () => Navigator.pop(context, true), + child: Text('Delete'), + ), + ], + ), + ); + if (confirm == true) { + await session.removeRefuel(r.id!); + } + }, + ), + ], + ), + ); + } else { + final s = item.service!; + final textStyle = const TextStyle( + fontFeatures: [FontFeature.tabularFigures()]); + return ListTile( + leading: Icon(Icons.build, color: Colors.orangeAccent), + title: Row( + children: [ + Expanded( + child: Text( + s.displayType, + style: textStyle, + ), + ), + Expanded( + child: Text( + _formatCurrency(s.cost), + textAlign: TextAlign.end, + style: textStyle, + ), + ), + ], + ), + subtitle: Text(_formatDateTime(s.date), style: textStyle), + onTap: () { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Service Details'), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Table( + columnWidths: {0: IntrinsicColumnWidth()}, + children: [ + _detailRow('Type', s.displayType), + _detailRow('Cost', _formatCurrency(s.cost)), + _detailRow('Mileage', '${_formatNumber(s.mileage)} km'), + if (s.shop != null && s.shop!.isNotEmpty) + _detailRow('Shop', s.shop!), + _detailRow('Self service', s.selfService ? 'Yes' : 'No'), + if (s.note != null && s.note!.isNotEmpty) + _detailRow('Note', s.note!), + _detailRow('Date', _formatDateTime(s.date)), + ], + ), + if (s.photos.isNotEmpty) ...[ + SizedBox(height: 12), + Wrap( + spacing: 8, + runSpacing: 8, + children: s.photos.map((p) { + Widget img; + if (p.startsWith('http') || p.startsWith('/')) { + final url = + p.startsWith('http') ? p : '$apiBaseUrl$p'; + img = Image.network( + url, + width: 100, + height: 100, + fit: BoxFit.cover, + ); + } else { + try { + img = Image.memory( + base64Decode(p), + width: 100, + height: 100, + fit: BoxFit.cover, + ); + } catch (_) { + img = SizedBox.shrink(); + } + } + return GestureDetector( + onTap: () => _showFullImage(context, p), + child: img, + ); + }).toList(), + ), + ], + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text('Close'), + ), + ], + ), + ); + }, + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: Icon(Icons.edit, color: Colors.blue), + onPressed: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (_) => AddServiceScreen(service: s, standalone: true), + ), + ); + }, + ), + if (s.id != null) + IconButton( + icon: Icon(Icons.delete, color: Colors.red), + onPressed: () async { + final confirm = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Confirm Deletion'), + content: Text('Are you sure you want to delete this record?'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context, false), + child: Text('Cancel'), + ), + TextButton( + onPressed: () => Navigator.pop(context, true), + child: Text('Delete'), + ), + ], + ), + ); + if (confirm == true) { + await session.removeService(s.id!); + } + }, + ), + ], + ), + ); + } + }, + ), + ), + ], + ), + ); + }, + ); + } +} + +class _HistoryItem { + final DateTime date; + final Refuel? refuel; + final ServiceRecord? service; + _HistoryItem({required this.date, this.refuel, this.service}); +} diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart new file mode 100644 index 0000000..88a10d2 --- /dev/null +++ b/lib/screens/home_screen.dart @@ -0,0 +1,196 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../models/refuel.dart'; +import '../services/session_manager.dart'; +import '../widgets/stat_card.dart'; +import '../widgets/gas_price_chart.dart'; +import '../widgets/consumption_chart.dart'; + +class HomeScreen extends StatelessWidget { + const HomeScreen({super.key}); + + String _formatDouble(double value) { + var s = value.toStringAsFixed(2); + if (s.endsWith('.00')) { + s = s.substring(0, s.length - 3); + } else if (s.endsWith('0')) { + s = s.substring(0, s.length - 1); + } + return s; + } + + double? _allTimeConsumption(List refuels) { + if (refuels.length < 2) return null; + final distance = refuels.last.mileage - refuels.first.mileage; + if (distance <= 0) return null; + final liters = + refuels.skip(1).fold(0.0, (sum, r) => sum + r.liters); + return liters / distance * 100; + } + + double? _lastConsumption(List refuels) { + if (refuels.length < 2) return null; + final last = refuels[refuels.length - 1]; + final prev = refuels[refuels.length - 2]; + final distance = last.mileage - prev.mileage; + if (distance <= 0) return null; + return last.liters / distance * 100; + } + + int? _kmSinceLast(List refuels) { + if (refuels.length < 2) return null; + return refuels.last.mileage - refuels[refuels.length - 2].mileage; + } + + int _kmForPeriod(List refuels, DateTime from) { + final list = refuels + .where((r) => r.createdAt != null && r.createdAt!.isAfter(from)) + .toList(); + if (list.length < 2) return 0; + return list.last.mileage - list.first.mileage; + } + + int _kmAllTime(List refuels) { + if (refuels.length < 2) return 0; + return refuels.last.mileage - refuels.first.mileage; + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, session, _) { + final vehicle = session.defaultVehicle; + if (vehicle == null) { + return const Scaffold( + body: Center(child: Text('No default vehicle selected')), + ); + } + + final refuels = session.refuels + .where((r) => r.vehicleId == vehicle.id) + .toList(); + refuels.sort((a, b) => a.mileage.compareTo(b.mileage)); + + final allCons = _allTimeConsumption(refuels); + final lastCons = _lastConsumption(refuels); + final kmLast = _kmSinceLast(refuels); + final now = DateTime.now(); + final km1m = _kmForPeriod(refuels, now.subtract(const Duration(days: 30))); + final km6m = + _kmForPeriod(refuels, now.subtract(const Duration(days: 182))); + final km1y = + _kmForPeriod(refuels, now.subtract(const Duration(days: 365))); + final kmAll = _kmAllTime(refuels); + + final lastRefuels = + refuels.length > 14 ? refuels.sublist(refuels.length - 14) : refuels; + + return Scaffold( + body: SafeArea( + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 32), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Card( + color: Theme.of(context).colorScheme.secondaryContainer, + child: ListTile( + leading: const Icon(Icons.directions_car), + title: Text(vehicle.name, + style: const TextStyle(fontWeight: FontWeight.bold)), + subtitle: Text(vehicle.registrationPlate), + trailing: + const Icon(Icons.star, color: Colors.amber), + ), + ), + const SizedBox(height: 16), + const Text('Refuel stats', + style: + TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + GridView.count( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + crossAxisCount: 2, + crossAxisSpacing: 8, + mainAxisSpacing: 8, + childAspectRatio: 2, + children: [ + StatCard( + title: 'Avg consumption (all time)', + value: allCons != null + ? '${_formatDouble(allCons)} L/100km' + : '-', + ), + StatCard( + title: 'Since last refuel', + value: lastCons != null + ? '${_formatDouble(lastCons)} L/100km' + : '-', + ), + ], + ), + const SizedBox(height: 24), + const Text('Kilometers driven', + style: + TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + Builder(builder: (context) { + final kmCards = [ + StatCard( + title: 'Since last refuel', + value: kmLast != null ? '$kmLast km' : '-', + ), + StatCard(title: 'Past month', value: '$km1m km'), + StatCard(title: 'Past 6 months', value: '$km6m km'), + StatCard(title: 'Past year', value: '$km1y km'), + StatCard(title: 'All time', value: '$kmAll km'), + ]; + if (kmCards.length.isOdd) { + kmCards.add(const SizedBox.shrink()); + } + return GridView.count( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + crossAxisCount: 2, + crossAxisSpacing: 8, + mainAxisSpacing: 8, + childAspectRatio: 2, + children: kmCards, + ); + }), + if (lastRefuels.isNotEmpty) ...[ + const SizedBox(height: 24), + Text('Gas price (last ${lastRefuels.length} refuels)', + style: const TextStyle( + fontSize: 18, fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + SizedBox( + height: 220, + child: GasPriceChart(refuels: lastRefuels), + ), + if (lastRefuels.length > 1) ...[ + const SizedBox(height: 24), + const Text('Consumption trend', + style: TextStyle( + fontSize: 18, fontWeight: FontWeight.bold)), + const SizedBox(height: 8), + SizedBox( + height: 220, + child: ConsumptionChart(refuels: lastRefuels), + ), + ], + ], + const SizedBox(height: 8), + ], + ), + ), + ), + ), + ); + }, + ); + } +} + diff --git a/lib/screens/login.dart b/lib/screens/login.dart new file mode 100644 index 0000000..a0f64c9 --- /dev/null +++ b/lib/screens/login.dart @@ -0,0 +1,152 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:provider/provider.dart'; + +import '../config.dart'; +import '../services/session_manager.dart'; + +class LoginScreen extends StatefulWidget { + final VoidCallback onSwitchToSignup; + final VoidCallback onLoginSuccess; + + const LoginScreen({ + required this.onSwitchToSignup, + required this.onLoginSuccess, + super.key, + }); + + @override + State createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State { + final _formKey = GlobalKey(); + final _emailController = TextEditingController(); + final _passwordController = TextEditingController(); + + Future _login() async { + if (_formKey.currentState!.validate()) { + final email = _emailController.text; + final password = _passwordController.text; + + try { + final response = await http.post( + Uri.parse('$apiBaseUrl/api/v1/auth/signin'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'email': email, 'password': password}), + ); + + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + final token = data['token']; + final name = data['user']?['username'] ?? data['username']; + + await Provider.of(context, listen: false).login( + token: token, + email: email, + name: name, + ); + + widget.onLoginSuccess(); + } else { + final data = jsonDecode(response.body); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(data['message'] ?? 'Login failed')), + ); + } + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Login error: $e')), + ); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Padding( + padding: const EdgeInsets.all(24.0), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 40), + ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Image.asset( + 'assets/icon/app_icon.png', + width: 100, + height: 100, + ), + ), + const SizedBox(height: 16), + Text( + 'Log in to Fuel Stats', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 32), + TextFormField( + controller: _emailController, + decoration: InputDecoration( + labelText: 'Email', + prefixIcon: Icon(Icons.email), + border: OutlineInputBorder(), + ), + keyboardType: TextInputType.emailAddress, + validator: (value) { + if (value == null || value.isEmpty) + return 'Please enter your email'; + if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) + return 'Enter a valid email'; + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + controller: _passwordController, + decoration: InputDecoration( + labelText: 'Password', + prefixIcon: Icon(Icons.lock), + border: OutlineInputBorder(), + ), + obscureText: true, + validator: (value) { + if (value == null || value.isEmpty) + return 'Please enter your password'; + if (value.length < 6) + return 'Password must be at least 6 characters'; + return null; + }, + ), + const SizedBox(height: 24), + ElevatedButton.icon( + onPressed: _login, + icon: Icon(Icons.login), + label: Text('Log In'), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.green, + foregroundColor: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 32, vertical: 12), + ), + ), + const SizedBox(height: 12), + TextButton( + onPressed: widget.onSwitchToSignup, + child: Text("Don't have an account? Sign up"), + ), + ], + ), + ), + ), + ), + ); + } +} + diff --git a/lib/screens/signup.dart b/lib/screens/signup.dart new file mode 100644 index 0000000..0d6215c --- /dev/null +++ b/lib/screens/signup.dart @@ -0,0 +1,186 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:provider/provider.dart'; + +import '../config.dart'; +import '../services/session_manager.dart'; + +class SignupScreen extends StatefulWidget { + final VoidCallback onSwitchToLogin; + final VoidCallback onSignupSuccess; + + const SignupScreen({ + required this.onSwitchToLogin, + required this.onSignupSuccess, + super.key, + }); + + @override + State createState() => _SignupScreenState(); +} + +class _SignupScreenState extends State { + final _formKey = GlobalKey(); + final _usernameController = TextEditingController(); + final _emailController = TextEditingController(); + final _passwordController = TextEditingController(); + + Future _signup() async { + if (_formKey.currentState!.validate()) { + final username = _usernameController.text; + final email = _emailController.text; + final password = _passwordController.text; + + try { + final signupResponse = await http.post( + Uri.parse('$apiBaseUrl/api/v1/auth/signup'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'username': username, + 'email': email, + 'password': password, + }), + ); + + if (signupResponse.statusCode == 200 || signupResponse.statusCode == 201) { + final signinResponse = await http.post( + Uri.parse('$apiBaseUrl/api/v1/auth/signin'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'email': email, 'password': password}), + ); + + if (signinResponse.statusCode == 200) { + final data = jsonDecode(signinResponse.body); + final token = data['token']; + final name = data['user']?['username'] ?? data['username'] ?? username; + + await Provider.of(context, listen: false).login( + token: token, + email: email, + name: name, + ); + + widget.onSignupSuccess(); + } else { + final data = jsonDecode(signinResponse.body); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(data['message'] ?? 'Sign in failed')), + ); + } + } else { + final data = jsonDecode(signupResponse.body); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(data['message'] ?? 'Signup failed')), + ); + } + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Signup error: $e')), + ); + } + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + //appBar: AppBar(title: Text('Sign Up')), + body: Padding( + padding: const EdgeInsets.all(24.0), + child: Form( + key: _formKey, + child: SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 40), + ClipRRect( + borderRadius: BorderRadius.circular(20), + child: Image.asset( + 'assets/icon/app_icon.png', + width: 100, + height: 100, + ), + ), + const SizedBox(height: 16), + Text( + 'Create your Fuel Stats account', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + ), + ), + const SizedBox(height: 32), + TextFormField( + controller: _usernameController, + decoration: InputDecoration( + labelText: 'Username', + prefixIcon: Icon(Icons.person), + border: OutlineInputBorder(), + ), + validator: (value) { + if (value == null || value.isEmpty) + return 'Please enter a username'; + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + controller: _emailController, + decoration: InputDecoration( + labelText: 'Email', + prefixIcon: Icon(Icons.email), + border: OutlineInputBorder(), + ), + keyboardType: TextInputType.emailAddress, + validator: (value) { + if (value == null || value.isEmpty) + return 'Please enter an email'; + if (!RegExp(r'^[^@]+@[^@]+\.[^@]+').hasMatch(value)) + return 'Enter a valid email'; + return null; + }, + ), + const SizedBox(height: 16), + TextFormField( + controller: _passwordController, + decoration: InputDecoration( + labelText: 'Password', + prefixIcon: Icon(Icons.lock), + border: OutlineInputBorder(), + ), + obscureText: true, + validator: (value) { + if (value == null || value.isEmpty) + return 'Please enter a password'; + if (value.length < 6) + return 'Password must be at least 6 characters'; + return null; + }, + ), + const SizedBox(height: 24), + ElevatedButton.icon( + onPressed: _signup, + icon: Icon(Icons.person_add), + label: Text('Sign Up'), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.blue, + foregroundColor: Colors.white, + padding: EdgeInsets.symmetric(horizontal: 32, vertical: 12), + ), + ), + const SizedBox(height: 12), + TextButton( + onPressed: widget.onSwitchToLogin, + child: Text("Already have an account? Log in"), + ), + ], + ), + ), + ), + ), + ); + } +} + diff --git a/lib/screens/user_settings.dart b/lib/screens/user_settings.dart new file mode 100644 index 0000000..61cc3ff --- /dev/null +++ b/lib/screens/user_settings.dart @@ -0,0 +1,71 @@ +import 'package:flutter/material.dart'; +import 'package:package_info_plus/package_info_plus.dart'; +import 'package:provider/provider.dart'; +import '../services/session_manager.dart'; + +class UserSettingsScreen extends StatelessWidget { + final VoidCallback onLogout; + + const UserSettingsScreen({required this.onLogout, super.key}); + + Future _getVersion() async { + final info = await PackageInfo.fromPlatform(); + return 'Version: ${info.version}+${info.buildNumber}'; + } + + @override + Widget build(BuildContext context) { + final session = Provider.of(context); + final userName = session.name ?? "Unknown User"; // fallback just in case + final userEmail = session.email ?? ''; + + return Scaffold( + appBar: AppBar(title: Text('User settings')), + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + userName, + style: TextStyle(fontSize: 32, fontWeight: FontWeight.bold), + ), + SizedBox(height: 8), + if (userEmail.isNotEmpty) + Text( + userEmail, + style: TextStyle(fontSize: 16), + ), + SizedBox(height: 20), + ElevatedButton.icon( + onPressed: () async { + await session.logout(); + onLogout(); + }, + icon: Icon(Icons.logout), + label: Text("Sign Out"), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.redAccent, + foregroundColor: Colors.white, + ), + ), + SizedBox(height: 8), + FutureBuilder( + future: _getVersion(), + builder: (context, snapshot) { + if (snapshot.connectionState == ConnectionState.done) { + return Text( + snapshot.data ?? '', + style: TextStyle(color: Colors.grey), + ); + } else { + return SizedBox.shrink(); + } + }, + ), + ], + ), + ), + ); + } +} + diff --git a/lib/screens/vehicles_screen.dart b/lib/screens/vehicles_screen.dart new file mode 100644 index 0000000..9995a8a --- /dev/null +++ b/lib/screens/vehicles_screen.dart @@ -0,0 +1,201 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +import '../models/vehicle.dart'; +import '../services/session_manager.dart'; + +class VehiclesScreen extends StatelessWidget { + @override + Widget build(BuildContext context) { + final session = Provider.of(context); + final vehicles = session.vehicles; + return Scaffold( + body: vehicles.isEmpty + ? Center(child: Text('No vehicles added yet.')) + : ListView.builder( + itemCount: vehicles.length, + itemBuilder: (context, index) { + final vehicle = vehicles[index]; + final isDefault = vehicle.isDefault; + return ListTile( + tileColor: isDefault + ? Theme.of(context).colorScheme.secondaryContainer + : null, + leading: IconButton( + icon: Icon(Icons.star, + color: isDefault ? Colors.amber : Colors.grey), + tooltip: isDefault ? 'Unset default' : 'Set as default', + onPressed: () => session.setDefaultVehicle( + isDefault ? null : vehicle.id), + ), + title: Text(vehicle.name), + subtitle: Text( + '${vehicle.registrationPlate} • ${vehicle.fuelType.label}' + '${vehicle.note != null ? ' • ${vehicle.note}' : ''}', + ), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + icon: Icon(Icons.edit, color: Colors.blue), + onPressed: () => _editVehicle(context, session, index, vehicle), + ), + IconButton( + icon: Icon(Icons.delete, color: Colors.red), + onPressed: () => _removeVehicle(context, session, index), + ), + ], + ), + ); + }, + ), + floatingActionButton: FloatingActionButton( + onPressed: () => _addVehicle(context, session), + child: Icon(Icons.add), + tooltip: 'Add Vehicle', + ), + ); + } + + void _addVehicle(BuildContext context, SessionManager session) async { + final newVehicle = await showDialog( + context: context, + builder: (context) => _VehicleDialog(), + ); + if (newVehicle != null) { + await session.addVehicle(newVehicle); + } + } + + void _editVehicle(BuildContext context, SessionManager session, int index, + Vehicle vehicle) async { + final updatedVehicle = await showDialog( + context: context, + builder: (context) => _VehicleDialog(vehicle: vehicle), + ); + if (updatedVehicle != null) { + await session.updateVehicle(index, updatedVehicle); + } + } + + void _removeVehicle( + BuildContext context, SessionManager session, int index) async { + final confirm = await showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text('Confirm Removal'), + content: Text( + 'Are you sure you want to delete this vehicle? This action cannot be undone.'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context, false), + child: Text('Cancel'), + ), + TextButton( + onPressed: () => Navigator.pop(context, true), + child: Text('Delete'), + ), + ], + ), + ); + + if (confirm == true) { + await session.removeVehicle(index); + } + } +} + +class _VehicleDialog extends StatefulWidget { + final Vehicle? vehicle; + const _VehicleDialog({this.vehicle}); + + @override + _VehicleDialogState createState() => _VehicleDialogState(); +} + +class _VehicleDialogState extends State<_VehicleDialog> { + final _formKey = GlobalKey(); + late TextEditingController _nameController; + late TextEditingController _plateController; + late TextEditingController _noteController; + FuelType? _selectedFuelType; + + @override + void initState() { + super.initState(); + _nameController = TextEditingController(text: widget.vehicle?.name ?? ''); + _plateController = + TextEditingController(text: widget.vehicle?.registrationPlate ?? ''); + _noteController = TextEditingController(text: widget.vehicle?.note ?? ''); + _selectedFuelType = widget.vehicle?.fuelType; + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(widget.vehicle == null ? 'Add New Vehicle' : 'Edit Vehicle'), + content: SingleChildScrollView( + child: Form( + key: _formKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + TextFormField( + controller: _nameController, + decoration: InputDecoration(labelText: 'Vehicle Name'), + validator: (value) => + value == null || value.isEmpty ? 'Enter a vehicle name' : null, + ), + TextFormField( + controller: _plateController, + decoration: InputDecoration(labelText: 'Registration Plate'), + validator: (value) => + value == null || value.isEmpty ? 'Enter a plate number' : null, + ), + DropdownButtonFormField( + decoration: InputDecoration(labelText: 'Fuel Type'), + value: _selectedFuelType, + items: FuelType.values + .map((fuelType) => DropdownMenuItem( + value: fuelType, + child: Text(fuelType.label), + )) + .toList(), + onChanged: (value) => setState(() => _selectedFuelType = value), + validator: (value) => + value == null ? 'Please select a fuel type' : null, + ), + TextFormField( + controller: _noteController, + decoration: InputDecoration(labelText: 'Note (optional)'), + ), + ], + ), + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text('Cancel'), + ), + ElevatedButton( + onPressed: () { + if (_formKey.currentState?.validate() ?? false) { + final vehicle = Vehicle( + id: widget.vehicle?.id, + name: _nameController.text, + registrationPlate: _plateController.text, + fuelType: _selectedFuelType!, + note: + _noteController.text.isEmpty ? null : _noteController.text, + isDefault: widget.vehicle?.isDefault ?? false, + ); + Navigator.pop(context, vehicle); + } + }, + child: Text(widget.vehicle == null ? 'Add' : 'Save'), + ), + ], + ); + } +} diff --git a/lib/services/session_manager.dart b/lib/services/session_manager.dart new file mode 100644 index 0000000..113ec66 --- /dev/null +++ b/lib/services/session_manager.dart @@ -0,0 +1,342 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:http/http.dart' as http; + +import '../config.dart'; + +import '../models/vehicle.dart'; +import '../models/refuel.dart'; +import '../models/service.dart'; + +class SessionManager extends ChangeNotifier { + static final SessionManager _instance = SessionManager._internal(); + factory SessionManager() => _instance; + SessionManager._internal(); + + bool _loggedIn = false; + String? _token; + String? _email; + String? _name; + + List _vehicles = []; + List _refuels = []; + List _services = []; + + bool get isLoggedIn => _loggedIn; + String? get token => _token; + String? get email => _email; + String? get name => _name; + + List get vehicles => List.unmodifiable(_vehicles); + List get refuels => List.unmodifiable(_refuels); + List get services => List.unmodifiable(_services); + Vehicle? get defaultVehicle { + try { + return _vehicles.firstWhere((v) => v.isDefault); + } catch (_) { + return null; + } + } + + final _prefs = SharedPreferencesAsync(); // ✅ New API + + Future init() async { + _token = await _prefs.getString('token'); + _email = await _prefs.getString('email'); + _name = await _prefs.getString('name'); + + if (_token != null) { + final valid = await _validateToken(); + if (valid) { + _loggedIn = true; + await fetchVehicles(); + await fetchRefuels(); + await fetchServices(); + notifyListeners(); + } else { + await logout(); + } + } else { + _loggedIn = false; + notifyListeners(); + } + } + + Future login({ + required String token, + required String email, + String? name, + }) async { + await _prefs.setString('token', token); + await _prefs.setString('email', email); + if (name != null) await _prefs.setString('name', name); + + _token = token; + _email = email; + _name = name; + _loggedIn = true; + + // Ensure we have the latest user info and that the token is valid + await _validateToken(); + + await fetchVehicles(); + await fetchRefuels(); + await fetchServices(); + notifyListeners(); + } + + Future logout() async { + await _prefs.remove('token'); + await _prefs.remove('email'); + await _prefs.remove('name'); + _token = null; + _email = null; + _name = null; + _vehicles.clear(); + _refuels.clear(); + _services.clear(); + _loggedIn = false; + notifyListeners(); + } + + Map _authHeaders() => { + 'Content-Type': 'application/json', + if (_token != null) 'Authorization': 'Bearer $_token', + }; + + Future _validateToken() async { + if (_token == null) return false; + try { + final response = await http.get( + Uri.parse('$apiBaseUrl/api/v1/user/me'), + headers: _authHeaders(), + ); + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + _email = data['email'] ?? _email; + _name = data['username'] ?? data['name'] ?? _name; + if (_email != null) await _prefs.setString('email', _email!); + if (_name != null) await _prefs.setString('name', _name!); + return true; + } + } catch (_) {} + return false; + } + + Future fetchVehicles() async { + try { + final response = await http.get( + Uri.parse('$apiBaseUrl/api/v1/vehicles'), + headers: _authHeaders(), + ); + if (response.statusCode == 200) { + final List data = jsonDecode(response.body); + _vehicles = data.map((e) => Vehicle.fromApi(e)).toList(); + notifyListeners(); + } + } catch (_) { + // ignore for now + } + } + + Future addVehicle(Vehicle vehicle) async { + try { + final response = await http.post( + Uri.parse('$apiBaseUrl/api/v1/vehicles'), + headers: _authHeaders(), + body: jsonEncode(vehicle.toApiMap()), + ); + if (response.statusCode == 200 || response.statusCode == 201) { + final data = jsonDecode(response.body); + _vehicles.add(Vehicle.fromApi(data)); + notifyListeners(); + } + } catch (_) {} + } + + Future updateVehicle(int index, Vehicle vehicle) async { + final id = _vehicles[index].id; + if (id == null) return; + try { + final response = await http.put( + Uri.parse('$apiBaseUrl/api/v1/vehicles/$id'), + headers: _authHeaders(), + body: jsonEncode(vehicle.toApiMap()), + ); + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + _vehicles[index] = Vehicle.fromApi(data); + notifyListeners(); + } + } catch (_) {} + } + + Future removeVehicle(int index) async { + final id = _vehicles[index].id; + if (id == null) return; + try { + final response = await http.delete( + Uri.parse('$apiBaseUrl/api/v1/vehicles/$id'), + headers: _authHeaders(), + ); + if (response.statusCode == 200 || response.statusCode == 204) { + _vehicles.removeAt(index); + notifyListeners(); + } + } catch (_) {} + } + + Future setDefaultVehicle(String? id) async { + if (id == null) { + // Unset default from any vehicle currently marked as default + for (var i = 0; i < _vehicles.length; i++) { + if (_vehicles[i].isDefault) { + await updateVehicle(i, _vehicles[i].copyWith(isDefault: false)); + } + } + } else { + // Clear default flag on all other vehicles first + for (var i = 0; i < _vehicles.length; i++) { + final vehicle = _vehicles[i]; + if (vehicle.isDefault && vehicle.id != id) { + await updateVehicle(i, vehicle.copyWith(isDefault: false)); + } + } + // Finally mark the selected vehicle as default + final idx = _vehicles.indexWhere((v) => v.id == id); + if (idx != -1) { + await updateVehicle(idx, _vehicles[idx].copyWith(isDefault: true)); + } + } + await fetchVehicles(); + } + + // Refuel records + Future fetchRefuels() async { + try { + final response = await http.get( + Uri.parse('$apiBaseUrl/api/v1/refuels'), + headers: _authHeaders(), + ); + if (response.statusCode == 200) { + final List data = jsonDecode(response.body); + _refuels = data.map((e) => Refuel.fromApi(e)).toList(); + notifyListeners(); + } + } catch (_) {} + } + + Future addRefuel(Refuel refuel) async { + try { + final response = await http.post( + Uri.parse('$apiBaseUrl/api/v1/refuels'), + headers: _authHeaders(), + body: jsonEncode(refuel.toApiMap()), + ); + if (response.statusCode == 200 || response.statusCode == 201) { + final data = jsonDecode(response.body); + _refuels.add(Refuel.fromApi(data)); + notifyListeners(); + } + } catch (_) {} + } + + Future updateRefuel(String id, Refuel refuel) async { + try { + final response = await http.put( + Uri.parse('$apiBaseUrl/api/v1/refuels/$id'), + headers: _authHeaders(), + body: jsonEncode(refuel.toApiMap()), + ); + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + final idx = _refuels.indexWhere((r) => r.id == id); + if (idx != -1) { + _refuels[idx] = Refuel.fromApi(data); + notifyListeners(); + } + } + } catch (_) {} + } + + Future removeRefuel(String id) async { + try { + final response = await http.delete( + Uri.parse('$apiBaseUrl/api/v1/refuels/$id'), + headers: _authHeaders(), + ); + if (response.statusCode == 200 || response.statusCode == 204) { + _refuels.removeWhere((r) => r.id == id); + notifyListeners(); + } + } catch (_) {} + } + + // Service records + Future fetchServices() async { + try { + final response = await http.get( + Uri.parse('$apiBaseUrl/api/v1/services'), + headers: _authHeaders(), + ); + if (response.statusCode == 200) { + final List data = jsonDecode(response.body); + _services = data.map((e) => ServiceRecord.fromApi(e)).toList(); + notifyListeners(); + } + } catch (_) {} + } + + Future addService(ServiceRecord service) async { + try { + final response = await http.post( + Uri.parse('$apiBaseUrl/api/v1/services'), + headers: _authHeaders(), + body: jsonEncode(service.toApiMap()), + ); + if (response.statusCode == 200 || response.statusCode == 201) { + final data = jsonDecode(response.body); + _services.add(ServiceRecord.fromApi(data)); + notifyListeners(); + return true; + } + } catch (_) {} + return false; + } + + Future updateService(String id, ServiceRecord service) async { + try { + final response = await http.put( + Uri.parse('$apiBaseUrl/api/v1/services/$id'), + headers: _authHeaders(), + body: jsonEncode(service.toApiMap()), + ); + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + final idx = _services.indexWhere((s) => s.id == id); + if (idx != -1) { + _services[idx] = ServiceRecord.fromApi(data); + notifyListeners(); + } + return true; + } + } catch (_) {} + return false; + } + + Future removeService(String id) async { + try { + final response = await http.delete( + Uri.parse('$apiBaseUrl/api/v1/services/$id'), + headers: _authHeaders(), + ); + if (response.statusCode == 200 || response.statusCode == 204) { + _services.removeWhere((s) => s.id == id); + notifyListeners(); + } + } catch (_) {} + } +} + diff --git a/lib/widgets/consumption_chart.dart b/lib/widgets/consumption_chart.dart new file mode 100644 index 0000000..57dcabd --- /dev/null +++ b/lib/widgets/consumption_chart.dart @@ -0,0 +1,98 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +import '../models/refuel.dart'; + +class ConsumptionChart extends StatelessWidget { + final List refuels; + + const ConsumptionChart({super.key, required this.refuels}); + + @override + Widget build(BuildContext context) { + final spots = []; + final labels = []; + for (var i = 1; i < refuels.length; i++) { + final prev = refuels[i - 1]; + final curr = refuels[i]; + final distance = curr.mileage - prev.mileage; + if (distance <= 0) continue; + final consumption = + double.parse((curr.liters / distance * 100).toStringAsFixed(2)); + spots.add(FlSpot(spots.length.toDouble(), consumption)); + final date = curr.createdAt; + labels.add(date != null ? '${date.month}/${date.day}' : ''); + } + + return LineChart( + LineChartData( + lineBarsData: [ + LineChartBarData( + spots: spots, + isCurved: true, + barWidth: 3, + color: Theme.of(context).colorScheme.secondary, + dotData: const FlDotData(show: true), + ) + ], + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: Colors.black87, + tooltipMargin: 40, + fitInsideHorizontally: true, + fitInsideVertically: true, + getTooltipItems: (spots) => spots + .map((s) => LineTooltipItem( + '${s.y.toStringAsFixed(2)} L/100km', + const TextStyle(color: Colors.white))) + .toList(), + ), + ), + titlesData: FlTitlesData( + leftTitles: AxisTitles( + axisNameSize: 28, + axisNameWidget: const Padding( + padding: EdgeInsets.only(right: 8), + child: Text('L/100km'), + ), + sideTitles: SideTitles( + showTitles: true, + reservedSize: 50, + getTitlesWidget: (value, meta) => Padding( + padding: const EdgeInsets.only(right: 4), + child: Text(value.toStringAsFixed(1), + style: const TextStyle(fontSize: 10)), + ), + ), + ), + bottomTitles: AxisTitles( + axisNameSize: 24, + axisNameWidget: const Padding( + padding: EdgeInsets.only(top: 8), + child: Text('Date'), + ), + sideTitles: SideTitles( + showTitles: true, + reservedSize: 36, + getTitlesWidget: (value, meta) { + final index = value.toInt(); + if (index < 0 || index >= labels.length) { + return const SizedBox.shrink(); + } + return Padding( + padding: const EdgeInsets.only(top: 4), + child: Text(labels[index], + style: const TextStyle(fontSize: 10)), + ); + }, + ), + ), + rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + ), + gridData: const FlGridData(show: false), + borderData: FlBorderData(show: false), + ), + ); + } +} diff --git a/lib/widgets/data_section.dart b/lib/widgets/data_section.dart new file mode 100644 index 0000000..2b0902a --- /dev/null +++ b/lib/widgets/data_section.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; + +class DataSection extends StatelessWidget { + final String title; + + const DataSection({required this.title}); + + @override + Widget build(BuildContext context) { + return Card( + margin: EdgeInsets.all(16), + child: Container( + height: 200, + padding: EdgeInsets.all(16), + child: Center(child: Text(title, style: TextStyle(fontSize: 18))), + ), + ); + } +} diff --git a/lib/widgets/gas_price_chart.dart b/lib/widgets/gas_price_chart.dart new file mode 100644 index 0000000..3d45564 --- /dev/null +++ b/lib/widgets/gas_price_chart.dart @@ -0,0 +1,93 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; + +import '../models/refuel.dart'; + +class GasPriceChart extends StatelessWidget { + final List refuels; + + const GasPriceChart({super.key, required this.refuels}); + + @override + Widget build(BuildContext context) { + final spots = []; + final labels = []; + for (var i = 0; i < refuels.length; i++) { + final refuel = refuels[i]; + spots.add(FlSpot(spots.length.toDouble(), refuel.pricePerLiter)); + final date = refuel.createdAt; + labels.add(date != null ? '${date.month}/${date.day}' : ''); + } + + return LineChart( + LineChartData( + lineBarsData: [ + LineChartBarData( + spots: spots, + isCurved: true, + barWidth: 3, + color: Theme.of(context).colorScheme.primary, + dotData: const FlDotData(show: true), + ) + ], + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + tooltipBgColor: Colors.black87, + tooltipMargin: 40, + fitInsideHorizontally: true, + fitInsideVertically: true, + getTooltipItems: (spots) => spots + .map((s) => LineTooltipItem( + s.y.toStringAsFixed(2), + const TextStyle(color: Colors.white))) + .toList(), + ), + ), + titlesData: FlTitlesData( + leftTitles: AxisTitles( + axisNameSize: 28, + axisNameWidget: const Padding( + padding: EdgeInsets.only(right: 8), + child: Text('Price/L'), + ), + sideTitles: SideTitles( + showTitles: true, + reservedSize: 50, + getTitlesWidget: (value, meta) => Padding( + padding: const EdgeInsets.only(right: 4), + child: Text(value.toStringAsFixed(1), + style: const TextStyle(fontSize: 10)), + ), + ), + ), + bottomTitles: AxisTitles( + axisNameSize: 24, + axisNameWidget: const Padding( + padding: EdgeInsets.only(top: 8), + child: Text('Date'), + ), + sideTitles: SideTitles( + showTitles: true, + reservedSize: 36, + getTitlesWidget: (value, meta) { + final index = value.toInt(); + if (index < 0 || index >= labels.length) { + return const SizedBox.shrink(); + } + return Padding( + padding: const EdgeInsets.only(top: 4), + child: Text(labels[index], + style: const TextStyle(fontSize: 10)), + ); + }, + ), + ), + rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + ), + gridData: const FlGridData(show: false), + borderData: FlBorderData(show: false), + ), + ); + } +} diff --git a/lib/widgets/stat_card.dart b/lib/widgets/stat_card.dart new file mode 100644 index 0000000..0354817 --- /dev/null +++ b/lib/widgets/stat_card.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; + +class StatCard extends StatelessWidget { + final String title; + final String value; + + const StatCard({super.key, required this.title, required this.value}); + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 16), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text( + value, + style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + const SizedBox(height: 2), + Text(title, textAlign: TextAlign.center), + ], + ), + ), + ); + } +} diff --git a/linux/.gitignore b/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000..71e0ab6 --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,128 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "android_fuelstats") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.android_fuelstats") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..d5bd016 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..64a0ece --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) file_selector_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin"); + file_selector_plugin_register_with_registrar(file_selector_linux_registrar); +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..2db3c22 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_linux +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/linux/runner/CMakeLists.txt b/linux/runner/CMakeLists.txt new file mode 100644 index 0000000..e97dabc --- /dev/null +++ b/linux/runner/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the application ID. +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/linux/runner/main.cc b/linux/runner/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/runner/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/runner/my_application.cc b/linux/runner/my_application.cc new file mode 100644 index 0000000..143e1e3 --- /dev/null +++ b/linux/runner/my_application.cc @@ -0,0 +1,130 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "Fuel Stats"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "Fuel Stats"); + } + + gtk_window_set_default_size(window, 1280, 720); + gtk_widget_show(GTK_WIDGET(window)); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments(project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + //MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems + // like GTK and desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); + + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/linux/runner/my_application.h b/linux/runner/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/linux/runner/my_application.h @@ -0,0 +1,18 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, my_application, MY, APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..825c3be --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,16 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import file_selector_macos +import package_info_plus +import shared_preferences_foundation + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) +} diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..45c91aa --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,705 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* android_fuelstats.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "android_fuelstats.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* android_fuelstats.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* android_fuelstats.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.androidFuelstats.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/android_fuelstats.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/android_fuelstats"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.androidFuelstats.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/android_fuelstats.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/android_fuelstats"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.androidFuelstats.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/android_fuelstats.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/android_fuelstats"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.14; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..29815a7 --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..b3c1761 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000000000000000000000000000000000000..82b6f9d9a33e198f5747104729e1fcef999772a5 GIT binary patch literal 102994 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ⅅ8MglG&ER{i5lN315cO?EdHNLrg? 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 z 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 Pe7HEdAEg|=c=LY&YVNkY literal 0 HcmV?d00001 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000000000000000000000000000000000000..13b35eba55c6dabc3aac36f33d859266c18fa0d0 GIT binary patch literal 5680 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 literal 0 HcmV?d00001 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000000000000000000000000000000000000..0a3f5fa40fb3d1e0710331a48de5d256da3f275d GIT binary patch literal 520 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 literal 0 HcmV?d00001 diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000000000000000000000000000000000000..2f1632cfddf3d9dade342351e627a0a75609fb46 GIT binary patch literal 2218 zcmV;b2vzrqP)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91K%fHv1ONa40RR91KmY&$07g+lumAuE6iGxuRCodHTWf3-RTMruyW6Fu zQYeUM04eX6D5c0FCjKKPrco1(K`<0SL=crI{PC3-^hZU0kQie$gh-5!7z6SH6Q0J% zqot*`H1q{R5fHFYS}dje@;kG=v$L0(yY0?wY2%*c?A&{2?!D*x?m71{of2gv!$5|C z3>qG_BW}7K_yUcT3A5C6QD<+{aq?x;MAUyAiJn#Jv8_zZtQ{P zTRzbL3U9!qVuZzS$xKU10KiW~Bgdcv1-!uAhQxf3a7q+dU6lj?yoO4Lq4TUN4}h{N z*fIM=SS8|C2$(T>w$`t@3Tka!(r!7W`x z-isCVgQD^mG-MJ;XtJuK3V{Vy72GQ83KRWsHU?e*wrhKk=ApIYeDqLi;JI1e zuvv}5^Dc=k7F7?nm3nIw$NVmU-+R>> zyqOR$-2SDpJ}Pt;^RkJytDVXNTsu|mI1`~G7yw`EJR?VkGfNdqK9^^8P`JdtTV&tX4CNcV4 z&N06nZa??Fw1AgQOUSE2AmPE@WO(Fvo`%m`cDgiv(fAeRA%3AGXUbsGw{7Q`cY;1BI#ac3iN$$Hw z0LT0;xc%=q)me?Y*$xI@GRAw?+}>=9D+KTk??-HJ4=A>`V&vKFS75@MKdSF1JTq{S zc1!^8?YA|t+uKigaq!sT;Z!&0F2=k7F0PIU;F$leJLaw2UI6FL^w}OG&!;+b%ya1c z1n+6-inU<0VM-Y_s5iTElq)ThyF?StVcebpGI znw#+zLx2@ah{$_2jn+@}(zJZ{+}_N9BM;z)0yr|gF-4=Iyu@hI*Lk=-A8f#bAzc9f z`Kd6K--x@t04swJVC3JK1cHY-Hq+=|PN-VO;?^_C#;coU6TDP7Bt`;{JTG;!+jj(` zw5cLQ-(Cz-Tlb`A^w7|R56Ce;Wmr0)$KWOUZ6ai0PhzPeHwdl0H(etP zUV`va_i0s-4#DkNM8lUlqI7>YQLf)(lz9Q3Uw`)nc(z3{m5ZE77Ul$V%m)E}3&8L0 z-XaU|eB~Is08eORPk;=<>!1w)Kf}FOVS2l&9~A+@R#koFJ$Czd%Y(ENTV&A~U(IPI z;UY+gf+&6ioZ=roly<0Yst8ck>(M=S?B-ys3mLdM&)ex!hbt+ol|T6CTS+Sc0jv(& z7ijdvFwBq;0a{%3GGwkDKTeG`b+lyj0jjS1OMkYnepCdoosNY`*zmBIo*981BU%%U z@~$z0V`OVtIbEx5pa|Tct|Lg#ZQf5OYMUMRD>Wdxm5SAqV2}3!ceE-M2 z@O~lQ0OiKQp}o9I;?uxCgYVV?FH|?Riri*U$Zi_`V2eiA>l zdSm6;SEm6#T+SpcE8Ro_f2AwxzI z44hfe^WE3!h@W3RDyA_H440cpmYkv*)6m1XazTqw%=E5Xv7^@^^T7Q2wxr+Z2kVYr + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..00cf63d --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = android_fuelstats + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.androidFuelstats + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2025 com.example. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..3cc05eb --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..61f3bd1 --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..3711487 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,658 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + archive: + dependency: transitive + description: + name: archive + sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd" + url: "https://pub.dev" + source: hosted + version: "4.0.7" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 + url: "https://pub.dev" + source: hosted + version: "2.12.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + change_app_package_name: + dependency: "direct main" + description: + name: change_app_package_name + sha256: "8e43b754fe960426904d77ed4c62fa8c9834deaf6e293ae40963fa447482c4c5" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + characters: + dependency: transitive + description: + name: characters + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff + url: "https://pub.dev" + source: hosted + version: "2.0.3" + cli_util: + dependency: transitive + description: + name: cli_util + sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c + url: "https://pub.dev" + source: hosted + version: "0.4.2" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" + source: hosted + version: "0.3.4+2" + crypto: + dependency: transitive + description: + name: crypto + sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" + url: "https://pub.dev" + source: hosted + version: "3.0.6" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + equatable: + dependency: transitive + description: + name: equatable + sha256: "567c64b3cb4cf82397aac55f4f0cbd3ca20d77c6c03bedbc4ceaddc08904aef7" + url: "https://pub.dev" + source: hosted + version: "2.0.7" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" + url: "https://pub.dev" + source: hosted + version: "1.3.2" + ffi: + dependency: transitive + description: + name: ffi + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + file_selector_linux: + dependency: transitive + description: + name: file_selector_linux + sha256: "54cbbd957e1156d29548c7d9b9ec0c0ebb6de0a90452198683a7d23aed617a33" + url: "https://pub.dev" + source: hosted + version: "0.9.3+2" + file_selector_macos: + dependency: transitive + description: + name: file_selector_macos + sha256: "19124ff4a3d8864fdc62072b6a2ef6c222d55a3404fe14893a3c02744907b60c" + url: "https://pub.dev" + source: hosted + version: "0.9.4+4" + file_selector_platform_interface: + dependency: transitive + description: + name: file_selector_platform_interface + sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b + url: "https://pub.dev" + source: hosted + version: "2.6.2" + file_selector_windows: + dependency: transitive + description: + name: file_selector_windows + sha256: "320fcfb6f33caa90f0b58380489fc5ac05d99ee94b61aa96ec2bff0ba81d3c2b" + url: "https://pub.dev" + source: hosted + version: "0.9.3+4" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "00b74ae680df6b1135bdbea00a7d1fc072a9180b7c3f3702e4b19a9943f5ed7d" + url: "https://pub.dev" + source: hosted + version: "0.66.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_launcher_icons: + dependency: "direct main" + description: + name: flutter_launcher_icons + sha256: "10f13781741a2e3972126fae08393d3c4e01fa4cd7473326b94b72cf594195e7" + url: "https://pub.dev" + source: hosted + version: "0.14.4" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" + url: "https://pub.dev" + source: hosted + version: "5.0.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: b0694b7fb1689b0e6cc193b3f1fcac6423c4f93c74fb20b806c6b6f196db0c31 + url: "https://pub.dev" + source: hosted + version: "2.0.30" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + sha256: fe7ab022b76f3034adc518fb6ea04a82387620e19977665ea18d30a1cf43442f + url: "https://pub.dev" + source: hosted + version: "1.3.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + image: + dependency: "direct main" + description: + name: image + sha256: "4e973fcf4caae1a4be2fa0a13157aa38a8f9cb049db6529aa00b4d71abc4d928" + url: "https://pub.dev" + source: hosted + version: "4.5.4" + image_picker: + dependency: "direct main" + description: + name: image_picker + sha256: "736eb56a911cf24d1859315ad09ddec0b66104bc41a7f8c5b96b4e2620cf5041" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + image_picker_android: + dependency: transitive + description: + name: image_picker_android + sha256: "28f3987ca0ec702d346eae1d90eda59603a2101b52f1e234ded62cff1d5cfa6e" + url: "https://pub.dev" + source: hosted + version: "0.8.13+1" + image_picker_for_web: + dependency: transitive + description: + name: image_picker_for_web + sha256: "40c2a6a0da15556dc0f8e38a3246064a971a9f512386c3339b89f76db87269b6" + url: "https://pub.dev" + source: hosted + version: "3.1.0" + image_picker_ios: + dependency: transitive + description: + name: image_picker_ios + sha256: eb06fe30bab4c4497bad449b66448f50edcc695f1c59408e78aa3a8059eb8f0e + url: "https://pub.dev" + source: hosted + version: "0.8.13" + image_picker_linux: + dependency: transitive + description: + name: image_picker_linux + sha256: "1f81c5f2046b9ab724f85523e4af65be1d47b038160a8c8deed909762c308ed4" + url: "https://pub.dev" + source: hosted + version: "0.2.2" + image_picker_macos: + dependency: transitive + description: + name: image_picker_macos + sha256: d58cd9d67793d52beefd6585b12050af0a7663c0c2a6ece0fb110a35d6955e04 + url: "https://pub.dev" + source: hosted + version: "0.2.2" + image_picker_platform_interface: + dependency: transitive + description: + name: image_picker_platform_interface + sha256: "9f143b0dba3e459553209e20cc425c9801af48e6dfa4f01a0fcf927be3f41665" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + image_picker_windows: + dependency: transitive + description: + name: image_picker_windows + sha256: d248c86554a72b5495a31c56f060cf73a41c7ff541689327b1a7dbccc33adfae + url: "https://pub.dev" + source: hosted + version: "0.2.2" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" + url: "https://pub.dev" + source: hosted + version: "4.9.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec + url: "https://pub.dev" + source: hosted + version: "10.0.8" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 + url: "https://pub.dev" + source: hosted + version: "3.0.9" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3" + url: "https://pub.dev" + source: hosted + version: "3.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + url: "https://pub.dev" + source: hosted + version: "5.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 + url: "https://pub.dev" + source: hosted + version: "0.12.17" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec + url: "https://pub.dev" + source: hosted + version: "0.11.1" + meta: + dependency: transitive + description: + name: meta + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c + url: "https://pub.dev" + source: hosted + version: "1.16.0" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + package_info_plus: + dependency: "direct main" + description: + name: package_info_plus + sha256: "7976bfe4c583170d6cdc7077e3237560b364149fcd268b5f53d95a991963b191" + url: "https://pub.dev" + source: hosted + version: "8.3.0" + package_info_plus_platform_interface: + dependency: transitive + description: + name: package_info_plus_platform_interface + sha256: "6c935fb612dff8e3cc9632c2b301720c77450a126114126ffaafe28d2e87956c" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + posix: + dependency: transitive + description: + name: posix + sha256: "6323a5b0fa688b6a010df4905a56b00181479e6d10534cecfecede2aa55add61" + url: "https://pub.dev" + source: hosted + version: "6.0.3" + provider: + dependency: "direct main" + description: + name: provider + sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84" + url: "https://pub.dev" + source: hosted + version: "6.1.5" + rename_app: + dependency: "direct main" + description: + name: rename_app + sha256: "387a88335f853674b39bed7943955388bbaf6aae4ffdc812e2ef275ce119abc7" + url: "https://pub.dev" + source: hosted + version: "1.6.5" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5" + url: "https://pub.dev" + source: hosted + version: "2.5.3" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac" + url: "https://pub.dev" + source: hosted + version: "2.4.10" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" + url: "https://pub.dev" + source: hosted + version: "1.10.1" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd + url: "https://pub.dev" + source: hosted + version: "0.7.4" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" + url: "https://pub.dev" + source: hosted + version: "14.3.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + win32: + dependency: transitive + description: + name: win32 + sha256: dc6ecaa00a7c708e5b4d10ee7bec8c270e9276dfcab1783f57e9962d7884305f + url: "https://pub.dev" + source: hosted + version: "5.12.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + xml: + dependency: transitive + description: + name: xml + sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226 + url: "https://pub.dev" + source: hosted + version: "6.5.0" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.7.2 <4.0.0" + flutter: ">=3.29.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..64d65fb --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,108 @@ +name: fuelstats +description: "Application for tracking vehicle fuel consumption and service history" +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: "none" # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0 + +environment: + sdk: ^3.7.2 + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + shared_preferences: ^2.5.3 + provider: ^6.1.5 + http: ^1.2.1 + fl_chart: ^0.66.1 + image_picker: ^1.0.4 + image: ^4.1.7 + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + package_info_plus: ^8.3.0 + rename_app: ^1.6.5 + change_app_package_name: ^1.5.0 + flutter_launcher_icons: ^0.14.4 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^5.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +flutter_launcher_icons: + android: true + ios: true + image_path: "assets/icon/app_icon.png" + adaptive_icon_foreground: "assets/icon/app_icon.png" + adaptive_icon_background: "#FFFFFF" + +# The following section is specific to Flutter packages. +flutter: + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + assets: + - assets/icon/app_icon.png + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..c7c1cbc --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,19 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:provider/provider.dart'; + +import 'package:android_fuelstats/main.dart'; +import 'package:android_fuelstats/services/session_manager.dart'; + +void main() { + testWidgets('shows login screen when not authenticated', (WidgetTester tester) async { + await tester.pumpWidget( + ChangeNotifierProvider( + create: (_) => SessionManager(), + child: FuelStatsApp(), + ), + ); + + expect(find.text('Log in to Fuel Stats'), findsOneWidget); + }); +} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..8aaa46ac1ae21512746f852a42ba87e4165dfdd1 GIT binary patch literal 917 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|I14-?iy0X7 zltGxWVyS%@P(fs7NJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8ErclUHn2 zVXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1AfjnEK zjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf|i<65o z3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp$>4P^%3{)XKjo zGZknv$b36P8?Z_gF{nK@`XI}Z90TzwSQO}0J1!f2c(B=V`5aP@1P1a|PZ!4!3&Gl8 zTYqUsf!gYFyJnXpu0!n&N*SYAX-%d(5gVjrHJWqXQshj@!Zm{!01WsQrH~9=kTxW#6SvuapgMqt>$=j#%eyGrQzr zP{L-3gsMA^$I1&gsBAEL+vxi1*Igl=8#8`5?A-T5=z-sk46WA1IUT)AIZHx1rdUrf zVJrJn<74DDw`j)Ki#gt}mIT-Q`XRa2-jQXQoI%w`nb|XblvzK${ZzlV)m-XcwC(od z71_OEC5Bt9GEXosOXaPTYOia#R4ID2TiU~`zVMl08TV_C%DnU4^+HE>9(CE4D6?Fz oujB08i7adh9xk7*FX66dWH6F5TM;?E2b5PlUHx3vIVCg!0Dx9vYXATM literal 0 HcmV?d00001 diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..b749bfef07473333cf1dd31e9eed89862a5d52aa GIT binary patch literal 5292 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 literal 0 HcmV?d00001 diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..88cfd48dff1169879ba46840804b412fe02fefd6 GIT binary patch literal 8252 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 literal 0 HcmV?d00001 diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9b4d76e525556d5d89141648c724331630325d GIT binary patch literal 5594 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 X>c!)3PgKfL&lX^$Z>Cpu&6)6jvi^Z! literal 0 HcmV?d00001 diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..d69c56691fbdb0b7efa65097c7cc1edac12a6d3e GIT binary patch literal 20998 zcmeFZ_gj-)&^4Nb2tlbLMU<{!p(#yjqEe+=0IA_oih%ScH9@5#MNp&}Y#;;(h=A0@ zh7{>lT2MkSQ344eAvrhici!td|HJuyvJm#Y_w1Q9Yu3!26dNlO-oxUDK_C#XnW^Co z5C{VN6#{~B0)K2j7}*1Xq(Nqemv23A-6&=ZpEijkVnSwVGqLv40?n0=p;k3-U5e5+ z+z3>aS`u9DS=!wg8ROu?X4TFoW6CFLL&{GzoVT)ldhLekLM|+j3tIxRd|*5=c{=s&*vfPdBr(Fyj(v@%eQj1Soy7m4^@VRl1~@-PV7y+c!xz$8436WBn$t{=}mEdK#k`aystimGgI{(IBx$!pAwFoE9Y`^t^;> zKAD)C(Dl^s%`?q5$P|fZf8Xymrtu^Pv(7D`rn>Z-w$Ahs!z9!94WNVxrJuXfHAaxg zC6s@|Z1$7R$(!#t%Jb{{s6(Y?NoQXDYq)!}X@jKPhe`{9KQ@sAU8y-5`xt?S9$jKH zoi}6m5PcG*^{kjvt+kwPpyQzVg4o)a>;LK`aaN2x4@itBD3Aq?yWTM20VRn1rrd+2 zKO=P0rMjEGq_UqpMa`~7B|p?xAN1SCoCp}QxAv8O`jLJ5CVh@umR%c%i^)6!o+~`F zaalSTQcl5iwOLC&H)efzd{8(88mo`GI(56T<(&p7>Qd^;R1hn1Y~jN~tApaL8>##U zd65bo8)79CplWxr#z4!6HvLz&N7_5AN#x;kLG?zQ(#p|lj<8VUlKY=Aw!ATqeL-VG z42gA!^cMNPj>(`ZMEbCrnkg*QTsn*u(nQPWI9pA{MQ=IsPTzd7q5E#7+z>Ch=fx$~ z;J|?(5jTo5UWGvsJa(Sx0?S#56+8SD!I^tftyeh_{5_31l6&Hywtn`bbqYDqGZXI( zCG7hBgvksX2ak8+)hB4jnxlO@A32C_RM&g&qDSb~3kM&)@A_j1*oTO@nicGUyv+%^ z=vB)4(q!ykzT==Z)3*3{atJ5}2PV*?Uw+HhN&+RvKvZL3p9E?gHjv{6zM!A|z|UHK z-r6jeLxbGn0D@q5aBzlco|nG2tr}N@m;CJX(4#Cn&p&sLKwzLFx1A5izu?X_X4x8r@K*d~7>t1~ zDW1Mv5O&WOxbzFC`DQ6yNJ(^u9vJdj$fl2dq`!Yba_0^vQHXV)vqv1gssZYzBct!j zHr9>ydtM8wIs}HI4=E}qAkv|BPWzh3^_yLH(|kdb?x56^BlDC)diWyPd*|f!`^12_U>TD^^94OCN0lVv~Sgvs94ecpE^}VY$w`qr_>Ue zTfH~;C<3H<0dS5Rkf_f@1x$Gms}gK#&k()IC0zb^QbR!YLoll)c$Agfi6MKI0dP_L z=Uou&u~~^2onea2%XZ@>`0x^L8CK6=I{ge;|HXMj)-@o~h&O{CuuwBX8pVqjJ*o}5 z#8&oF_p=uSo~8vn?R0!AMWvcbZmsrj{ZswRt(aEdbi~;HeVqIe)-6*1L%5u$Gbs}| zjFh?KL&U(rC2izSGtwP5FnsR@6$-1toz?RvLD^k~h9NfZgzHE7m!!7s6(;)RKo2z} zB$Ci@h({l?arO+vF;s35h=|WpefaOtKVx>l399}EsX@Oe3>>4MPy%h&^3N_`UTAHJ zI$u(|TYC~E4)|JwkWW3F!Tib=NzjHs5ii2uj0^m|Qlh-2VnB#+X~RZ|`SA*}}&8j9IDv?F;(Y^1=Z0?wWz;ikB zewU>MAXDi~O7a~?jx1x=&8GcR-fTp>{2Q`7#BE#N6D@FCp`?ht-<1|y(NArxE_WIu zP+GuG=Qq>SHWtS2M>34xwEw^uvo4|9)4s|Ac=ud?nHQ>ax@LvBqusFcjH0}{T3ZPQ zLO1l<@B_d-(IS682}5KA&qT1+{3jxKolW+1zL4inqBS-D>BohA!K5++41tM@ z@xe<-qz27}LnV#5lk&iC40M||JRmZ*A##K3+!j93eouU8@q-`W0r%7N`V$cR&JV;iX(@cS{#*5Q>~4BEDA)EikLSP@>Oo&Bt1Z~&0d5)COI%3$cLB_M?dK# z{yv2OqW!al-#AEs&QFd;WL5zCcp)JmCKJEdNsJlL9K@MnPegK23?G|O%v`@N{rIRa zi^7a}WBCD77@VQ-z_v{ZdRsWYrYgC$<^gRQwMCi6);%R~uIi31OMS}=gUTE(GKmCI z$zM>mytL{uNN+a&S38^ez(UT=iSw=l2f+a4)DyCA1Cs_N-r?Q@$3KTYosY!;pzQ0k zzh1G|kWCJjc(oZVBji@kN%)UBw(s{KaYGy=i{g3{)Z+&H8t2`^IuLLKWT6lL<-C(! zSF9K4xd-|VO;4}$s?Z7J_dYqD#Mt)WCDnsR{Kpjq275uUq6`v0y*!PHyS(}Zmv)_{>Vose9-$h8P0|y;YG)Bo}$(3Z%+Gs0RBmFiW!^5tBmDK-g zfe5%B*27ib+7|A*Fx5e)2%kIxh7xWoc3pZcXS2zik!63lAG1;sC1ja>BqH7D zODdi5lKW$$AFvxgC-l-)!c+9@YMC7a`w?G(P#MeEQ5xID#<}W$3bSmJ`8V*x2^3qz zVe<^^_8GHqYGF$nIQm0Xq2kAgYtm#UC1A(=&85w;rmg#v906 zT;RyMgbMpYOmS&S9c38^40oUp?!}#_84`aEVw;T;r%gTZkWeU;;FwM@0y0adt{-OK z(vGnPSlR=Nv2OUN!2=xazlnHPM9EWxXg2EKf0kI{iQb#FoP>xCB<)QY>OAM$Dcdbm zU6dU|%Mo(~avBYSjRc13@|s>axhrPl@Sr81{RSZUdz4(=|82XEbV*JAX6Lfbgqgz584lYgi0 z2-E{0XCVON$wHfvaLs;=dqhQJ&6aLn$D#0i(FkAVrXG9LGm3pSTf&f~RQb6|1_;W> z?n-;&hrq*~L=(;u#jS`*Yvh@3hU-33y_Kv1nxqrsf>pHVF&|OKkoC)4DWK%I!yq?P z=vXo8*_1iEWo8xCa{HJ4tzxOmqS0&$q+>LroMKI*V-rxhOc%3Y!)Y|N6p4PLE>Yek>Y(^KRECg8<|%g*nQib_Yc#A5q8Io z6Ig&V>k|~>B6KE%h4reAo*DfOH)_01tE0nWOxX0*YTJgyw7moaI^7gW*WBAeiLbD?FV9GSB zPv3`SX*^GRBM;zledO`!EbdBO_J@fEy)B{-XUTVQv}Qf~PSDpK9+@I`7G7|>Dgbbu z_7sX9%spVo$%qwRwgzq7!_N;#Td08m5HV#?^dF-EV1o)Q=Oa+rs2xH#g;ykLbwtCh znUnA^dW!XjspJ;otq$yV@I^s9Up(5k7rqhQd@OLMyyxVLj_+$#Vc*}Usevp^I(^vH zmDgHc0VMme|K&X?9&lkN{yq_(If)O`oUPW8X}1R5pSVBpfJe0t{sPA(F#`eONTh_) zxeLqHMfJX#?P(@6w4CqRE@Eiza; z;^5)Kk=^5)KDvd9Q<`=sJU8rjjxPmtWMTmzcH={o$U)j=QBuHarp?=}c??!`3d=H$nrJMyr3L-& zA#m?t(NqLM?I3mGgWA_C+0}BWy3-Gj7bR+d+U?n*mN$%5P`ugrB{PeV>jDUn;eVc- zzeMB1mI4?fVJatrNyq|+zn=!AiN~<}eoM#4uSx^K?Iw>P2*r=k`$<3kT00BE_1c(02MRz4(Hq`L^M&xt!pV2 zn+#U3@j~PUR>xIy+P>51iPayk-mqIK_5rlQMSe5&tDkKJk_$i(X&;K(11YGpEc-K= zq4Ln%^j>Zi_+Ae9eYEq_<`D+ddb8_aY!N;)(&EHFAk@Ekg&41ABmOXfWTo)Z&KotA zh*jgDGFYQ^y=m)<_LCWB+v48DTJw*5dwMm_YP0*_{@HANValf?kV-Ic3xsC}#x2h8 z`q5}d8IRmqWk%gR)s~M}(Qas5+`np^jW^oEd-pzERRPMXj$kS17g?H#4^trtKtq;C?;c ztd|%|WP2w2Nzg@)^V}!Gv++QF2!@FP9~DFVISRW6S?eP{H;;8EH;{>X_}NGj^0cg@ z!2@A>-CTcoN02^r6@c~^QUa={0xwK0v4i-tQ9wQq^=q*-{;zJ{Qe%7Qd!&X2>rV@4 z&wznCz*63_vw4>ZF8~%QCM?=vfzW0r_4O^>UA@otm_!N%mH)!ERy&b!n3*E*@?9d^ zu}s^By@FAhG(%?xgJMuMzuJw2&@$-oK>n z=UF}rt%vuaP9fzIFCYN-1&b#r^Cl6RDFIWsEsM|ROf`E?O(cy{BPO2Ie~kT+^kI^i zp>Kbc@C?}3vy-$ZFVX#-cx)Xj&G^ibX{pWggtr(%^?HeQL@Z( zM-430g<{>vT*)jK4aY9(a{lSy{8vxLbP~n1MXwM527ne#SHCC^F_2@o`>c>>KCq9c(4c$VSyMl*y3Nq1s+!DF| z^?d9PipQN(mw^j~{wJ^VOXDCaL$UtwwTpyv8IAwGOg<|NSghkAR1GSNLZ1JwdGJYm zP}t<=5=sNNUEjc=g(y)1n5)ynX(_$1-uGuDR*6Y^Wgg(LT)Jp><5X|}bt z_qMa&QP?l_n+iVS>v%s2Li_;AIeC=Ca^v1jX4*gvB$?H?2%ndnqOaK5-J%7a} zIF{qYa&NfVY}(fmS0OmXA70{znljBOiv5Yod!vFU{D~*3B3Ka{P8?^ zfhlF6o7aNT$qi8(w<}OPw5fqA7HUje*r*Oa(YV%*l0|9FP9KW@U&{VSW{&b0?@y)M zs%4k1Ax;TGYuZ9l;vP5@?3oQsp3)rjBeBvQQ>^B;z5pc=(yHhHtq6|0m(h4envn_j787fizY@V`o(!SSyE7vlMT zbo=Z1c=atz*G!kwzGB;*uPL$Ei|EbZLh8o+1BUMOpnU(uX&OG1MV@|!&HOOeU#t^x zr9=w2ow!SsTuJWT7%Wmt14U_M*3XiWBWHxqCVZI0_g0`}*^&yEG9RK9fHK8e+S^m? zfCNn$JTswUVbiC#>|=wS{t>-MI1aYPLtzO5y|LJ9nm>L6*wpr_m!)A2Fb1RceX&*|5|MwrvOk4+!0p99B9AgP*9D{Yt|x=X}O% zgIG$MrTB=n-!q%ROT|SzH#A$Xm;|ym)0>1KR}Yl0hr-KO&qMrV+0Ej3d@?FcgZ+B3 ztEk16g#2)@x=(ko8k7^Tq$*5pfZHC@O@}`SmzT1(V@x&NkZNM2F#Q-Go7-uf_zKC( zB(lHZ=3@dHaCOf6C!6i8rDL%~XM@rVTJbZL09?ht@r^Z_6x}}atLjvH^4Vk#Ibf(^LiBJFqorm?A=lE zzFmwvp4bT@Nv2V>YQT92X;t9<2s|Ru5#w?wCvlhcHLcsq0TaFLKy(?nzezJ>CECqj zggrI~Hd4LudM(m{L@ezfnpELsRFVFw>fx;CqZtie`$BXRn#Ns%AdoE$-Pf~{9A8rV zf7FbgpKmVzmvn-z(g+&+-ID=v`;6=)itq8oM*+Uz**SMm_{%eP_c0{<%1JGiZS19o z@Gj7$Se~0lsu}w!%;L%~mIAO;AY-2i`9A*ZfFs=X!LTd6nWOZ7BZH2M{l2*I>Xu)0 z`<=;ObglnXcVk!T>e$H?El}ra0WmPZ$YAN0#$?|1v26^(quQre8;k20*dpd4N{i=b zuN=y}_ew9SlE~R{2+Rh^7%PA1H5X(p8%0TpJ=cqa$65XL)$#ign-y!qij3;2>j}I; ziO@O|aYfn&up5F`YtjGw68rD3{OSGNYmBnl?zdwY$=RFsegTZ=kkzRQ`r7ZjQP!H( zp4>)&zf<*N!tI00xzm-ME_a{_I!TbDCr;8E;kCH4LlL-tqLxDuBn-+xgPk37S&S2^ z2QZumkIimwz!c@!r0)j3*(jPIs*V!iLTRl0Cpt_UVNUgGZzdvs0(-yUghJfKr7;=h zD~y?OJ-bWJg;VdZ^r@vlDoeGV&8^--!t1AsIMZ5S440HCVr%uk- z2wV>!W1WCvFB~p$P$$_}|H5>uBeAe>`N1FI8AxM|pq%oNs;ED8x+tb44E) zTj{^fbh@eLi%5AqT?;d>Es5D*Fi{Bpk)q$^iF!!U`r2hHAO_?#!aYmf>G+jHsES4W zgpTKY59d?hsb~F0WE&dUp6lPt;Pm zcbTUqRryw^%{ViNW%Z(o8}dd00H(H-MmQmOiTq{}_rnwOr*Ybo7*}3W-qBT!#s0Ie z-s<1rvvJx_W;ViUD`04%1pra*Yw0BcGe)fDKUK8aF#BwBwMPU;9`!6E(~!043?SZx z13K%z@$$#2%2ovVlgFIPp7Q6(vO)ud)=*%ZSucL2Dh~K4B|%q4KnSpj#n@(0B})!9 z8p*hY@5)NDn^&Pmo;|!>erSYg`LkO?0FB@PLqRvc>4IsUM5O&>rRv|IBRxi(RX(gJ ztQ2;??L~&Mv;aVr5Q@(?y^DGo%pO^~zijld41aA0KKsy_6FeHIn?fNHP-z>$OoWer zjZ5hFQTy*-f7KENRiCE$ZOp4|+Wah|2=n@|W=o}bFM}Y@0e62+_|#fND5cwa3;P{^pEzlJbF1Yq^}>=wy8^^^$I2M_MH(4Dw{F6hm+vrWV5!q;oX z;tTNhz5`-V={ew|bD$?qcF^WPR{L(E%~XG8eJx(DoGzt2G{l8r!QPJ>kpHeOvCv#w zr=SSwMDaUX^*~v%6K%O~i)<^6`{go>a3IdfZ8hFmz&;Y@P%ZygShQZ2DSHd`m5AR= zx$wWU06;GYwXOf(%MFyj{8rPFXD};JCe85Bdp4$YJ2$TzZ7Gr#+SwCvBI1o$QP0(c zy`P51FEBV2HTisM3bHqpmECT@H!Y2-bv2*SoSPoO?wLe{M#zDTy@ujAZ!Izzky~3k zRA1RQIIoC*Mej1PH!sUgtkR0VCNMX(_!b65mo66iM*KQ7xT8t2eev$v#&YdUXKwGm z7okYAqYF&bveHeu6M5p9xheRCTiU8PFeb1_Rht0VVSbm%|1cOVobc8mvqcw!RjrMRM#~=7xibH&Fa5Imc|lZ{eC|R__)OrFg4@X_ ze+kk*_sDNG5^ELmHnZ7Ue?)#6!O)#Nv*Dl2mr#2)w{#i-;}0*_h4A%HidnmclH#;Q zmQbq+P4DS%3}PpPm7K_K3d2s#k~x+PlTul7+kIKol0@`YN1NG=+&PYTS->AdzPv!> zQvzT=)9se*Jr1Yq+C{wbK82gAX`NkbXFZ)4==j4t51{|-v!!$H8@WKA={d>CWRW+g z*`L>9rRucS`vbXu0rzA1#AQ(W?6)}1+oJSF=80Kf_2r~Qm-EJ6bbB3k`80rCv(0d` zvCf3;L2ovYG_TES%6vSuoKfIHC6w;V31!oqHM8-I8AFzcd^+_86!EcCOX|Ta9k1!s z_Vh(EGIIsI3fb&dF$9V8v(sTBC%!#<&KIGF;R+;MyC0~}$gC}}= zR`DbUVc&Bx`lYykFZ4{R{xRaUQkWCGCQlEc;!mf=+nOk$RUg*7 z;kP7CVLEc$CA7@6VFpsp3_t~m)W0aPxjsA3e5U%SfY{tp5BV5jH-5n?YX7*+U+Zs%LGR>U- z!x4Y_|4{gx?ZPJobISy991O znrmrC3otC;#4^&Rg_iK}XH(XX+eUHN0@Oe06hJk}F?`$)KmH^eWz@@N%wEc)%>?Ft z#9QAroDeyfztQ5Qe{m*#R#T%-h*&XvSEn@N$hYRTCMXS|EPwzF3IIysD2waj`vQD{ zv_#^Pgr?s~I*NE=acf@dWVRNWTr(GN0wrL)Z2=`Dr>}&ZDNX|+^Anl{Di%v1Id$_p zK5_H5`RDjJx`BW7hc85|> zHMMsWJ4KTMRHGu+vy*kBEMjz*^K8VtU=bXJYdhdZ-?jTXa$&n)C?QQIZ7ln$qbGlr zS*TYE+ppOrI@AoPP=VI-OXm}FzgXRL)OPvR$a_=SsC<3Jb+>5makX|U!}3lx4tX&L z^C<{9TggZNoeX!P1jX_K5HkEVnQ#s2&c#umzV6s2U-Q;({l+j^?hi7JnQ7&&*oOy9 z(|0asVTWUCiCnjcOnB2pN0DpuTglKq;&SFOQ3pUdye*eT<2()7WKbXp1qq9=bhMWlF-7BHT|i3TEIT77AcjD(v=I207wi-=vyiw5mxgPdTVUC z&h^FEUrXwWs9en2C{ywZp;nvS(Mb$8sBEh-*_d-OEm%~p1b2EpcwUdf<~zmJmaSTO zSX&&GGCEz-M^)G$fBvLC2q@wM$;n4jp+mt0MJFLuJ%c`tSp8$xuP|G81GEd2ci$|M z4XmH{5$j?rqDWoL4vs!}W&!?!rtj=6WKJcE>)?NVske(p;|#>vL|M_$as=mi-n-()a*OU3Okmk0wC<9y7t^D(er-&jEEak2!NnDiOQ99Wx8{S8}=Ng!e0tzj*#T)+%7;aM$ z&H}|o|J1p{IK0Q7JggAwipvHvko6>Epmh4RFRUr}$*2K4dz85o7|3#Bec9SQ4Y*;> zXWjT~f+d)dp_J`sV*!w>B%)#GI_;USp7?0810&3S=WntGZ)+tzhZ+!|=XlQ&@G@~3 z-dw@I1>9n1{+!x^Hz|xC+P#Ab`E@=vY?3%Bc!Po~e&&&)Qp85!I|U<-fCXy*wMa&t zgDk!l;gk;$taOCV$&60z+}_$ykz=Ea*)wJQ3-M|p*EK(cvtIre0Pta~(95J7zoxBN zS(yE^3?>88AL0Wfuou$BM{lR1hkrRibz=+I9ccwd`ZC*{NNqL)3pCcw^ygMmrG^Yp zn5f}Xf>%gncC=Yq96;rnfp4FQL#{!Y*->e82rHgY4Zwy{`JH}b9*qr^VA{%~Z}jtp z_t$PlS6}5{NtTqXHN?uI8ut8rOaD#F1C^ls73S=b_yI#iZDOGz3#^L@YheGd>L;<( z)U=iYj;`{>VDNzIxcjbTk-X3keXR8Xbc`A$o5# zKGSk-7YcoBYuAFFSCjGi;7b<;n-*`USs)IX z=0q6WZ=L!)PkYtZE-6)azhXV|+?IVGTOmMCHjhkBjfy@k1>?yFO3u!)@cl{fFAXnRYsWk)kpT?X{_$J=|?g@Q}+kFw|%n!;Zo}|HE@j=SFMvT8v`6Y zNO;tXN^036nOB2%=KzxB?n~NQ1K8IO*UE{;Xy;N^ZNI#P+hRZOaHATz9(=)w=QwV# z`z3+P>9b?l-@$@P3<;w@O1BdKh+H;jo#_%rr!ute{|YX4g5}n?O7Mq^01S5;+lABE+7`&_?mR_z7k|Ja#8h{!~j)| zbBX;*fsbUak_!kXU%HfJ2J+G7;inu#uRjMb|8a){=^))y236LDZ$$q3LRlat1D)%7K0!q5hT5V1j3qHc7MG9 z_)Q=yQ>rs>3%l=vu$#VVd$&IgO}Za#?aN!xY>-<3PhzS&q!N<=1Q7VJBfHjug^4|) z*fW^;%3}P7X#W3d;tUs3;`O&>;NKZBMR8au6>7?QriJ@gBaorz-+`pUWOP73DJL=M z(33uT6Gz@Sv40F6bN|H=lpcO z^AJl}&=TIjdevuDQ!w0K*6oZ2JBOhb31q!XDArFyKpz!I$p4|;c}@^bX{>AXdt7Bm zaLTk?c%h@%xq02reu~;t@$bv`b3i(P=g}~ywgSFpM;}b$zAD+=I!7`V~}ARB(Wx0C(EAq@?GuxOL9X+ffbkn3+Op0*80TqmpAq~EXmv%cq36celXmRz z%0(!oMp&2?`W)ALA&#|fu)MFp{V~~zIIixOxY^YtO5^FSox8v$#d0*{qk0Z)pNTt0QVZ^$`4vImEB>;Lo2!7K05TpY-sl#sWBz_W-aDIV`Ksabi zvpa#93Svo!70W*Ydh)Qzm{0?CU`y;T^ITg-J9nfWeZ-sbw)G@W?$Eomf%Bg2frfh5 zRm1{|E0+(4zXy){$}uC3%Y-mSA2-^I>Tw|gQx|7TDli_hB>``)Q^aZ`LJC2V3U$SABP}T)%}9g2pF9dT}aC~!rFFgkl1J$ z`^z{Arn3On-m%}r}TGF8KQe*OjSJ=T|caa_E;v89A{t@$yT^(G9=N9F?^kT*#s3qhJq!IH5|AhnqFd z0B&^gm3w;YbMNUKU>naBAO@fbz zqw=n!@--}o5;k6DvTW9pw)IJVz;X}ncbPVrmH>4x);8cx;q3UyiML1PWp%bxSiS|^ zC5!kc4qw%NSOGQ*Kcd#&$30=lDvs#*4W4q0u8E02U)7d=!W7+NouEyuF1dyH$D@G& zaFaxo9Ex|ZXA5y{eZT*i*dP~INSMAi@mvEX@q5i<&o&#sM}Df?Og8n8Ku4vOux=T% zeuw~z1hR}ZNwTn8KsQHKLwe2>p^K`YWUJEdVEl|mO21Bov!D0D$qPoOv=vJJ`)|%_ z>l%`eexY7t{BlVKP!`a^U@nM?#9OC*t76My_E_<16vCz1x_#82qj2PkWiMWgF8bM9 z(1t4VdHcJ;B~;Q%x01k_gQ0>u2*OjuEWNOGX#4}+N?Gb5;+NQMqp}Puqw2HnkYuKA zzKFWGHc&K>gwVgI1Sc9OT1s6fq=>$gZU!!xsilA$fF`kLdGoX*^t}ao@+^WBpk>`8 z4v_~gK|c2rCq#DZ+H)$3v~Hoi=)=1D==e3P zpKrRQ+>O^cyTuWJ%2}__0Z9SM_z9rptd*;-9uC1tDw4+A!=+K%8~M&+Zk#13hY$Y$ zo-8$*8dD5@}XDi19RjK6T^J~DIXbF5w&l?JLHMrf0 zLv0{7*G!==o|B%$V!a=EtVHdMwXLtmO~vl}P6;S(R2Q>*kTJK~!}gloxj)m|_LYK{ zl(f1cB=EON&wVFwK?MGn^nWuh@f95SHatPs(jcwSY#Dnl1@_gkOJ5=f`%s$ZHljRH0 z+c%lrb=Gi&N&1>^L_}#m>=U=(oT^vTA&3!xXNyqi$pdW1BDJ#^{h|2tZc{t^vag3& zAD7*8C`chNF|27itjBUo^CCDyEpJLX3&u+(L;YeeMwnXEoyN(ytoEabcl$lSgx~Ltatn}b$@j_yyMrBb03)shJE*$;Mw=;mZd&8e>IzE+4WIoH zCSZE7WthNUL$|Y#m!Hn?x7V1CK}V`KwW2D$-7&ODy5Cj;!_tTOOo1Mm%(RUt)#$@3 zhurA)t<7qik%%1Et+N1?R#hdBB#LdQ7{%-C zn$(`5e0eFh(#c*hvF>WT*07fk$N_631?W>kfjySN8^XC9diiOd#s?4tybICF;wBjp zIPzilX3{j%4u7blhq)tnaOBZ_`h_JqHXuI7SuIlNTgBk9{HIS&3|SEPfrvcE<@}E` zKk$y*nzsqZ{J{uWW9;#n=de&&h>m#A#q)#zRonr(?mDOYU&h&aQWD;?Z(22wY?t$U3qo`?{+amA$^TkxL+Ex2dh`q7iR&TPd0Ymwzo#b? zP$#t=elB5?k$#uE$K>C$YZbYUX_JgnXA`oF_Ifz4H7LEOW~{Gww&3s=wH4+j8*TU| zSX%LtJWqhr-xGNSe{;(16kxnak6RnZ{0qZ^kJI5X*It_YuynSpi(^-}Lolr{)#z_~ zw!(J-8%7Ybo^c3(mED`Xz8xecP35a6M8HarxRn%+NJBE;dw>>Y2T&;jzRd4FSDO3T zt*y+zXCtZQ0bP0yf6HRpD|WmzP;DR^-g^}{z~0x~z4j8m zucTe%k&S9Nt-?Jb^gYW1w6!Y3AUZ0Jcq;pJ)Exz%7k+mUOm6%ApjjSmflfKwBo6`B zhNb@$NHTJ>guaj9S{@DX)!6)b-Shav=DNKWy(V00k(D!v?PAR0f0vDNq*#mYmUp6> z76KxbFDw5U{{qx{BRj(>?|C`82ICKbfLxoldov-M?4Xl+3;I4GzLHyPOzYw7{WQST zPNYcx5onA%MAO9??41Po*1zW(Y%Zzn06-lUp{s<3!_9vv9HBjT02On0Hf$}NP;wF) zP<`2p3}A^~1YbvOh{ePMx$!JGUPX-tbBzp3mDZMY;}h;sQ->!p97GA)9a|tF(Gh{1$xk7 zUw?ELkT({Xw!KIr);kTRb1b|UL`r2_`a+&UFVCdJ)1T#fdh;71EQl9790Br0m_`$x z9|ZANuchFci8GNZ{XbP=+uXSJRe(;V5laQz$u18#?X*9}x7cIEbnr%<=1cX3EIu7$ zhHW6pe5M(&qEtsqRa>?)*{O;OJT+YUhG5{km|YI7I@JL_3Hwao9aXneiSA~a* z|Lp@c-oMNyeAEuUz{F?kuou3x#C*gU?lon!RC1s37gW^0Frc`lqQWH&(J4NoZg3m8 z;Lin#8Q+cFPD7MCzj}#|ws7b@?D9Q4dVjS4dpco=4yX5SSH=A@U@yqPdp@?g?qeia zH=Tt_9)G=6C2QIPsi-QipnK(mc0xXIN;j$WLf@n8eYvMk;*H-Q4tK%(3$CN}NGgO8n}fD~+>?<3UzvsrMf*J~%i;VKQHbF%TPalFi=#sgj)(P#SM^0Q=Tr>4kJVw8X3iWsP|e8tj}NjlMdWp z@2+M4HQu~3!=bZpjh;;DIDk&X}=c8~kn)FWWH z2KL1w^rA5&1@@^X%MjZ7;u(kH=YhH2pJPFQe=hn>tZd5RC5cfGYis8s9PKaxi*}-s6*W zRA^PwR=y^5Z){!(4D9-KC;0~;b*ploznFOaU`bJ_7U?qAi#mTo!&rIECRL$_y@yI27x2?W+zqDBD5~KCVYKFZLK+>ABC(Kj zeAll)KMgIlAG`r^rS{loBrGLtzhHY8$)<_S<(Dpkr(Ym@@vnQ&rS@FC*>2@XCH}M+an74WcRDcoQ+a3@A z9tYhl5$z7bMdTvD2r&jztBuo37?*k~wcU9GK2-)MTFS-lux-mIRYUuGUCI~V$?s#< z?1qAWb(?ZLm(N>%S%y10COdaq_Tm5c^%ooIxpR=`3e4C|@O5wY+eLik&XVi5oT7oe zmxH)Jd*5eo@!7t`x8!K=-+zJ-Sz)B_V$)s1pW~CDU$=q^&ABvf6S|?TOMB-RIm@CoFg>mjIQE)?+A1_3s6zmFU_oW&BqyMz1mY*IcP_2knjq5 zqw~JK(cVsmzc7*EvTT2rvpeqhg)W=%TOZ^>f`rD4|7Z5fq*2D^lpCttIg#ictgqZ$P@ru6P#f$x#KfnfTZj~LG6U_d-kE~`;kU_X)`H5so@?C zWmb!7x|xk@0L~0JFall*@ltyiL^)@3m4MqC7(7H0sH!WidId1#f#6R{Q&A!XzO1IAcIx;$k66dumt6lpUw@nL2MvqJ5^kbOVZ<^2jt5-njy|2@`07}0w z;M%I1$FCoLy`8xp8Tk)bFr;7aJeQ9KK6p=O$U0-&JYYy8woV*>b+FB?xLX`=pirYM z5K$BA(u)+jR{?O2r$c_Qvl?M{=Ar{yQ!UVsVn4k@0!b?_lA;dVz9uaQUgBH8Oz(Sb zrEs;&Ey>_ex8&!N{PmQjp+-Hlh|OA&wvDai#GpU=^-B70V0*LF=^bi+Nhe_o|azZ%~ZZ1$}LTmWt4aoB1 zPgccm$EwYU+jrdBaQFxQfn5gd(gM`Y*Ro1n&Zi?j=(>T3kmf94vdhf?AuS8>$Va#P zGL5F+VHpxdsCUa}+RqavXCobI-@B;WJbMphpK2%6t=XvKWWE|ruvREgM+|V=i6;;O zx$g=7^`$XWn0fu!gF=Xe9cMB8Z_SelD>&o&{1XFS`|nInK3BXlaeD*rc;R-#osyIS zWv&>~^TLIyBB6oDX+#>3<_0+2C4u2zK^wmHXXDD9_)kmLYJ!0SzM|%G9{pi)`X$uf zW}|%%#LgyK7m(4{V&?x_0KEDq56tk|0YNY~B(Sr|>WVz-pO3A##}$JCT}5P7DY+@W z#gJv>pA5>$|E3WO2tV7G^SuymB?tY`ooKcN3!vaQMnBNk-WATF{-$#}FyzgtJ8M^; zUK6KWSG)}6**+rZ&?o@PK3??uN{Q)#+bDP9i1W&j)oaU5d0bIWJ_9T5ac!qc?x66Q z$KUSZ`nYY94qfN_dpTFr8OW~A?}LD;Yty-BA)-be5Z3S#t2Io%q+cAbnGj1t$|qFR z9o?8B7OA^KjCYL=-!p}w(dkC^G6Nd%_I=1))PC0w5}ZZGJxfK)jP4Fwa@b-SYBw?% zdz9B-<`*B2dOn(N;mcTm%Do)rIvfXRNFX&1h`?>Rzuj~Wx)$p13nrDlS8-jwq@e@n zNIj_|8or==8~1h*Ih?w*8K7rYkGlwlTWAwLKc5}~dfz3y`kM&^Q|@C%1VAp_$wnw6zG~W4O+^ z>i?NY?oXf^Puc~+fDM$VgRNBpOZj{2cMP~gCqWAX4 z7>%$ux8@a&_B(pt``KSt;r+sR-$N;jdpY>|pyvPiN)9ohd*>mVST3wMo)){`B(&eX z1?zZJ-4u9NZ|~j1rdZYq4R$?swf}<6(#ex%7r{kh%U@kT)&kWuAszS%oJts=*OcL9 zaZwK<5DZw%1IFHXgFplP6JiL^dk8+SgM$D?8X+gE4172hXh!WeqIO>}$I9?Nry$*S zQ#f)RuH{P7RwA3v9f<-w>{PSzom;>(i&^l{E0(&Xp4A-*q-@{W1oE3K;1zb{&n28dSC2$N+6auXe0}e4b z)KLJ?5c*>@9K#I^)W;uU_Z`enquTUxr>mNq z1{0_puF-M7j${rs!dxxo3EelGodF1TvjV;Zpo;s{5f1pyCuRp=HDZ?s#IA4f?h|-p zGd|Mq^4hDa@Bh!c4ZE?O&x&XZ_ptZGYK4$9F4~{%R!}G1leCBx`dtNUS|K zL-7J5s4W@%mhXg1!}a4PD%!t&Qn%f_oquRajn3@C*)`o&K9o7V6DwzVMEhjVdDJ1fjhr#@=lp#@4EBqi=CCQ>73>R(>QKPNM&_Jpe5G`n4wegeC`FYEPJ{|vwS>$-`fuRSp3927qOv|NC3T3G-0 zA{K`|+tQy1yqE$ShWt8ny&5~)%ITb@^+x$w0)f&om;P8B)@}=Wzy59BwUfZ1vqw87 za2lB8J(&*l#(V}Id8SyQ0C(2amzkz3EqG&Ed0Jq1)$|&>4_|NIe=5|n=3?siFV0fI z{As5DLW^gs|B-b4C;Hd(SM-S~GQhzb>HgF2|2Usww0nL^;x@1eaB)=+Clj+$fF@H( z-fqP??~QMT$KI-#m;QC*&6vkp&8699G3)Bq0*kFZXINw=b9OVaed(3(3kS|IZ)CM? zJdnW&%t8MveBuK21uiYj)_a{Fnw0OErMzMN?d$QoPwkhOwcP&p+t>P)4tHlYw-pPN z^oJ=uc$Sl>pv@fZH~ZqxSvdhF@F1s=oZawpr^-#l{IIOGG=T%QXjtwPhIg-F@k@uIlr?J->Ia zpEUQ*=4g|XYn4Gez&aHr*;t$u3oODPmc2Ku)2Og|xjc%w;q!Zz+zY)*3{7V8bK4;& zYV82FZ+8?v)`J|G1w4I0fWdKg|2b#iaazCv;|?(W-q}$o&Y}Q5d@BRk^jL7#{kbCK zSgkyu;=DV+or2)AxCBgq-nj5=@n^`%T#V+xBGEkW4lCqrE)LMv#f;AvD__cQ@Eg3`~x| zW+h9mofSXCq5|M)9|ez(#X?-sxB%Go8};sJ?2abp(Y!lyi>k)|{M*Z$c{e1-K4ky` MPgg&ebxsLQ025IeI{*Lx literal 0 HcmV?d00001 diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..c1194c9 --- /dev/null +++ b/web/index.html @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + android_fuelstats + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..e9f0096 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "Fuel Stats", + "short_name": "Fuel Stats", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} \ No newline at end of file diff --git a/windows/.gitignore b/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt new file mode 100644 index 0000000..4f9c498 --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(android_fuelstats LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "android_fuelstats") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..903f489 --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..77ab7a0 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,14 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + FileSelectorWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FileSelectorWindows")); +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..a423a02 --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,24 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + file_selector_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..394917c --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc new file mode 100644 index 0000000..e02c4fb --- /dev/null +++ b/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "android_fuelstats" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "android_fuelstats" "\0" + VALUE "LegalCopyright", "Copyright (C) 2025 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "android_fuelstats.exe" "\0" + VALUE "ProductName", "android_fuelstats" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..955ee30 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp new file mode 100644 index 0000000..4c2b156 --- /dev/null +++ b/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"Fuel Stats", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/windows/runner/resource.h b/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c04e20caf6370ebb9253ad831cc31de4a9c965f6 GIT binary patch literal 33772 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 literal 0 HcmV?d00001 diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..153653e --- /dev/null +++ b/windows/runner/runner.exe.manifest @@ -0,0 +1,14 @@ + + + + + PerMonitorV2 + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000..3a0b465 --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/windows/runner/utils.h b/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp new file mode 100644 index 0000000..60608d0 --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000..e901dde --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_