commit 0a71a194b9f88d478a81e2c9f3b84bbf59a42ec5 Author: Hamza-Ayed Date: Sat Jun 22 16:34:02 2024 +0300 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..014d0e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +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 +.env + +lib/env/env.dart +lib/env/env.g.dart +# 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..94c106f --- /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: "68bfaea224880b488c617afe30ab12091ea8fa4e" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + base_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + - platform: android + create_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + base_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + - platform: ios + create_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + base_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + - platform: linux + create_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + base_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + - platform: macos + create_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + base_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + - platform: web + create_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + base_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + - platform: windows + create_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + base_revision: 68bfaea224880b488c617afe30ab12091ea8fa4e + + # 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..92aac27 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# sefer_admin1 + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. +# seferAdmin 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..6f56801 --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,13 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java + +# Remember to never publicly share your keystore. +# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle b/android/app/build.gradle new file mode 100644 index 0000000..b341872 --- /dev/null +++ b/android/app/build.gradle @@ -0,0 +1,70 @@ +plugins { + id "com.android.application" + // START: FlutterFire Configuration + id 'com.google.gms.google-services' + // END: FlutterFire Configuration + id "kotlin-android" + id "dev.flutter.flutter-gradle-plugin" +} + +def localProperties = new Properties() +def localPropertiesFile = rootProject.file('local.properties') +if (localPropertiesFile.exists()) { + localPropertiesFile.withReader('UTF-8') { reader -> + localProperties.load(reader) + } +} + +def flutterVersionCode = localProperties.getProperty('flutter.versionCode') +if (flutterVersionCode == null) { + flutterVersionCode = '1' +} + +def flutterVersionName = localProperties.getProperty('flutter.versionName') +if (flutterVersionName == null) { + flutterVersionName = '1.0' +} + +android { + namespace "com.example.sefer_admin1" + compileSdk flutter.compileSdkVersion + ndkVersion flutter.ndkVersion + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = '1.8' + } + + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId "com.example.sefer_admin1" + // You can update the following values to match your application needs. + // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration. + minSdkVersion 23 + targetSdkVersion flutter.targetSdkVersion + versionCode flutterVersionCode.toInteger() + versionName flutterVersionName + } + + 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.debug + } + } +} + +flutter { + source '../..' +} + +dependencies {} diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..2993aac --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,150 @@ +{ + "project_info": { + "project_number": "594687661098", + "project_id": "ride-b1bd8", + "storage_bucket": "ride-b1bd8.appspot.com" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:594687661098:android:8ec72f5f8b0b0ab8595f53", + "android_client_info": { + "package_name": "com.example.sefer_admin1" + } + }, + "oauth_client": [ + { + "client_id": "594687661098-2u640akrb3k7sak5t0nqki6f4v6hq1bq.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "594687661098-2hfb9gumub3j60vb7mqtq794k8spihuh.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "594687661098-8e26699cris2k3nj5msj1osi59it9kpf.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.mobileapp.store.ride" + } + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:594687661098:android:683982cbf71fa423595f53", + "android_client_info": { + "package_name": "com.mobileapp.store.ride" + } + }, + "oauth_client": [ + { + "client_id": "594687661098-2dhoogl7be9phobfbu8bbg1sj567iv88.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.mobileapp.store.ride", + "certificate_hash": "9bf3876c66e490f30cd7982fa972d8e52e0edbb6" + } + }, + { + "client_id": "594687661098-4f8qbb4r223su1pphor33l3oe0ie2v46.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.mobileapp.store.ride", + "certificate_hash": "765bbb7c5d30bc58a7ba44372db614d6bbe6e34d" + } + }, + { + "client_id": "594687661098-2u640akrb3k7sak5t0nqki6f4v6hq1bq.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "594687661098-2hfb9gumub3j60vb7mqtq794k8spihuh.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "594687661098-8e26699cris2k3nj5msj1osi59it9kpf.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.mobileapp.store.ride" + } + } + ] + } + } + }, + { + "client_info": { + "mobilesdk_app_id": "1:594687661098:android:46557bd4f534b5bb595f53", + "android_client_info": { + "package_name": "com.sefer_driver" + } + }, + "oauth_client": [ + { + "client_id": "594687661098-7mj1ngkp5aodosos3gsr4252qfemuvan.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.sefer_driver", + "certificate_hash": "765bbb7c5d30bc58a7ba44372db614d6bbe6e34d" + } + }, + { + "client_id": "594687661098-op7a9cpgm9dilgh8nl48bu6aor55f7qj.apps.googleusercontent.com", + "client_type": 1, + "android_info": { + "package_name": "com.sefer_driver", + "certificate_hash": "6f83a0b80b7e1b30b3dd42811cbc2c60ee931a3b" + } + }, + { + "client_id": "594687661098-2u640akrb3k7sak5t0nqki6f4v6hq1bq.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "594687661098-2hfb9gumub3j60vb7mqtq794k8spihuh.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "594687661098-8e26699cris2k3nj5msj1osi59it9kpf.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.mobileapp.store.ride" + } + } + ] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file 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..8ed9141 --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/sefer_admin1/MainActivity.kt b/android/app/src/main/kotlin/com/example/sefer_admin1/MainActivity.kt new file mode 100644 index 0000000..7523148 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/sefer_admin1/MainActivity.kt @@ -0,0 +1,5 @@ +package com.example.sefer_admin1 + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity: FlutterActivity() diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + 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-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/launcher_icon.png b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png new file mode 100644 index 0000000..db93cb7 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/launcher_icon.png differ 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 0000000..17987b7 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/launcher_icon.png b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png new file mode 100644 index 0000000..af42b5b Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png new file mode 100644 index 0000000..6b78c9c Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png new file mode 100644 index 0000000..397b79b Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/launcher_icon.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png new file mode 100644 index 0000000..0db9801 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/launcher_icon.png differ 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/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 b/android/build.gradle new file mode 100644 index 0000000..f9e7f92 --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,32 @@ +buildscript { + ext.kotlin_version = '2.0.0' // Update to the latest version + + repositories { + google() + mavenCentral() + } + + dependencies { + classpath "com.android.tools.build:gradle:8.1.4" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = '../build' +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(':app') +} + +tasks.register("clean", Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..598d13f --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx4G +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..a6c0c1c --- /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.1-bin.zip diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..816dbe0 --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1,29 @@ +pluginManagement { + def flutterSdkPath = { + def properties = new Properties() + file("local.properties").withInputStream { properties.load(it) } + def flutterSdkPath = properties.getProperty("flutter.sdk") + assert flutterSdkPath != null, "flutter.sdk not set in local.properties" + return flutterSdkPath + } + settings.ext.flutterSdkPath = flutterSdkPath() + + includeBuild("${settings.ext.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 "7.3.0" apply false + // START: FlutterFire Configuration + id "com.google.gms.google-services" version "4.3.15" apply false + // END: FlutterFire Configuration + id "org.jetbrains.kotlin.android" version "1.7.10" apply false +} + +include ":app" diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 0000000..d7dbea8 Binary files /dev/null and b/assets/images/logo.png differ diff --git a/assets/notify.mp3 b/assets/notify.mp3 new file mode 100644 index 0000000..d10bc28 Binary files /dev/null and b/assets/notify.mp3 differ diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..ca2754e --- /dev/null +++ b/firebase.json @@ -0,0 +1 @@ +{"flutter":{"platforms":{"android":{"default":{"projectId":"ride-b1bd8","appId":"1:594687661098:android:8ec72f5f8b0b0ab8595f53","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"ride-b1bd8","appId":"1:594687661098:ios:9f46a169fad13752595f53","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"ride-b1bd8","configurations":{"android":"1:594687661098:android:8ec72f5f8b0b0ab8595f53","ios":"1:594687661098:ios:9f46a169fad13752595f53"}}}}}} \ 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..ec97fc6 --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..c4855bf --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "Generated.xcconfig" diff --git a/ios/Podfile b/ios/Podfile new file mode 100644 index 0000000..04c36cf --- /dev/null +++ b/ios/Podfile @@ -0,0 +1,44 @@ +# Uncomment this line to define a global platform for your project +platform :ios, '14.0' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_ios_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_ios_build_settings(target) + end +end diff --git a/ios/Podfile.lock b/ios/Podfile.lock new file mode 100644 index 0000000..b48d476 --- /dev/null +++ b/ios/Podfile.lock @@ -0,0 +1,192 @@ +PODS: + - AppAuth (1.7.5): + - AppAuth/Core (= 1.7.5) + - AppAuth/ExternalUserAgent (= 1.7.5) + - AppAuth/Core (1.7.5) + - AppAuth/ExternalUserAgent (1.7.5): + - AppAuth/Core + - Firebase/CoreOnly (10.25.0): + - FirebaseCore (= 10.25.0) + - Firebase/Messaging (10.25.0): + - Firebase/CoreOnly + - FirebaseMessaging (~> 10.25.0) + - firebase_core (2.32.0): + - Firebase/CoreOnly (= 10.25.0) + - Flutter + - firebase_messaging (14.9.4): + - Firebase/Messaging (= 10.25.0) + - firebase_core + - Flutter + - FirebaseCore (10.25.0): + - FirebaseCoreInternal (~> 10.0) + - GoogleUtilities/Environment (~> 7.12) + - GoogleUtilities/Logger (~> 7.12) + - FirebaseCoreInternal (10.27.0): + - "GoogleUtilities/NSData+zlib (~> 7.8)" + - FirebaseInstallations (10.27.0): + - FirebaseCore (~> 10.0) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - PromisesObjC (~> 2.1) + - FirebaseMessaging (10.25.0): + - FirebaseCore (~> 10.0) + - FirebaseInstallations (~> 10.0) + - GoogleDataTransport (~> 9.3) + - GoogleUtilities/AppDelegateSwizzler (~> 7.8) + - GoogleUtilities/Environment (~> 7.8) + - GoogleUtilities/Reachability (~> 7.8) + - GoogleUtilities/UserDefaults (~> 7.8) + - nanopb (< 2.30911.0, >= 2.30908.0) + - Flutter (1.0.0) + - flutter_secure_storage (6.0.0): + - Flutter + - google_sign_in_ios (0.0.1): + - AppAuth (>= 1.7.4) + - Flutter + - FlutterMacOS + - GoogleSignIn (~> 7.1) + - GTMSessionFetcher (>= 3.4.0) + - GoogleDataTransport (9.4.1): + - GoogleUtilities/Environment (~> 7.7) + - nanopb (< 2.30911.0, >= 2.30908.0) + - PromisesObjC (< 3.0, >= 1.2) + - GoogleSignIn (7.1.0): + - AppAuth (< 2.0, >= 1.7.3) + - GTMAppAuth (< 5.0, >= 4.1.1) + - GTMSessionFetcher/Core (~> 3.3) + - GoogleUtilities/AppDelegateSwizzler (7.13.3): + - GoogleUtilities/Environment + - GoogleUtilities/Logger + - GoogleUtilities/Network + - GoogleUtilities/Privacy + - GoogleUtilities/Environment (7.13.3): + - GoogleUtilities/Privacy + - PromisesObjC (< 3.0, >= 1.2) + - GoogleUtilities/Logger (7.13.3): + - GoogleUtilities/Environment + - GoogleUtilities/Privacy + - GoogleUtilities/Network (7.13.3): + - GoogleUtilities/Logger + - "GoogleUtilities/NSData+zlib" + - GoogleUtilities/Privacy + - GoogleUtilities/Reachability + - "GoogleUtilities/NSData+zlib (7.13.3)": + - GoogleUtilities/Privacy + - GoogleUtilities/Privacy (7.13.3) + - GoogleUtilities/Reachability (7.13.3): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GoogleUtilities/UserDefaults (7.13.3): + - GoogleUtilities/Logger + - GoogleUtilities/Privacy + - GTMAppAuth (4.1.1): + - AppAuth/Core (~> 1.7) + - GTMSessionFetcher/Core (< 4.0, >= 3.3) + - GTMSessionFetcher (3.4.1): + - GTMSessionFetcher/Full (= 3.4.1) + - GTMSessionFetcher/Core (3.4.1) + - GTMSessionFetcher/Full (3.4.1): + - GTMSessionFetcher/Core + - local_auth_darwin (0.0.1): + - Flutter + - location (0.0.1): + - Flutter + - nanopb (2.30910.0): + - nanopb/decode (= 2.30910.0) + - nanopb/encode (= 2.30910.0) + - nanopb/decode (2.30910.0) + - nanopb/encode (2.30910.0) + - path_provider_foundation (0.0.1): + - Flutter + - FlutterMacOS + - PromisesObjC (2.4.0) + - sqflite (0.0.3): + - Flutter + - FlutterMacOS + - url_launcher_ios (0.0.1): + - Flutter + - webview_flutter_wkwebview (0.0.1): + - Flutter + +DEPENDENCIES: + - firebase_core (from `.symlinks/plugins/firebase_core/ios`) + - firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`) + - Flutter (from `Flutter`) + - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) + - google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`) + - local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`) + - location (from `.symlinks/plugins/location/ios`) + - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) + - sqflite (from `.symlinks/plugins/sqflite/darwin`) + - url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`) + - webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/ios`) + +SPEC REPOS: + trunk: + - AppAuth + - Firebase + - FirebaseCore + - FirebaseCoreInternal + - FirebaseInstallations + - FirebaseMessaging + - GoogleDataTransport + - GoogleSignIn + - GoogleUtilities + - GTMAppAuth + - GTMSessionFetcher + - nanopb + - PromisesObjC + +EXTERNAL SOURCES: + firebase_core: + :path: ".symlinks/plugins/firebase_core/ios" + firebase_messaging: + :path: ".symlinks/plugins/firebase_messaging/ios" + Flutter: + :path: Flutter + flutter_secure_storage: + :path: ".symlinks/plugins/flutter_secure_storage/ios" + google_sign_in_ios: + :path: ".symlinks/plugins/google_sign_in_ios/darwin" + local_auth_darwin: + :path: ".symlinks/plugins/local_auth_darwin/darwin" + location: + :path: ".symlinks/plugins/location/ios" + path_provider_foundation: + :path: ".symlinks/plugins/path_provider_foundation/darwin" + sqflite: + :path: ".symlinks/plugins/sqflite/darwin" + url_launcher_ios: + :path: ".symlinks/plugins/url_launcher_ios/ios" + webview_flutter_wkwebview: + :path: ".symlinks/plugins/webview_flutter_wkwebview/ios" + +SPEC CHECKSUMS: + AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa + Firebase: 0312a2352584f782ea56f66d91606891d4607f06 + firebase_core: a626d00494efa398e7c54f25f1454a64c8abf197 + firebase_messaging: 06391e8f35dc65a00c56580266285263d2861f10 + FirebaseCore: 7ec4d0484817f12c3373955bc87762d96842d483 + FirebaseCoreInternal: 4b297a2d56063dbea2c1d0d04222d44a8d058862 + FirebaseInstallations: 766dabca09fd94aef922538aaf144cc4a6fb6869 + FirebaseMessaging: 88950ba9485052891ebe26f6c43a52bb62248952 + Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7 + flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 + google_sign_in_ios: 07375bfbf2620bc93a602c0e27160d6afc6ead38 + GoogleDataTransport: 6c09b596d841063d76d4288cc2d2f42cc36e1e2a + GoogleSignIn: d4281ab6cf21542b1cfaff85c191f230b399d2db + GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 + GTMAppAuth: f69bd07d68cd3b766125f7e072c45d7340dea0de + GTMSessionFetcher: 8000756fc1c19d2e5697b90311f7832d2e33f6cd + local_auth_darwin: 4d56c90c2683319835a61274b57620df9c4520ab + location: d5cf8598915965547c3f36761ae9cc4f4e87d22e + nanopb: 438bc412db1928dac798aa6fd75726007be04262 + path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 + PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47 + sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec + url_launcher_ios: 5334b05cef931de560670eeae103fd3e431ac3fe + webview_flutter_wkwebview: be0f0d33777f1bfd0c9fdcb594786704dbf65f36 + +PODFILE CHECKSUM: 1959d098c91d8a792531a723c4a9d7e9f6a01e38 + +COCOAPODS: 1.15.2 diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e9f7149 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,757 @@ +// !$*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 */; }; + 536131ECA2F90A36243E82F1 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 51EDD0F6DE0C2DD1B481E60C /* GoogleService-Info.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 */; }; + AE788943CA93312FDB0A3D6C /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B7E216D92402E89BBF0C8A6 /* Pods_RunnerTests.framework */; }; + B5D96EA9C34A11D9DC922EB4 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A9AC52F9E7303DD2AADC56F7 /* Pods_Runner.framework */; }; +/* 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 = ""; }; + 3DD7F287CDCC3C5A3FC9B074 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 51EDD0F6DE0C2DD1B481E60C /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = ""; }; + 5BACD61BA97701EA585BB32D /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + 69F3204B769FEC2193D583DD /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; + 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 = ""; }; + 7B365EAF9143E50C184FBF9C /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; + 8B7E216D92402E89BBF0C8A6 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 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 = ""; }; + A9AC52F9E7303DD2AADC56F7 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + C66754E42C263D38002C21AF /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = ""; }; + D3C7EF4530833ECC59D933EB /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + EE8DDDC671B36FB3C0532FA2 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + B5D96EA9C34A11D9DC922EB4 /* Pods_Runner.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + AEAB95EFF3B3BF7F893B510B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + AE788943CA93312FDB0A3D6C /* Pods_RunnerTests.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 2547B9228653078BD5BC8D85 /* Frameworks */ = { + isa = PBXGroup; + children = ( + A9AC52F9E7303DD2AADC56F7 /* Pods_Runner.framework */, + 8B7E216D92402E89BBF0C8A6 /* Pods_RunnerTests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 89895ABD55CE43E236B6CAF3 /* Pods */ = { + isa = PBXGroup; + children = ( + 3DD7F287CDCC3C5A3FC9B074 /* Pods-Runner.debug.xcconfig */, + 69F3204B769FEC2193D583DD /* Pods-Runner.release.xcconfig */, + 5BACD61BA97701EA585BB32D /* Pods-Runner.profile.xcconfig */, + 7B365EAF9143E50C184FBF9C /* Pods-RunnerTests.debug.xcconfig */, + EE8DDDC671B36FB3C0532FA2 /* Pods-RunnerTests.release.xcconfig */, + D3C7EF4530833ECC59D933EB /* Pods-RunnerTests.profile.xcconfig */, + ); + path = Pods; + 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 */, + 89895ABD55CE43E236B6CAF3 /* Pods */, + 2547B9228653078BD5BC8D85 /* Frameworks */, + 51EDD0F6DE0C2DD1B481E60C /* GoogleService-Info.plist */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + C66754E42C263D38002C21AF /* Runner.entitlements */, + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + B9EB5DEA5F772729C796DD11 /* [CP] Check Pods Manifest.lock */, + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + AEAB95EFF3B3BF7F893B510B /* Frameworks */, + ); + 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 = ( + F30F6A7446087F285F80AA2C /* [CP] Check Pods Manifest.lock */, + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + E9260FFCE0F15D904C6E7C16 /* [CP] Embed Pods Frameworks */, + 6A69BFBF5DAB5F688C4AF4E3 /* [CP] Copy Pods Resources */, + ); + 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 */, + 536131ECA2F90A36243E82F1 /* GoogleService-Info.plist 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"; + }; + 6A69BFBF5DAB5F688C4AF4E3 /* [CP] Copy Pods Resources */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Copy Pods Resources"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; + showEnvVarsInLog = 0; + }; + 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"; + }; + B9EB5DEA5F772729C796DD11 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-RunnerTests-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + E9260FFCE0F15D904C6E7C16 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + F30F6A7446087F285F80AA2C /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* 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; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 63CVT8G5P8; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.seferAdmin1; + 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; + baseConfigurationReference = 7B365EAF9143E50C184FBF9C /* Pods-RunnerTests.debug.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.seferAdmin1.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; + baseConfigurationReference = EE8DDDC671B36FB3C0532FA2 /* Pods-RunnerTests.release.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.seferAdmin1.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; + baseConfigurationReference = D3C7EF4530833ECC59D933EB /* Pods-RunnerTests.profile.xcconfig */; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.seferAdmin1.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 = 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; + 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 = 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; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 63CVT8G5P8; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.seferAdmin1; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + DEVELOPMENT_TEAM = 63CVT8G5P8; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.seferAdmin1; + 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..8e3ca5d --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..21a3cc1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..beb37e3 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,31 @@ +// import UIKit +// import Flutter + +// @UIApplicationMain +// @objc class AppDelegate: FlutterAppDelegate { +// override func application( +// _ application: UIApplication, +// didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? +// ) -> Bool { +// GeneratedPluginRegistrant.register(with: self) +// return super.application(application, didFinishLaunchingWithOptions: launchOptions) +// } +// } + +import UIKit +import Flutter +import FirebaseCore + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + // GMSServices.provideAPIKey("AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0") + FirebaseApp.configure() + GeneratedPluginRegistrant.register(with: self) + return true + } +} \ No newline at end of file diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..6969d87 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ 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 0000000..7ea141e Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ 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 0000000..5cb28c2 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ 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 0000000..099123f Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ 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 0000000..eeafd09 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..9303207 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ 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 0000000..666e4a2 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ 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 0000000..5cb28c2 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ 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 0000000..e47feb5 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ 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 0000000..8509aef Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ 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 0000000..7b5327f Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png new file mode 100644 index 0000000..42d5600 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png new file mode 100644 index 0000000..acf710c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png differ 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 0000000..8cbf9fd Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..8509aef Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ 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 0000000..c080f8b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ 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 0000000..db93cb7 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png differ 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 0000000..397b79b Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..11d5bf2 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ 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 0000000..473bcf0 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ 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 0000000..e181631 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ 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 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ 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 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ 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 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ 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/GoogleService-Info.plist b/ios/Runner/GoogleService-Info.plist new file mode 100644 index 0000000..0d05278 --- /dev/null +++ b/ios/Runner/GoogleService-Info.plist @@ -0,0 +1,36 @@ + + + + + CLIENT_ID + 594687661098-aj48k038fjst4k8jiprfbq8895b11cci.apps.googleusercontent.com + REVERSED_CLIENT_ID + com.googleusercontent.apps.594687661098-aj48k038fjst4k8jiprfbq8895b11cci + ANDROID_CLIENT_ID + 594687661098-2dhoogl7be9phobfbu8bbg1sj567iv88.apps.googleusercontent.com + API_KEY + AIzaSyCf2mW2h0HD8ZYjwh4VOa2ladw6MJkCDTM + GCM_SENDER_ID + 594687661098 + PLIST_VERSION + 1 + BUNDLE_ID + com.example.seferAdmin1 + PROJECT_ID + ride-b1bd8 + STORAGE_BUCKET + ride-b1bd8.appspot.com + IS_ADS_ENABLED + + IS_ANALYTICS_ENABLED + + IS_APPINVITE_ENABLED + + IS_GCM_ENABLED + + IS_SIGNIN_ENABLED + + GOOGLE_APP_ID + 1:594687661098:ios:9f46a169fad13752595f53 + + \ No newline at end of file diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..4230939 --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,49 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Sefer Admin1 + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + sefer_admin1 + 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 + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/Runner/Runner.entitlements b/ios/Runner/Runner.entitlements new file mode 100644 index 0000000..903def2 --- /dev/null +++ b/ios/Runner/Runner.entitlements @@ -0,0 +1,8 @@ + + + + + aps-environment + development + + diff --git a/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/constant/api_key.dart b/lib/constant/api_key.dart new file mode 100644 index 0000000..f8ae211 --- /dev/null +++ b/lib/constant/api_key.dart @@ -0,0 +1,72 @@ +import '../env/env.dart'; +import 'char_map.dart'; +import 'credential.dart'; + +class AK { + static final AC a = AC(); + + static final String publishableKey = + AC().r(AC().r(AC().r(Env.stripePublishableKe, cn), cC), cs); + static final String secretKey = a.r(a.r(a.r(Env.secretKey, cn), cC), cs); + static final String basicAuthCredentials = + a.r(a.r(a.r(Env.basicAuthCredentials, cn), cC), cs); + static final String accountSIDTwillo = + a.r(a.r(a.r(Env.accountSIDTwillo, cn), cC), cs); + static final String serverAPI = a.r(a.r(a.r(Env.serverAPI, cn), cC), cs); + static final String mapAPIKEY = a.r(a.r(a.r(Env.mapAPIKEY, cn), cC), cs); + static final String twilloRecoveryCode = + a.r(a.r(a.r(Env.twilloRecoveryCode, cn), cC), cs); + static final String authTokenTwillo = + a.r(a.r(a.r(Env.authTokenTwillo, cn), cC), cs); + static final String chatGPTkey = a.r(a.r(a.r(Env.chatGPTkey, cn), cC), cs); + static final String transactionCloude = + a.r(a.r(a.r(Env.transactionCloude, cn), cC), cs); + static final String visionApi = a.r(a.r(a.r(Env.visionApi, cn), cC), cs); + static final String chatGPTkeySefer = + a.r(a.r(a.r(Env.chatGPTkeySefer, cn), cC), cs); + static final String chatGPTkeySeferNew = + a.r(a.r(a.r(Env.chatGPTkeySeferNew, cn), cC), cs); + static final String serverPHP = Env.serverPHP; + static final String llamaKey = a.r(a.r(a.r(Env.llamaKey, cn), cC), cs); + static final String cohere = a.r(a.r(a.r(Env.cohere, cn), cC), cs); + static final String claudeAiAPI = a.r(a.r(a.r(Env.claudeAiAPI, cn), cC), cs); + static final String payPalClientId = + a.r(a.r(a.r(Env.payPalClientId, cn), cC), cs); + static final String payPalSecret = + a.r(a.r(a.r(Env.payPalSecret, cn), cC), cs); + static final String geminiApi = a.r(a.r(a.r(Env.geminiApi, cn), cC), cs); + static final String agoraAppId = a.r(a.r(a.r(Env.agoraAppId, cn), cC), cs); + static final String agoraAppCertificate = + a.r(a.r(a.r(Env.agoraAppCertificate, cn), cC), cs); + static final String payPalClientIdLive = + a.r(a.r(a.r(Env.payPalClientIdLive, cn), cC), cs); + static final String payPalSecretLive = + a.r(a.r(a.r(Env.payPalSecretLive, cn), cC), cs); + static final String integrationIdPayMob = + a.r(a.r(a.r(Env.integrationIdPayMob, cn), cC), cs); + static final String passwordPayMob = + a.r(a.r(a.r(Env.passwordPayMob, cn), cC), cs); + static final String usernamePayMob = + a.r(a.r(a.r(Env.usernamePayMob, cn), cC), cs); + static final String payMobApikey = + a.r(a.r(a.r(Env.payMobApikey, cn), cC), cs); + static final String integrationIdPayMobWallet = + a.r(a.r(a.r(Env.integrationIdPayMobWallet, cn), cC), cs); + static final String smsPasswordEgypt = + a.r(a.r(a.r(Env.smsPasswordEgypt, cn), cC), cs); + static final String ocpApimSubscriptionKey = + a.r(a.r(a.r(Env.ocpApimSubscriptionKey, cn), cC), cs); + static final String chatGPTkeySeferNew4 = + a.r(a.r(a.r(Env.chatGPTkeySeferNew4, cn), cC), cs); + static final String anthropicAIkeySeferNew = + a.r(a.r(a.r(Env.anthropicAIkeySeferNew, cn), cC), cs); + static final String llama3Key = a.r(a.r(a.r(Env.llama3Key, cn), cC), cs); + static final String payMobOutClientSecrret = + a.r(a.r(a.r(Env.payMobOutClientSecrret, cn), cC), cs); + static final String payMobOutClient_id = + a.r(a.r(a.r(Env.payMobOutClient_id, cn), cC), cs); + static final String payMobOutPassword = + a.r(a.r(a.r(Env.payMobOutPassword, cn), cC), cs); + static final String payMobOutUserName = + a.r(a.r(a.r(Env.payMobOutUserName, cn), cC), cs); +} diff --git a/lib/constant/box_name.dart b/lib/constant/box_name.dart new file mode 100644 index 0000000..932ad42 --- /dev/null +++ b/lib/constant/box_name.dart @@ -0,0 +1,73 @@ +class BoxName { + static const String driverID = "driverID"; + static const String countryCode = "countryCode"; + static const String googlaMapApp = "googlaMapApp"; + + static const String lang = "lang"; + static const String carType = "carType"; + static const String carPlate = "carPlate"; + static const String statusDriverLocation = "statusDriverLocation"; + static const String password = "password"; + static const String arrivalTime = "arrivalTime"; + static const String passwordDriver = "passwordDriver"; + static const String agreeTerms = "agreeTerms"; + static const String addWork = 'addWork'; + static const String addHome = 'addHome'; + static const String tipPercentage = 'tipPercentage'; + static const String accountIdStripeConnect = "accountIdStripeConnect"; + static const String faceDetectTimes = "faceDetectTimes"; + static const String sosPhonePassenger = "sosPhonePassenger"; + static const String sosPhoneDriver = "sosPhoneDriver"; + static const String passengerID = "pasengerID"; + static const String phone = "phone"; + static const String phoneDriver = "phoneDriver"; + static const String dobDriver = "dobDriver"; + static const String sexDriver = "sexDriver"; + static const String lastNameDriver = "lastNameDriver"; + static const String name = "name"; + static const String nameDriver = "nameDriver"; + static const String driverPhotoUrl = "driverPhotoUrl"; + static const String email = "email"; + static const String emailDriver = "emailDriver"; + static const String tokens = "tokens"; + static const String tokensDrivers = "tokensDrivers"; + static const String tokensPassengers = "tokensPassengers"; + static const String tokenFCM = "tokenFCM"; + static const String tokenDriver = "tokenDriver"; + static const String cardNumber = "cardNumber"; + static const String cardNumberDriver = "cardNumberDriver"; + static const String cardHolderName = "cardHolderName"; + static const String cardHolderNameDriver = "cardHolderNameDriver"; + static const String expiryDate = "expiryDate"; + static const String expiryDateDriver = "expiryDateDriver"; + static const String cvvCode = "cvvCode"; + static const String cvvCodeDriver = "cvvCodeDriver"; + static const String passengerWalletDetails = "passengerWalletDetails"; + static const String passengerWalletTotal = "passengerWalletTotal"; + static const String passengerWalletFound = "passengerWalletFound"; + static const String periods = 'periods'; + static const String onBoarding = 'onBoarding'; + static const String stripePublishableKey = 'stripe_publishableKe'; + static const String apiKeyRun = 'apiKeyRun'; + static const String serverAPI = 'serverAPI'; + static const String secretKey = 'secretKey'; + static const String basicAuthCredentials = 'basicAuthCredentials'; + static const String mapAPIKEY = 'mapAPIKEY'; + static const String twilloRecoveryCode = 'twilloRecoveryCode'; + static const String accountSIDTwillo = 'accountSIDTwillo'; + static const String authTokenTwillo = 'authTokenTwillo'; + static const String chatGPTkey = 'chatGPTkey'; + static const String chatGPTkeySefer = 'chatGPTkeySefer'; + static const String transactionCloude = 'transactionCloude'; + static const String visionApi = 'visionApi'; + static const String vin = "vin"; + static const String make = "make"; + static const String model = "model"; + static const String year = "year"; + static const String expirationDate = "expirationDate"; + static const String color = "color"; + static const String owner = "owner"; + static const String registrationDate = "registrationDate"; + static const String recentLocations = 'recentLocations'; + static const String tripData = 'tripData'; +} diff --git a/lib/constant/char_map.dart b/lib/constant/char_map.dart new file mode 100644 index 0000000..d6a6ee7 --- /dev/null +++ b/lib/constant/char_map.dart @@ -0,0 +1,68 @@ +Map cn = { + "0": "3", + "1": "7", + "2": "1", + "3": "9", + "4": "0", + "5": "5", + "6": "2", + "7": "6", + "8": "4", + "9": "8" +}; +Map cs = { + "a": "q", + "b": "x", + "c": "f", + "d": "y", + "e": "j", + "f": "u", + "g": "k", + "h": "w", + "i": "o", + "j": "e", + "k": "g", + "l": "r", + "m": "n", + "n": "b", + "o": "i", + "p": "v", + "q": "a", + "r": "l", + "s": "z", + "t": "c", + "u": "h", + "v": "p", + "w": "t", + "x": "d", + "y": "s", + "z": "m" +}; +Map cC = { + "A": "Q", + "B": "X", + "C": "F", + "D": "Y", + "E": "J", + "F": "U", + "G": "K", + "H": "W", + "I": "O", + "J": "E", + "K": "G", + "L": "R", + "M": "N", + "N": "B", + "O": "I", + "P": "V", + "Q": "A", + "R": "L", + "S": "Z", + "T": "C", + "U": "H", + "V": "P", + "W": "T", + "X": "D", + "Y": "S", + "Z": "M" +}; diff --git a/lib/constant/colors.dart b/lib/constant/colors.dart new file mode 100644 index 0000000..18c087a --- /dev/null +++ b/lib/constant/colors.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; + +class AppColor { + static const Color primaryColor = Colors.black; + static const Color secondaryColor = Colors.white; + static const Color accentColor = Colors.grey; + static const Color redColor = Color(0xFFEA4335); // Google Red + static const Color greenColor = Color(0xFF34A853); // Google Green + static const Color blueColor = + Color.fromARGB(255, 66, 135, 246); // Google Blue + static const Color yellowColor = Color(0xFFFBBC05); // Google Yellow + static Color deepPurpleAccent = + const Color.fromARGB(255, 123, 76, 254).withOpacity(0.3); +} diff --git a/lib/constant/credential.dart b/lib/constant/credential.dart new file mode 100644 index 0000000..0054b50 --- /dev/null +++ b/lib/constant/credential.dart @@ -0,0 +1,144 @@ +import 'dart:convert'; +import 'package:crypto/crypto.dart'; + +import '../controller/functions/crud.dart'; +import '../main.dart'; +import 'box_name.dart'; +import 'char_map.dart'; +import 'links.dart'; + +class AC { + gAK() async { + if (box.read(BoxName.apiKeyRun).toString() != 'run') { + var res = await CRUD().get(link: AppLink.getApiKey, payload: {}); + var decod = jsonDecode(res); + print(decod); + Map jsonData = {}; + for (var i = 0; i < decod['message'].length; i++) { + String h = decod['message'][i]['hashed_key'].toString(); + String retrievedString = r(r(r(h, cn), cC), cs); + + await storage.write( + key: decod['message'][i]['name'].toString(), + value: retrievedString.toString(), + ); + // + String name = decod['message'][i]['name'].toString(); + String value = decod['message'][i]['hashed_key'].toString(); + + jsonData[name] = value; + } + String jsonString = json.encode(jsonData); + print(jsonString); + box.write(BoxName.apiKeyRun, 'run'); + } + } + + String q(String b, String c) { + final d = utf8.encode(c); + final e = utf8.encode(b); + + final f = Hmac(sha256, d); + final g = f.convert(e); + + final h = g.bytes; + final i = base64Url.encode(h); + return i; + } + + String j(String k, String l) { + final m = utf8.encode(l); + final n = base64Url.decode(k); + + final o = Hmac(sha256, m); + final p = o.convert(n); + + final q = utf8.decode(p.bytes); + return q; + } + + String a(String b, String c) { + int d = b.length; + int e = d ~/ 4; + + List f = []; + for (int g = 0; g < d; g += e) { + int h = g + e; + if (h > d) { + h = d; + } + String i = b.substring(g, h); + f.add(i); + } + + print(f); + Map j = {}; + j['birinci'] = f[4]; + j['ikinci'] = f[2]; + j['üçüncü'] = c + f[1]; + j['dördüncü'] = f[0]; + j['beş'] = f[3]; + + String k = ''; + j.forEach((l, m) { + k += m; + }); + + return k; + } + + Map n(String o, String c) { + String p = o.replaceAll(c, ''); + + Map q = {}; + q['birinci'] = p[p.length - 5] + p[p.length - 3]; + q['ikinci'] = p[p.length - 1] + p[p.length - 15]; + q['üçüncü'] = p[p.length - 9] + p[p.length - 12]; + q['dördüncü'] = p[p.length - 11] + p[p.length - 6]; + q['beş'] = p[p.length - 2] + p[p.length - 8]; + + return q; + } + + String c(String a, Map b) { + StringBuffer c = StringBuffer(); + c.write(a); + + String d = "Bl"; + c.write(b[d] ?? d); + + StringBuffer e = StringBuffer(); + String f = c.toString(); + + for (int g = 0; g < f.length; g++) { + String h = f[g]; + e.write(b[h] ?? h); + } + + return e.toString(); + } + + String r(String a, Map b) { + StringBuffer c = StringBuffer(); + String d = "Bl"; + int e = d.length; + + for (int f = 0; f < a.length; f++) { + String g = a[f]; + String h = b.keys.firstWhere( + (i) => b[i] == g, + orElse: () => g, + ); + + c.write(h); + } + + String j = c.toString(); + + if (j.endsWith(d)) { + j = j.substring(0, j.length - e); + } + + return j; + } +} diff --git a/lib/constant/info.dart b/lib/constant/info.dart new file mode 100644 index 0000000..5254d29 --- /dev/null +++ b/lib/constant/info.dart @@ -0,0 +1,4469 @@ +class AppInformation { + static const String companyName = 'Mobile-App'; + static const String appName = 'SEFER'; + static const String phoneNumber = '962798583052'; + static const String linkedInProfile = + 'https://www.linkedin.com/in/hamza-ayed/'; + static const String website = 'https://mobile-app.store'; + static const String email = 'hamzaayed@mobile-app.store'; + + static const String privacyPolicy = + ''' + + + + + + + + + + + + +
+
+
+
+
+
+

Terms and Conditions

+

1 TERMS OF USE

+

By downloading, browsing, accessing or using the Mobile Application; “Sefer”, Users agree to be bound by these Terms and Conditions of Use. We reserve the right to amend these terms and conditions at any time. If the User disagrees with any of these Terms and Conditions of Use, the User must immediately discontinue their access to the Mobile Application and their use of the services offered on the Mobile Application. Continued use of the Mobile Application will constitute acceptance of these Terms and Conditions of Use, as may be amended from time to time.

+

2.1. DEFINITIONS

+

In these Terms and Conditions of Use, the following capitalized terms shall have the following meanings, except where the context otherwise requires:

+

“Mobile Application” or “Sefer” refers to the smartphone software through which the company mediates services between Users and Service Providers.

+

"Account" means an account created by a User or a Service Provider on the Mobile Application as part of Registration.

+

“Service Providers” refers to the individuals or companies registered within the Company to provide products or services approved and mediated by the Company/Mobile Application and that are requested/purchased by “Users”. “Service Provider” means any one of them.

+

"Users" means users of the Mobile Application, including you and "User" means any one of them. “Users” also includes Service Providers using the Mobile Application version dedicated to the use of Service Providers.

+

"Privacy Policy" means the privacy policy set out in Clause 14 of these Terms and Conditions of Use.

+

"Redeem" means to redeem a company’s products or services on these Terms and Conditions of Use and

+

"Redemption" means the act of redeeming such products or services.

+

"Register" means to create an Account on the Mobile Application and "Registration" means the act of creating such an Account.

+

"Services" means all the services provided by Service Providers via the Mobile Application and mediated by the Company to Users, and "Service" means any one of them.

+

2.2. WHAT IS THE MOBILE APPLICATION, “Sefer”?

+

The “Sefer” Mobile Application consists in a specialize service with the purpose to schedule/match the Service Provider with the User, however without creating any employee relationship with the Service Provider, meaning that the Mobile Application should be considered only as a service mediator with the purpose of scheduling/matching between Users and Service Providers for the latter to fulfill the service requested by Users. Through the system, the Company allows, totally free of charge, the Users to sign up and request the desired available services from Service Providers in a more efficient way than the conventional existing methods. The Service Providers, by their means, can register on the Mobile Application dedicated for Service Providers through the methods indicated by the Company, pending an evaluation from the Company and the necessary documentation when signing up in accordance with guidelines set by the Transportation General Authority (TGA) to provide services through the Mobile Application. The Service Provider will pay a profit margin fee determined by the Company -in knowledge of the Service Provider- per completed service. Users can pay their ride fare using Apple Pay as an additional payment method in Saudi Arabia on iPhones

+

+

3. GENERAL ISSUES ABOUT THE MOBILE APPLICATION AND THE SERVICES

+

3.1 Applicability of terms and conditions: The use of any Services and/or the Mobile Application and the making of any Redemptions are subject to these Terms and Conditions of Use.

+

3.2 Location: The Mobile Application, the Services and any Redemptions are intended solely for use by Users who access the Mobile Application where it operates and provides its services regionally. We make no representation that the Services (or any goods or services) are available or otherwise suitable for use outside of the regions indicated by the Company. Notwithstanding the above, if the User accesses the Mobile Application, use the Services or make any Redemptions from locations outside the regions indicated by the Service Provider, the User does so on their own initiative and are responsible for the consequences and for compliance with all applicable laws.

+

3.3 Scope: The Mobile Application, the Services and any Redemptions are for Users’ non-commercial, personal use only and must not be used for business purposes unless an official written permission is granted by the Company.

+

3.4 Prevention on use: We reserve the right to prevent the User using the Mobile Application and the Service (or any part of them) and to prevent the User from making any Redemptions.

+

3.5 Equipment and Networks: The provision of the Services and the Mobile Application does not include the provision of a mobile telephone or handheld device or other necessary equipment to access the Mobile Application or the Services or make any Redemptions. To use the Mobile Application or Services or to make Redemptions, the User will require Internet connectivity and appropriate telecommunication links. The User acknowledges that the terms of agreement with their respective mobile network provider will continue to apply when using the Mobile Application. As a result, the User may be charged by the Mobile Provider for access to network connection services for the duration of the connection while accessing the Mobile Application or any such third party charges as may arise. The User accepts responsibility for any such charges that arise.

+

3.6 Permission to use Mobile Application: If the User is not the bill payer for the mobile telephone or handheld device being used to access the Mobile Application, the User will be assumed to have received permission from the bill payer for using the Mobile Application.

+

3.7 License to Use Material: By submitting any text or images (including photographs) via the Application, the User represents that they are the owner of the Material, or have proper authorization from the owner of the Material to use, reproduce and distribute it. The User hereby grants us a worldwide, royalty-free, non-exclusive license to use the Material to promote any products or services.

+

4. REDEMPTIONS

+

4.1 Need for registration: a) Users must Register to make a Redemption from the Mobile Application. b) The Service Provider agrees that by registering they will be scrutinized to be accepted by the Company who may refuse or cancel the Service Provider account at any time, whether by complaints or by internal policy.

+

4.2 Application of these Terms and Conditions of Use: By making any Redemption, the User acknowledges that the Redemption is subject to these Terms and Conditions of Use.

+

4.3 Redemption: Any attempted Redemption not consistent with these Terms and Conditions of Use may be disallowed or rendered void at our or the relevant Service Provider’s discretion.

+

4.4 Responsibility for Redemptions of perishable products of services: Each Service Provider shall be responsible to ensure that any of its products or services for Redemption that are perishable has not expired.

+

4.5 Restrictions: (a) Reproduction, sale, resale or trading of any products or services or Redeemed products is prohibited. (b) If any product or service is Redeemed for less than its face value, there is no entitlement to a credit, cash or Sample equal to the difference between the face value and the amount Redeemed. (c) Redemption of products or services is subject to availability of the relevant Service Providers’ stocks.

+

4.6 Company Not Liable: For the avoidance of doubt, the Company shall not be liable for any losses or damages suffered by Users resulting from a failure by the relevant Service Provider to fulfil any Redemptions in accordance with Clause 4.4 or for a failure by us to deliver any products or services to Users due to the unavailability of such products or services pursuant to Clause 4.5(c). Users accept that the Mobile Application acts solely as a scheduling/matching service between its Users and Service Providers, and that it is not responsible for any issues that arise, including but not limited to accidents, delays, car discomfort, and unavailability of products or services.

+

4.7 Lost/stolen services: Neither we nor any Service Provider shall be responsible for lost or stolen Samples or products that have been Redeemed.

+

+

5. LOCATION ALERTS AND NOTIFICATIONS

+

5.1 The USer agrees to receive pre-programmed notifications (“Location Alerts”) on the Mobile Application from Service Providers if the User has turned on locational services on their mobile telephone or other handheld devices (as the case may be).

+

+

6. USERS’ OBLIGATIONS

+

6.1 Service Provider terms: Users agree to (and shall) abide by the terms and conditions of the relevant Service Provider for which their Redemption relates to, as may be amended from time to time.

+

6.2 Accurate information: The User warrants that all information provided on Registration and contained as part of their Account is true, complete and accurate and that the User will promptly inform us of any changes to such information by updating the information in their Account.

+

6.3 Content on the Mobile Application and Service: It is the User’s responsibility to ensure that any products, services or information available through the Mobile Application or the Services meet their specific requirements before making any Redemption.

+

6.4 Prohibitions in relation to usage of Services or Mobile Application: Without limitation, the User undertakes not to use or permit anyone else to use the Services or Mobile Application:-

+

6.4.1 to send or receive any material which is not civil or tasteful

+

6.4.2 to send or receive any material which is threatening, grossly offensive, of an indecent, obscene or menacing character, blasphemous or defamatory of any person, in contempt of court or in breach of confidence, copyright, rights of personality, publicity or privacy or any other third party rights;

+

6.4.3 to send or receive any material for which the User has not obtained all necessary licenses and/or approvals (from us or third parties); or which constitutes or encourages conduct that would be considered a criminal offence, give rise to civil liability, or otherwise be contrary to the law of or infringe the rights of any third party in any country in the world;

+

6.4.4 to send or receive any material which is technically harmful (including computer viruses, logic bombs, Trojan horses, worms, harmful components, corrupted data or other malicious software or harmful data);

+

6.4.5 to cause annoyance, inconvenience or needless anxiety;

+

6.4.6 to intercept or attempt to intercept any communications transmitted by way of a telecommunications system;

+

6.4.7 for a purpose other than which we have designed them or intended them to be used;

+

6.4.8 for any fraudulent purpose;

+

6.4.9 other than in conformance with accepted Internet practices and practices of any connected networks;

+

6.4.10 in any way which is calculated to incite hatred against any ethnic, religious or any other minority or is otherwise calculated to adversely affect any individual, group or entity; or

+

6.4.11 in such a way as to, or commit any act that would or does, impose an unreasonable or disproportionately large load on our infrastructure.

+

6.5 Prohibitions in relation to usage of Services, Mobile Application: Without limitation, the User further undertakes not to or permit anyone else to:-

+

6.5.1 resell any products or services;

+

6.5.2 furnish false data including false names, addresses and contact details and fraudulently use credit/debit card numbers;

+

6.5.3 attempt to circumvent our security or network including to access data not intended for the User, log into a server or account the User is not expressly authorized to access, or probe the security of other networks (such as running a port scan);

+

6.5.4 execute any form of network monitoring which will intercept data not intended for the User;

+

6.5.5 enter into fraudulent interactions or transactions with us or a Service Provider (including interacting or transacting purportedly on behalf of a third party where the User has no authority to bind that third party or the User is pretending to be a third party);

+

6.5.6 extract data from or hack into the Mobile Application;

+

6.5.7 use the Services or Mobile Application in breach of these Terms and Conditions of Use;

+

6.5.8 engage in any unlawful activity in connection with the use of the Mobile Application or the Services; or

+

6.5.9 engage in any conduct which, in our exclusive reasonable opinion, restricts or inhibits any other customer from properly using or enjoying the Mobile Application or Services.

+

+

7. RULES ABOUT USE OF THE SERVICE AND THE MOBILE APPLICATION

+

7.1 We will use reasonable endeavors to correct any errors or omissions as soon as practicable after being notified of them. However, we do not guarantee that the Services or the Mobile Application will be free of faults, and we do not accept liability for any such faults, errors or omissions. In the event of any such error, fault or omission, Users should report it by contacting us at JORDAN: 962798583052 .

+

7.2 We do not warrant that Users’ use of the Services or the Mobile Application will be uninterrupted and we do not warrant that any information (or messages) transmitted via the Services or the Mobile Application will be transmitted accurately, reliably, in a timely manner or at all. Notwithstanding that we will try to allow uninterrupted access to the Services and the Mobile Application, access to the Services and the Mobile Application may be suspended, restricted or terminated at any time.

+

7.3 We do not give any warranty that the Services and the Mobile Application are free from viruses or anything else which may have a harmful effect on any technology.

+

7.4 We reserve the right to change, modify, substitute, suspend or remove without notice any information or Services on the Mobile Application from time to time. Users’ access to the Mobile Application and/or the Services may also be occasionally restricted to allow for repairs, maintenance or the introduction of new facilities or services. We will attempt to restore such access as soon as we reasonably can. For the avoidance of doubt, we reserve the right to withdraw any information or Services from the Mobile Application at any time.

+

7.5 We reserve the right to block access to and/or to edit or remove any material which in our reasonable opinion may give rise to a breach of these Terms and Conditions of Use.

+

7.6 The acceptance and denial of the service request may occur at first by the Service Provider, who can accept or deny the service when receiving a notification for a request. The User may cancel the contract for any reason which may or may not apply cancellation fees for which the conditions and amount is determined and communicated by the Company. Both recognize that “Sefer” is not liable for any delays, cancellations, failure to cancel the contract and miscommunication between the User and the Service Provider, nor for any delay or failure in the delivery of services from the Service Provider.

+

+

8. SUSPENSION AND TERMINATION

+

8.1 If the User uses (or others, with the User’s permission use) the Mobile Application, any Services in contravention of these Terms and Conditions of Use, we may suspend their use of the Services and/or Mobile Application.

+

8.2 If we suspend the Services or Mobile Application, we may refuse to restore the Services or Mobile Application for the User’s use until we receive an assurance from them, in a form we deem acceptable, that there will be no further breach of the provisions of these Terms and Conditions of Use.

+

8.3 The Company shall fully co-operate with any law enforcement authorities or court order requesting or directing the Company to disclose the identity or locate anyone in breach of these Terms and Conditions of Use.

+

8.4 Without limitation to anything else in this Clause 8, we shall be entitled immediately or at any time (in whole or in part) to: (a) suspend the Services and/or Mobile Application; (b) suspend Users’ use of the Services and/or Mobile Application; and/or (c) suspend the use of the Services and/or Mobile Application for persons we believe to be connected (in whatever manner) to the concerned User, if:

+

8.4.1 the User commits any breach of these Terms and Conditions of Use;

+

8.4.2 we suspect, on reasonable grounds, that the User has, might or will commit a breach of these Terms and Conditions of Use; or

+

8.4.3 we suspect, on reasonable grounds, that the User may have committed or will be committing any fraud against us or any person.

+

8.5 Our rights under this Clause 8 shall not prejudice any other right or remedy we may have in respect of any breach or any rights, obligations or liabilities accrued prior to termination.

+

+

9. DISCLAIMER AND EXCLUSION OF LIABILITY

+

9.1 The Mobile Application, the Services, the information on the Mobile Application and use of all related facilities are provided on an "as is, as available" basis without any warranties whether express or implied.

+

9.2 The credit balance shall remain valid for the specific period. The credit in the wallet will be expired after 6 months of inactivity.

+

9.3 To the fullest extent permitted by applicable law, we disclaim all representations and warranties relating to the Mobile Application and its contents, including in relation to any inaccuracies or omissions in the Mobile Application, warranties of merchantability, quality, fitness for a particular purpose, accuracy, availability, non-infringement or implied warranties from course of dealing or usage of trade.

+

9.4 We do not warrant that the Mobile Application will always be accessible, uninterrupted, timely, secure, error free or free from computer virus or other invasive or damaging code or that the Mobile Application will not be affected by any acts of nature or other force majeure events, including inability to obtain or shortage of necessary materials, equipment facilities, power or telecommunications, lack of telecommunications equipment or facilities and failure of information technology or telecommunications equipment or facilities.

+

9.5 While we may use reasonable efforts to include accurate and up-to-date information on the Mobile Application, we make no warranties or representations as to its accuracy, timeliness or completeness.

+

9.6 We shall not be liable for any acts or omissions of any third parties howsoever caused, and for any direct, indirect, incidental, special, consequential or punitive damages, howsoever caused, resulting from or in connection with the Mobile Application and the services offered in the mobile application, Users’ access to, use of or inability to use the mobile application or the services offered in the mobile application, reliance on or downloading from the mobile application and/or services, or any delays, inaccuracies in the information or in its transmission including but not limited to damages for loss of business or profits, use, data or other intangible, even if we have been advised of the possibility of such damages.

+

9.7 We shall not be liable in contract, tort (including negligence or breach of statutory duty) or otherwise howsoever and whatever the cause thereof, for any indirect, consequential, collateral, special or incidental loss or damage suffered or incurred by the User in connection with the Mobile Application and these Terms and Conditions of Use. For the purposes of these Terms and Conditions of Use, indirect or consequential loss or damage includes, without limitation, loss of revenue, profits, anticipated savings or business, loss of data or goodwill, loss of use or value of any equipment including software, claims of third parties, and all associated and incidental costs and expenses.

+

9.8 The above exclusions and limitations apply only to the extent permitted by law. None of the User’s statutory rights as a consumer that cannot be excluded or limited are affected.

+

9.9 Notwithstanding our efforts to ensure that our system is secure, the User acknowledges that all electronic data transfers are potentially susceptible to interception by others. We cannot, and do not, warrant that data transfers pursuant to the Mobile Application, or electronic mail transmitted to and from us, will not be monitored or read by others.

+

+

10. INDEMNITY

+

The User agrees to indemnify and keep us indemnified against any claim, action, suit or proceeding brought or threatened to be brought against us which is caused by or arising out of (a) the User’s use of the Services, (b) any other party’s use of the Services using the User’s user ID, verification PIN and/or any identifier number allocated by the Company, and/or (c) the User’s breach of any of these Terms and Conditions of Use, and to pay us damages, costs and interest in connection with such claim, action, suit or proceeding.

+

+

11. INTELLECTUAL PROPERTY RIGHTS

+

11.1 All editorial content, information, photographs, illustrations, artwork and other graphic materials, and names, logos and trade marks on the Mobile Application are protected by copyright laws and/or other laws and/or international treaties, and belong to us and/or our suppliers, as the case may be. These works, logos, graphics, sounds or images may not be copied, reproduced, retransmitted, distributed, disseminated, sold, published, broadcasted or circulated whether in whole or in part, unless expressly permitted by us and/or our suppliers, as the case may be.

+

11.2 Nothing contained on the Mobile Application should be construed as granting by implication, estoppel, or otherwise, any license or right to use any trademark displayed on the Mobile Application without our written permission. Misuse of any trademarks or any other content displayed on the Mobile Application is prohibited.

+

11.3 We will not hesitate to take legal action against any unauthorized usage of our trade marks, name or symbols to preserve and protect its rights in the matter. All rights not expressly granted herein are reserved. Other product and company names mentioned herein may also be the trademarks of their respective owners.

+

+

12. AMENDMENTS

+

12.1 We may periodically make changes to the contents of the Mobile Application, including to the descriptions and prices of goods and services advertised, at any time and without notice. We assume no liability or responsibility for any errors or omissions in the content of the Mobile Application.

+

12.2 We reserve the right to amend these Terms and Conditions of Use from time to time without notice. The revised Terms and Conditions of Use will be posted on the Mobile Application and shall take effect from the date of such posting. The User is advised to review these terms and conditions periodically as they are binding upon the User.

+

+

13. APPLICABLE LAW AND JURISDICTION

+

13.1 These Terms and Conditions of Use shall be governed by and construed in accordance with the applicable Federal laws of Kingdom of Saudi Arabia.

+

13.2 The Mobile Application can be accessed from all countries around the world where the local technology permits. As each of these places have differing laws, by accessing the Mobile Application both the User and we agree that the laws of the country where accessed, without regard to the conflicts of laws principles thereof, will apply to all matters relating to the use of the Mobile Application.

+

13.3 the User accepts and agrees that both the User and we shall submit to the exclusive jurisdiction of the courts of the country where accessed in respect of any dispute arising out of and/or in connection with these Terms and Conditions of Use.

+

+

14. PRIVACY POLICY

+

14.1 Access to the Mobile Application and use of the Services offered on the Mobile Application by the Company and/or its group of companies & partners is subject to this Privacy Policy. By accessing the Mobile Application and by continuing to use the Services offered, Users are deemed to have accepted this Privacy Policy, and in particular, they are deemed to have consented to our use and disclosure of their personal information in the manner prescribed in this Privacy Policy and for the purposes set out in Clauses 3.7 and/or 4.1.1 We reserve the right to amend this Privacy Policy from time to time. If the User disagrees with any part of this Privacy Policy, the User must immediately discontinue their access to the Mobile Application and their use of the Services.

+

14.2 As part of the normal operation of our Services, we collect, use and, in some cases, disclose information about the User to third parties. Accordingly, we have developed this Privacy Policy in order for Users to understand how we collect, use, communicate and disclose and make use of their personal information when they use the Services on the Mobile Application:-

+

(a) Before or at the time of collecting personal information, we will identify the purposes for which information is being collected.

+

(b) We will collect and use of personal information solely with the objective of fulfilling those purposes specified by us and for other compatible purposes, unless we obtain the consent of the individual concerned or as required by law.

+

(c) We will only retain personal information as long as necessary for the fulfillment of those purposes.

+

(d) We will collect personal information by lawful and fair means and, where appropriate, with the knowledge or consent of the individual concerned.

+

(e) Personal information should be relevant to the purposes for which it is to be used, and, to the extent necessary for those purposes, should be accurate, complete, and up-to-date.

+

(f) We will protect personal information by reasonable security safeguards against loss or theft, as well as unauthorized access, disclosure, copying, use or modification.

+

(g) The Company further reserves the right to use all legal means possible and to identify the Users, as well as to request, at any time, additional data and documents it considers appropriate in order to verify personal data informed by the user.

+

We are committed to conducting our business in accordance with these principles in order to ensure that the confidentiality of personal information is protected and maintained.

+

14.3 Social logins policy
Our Services offers you the ability to register and login using Facebook. Where you choose to do this, we will receive certain profile information about you from your social media provider. The profile Information may include your name and social token.
We will use the information we receive only to associate your social token with your Sefer account or for the purposes that are described in this privacy policy.

14.4 Account and data deletion
Based on the applicable laws of your country, you may have the right to request the deletion of your personal data in some circumstances. If you want to delete your account or personal data in the application, please contact us via e-mail: support@mobile-app.store. We will respond to your request within 30 days.

+

15. In-Ride Policy

+

15.1 Smoking Policy:

+

No smoking or other use of tobacco products (including, but not limited to, cigarettes, pipes, cigars, snuff, or chewing tobacco) is permitted during rides. No cigarette butts or other traces of smell, litter, or tobacco use should be present in the vehicle. image

+

15.2 COVID-19 Policy: Face masks must be always worn during rides.

+
+
+
+
+
+
+ + + + + +
+
+ + + + +
+

+ All rights reserved. Fast Global Technology Holding Limited. © 2022 +

+
+
+ +
+ + + + +
+ + + + + + +
+ +'''; +} diff --git a/lib/constant/links.dart b/lib/constant/links.dart new file mode 100644 index 0000000..c51f7a9 --- /dev/null +++ b/lib/constant/links.dart @@ -0,0 +1,225 @@ +import '../env/env.dart'; + +class AppLink { + static final String server = Env.serverPHP; + static String googleMapsLink = 'https://maps.googleapis.com/maps/api/'; + static String llama = 'https://api.llama-api.com/chat/completions'; + static String gemini = + 'https://generativelanguage.googleapis.com/v1beta3/models/text-bison-001:generateText'; + + static String test = "$server/test.php"; + //===============firebase========================== + static String getTokens = "$server/ride/firebase/get.php"; + static String getAllTokenDrivers = + "$server/ride/firebase/getALlTokenDrivers.php"; + static String getAllTokenPassengers = + "$server/ride/firebase/getAllTokenPassengers.php"; + static String addTokens = "$server/ride/firebase/add.php"; + static String addTokensDriver = "$server/ride/firebase/addDriver.php"; + + //=======================Wallet=================== + static String addPaymentTokenDriver = + "$ride/driverWallet/addPaymentToken.php"; + static String addSeferWallet = "$ride/seferWallet/add.php"; + static String getSeferWallet = "$ride/seferWallet/get.php"; + static String addDrivePayment = "$ride/payment/add.php"; + static String updatePaymetToPaid = "$ride/payment/updatePaymetToPaid.php"; + static String wallet = '$server/ride/passengerWallet'; + static String walletDriver = '$server/ride/driverWallet'; + static String getAllPassengerTransaction = + "$wallet/getAllPassengerTransaction.php"; + static String getWalletByPassenger = "$wallet/getWalletByPassenger.php"; + static String getPassengersWallet = "$wallet/get.php"; + static String getPassengerWalletArchive = + "$wallet/getPassengerWalletArchive.php"; + static String addPassengersWallet = "$wallet/add.php"; + static String deletePassengersWallet = "$wallet/delete.php"; + static String updatePassengersWallet = "$wallet/update.php"; + + static String getWalletByDriver = "$walletDriver/getWalletByDriver.php"; + static String getDriversWallet = "$walletDriver/get.php"; + static String addDriversWalletPoints = "$walletDriver/add.php"; + static String deleteDriversWallet = "$walletDriver/delete.php"; + static String updateDriversWallet = "$walletDriver/update.php"; + + //=======================promo===================ride.mobile-app.store/ride/promo/get.php + static String promo = '$server/ride/promo'; + static String getPassengersPromo = "$promo/get.php"; + static String getPromoBytody = "$promo/getPromoBytody.php"; + static String addPassengersPromo = "$promo/add.php"; + static String deletePassengersPromo = "$promo/delete.php"; + static String updatePassengersPromo = "$promo/update.php"; + + ////=======================cancelRide=================== + static String ride = '$server/ride'; + static String addCancelRideFromPassenger = "$server/ride/cancelRide/add.php"; + static String cancelRide = "$server/ride/cancelRide/get.php"; +//-----------------ridessss------------------ + static String addRides = "$ride/rides/add.php"; + static String getRides = "$ride/rides/get.php"; + static String getRideOrderID = "$ride/rides/getRideOrderID.php"; + static String getRideStatus = "$ride/rides/getRideStatus.php"; + static String getRideStatusBegin = "$ride/rides/getRideStatusBegin.php"; + static String getRideStatusFromStartApp = + "$ride/rides/getRideStatusFromStartApp.php"; + static String updateRides = "$ride/rides/update.php"; + static String updateStausFromSpeed = "$ride/rides/updateStausFromSpeed.php"; + static String deleteRides = "$ride/rides/delete.php"; + +//-----------------DriverPayment------------------ + static String adddriverScam = "$ride/driver_scam/add.php"; + static String getdriverScam = "$ride/driver_scam/get.php"; + +/////////---getKazanPercent===//////////// + static String getKazanPercent = "$ride/kazan/get.php"; + static String addKazanPercent = "$ride/kazan/add.php"; + +////-----------------DriverPayment------------------ + static String addDriverpayment = "$ride/payment/add.php"; + static String addDriverPaymentPoints = "$ride/driverPayment/add.php"; + static String getDriverPaymentPoints = "$ride/driverWallet/get.php"; + static String getDriverpaymentToday = "$ride/payment/get.php"; + static String getCountRide = "$ride/payment/getCountRide.php"; + static String getAllPaymentFromRide = "$ride/payment/getAllPayment.php"; + static String getAllPaymentVisa = "$ride/payment/getAllPaymentVisa.php"; + +//-----------------Passenger NotificationCaptain------------------ + static String addNotificationPassenger = + "$ride/notificationPassenger/add.php"; + static String getNotificationPassenger = + "$ride/notificationPassenger/get.php"; + static String updateNotificationPassenger = + "$ride/notificationPassenger/update.php"; +//-----------------Driver NotificationCaptain------------------ + static String addNotificationCaptain = "$ride/notificationCaptain/add.php"; + static String addWaitingRide = "$ride/notificationCaptain/addWaitingRide.php"; + static String getRideWaiting = "$ride/notificationCaptain/getRideWaiting.php"; + static String getNotificationCaptain = "$ride/notificationCaptain/get.php"; + static String updateNotificationCaptain = + "$ride/notificationCaptain/update.php"; + static String deleteNotificationCaptain = + "$ride/notificationCaptain/delete.php"; + //-----------------Api Key------------------ + static String addApiKey = "$ride/apiKey/add.php"; + static String getApiKey = "$ride/apiKey/get.php"; + static String getCnMap = "$server/auth/cnMap.php"; + static String updateApiKey = "$ride/apiKey/update.php"; + static String deleteApiKey = "$ride/apiKey/delete.php"; + +//-----------------Feed Back------------------ + static String addFeedBack = "$ride/feedBack/add.php"; + static String getFeedBack = "$ride/feedBack/get.php"; + static String updateFeedBack = "$ride/feedBack/updateFeedBack.php"; + + //-----------------Tips------------------ + static String addTips = "$ride/tips/add.php"; + static String getTips = "$ride/tips/get.php"; + static String updateTips = "$ride/tips/update.php"; + +//-----------------Help Center------------------ + static String addhelpCenter = "$ride/helpCenter/add.php"; + static String gethelpCenter = "$ride/helpCenter/get.php"; + static String getByIdhelpCenter = "$ride/helpCenter/getById.php"; + static String updatehelpCenter = "$ride/helpCenter/update.php"; + static String deletehelpCenter = "$ride/helpCenter/delete.php"; + + //-----------------license------------------ + static String addLicense = "$ride/license/add.php"; + static String getLicense = "$ride/license/get.php"; + static String updateLicense = "$ride/license/updateFeedBack.php"; +//-----------------RegisrationCar------------------ + static String addRegisrationCar = "$ride/RegisrationCar/add.php"; + static String getRegisrationCar = "$ride/RegisrationCar/get.php"; + static String updateRegisrationCar = "$ride/RegisrationCar/update.php"; + +//-----------------DriverOrder------------------ + + static String addDriverOrder = "$ride/driver_order/add.php"; + static String getDriverOrder = "$ride/driver_order/get.php"; + static String getOrderCancelStatus = + "$ride/driver_order/getOrderCancelStatus.php"; + static String updateDriverOrder = "$ride/driver_order/update.php"; + static String deleteDriverOrder = "$ride/driver_order/delete.php"; + + // ===================================== + static String addRateToPassenger = "$ride/rate/add.php"; + static String addRateToDriver = "$ride/rate/addRateToDriver.php"; + static String getDriverRate = "$ride/rate/getDriverRate.php"; + static String getPassengerRate = "$ride/rate/getPassengerRate.php"; + + ////////////////emails ============// + static String sendEmailToPassengerForTripDetails = + "$ride/rides/emailToPassengerTripDetail.php"; + static String sendEmailToDrivertransaction = + "https://api.sefer.live/sefer/Admin/sendEmailToDrivertransaction.php"; + +// =========================================== + static String pathImage = "$server/upload/types/"; + static String uploadImage = "$server/uploadImage.php"; + static String uploadImage1 = "$server/uploadImage1.php"; + static String uploadImagePortrate = "$server/uploadImagePortrate.php"; + static String uploadImageType = "$server/uploadImageType.php"; +//=============egypt documents ============== + static String uploadEgyptidFront = + "$server/EgyptDocuments/uploadEgyptidFront.php"; + static String uploadEgypt = "$server/uploadEgypt.php"; + + //==================certifcate========== + static String location = '$server/ride/location'; + static String getCarsLocationByPassenger = "$location/get.php"; + static String getFemalDriverLocationByPassenger = + "$location/getFemalDriver.php"; + static String getDriverCarsLocationToPassengerAfterApplied = + "$location/getDriverCarsLocationToPassengerAfterApplied.php"; + static String addCarsLocationByPassenger = "$location/add.php"; + static String deleteCarsLocationByPassenger = "$location/delete.php"; + static String updateCarsLocationByPassenger = "$location/update.php"; + static String getTotalDriverDuration = "$location/getTotalDriverDuration.php"; + static String getTotalDriverDurationToday = + "$location/getTotalDriverDurationToday.php"; + + //==================Blog============= + static String profile = '$server/ride/profile'; + static String getprofile = "$profile/get.php"; + static String getCaptainProfile = "$profile/getCaptainProfile.php"; + static String addprofile = "$profile/add.php"; + static String deleteprofile = "$profile/delete.php"; + static String updateprofile = "$profile/update.php"; + + //===================Auth============ + + static String auth = '$server/auth'; + static String login = "$auth/login.php"; + static String signUp = "$auth/signup.php"; + static String sendVerifyEmail = "$auth/sendVerifyEmail.php"; + static String passengerRemovedAccountEmail = + "$auth/passengerRemovedAccountEmail.php"; + static String verifyEmail = "$auth/verifyEmail.php"; +//===================Auth Captin============ + static String authCaptin = '$server/auth/captin'; + static String loginCaptin = "$authCaptin/login.php"; + static String signUpCaptin = "$authCaptin/register.php"; + static String sendVerifyEmailCaptin = "$authCaptin/sendVerifyEmail.php"; + static String verifyEmailCaptin = "$authCaptin/verifyEmail.php"; + static String removeUser = "$authCaptin/removeAccount.php"; + static String deletecaptainAccounr = "$authCaptin/deletecaptainAccounr.php"; + static String updateAccountBank = "$authCaptin/updateAccountBank.php"; + static String getAccount = "$authCaptin/getAccount.php"; + + //===================Admin Captin============ + + static String getPassengerDetailsByPassengerID = + "$server/Admin/getPassengerDetailsByPassengerID.php"; + static String getPassengerDetails = "$server/Admin/getPassengerDetails.php"; + static String getPassengerbyEmail = "$server/Admin/getPassengerbyEmail.php"; + static String addAdminUser = "$server/Admin/adminUser/add.php"; + static String getdashbord = "$server/Admin/dashbord.php"; + static String getAdminUser = "$server/Admin/adminUser/get.php"; + static String getCaptainDetailsByEmailOrIDOrPhone = + "$server/Admin/AdminCaptain/getCaptainDetailsByEmailOrIDOrPhone.php"; + static String getCaptainDetails = "$server/Admin/AdminCaptain/get.php"; + static String getVisaForEachDriver = "$server/Admin/getVisaForEachDriver.php"; + static String getRidesPerMonth = + "$server/Admin/AdminRide/getRidesPerMonth.php"; + static String getRidesDetails = "$server/Admin/AdminRide/get.php"; +} diff --git a/lib/constant/style.dart b/lib/constant/style.dart new file mode 100644 index 0000000..ddbf7d8 --- /dev/null +++ b/lib/constant/style.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; + +import '../main.dart'; +import 'box_name.dart'; +import 'colors.dart'; + +class AppStyle { + static TextStyle headTitle = TextStyle( + fontWeight: FontWeight.bold, + fontSize: 40, + color: AppColor.accentColor, + fontFamily: box.read(BoxName.lang) == 'en' + ? GoogleFonts.josefinSans().fontFamily + : box.read(BoxName.lang) == 'ar' + ? GoogleFonts.habibi().fontFamily + : GoogleFonts.josefinSans().fontFamily); + static TextStyle headTitle2 = TextStyle( + fontWeight: FontWeight.bold, + fontSize: 26, + color: AppColor.primaryColor, + fontFamily: box.read(BoxName.lang) == 'en' + ? GoogleFonts.josefinSans().fontFamily + : box.read(BoxName.lang) == 'ar' + ? GoogleFonts.amiri().fontFamily + : GoogleFonts.josefinSans().fontFamily); + static TextStyle title = TextStyle( + fontWeight: FontWeight.bold, + fontSize: 16, + color: AppColor.primaryColor, + fontFamily: box.read(BoxName.lang) == 'en' + ? GoogleFonts.josefinSans().fontFamily + : box.read(BoxName.lang) == 'ar' + ? GoogleFonts.amiri().fontFamily + : GoogleFonts.josefinSans().fontFamily); + static TextStyle subtitle = TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + color: AppColor.primaryColor, + fontFamily: box.read(BoxName.lang) == 'en' + ? GoogleFonts.josefinSans().fontFamily + : box.read(BoxName.lang) == 'ar' + ? GoogleFonts.amiri().fontFamily + : GoogleFonts.josefinSans().fontFamily); + static TextStyle number = TextStyle( + fontWeight: FontWeight.bold, + fontSize: 14, + color: AppColor.primaryColor, + fontFamily: GoogleFonts.averiaSansLibre().fontFamily); + + static BoxDecoration boxDecoration = const BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(12)), + color: AppColor.secondaryColor, + boxShadow: [ + BoxShadow( + color: AppColor.accentColor, + offset: Offset(-3, -3), + blurRadius: 0, + spreadRadius: 0, + blurStyle: BlurStyle.outer), + BoxShadow( + color: AppColor.accentColor, + offset: Offset(3, 3), + blurRadius: 0, + spreadRadius: 0, + blurStyle: BlurStyle.outer) + ]); + static BoxDecoration boxDecoration1 = const BoxDecoration( + boxShadow: [ + BoxShadow( + color: AppColor.accentColor, blurRadius: 5, offset: Offset(2, 4)), + BoxShadow( + color: AppColor.accentColor, blurRadius: 5, offset: Offset(-2, -2)) + ], + color: AppColor.secondaryColor, + borderRadius: BorderRadius.all( + Radius.elliptical(15, 30), + ), + ); +} diff --git a/lib/constant/table_names.dart b/lib/constant/table_names.dart new file mode 100644 index 0000000..47cd831 --- /dev/null +++ b/lib/constant/table_names.dart @@ -0,0 +1,9 @@ +class TableName { + static const String placesFavorite = "placesFavorite"; + static const String recentLocations = "recentLocations"; + static const String carLocations = "carLocations"; + static const String driverOrdersRefuse = "driverOrdersRefuse"; + static const String rideLocation = "rideLocation"; + static const String faceDetectTimes = "faceDetectTimes"; + static const String captainNotification = "captainNotification"; +} diff --git a/lib/controller/admin/captain_admin_controller.dart b/lib/controller/admin/captain_admin_controller.dart new file mode 100644 index 0000000..debca72 --- /dev/null +++ b/lib/controller/admin/captain_admin_controller.dart @@ -0,0 +1,105 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:local_auth/local_auth.dart'; + +import '../../constant/colors.dart'; +import '../../constant/links.dart'; +import '../functions/crud.dart'; + +class CaptainAdminController extends GetxController { + bool isLoading = false; + Map captainData = {}; + Map captain = {}; + final captainController = TextEditingController(); + final captainPrizeController = TextEditingController(); + final titleNotify = TextEditingController(); + final bodyNotify = TextEditingController(); + final formCaptainKey = GlobalKey(); + final formCaptainPrizeKey = GlobalKey(); + + Future getCaptainCount() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getCaptainDetails, payload: {}); + var d = jsonDecode(res); + if (d['status'] == 'success') { + captainData = d; + } + + isLoading = false; + update(); + } + + Future addCaptainPrizeToWallet() async { + String? paymentId; + //todo link to add wallet to captain + for (var i = 0; i < captainData['message'].length; i++) { + await CRUD().post(link: AppLink.addDriverPaymentPoints, payload: { + 'driverID': captainData['message'][i]['id'], + 'amount': captainPrizeController.text, + 'paymentMethod': 'Prize', + }).then((value) { + paymentId = value['message'].toString(); + }); + await CRUD().post(link: AppLink.addPassengersWallet, payload: { + 'driverID': captainData['message'][i]['id'], + 'amount': captainPrizeController.text, + 'paymentMethod': 'Prize', + 'paymentID': paymentId.toString(), + }); + } + + Get.back(); + } + + void addCaptainsPrizeToWalletSecure() async { + try { + // Check if local authentication is available + bool isAvailable = await LocalAuthentication().isDeviceSupported(); + if (isAvailable) { + // Authenticate the user + bool didAuthenticate = await LocalAuthentication().authenticate( + localizedReason: 'Use Touch ID or Face ID to confirm payment', + ); + if (didAuthenticate) { + // User authenticated successfully, proceed with payment + await addCaptainPrizeToWallet(); + Get.snackbar('Prize Added', '', backgroundColor: AppColor.greenColor); + } else { + // Authentication failed, handle accordingly + Get.snackbar('Authentication failed', '', + backgroundColor: AppColor.redColor); + // 'Authentication failed'); + } + } else { + // Local authentication not available, proceed with payment without authentication + await addCaptainPrizeToWallet(); + Get.snackbar('Prize Added', '', backgroundColor: AppColor.greenColor); + } + } catch (e) { + rethrow; + } + } + + Future getCaptains() async { + var res = await CRUD() + .get(link: AppLink.getCaptainDetailsByEmailOrIDOrPhone, payload: { + 'driver_id': captainController.text, + 'driverEmail': captainController.text, + 'driverPhone': captainController.text, + }); + var d = jsonDecode(res); + if (d['status'] == 'success') { + captain = d; + } + update(); + } + + @override + void onInit() { + getCaptainCount(); + super.onInit(); + } +} diff --git a/lib/controller/admin/dashboard_controller.dart b/lib/controller/admin/dashboard_controller.dart new file mode 100644 index 0000000..71d152a --- /dev/null +++ b/lib/controller/admin/dashboard_controller.dart @@ -0,0 +1,38 @@ +import 'dart:convert'; + +import 'package:get/get.dart'; +import 'package:sefer_admin1/constant/links.dart'; +import 'package:sefer_admin1/controller/functions/crud.dart'; + +import '../../constant/api_key.dart'; + +class DashboardController extends GetxController { + bool isLoading = false; + List dashbord = []; + int creditSMS = 0; + Future getDashBoard() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getdashbord, payload: {}); + if (res != 'failure') { + var d = jsonDecode(res); + dashbord = d['message']; + isLoading = false; + update(); + } + var res2 = await CRUD().kazumiSMS( + link: 'https://sms.kazumi.me/api/sms/check-credit', + payload: {"username": "Sefer", "password": AK.smsPasswordEgypt}, + ); + + creditSMS = res2['credit']; + + update(); + } + + @override + void onInit() { + getDashBoard(); + super.onInit(); + } +} diff --git a/lib/controller/admin/passenger_admin_controller.dart b/lib/controller/admin/passenger_admin_controller.dart new file mode 100644 index 0000000..eb6b50a --- /dev/null +++ b/lib/controller/admin/passenger_admin_controller.dart @@ -0,0 +1,108 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:local_auth/local_auth.dart'; + +import '../../constant/colors.dart'; +import '../../constant/links.dart'; +import '../functions/crud.dart'; + +class PassengerAdminController extends GetxController { + bool isLoading = false; + Map passengersData = {}; + Map passengers = {}; + double height = 150; + final formPassKey = GlobalKey(); + final formPrizeKey = GlobalKey(); + final titleNotify = TextEditingController(); + final bodyNotify = TextEditingController(); + final passengerController = TextEditingController(); + final passengerPrizeController = TextEditingController(); + + Future getPassengerCount() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getPassengerDetails, payload: {}); + var d = jsonDecode(res); + if (d['status'] == 'success') { + passengersData = d; + } + + isLoading = false; + update(); + } + + Future addPassengerPrizeToWallet() async { + for (var i = 0; i < passengersData['message'].length; i++) { + await CRUD().post(link: AppLink.addPassengersWallet, payload: { + 'passenger_id': passengersData['message'][i]['id'], + 'balance': passengerPrizeController.text, + }); + } + + Get.back(); + } + + void addPassengerPrizeToWalletSecure() async { + try { + // Check if local authentication is available + bool isAvailable = await LocalAuthentication().isDeviceSupported(); + if (isAvailable) { + // Authenticate the user + bool didAuthenticate = await LocalAuthentication().authenticate( + localizedReason: 'Use Touch ID or Face ID to confirm payment', + ); + if (didAuthenticate) { + // User authenticated successfully, proceed with payment + await addPassengerPrizeToWallet(); + Get.snackbar('Prize Added', '', backgroundColor: AppColor.greenColor); + } else { + // Authentication failed, handle accordingly + Get.snackbar('Authentication failed', '', + backgroundColor: AppColor.redColor); + // 'Authentication failed'); + } + } else { + // Local authentication not available, proceed with payment without authentication + await addPassengerPrizeToWallet(); + Get.snackbar('Prize Added', '', backgroundColor: AppColor.greenColor); + } + } catch (e) { + rethrow; + } + } + + Future getPassengers() async { + var res = await CRUD().get(link: AppLink.getPassengerbyEmail, payload: { + 'passengerEmail': passengerController.text, + 'passengerId': passengerController.text, + 'passengerphone': passengerController.text, + }); + var d = jsonDecode(res); + if (d['status'] == 'success') { + passengers = d; + } + update(); + } + + changeHeight() { + if (passengers.isEmpty) { + height = 0; + update(); + } + height = 150; + update(); + } + + void clearPlaces() { + passengers = {}; + update(); + } + + @override + void onInit() { + getPassengerCount(); + super.onInit(); + } +} diff --git a/lib/controller/admin/ride_admin_controller.dart b/lib/controller/admin/ride_admin_controller.dart new file mode 100644 index 0000000..ee1ffcd --- /dev/null +++ b/lib/controller/admin/ride_admin_controller.dart @@ -0,0 +1,73 @@ +import 'dart:convert'; + +import 'package:fl_chart/fl_chart.dart'; +import 'package:get/get.dart'; + +import '../../constant/links.dart'; +import '../../models/model/admin/monthly_ride.dart'; +import '../functions/crud.dart'; + +class RideAdminController extends GetxController { + bool isLoading = false; + late List rideData; + late Map jsonResponse; + List ridesDetails = []; + var chartData; + // late List chartDatasync; + Future getRidesAdminDash() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getRidesPerMonth, payload: {}); + jsonResponse = jsonDecode(res); + rideData = (jsonResponse['message'] as List) + .map((item) => MonthlyDataModel.fromJson(item)) + .toList(); + + chartData = rideData + .map((data) => FlSpot(data.day.toDouble(), data.ridesCount.toDouble())) + .toList(); + + // chartDatasync = (jsonResponse['message'] as List) + // .map((item) => ChartDataS( + // item['year'], + // item['month'], + // item['day'], + // item['rides_count'], + // )) + // .toList(); + isLoading = false; + update(); + } + + Future getRidesDetails() async { + // isLoading = true; + // update(); + var res = await CRUD().get(link: AppLink.getRidesDetails, payload: {}); + + var d = jsonDecode(res); + ridesDetails = d['message']; + + // isLoading = false; + // update(); + } + + @override + void onInit() async { + List initializationTasks = [ + getRidesAdminDash(), + getRidesDetails(), + ]; + // cameras = await availableCameras(); + await Future.wait(initializationTasks); + super.onInit(); + } +} + +// class ChartDataS { +// ChartDataS(this.year, this.month, this.day, this.ridesCount); + +// final int year; +// final int month; +// final int day; +// final int ridesCount; +// } diff --git a/lib/controller/admin/wallet_admin_controller.dart b/lib/controller/admin/wallet_admin_controller.dart new file mode 100644 index 0000000..6315444 --- /dev/null +++ b/lib/controller/admin/wallet_admin_controller.dart @@ -0,0 +1,189 @@ +import 'dart:async'; +import 'dart:convert'; + +import 'package:get/get.dart'; +import 'package:http/http.dart' as http; +import '../../constant/api_key.dart'; +import '../../constant/box_name.dart'; +import '../../constant/links.dart'; +import '../../main.dart'; +import '../../print.dart'; +import '../functions/crud.dart'; + +class WalletAdminController extends GetxController { + bool isLoading = false; + + late Map jsonResponse; + List walletDetails = []; + List driversWalletPoints = []; + + @override + void onInit() { + getWalletForEachDriverToPay(); + super.onInit(); + } + + Future getWalletAdminDash() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getRidesPerMonth, payload: {}); + jsonResponse = jsonDecode(res); + } + + Future payToBankDriverAll() async { + for (var i = 0; i < driversWalletPoints.length; i++) { + String token = await getToken(); + await Future.delayed(const Duration(seconds: 1)); + try { + await payToDriverBankAccount( + token, + driversWalletPoints[i]['total_amount'].toString(), + driversWalletPoints[i]['accountBank'].toString(), + driversWalletPoints[i]['bankCode'].toString(), + driversWalletPoints[i]['name_arabic'].toString(), + driversWalletPoints[i]['driverID'].toString(), + driversWalletPoints[i]['phone'].toString(), + driversWalletPoints[i]['email'].toString(), + ); + await Future.delayed(const Duration(seconds: 3)); + } on FormatException catch (e) { + // Handle the error or rethrow the exception as needed + } + } + } + + Future payToDriverBankAccount( + String token, + String amount, + String bankCardNumber, + String bankCode, + String name, + String driverId, + String phone, + String email) async { + var headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + + var body = jsonEncode({ + "issuer": "bank_card", + "amount": amount, + "full_name": name, + "bank_card_number": bankCardNumber, + "bank_code": bankCode, + "bank_transaction_type": "cash_transfer" + }); + + var response = await http.post( + Uri.parse( + 'https://stagingpayouts.paymobsolutions.com/api/secure/disburse/'), + headers: headers, + body: body); + + if (response.statusCode == 200) { + var d = jsonDecode(response.body); + + if (d['status_description'] == + "Transaction received and validated successfully. Dispatched for being processed by the bank") { + await addPayment('payFromSeferToDriver', driverId, + ((-1) * double.parse(amount)).toString()); + await addSeferWallet('payFromSeferToDriver', driverId, + ((-1) * double.parse(amount)).toString()); + await updatePaymentToPaid(driverId); + await sendEmail(driverId, amount, phone, name, bankCardNumber, email); + } + } else {} + } + + // String paymentToken = ''; + Future generateToken(String amount) async { + var res = await CRUD().post(link: AppLink.addPaymentTokenDriver, payload: { + 'driverID': box.read(BoxName.driverID).toString(), + 'amount': amount.toString(), + }); + var d = jsonDecode(res); + return d['message']; + } + + Future sendEmail( + String driverId, amount, phone, name, bankCardNumber, email) async { + await CRUD().sendEmail(AppLink.sendEmailToDrivertransaction, { + "driverID": driverId, + "total_amount": amount, + "phone": phone, + "name_arabic": name, + "accountBank": bankCardNumber, + "email": email + }); + } + + Future addSeferWallet( + String paymentMethod, String driverID, String point) async { + var seferToken = await generateToken(point.toString()); + await CRUD().post(link: AppLink.addSeferWallet, payload: { + 'amount': point.toString(), + 'paymentMethod': paymentMethod, + 'passengerId': 'driver', + 'token': seferToken, + 'driverId': driverID.toString(), + }); + } + + Future addPayment( + String paymentMethod, String driverID, String amount) async { + var paymentToken = + await generateToken(((double.parse(amount))).toStringAsFixed(0)); + await CRUD().post(link: AppLink.addDrivePayment, payload: { + 'rideId': DateTime.now().toIso8601String(), + 'amount': ((double.parse(amount))).toStringAsFixed(0), + 'payment_method': paymentMethod, + 'passengerID': 'myself', + 'token': paymentToken, + 'driverID': driverID.toString(), + }); + } + + Future updatePaymentToPaid(String driverID) async { + await CRUD().post(link: AppLink.updatePaymetToPaid, payload: { + 'driverID': driverID.toString(), + }); + } + + Future getToken() async { + var headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + // 'Cookie': + // 'csrftoken=74iZJ8XYyuTm5WRq2W4tpWX5eqoJLZVK5QhuDrChWpDtzpgGA269bbCWuEcW85t4' + }; + var body = { + 'grant_type': 'password', + 'username': AK.payMobOutUserName, + 'password': AK.payMobOutPassword, + 'client_id': AK.payMobOutClient_id, + 'client_secret': AK.payMobOutClientSecrret + }; + var res = await http.post( + Uri.parse( + 'https://stagingpayouts.paymobsolutions.com/api/secure/o/token/'), + headers: headers, + body: body, + ); + String token = ''; + if (res.statusCode == 200) { + var decode = jsonDecode(res.body); + token = decode['access_token']; + } + return token; + } + + Future getWalletForEachDriverToPay() async { + isLoading = true; + update(); + var res = await CRUD().get(link: AppLink.getVisaForEachDriver, payload: {}); + var d = jsonDecode(res); + driversWalletPoints = d['message']; + isLoading = false; + update(); + } +} diff --git a/lib/controller/bank_account/payout.dart b/lib/controller/bank_account/payout.dart new file mode 100644 index 0000000..dadd402 --- /dev/null +++ b/lib/controller/bank_account/payout.dart @@ -0,0 +1,116 @@ +import 'dart:convert'; + +import 'package:get/get.dart'; +import 'package:http/http.dart' as http; + +import '../../../constant/links.dart'; +import '../../constant/box_name.dart'; +import '../../constant/colors.dart'; +import '../../main.dart'; +import '../functions/crud.dart'; + +class PaymobPayout extends GetxController { + bool isLoading = false; + String dropdownValue = 'etisalat'; + + Future getToken() async { + var headers = { + 'Content-Type': 'application/x-www-form-urlencoded', + // 'Cookie': + // 'csrftoken=74iZJ8XYyuTm5WRq2W4tpWX5eqoJLZVK5QhuDrChWpDtzpgGA269bbCWuEcW85t4' + }; + var body = { + 'grant_type': 'password', + 'username': 'sefer_api_checker', + 'password': '#c3pSwbUxOKpQnr5hHZAgpkSW', + 'client_id': 'kmNWU5gKsL8LKVhsJFbOGTEb3YQ5sQhvBoB8pqoW', + 'client_secret': + 'htV6nFANLDd658ueTEuMrIqwjcXsocMXmBLAYof7FuutBcSxdTdoNqFl3EAvO6zrOgGPLdiMrofNp2V9ASVRpjoSlFjDNRzY7hfPunAJEgf2N5ZUuknN4QniaqIZvaNt' + }; + var res = await http.post( + Uri.parse( + 'https://stagingpayouts.paymobsolutions.com/api/secure/o/token/'), + headers: headers, + body: body, + ); + String token = ''; + if (res.statusCode == 200) { + var decode = jsonDecode(res.body); + token = decode['access_token']; + } + return token; + } + + payToDriverWallet( + String token, String amount, String issuer, String msisdn) async { + var headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + var body = json.encode({ + "amount": amount, //"10.00", + "issuer": issuer, //"vodafone", + "msisdn": msisdn, // "01023456789" + }); + var res = await http.post( + Uri.parse( + 'https://stagingpayouts.paymobsolutions.com/api/secure/disburse/'), + headers: headers, + body: body, + ); + var dec = jsonDecode(res.body); + if (dec['disbursement_status'] == 'successful') { + await CRUD().post(link: AppLink.addDriverpayment, payload: { + 'rideId': DateTime.now().toIso8601String(), + 'amount': ((-1) * (double.parse(dec['amount'])) + 5).toStringAsFixed(0), + 'payment_method': 'payout', + 'passengerID': 'myself', + 'driverID': box.read(BoxName.driverID).toString(), + }); + Get.snackbar('Transaction successful'.tr, + '${'Transaction successful'.tr} ${dec['amount']}', + backgroundColor: AppColor.greenColor); + // Get.find().getCaptainWalletFromRide(); + } else if (dec['disbursement_status'] == 'failed') { + Get.snackbar('Transaction failed'.tr, 'Transaction failed'.tr, + backgroundColor: AppColor.redColor); + } + } + + payToDriverBankAccount(String token, String amount, String bankCardNumber, + String bankCode) async { + var headers = { + 'Authorization': 'Bearer $token', + 'Content-Type': 'application/json', + }; + var body = { + "issuer": "bank_card", + "amount": amount, //9.0, + "full_name": + '${box.read(BoxName.nameDriver)} ${box.read(BoxName.lastNameDriver)}', + "bank_card_number": bankCardNumber, //"1111-2222-3333-4444", + "bank_code": bankCode, //"CIB", + "bank_transaction_type": "cash_transfer" + }; + var res = await http + .post( + Uri.parse( + 'https://stagingpayouts.paymobsolutions.com/api/secure/disburse/'), + headers: headers, + body: body, + ) + .then((value) {}); + } + + Future payToWalletDriverAll( + String amount, String issuer, String msisdn) async { + String token = await getToken(); + await payToDriverWallet(token, amount, issuer, msisdn); + } + + Future payToBankDriverAll( + String amount, String bankCardNumber, String bankCode) async { + String token = await getToken(); + await payToDriverBankAccount(token, amount, bankCardNumber, bankCode); + } +} diff --git a/lib/controller/firebase/firbase_messge.dart b/lib/controller/firebase/firbase_messge.dart new file mode 100644 index 0000000..2bcf8af --- /dev/null +++ b/lib/controller/firebase/firbase_messge.dart @@ -0,0 +1,461 @@ +import 'dart:convert'; +import 'dart:io'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:http/http.dart' as http; + +import '../../constant/api_key.dart'; +import '../../constant/box_name.dart'; +import '../../constant/colors.dart'; +import '../../constant/links.dart'; +import '../../constant/style.dart'; +import '../../main.dart'; +import '../../views/widgets/elevated_btn.dart'; +import 'local_notification.dart'; + +class FirebaseMessagesController extends GetxController { + final fcmToken = FirebaseMessaging.instance; + + List tokens = []; + List tokensPassengers = []; + List dataTokens = []; + late String driverID; + late String driverToken; + NotificationSettings? notificationSettings; + + Future getNotificationSettings() async { + // Get the current notification settings + NotificationSettings? notificationSettings = + await FirebaseMessaging.instance.getNotificationSettings(); + 'Notification authorization status: ${notificationSettings.authorizationStatus}'; + + // Call the update function if needed + update(); + } + + Future requestFirebaseMessagingPermission() async { + FirebaseMessaging messaging = FirebaseMessaging.instance; + + // Check if the platform is Android + if (Platform.isAndroid) { + // Request permission for Android + await messaging.requestPermission(); + } else if (Platform.isIOS) { + // Request permission for iOS + NotificationSettings settings = await messaging.requestPermission( + alert: true, + announcement: true, + badge: true, + carPlay: true, + criticalAlert: true, + provisional: false, + sound: true, + ); + messaging.setForegroundNotificationPresentationOptions( + alert: true, badge: true, sound: true); + } + } + + Future getTokens() async { + var res = await http.post( + Uri.parse(AppLink.getTokens), + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + }, + body: {}, + ); + var jsonResponse = jsonDecode(res.body); + if (jsonResponse['status'] == 'success') { + dataTokens = jsonResponse['data']; + for (var i = 0; i < dataTokens.length; i++) { + tokens.add(jsonResponse['data'][i]['token']); + } + box.write(BoxName.tokens, tokens); + } else { + Get.defaultDialog(title: "Warning", middleText: "Server Error"); + } + } + + Future getAllTokenDrivers() async { + var res = await http.post( + Uri.parse(AppLink.getAllTokenDrivers), + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + }, + body: {}, + ); + var jsonResponse = jsonDecode(res.body); + if (jsonResponse['status'] == 'success') { + dataTokens = jsonResponse['data']; + for (var i = 0; i < dataTokens.length; i++) { + tokens.add(jsonResponse['data'][i]['token']); + } + box.write(BoxName.tokensDrivers, tokens); + } else { + Get.defaultDialog(title: "Warning", middleText: "Server Error"); + } + } + + Future getAllTokenPassengers() async { + var res = await http.post( + Uri.parse(AppLink.getAllTokenPassengers), + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + }, + body: {}, + ); + var jsonResponse = jsonDecode(res.body); + if (jsonResponse['status'] == 'success') { + dataTokens = jsonResponse['data']; + for (var i = 0; i < dataTokens.length; i++) { + tokensPassengers.add(jsonResponse['data'][i]['token']); + } + box.write(BoxName.tokensPassengers, tokensPassengers); + } else { + Get.defaultDialog(title: "Warning", middleText: "Server Error"); + } + } + + Future getToken() async { + fcmToken.getToken().then((token) { + if (box.read(BoxName.email) == null) { + box.write(BoxName.tokenDriver, token); + } else { + box.write(BoxName.tokenFCM, token); + } + }); + + FirebaseMessaging.onMessage.listen((RemoteMessage message) { + // If the app is in the background or terminated, show a system tray message + RemoteNotification? notification = message.notification; + AndroidNotification? android = notification?.android; + // if (notification != null && android != null) { + if (message.data.isNotEmpty && message.notification != null) { + fireBaseTitles(message); + } + }); + } + + void fireBaseTitles(RemoteMessage message) { + if (message.notification!.title! == 'Order') { + if (Platform.isAndroid) { + // NotificationController().showNotification('Order', '', 'order'); + } + var myListString = message.data['DriverList']; + // var points = message.data['PolylineJson']; + + var myList = jsonDecode(myListString) as List; + // var myPoints = jsonDecode(points) as List; + driverToken = myList[14].toString(); + // This is for location using and uploading status + + update(); + } + } + + SnackbarController driverAppliedTripSnakBar() { + return Get.snackbar( + 'Driver Applied the Ride for You'.tr, + '', + colorText: AppColor.greenColor, + duration: const Duration(seconds: 3), + snackPosition: SnackPosition.TOP, + titleText: Text( + 'Applied'.tr, + style: const TextStyle(color: AppColor.redColor), + ), + messageText: Text( + 'Driver Applied the Ride for You'.tr, + style: AppStyle.title, + ), + icon: const Icon(Icons.approval), + shouldIconPulse: true, + margin: const EdgeInsets.all(16), + padding: const EdgeInsets.all(16), + ); + } + + Future passengerDialog(String message) { + return Get.defaultDialog( + barrierDismissible: false, + title: 'message From passenger'.tr, + titleStyle: AppStyle.title, + middleTextStyle: AppStyle.title, + middleText: message.tr, + confirm: MyElevatedButton( + title: 'Ok'.tr, + onPressed: () { + // FirebaseMessagesController().sendNotificationToPassengerToken( + // 'Hi ,I will go now'.tr, + // 'I will go now'.tr, + // Get.find().driverToken, []); + // Get.find() + // .startTimerDriverWaitPassenger5Minute(); + + Get.back(); + })); + } + + // Future driverFinishTripDialoge(List driverList) { + // return Get.defaultDialog( + // title: 'Driver Finish Trip'.tr, + // content: const DriverTipWidget(), + // confirm: MyElevatedButton( + // title: 'Yes'.tr, + // onPressed: () async { + // var tip = (Get.find().totalPassenger) * + // (double.parse(box.read(BoxName.tipPercentage.toString()))); + // var res = await CRUD().post(link: AppLink.addTips, payload: { + // 'passengerID': box.read(BoxName.passengerID), + // 'driverID': driverList[0].toString(), + // 'rideID': driverList[1].toString(), + // 'tipAmount': tip.toString(), + // }); + // await CRUD().post(link: AppLink.addPassengersWallet, payload: { + // 'passenger_id': box.read(BoxName.passengerID).toString(), + // 'balance': ((-1) * tip).toString() + // }); + + // await CRUD().post(link: AppLink.addDriversWalletPoints, payload: { + // 'driverID': driverList[0].toString(), + // 'paymentID': '${Get.find().rideId}tip', + // 'amount': (tip * 100).toString(), + // 'paymentMethod': 'visa-tip', + // }); + + // if (res != 'failure') { + // FirebaseMessagesController().sendNotificationToAnyWithoutData( + // 'You Have Tips', + // '${'${tip.toString()}\$${' tips\nTotal is'.tr}'} ${tip + (Get.find().totalPassenger)}', + // driverList[2].toString(), + // ); + // } + // Get.to(() => RateDriverFromPassenger(), arguments: { + // 'driverId': driverList[0].toString(), + // 'rideId': driverList[1].toString(), + // 'price': driverList[3].toString() + // }); + // }, + // kolor: AppColor.greenColor, + // ), + // cancel: MyElevatedButton( + // title: 'No,I want'.tr, + // onPressed: () { + // Get.to(() => RateDriverFromPassenger(), arguments: { + // 'driverId': driverList[0].toString(), + // 'rideId': driverList[1].toString(), + // 'price': driverList[3].toString() + // }); + // }, + // kolor: AppColor.redColor, + // )); + // } + + void sendNotificationAll(String title, body) async { + // Get the token you want to subtract. + String token = box.read(BoxName.tokenFCM); + tokens = box.read(BoxName.tokensDrivers); + // Subtract the token from the list of tokens. + tokens.remove(token); + + // Save the list of tokens back to the box. + // box.write(BoxName.tokens, tokens); + // tokens = box.read(BoxName.tokens); + for (var i = 0; i < tokens.length; i++) { + http + .post(Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=${AK.serverAPI}' + }, + body: jsonEncode({ + 'notification': { + 'title': title, + 'body': body, + 'sound': 'start.wav' + }, + 'priority': 'high', + 'data': { + 'click_action': 'FLUTTER_NOTIFICATION_CLICK', + 'id': '1', + 'status': 'done' + }, + 'to': tokens[i], + })) + .whenComplete(() {}) + .catchError((e) {}); + } + } + + // for (var i = 0; i < tokens.length; i++) { + // http + // .post(Uri.parse('https://fcm.googleapis.com/fcm/send'), + // headers: { + // 'Content-Type': 'application/json', + // 'Authorization': 'key=${storage.read(key: BoxName.serverAPI}' + // }, + // body: jsonEncode({ + // 'notification': { + // 'title': title, + // 'body': body, + // 'sound': 'true' + // }, + // 'priority': 'high', + // 'data': { + // 'click_action': 'FLUTTER_NOTIFICATION_CLICK', + // 'id': '1', + // 'status': 'done' + // }, + // 'to': tokens[i], + // })) + // .whenComplete(() {}) + // .catchError((e) { + // }); + // } + // } + + void sendNotificationToPassengerToken( + String title, body, token, List map) async { + try { + final response = await http.post( + Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=${AK.serverAPI}' + }, + body: jsonEncode({ + 'notification': { + 'title': title, + 'body': body, + 'sound': 'tone2.wav' + }, + 'data': { + 'passengerList': map, + }, + 'priority': 'high', + 'to': token, + }), + ); + + if (response.statusCode == 200) { + // Notification sent successfully + } else { + // Handle error response + 'Failed to send notification. Status code: ${response.statusCode}'; + } + } catch (e) { + // Handle other exceptions + } + } + + void sendNotificationToAnyWithoutData( + String title, String body, String token) async { + try { + final response = await http.post( + Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=${AK.serverAPI}' + }, + body: jsonEncode({ + 'notification': { + 'title': title, + 'body': body, + 'sound': 'notify.wav' + }, + 'data': { + 'click_action': 'FLUTTER_NOTIFICATION_CLICK', + 'id': '1', + 'status': 'done' + }, + 'priority': 'high', + 'to': token, + }), + ); + + if (response.statusCode == 200) { + // Notification sent successfully + } else { + // Handle error response + 'Failed to send notification. Status code: ${response.statusCode}'; + } + } catch (e) { + // Handle other exceptions + } + } + + void sendNotificationToDriverMAP( + String title, String body, String token, List data) async { + try { + final response = await http.post( + Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=${AK.serverAPI}' + }, + body: jsonEncode({ + 'notification': { + 'title': title, + 'body': body, + // 'sound': 'tone2.wav', + 'sound': 'order.wav' + }, + 'data': { + 'DriverList': data, + }, + 'priority': 'high', + 'to': token, + }), + ); + + if (response.statusCode == 200) { + // Notification sent successfully + } else { + // Handle error response + 'Failed to send notification. Status code: ${response.statusCode}'; + } + } catch (e) { + // Handle other exceptions + } + } + + void sendNotificationToDriverMapPolyline(String title, String body, + String token, List data, String polylineJson) async { + try { + final response = await http.post( + Uri.parse('https://fcm.googleapis.com/fcm/send'), + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'key=${AK.serverAPI}' + }, + body: jsonEncode({ + 'notification': { + 'title': title, + 'body': body, + // 'sound': 'tone2.wav', + 'sound': 'order.wav' + }, + 'data': { + 'DriverList': data, + 'PolylineJson': polylineJson, + }, + 'priority': 'high', + 'to': token, + }), + ); + + if (response.statusCode == 200) { + // Notification sent successfully + } else { + // Handle error response + 'Failed to send notification. Status code: ${response.statusCode}'; + } + } catch (e) { + // Handle other exceptions + } + } +} diff --git a/lib/controller/firebase/local_notification.dart b/lib/controller/firebase/local_notification.dart new file mode 100644 index 0000000..6ea5160 --- /dev/null +++ b/lib/controller/firebase/local_notification.dart @@ -0,0 +1,29 @@ +// import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +// import 'package:get/get.dart'; + +// class NotificationController extends GetxController { +// final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin = +// FlutterLocalNotificationsPlugin(); + +// // Initializes the local notifications plugin +// Future initNotifications() async { +// const AndroidInitializationSettings android = +// AndroidInitializationSettings('@mipmap/launcher_icon'); +// const InitializationSettings initializationSettings = +// InitializationSettings(android: android); +// await _flutterLocalNotificationsPlugin.initialize(initializationSettings); +// } + +// // Displays a notification with the given title and message +// void showNotification(String title, String message, String tone) async { +// AndroidNotificationDetails android = AndroidNotificationDetails( +// 'your channel id', 'your channel name', +// importance: Importance.max, +// priority: Priority.high, +// showWhen: false, +// sound: RawResourceAndroidNotificationSound(tone)); + +// NotificationDetails details = NotificationDetails(android: android); +// await _flutterLocalNotificationsPlugin.show(0, title, message, details); +// } +// } diff --git a/lib/controller/functions/crud.dart b/lib/controller/functions/crud.dart new file mode 100644 index 0000000..7ba4186 --- /dev/null +++ b/lib/controller/functions/crud.dart @@ -0,0 +1,484 @@ +import 'dart:convert'; + +import 'package:get/get.dart'; +import 'package:http/http.dart' as http; + +import '../../constant/api_key.dart'; +import '../../constant/box_name.dart'; +import '../../constant/links.dart'; +import '../../env/env.dart'; +import '../../main.dart'; +import 'gemeni.dart'; +import 'llama_ai.dart'; +import 'upload_image.dart'; + +class CRUD { + Future get({ + required String link, + Map? payload, + }) async { + var url = Uri.parse( + link, + ); + var response = await http.post( + url, + body: payload, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', + }, + ); + // if (response.statusCode == 200) { + var jsonData = jsonDecode(response.body); + if (jsonData['status'] == 'success') { + return response.body; + } + + return jsonData['status']; + } + // } + + Future getAgoraToken({ + required String channelName, + required String uid, + }) async { + var uid = box.read(BoxName.phone) ?? box.read(BoxName.phoneDriver); + var res = await http.get( + Uri.parse( + 'https://repulsive-pig-rugby-shirt.cyclic.app/token?channelName=$channelName'), + headers: {'Authorization': 'Bearer ${AK.agoraAppCertificate}'}); + + if (res.statusCode == 200) { + var response = jsonDecode(res.body); + return response['token']; + } else {} + } + + Future getLlama({ + required String link, + required String payload, + required String prompt, + }) async { + var url = Uri.parse( + link, + ); + var headers = { + 'Content-Type': 'application/json', + 'Authorization': + 'Bearer LL-X5lJ0Px9CzKK0HTuVZ3u2u4v3tGWkImLTG7okGRk4t25zrsLqJ0qNoUzZ2x4ciPy' + // 'Authorization': 'Bearer ${Env.llamaKey}' + }; + var data = json.encode({ + "model": "Llama-3-70b-Inst-FW", + // "model": "llama-13b-chat", + "messages": [ + { + "role": "user", + "content": + "Extract the desired information from the following passage as json decoded like $prompt just in this:\n\n$payload" + } + ], + "temperature": 0.9 + }); + var response = await http.post( + url, + body: data, + headers: headers, + ); + + if (response.statusCode == 200) { + return response.body; + } + return response.statusCode; + } + + Future allMethodForAI(String prompt, linkPHP, imagePath) async { + // await ImageController().choosImage(linkPHP, imagePath); + Future.delayed(const Duration(seconds: 2)); + var extractedString = + await arabicTextExtractByVisionAndAI(imagePath: imagePath); + var json = jsonDecode(extractedString); + var textValues = getAllTextValuesWithLineNumbers(json); + // List textValues = getAllTextValues(json); + + // await AI().geminiAiExtraction(prompt, textValues); + } + + Map>> getAllTextValuesWithLineNumbers( + Map json) { + Map>> output = {}; + int lineNumber = 1; + + if (json.containsKey('regions')) { + List regions = json['regions']; + for (Map region in regions) { + if (region.containsKey('lines')) { + List lines = region['lines']; + List> linesWithText = []; + for (Map line in lines) { + if (line.containsKey('words')) { + List words = line['words']; + String lineText = ""; + for (Map word in words) { + if (word.containsKey('text')) { + lineText += word['text'] + " "; + } + } + lineText = lineText.trim(); + linesWithText.add( + {"line_number": lineNumber.toString(), "text": lineText}); + lineNumber++; + } + } + output["region_${region.hashCode}"] = linesWithText; + } + } + } + + return output; + } + + // List getAllTextValues(Map json) { + // List textValues = []; + + // if (json.containsKey('regions')) { + // List regions = json['regions']; + // for (Map region in regions) { + // if (region.containsKey('lines')) { + // List lines = region['lines']; + // for (Map line in lines) { + // if (line.containsKey('words')) { + // List words = line['words']; + // for (Map word in words) { + // if (word.containsKey('text')) { + // textValues.add(word['text']); + // } + // } + // } + // } + // } + // } + // } + + // return textValues; + // } + + Future arabicTextExtractByVisionAndAI({ + required String imagePath, + }) async { + var headers = { + 'Content-Type': 'application/json', + 'Ocp-Apim-Subscription-Key': '21010e54b50f41a4904708c526e102df' + }; + // var url = Uri.parse( + // 'https://ocrhamza.cognitiveservices.azure.com/vision/v2.1/ocr?language=ar', + // ); + String imagePathFull = + '${AppLink.server}card_image/$imagePath-${box.read(BoxName.driverID)}.jpg'; + + var request = http.Request( + 'POST', + Uri.parse( + 'https://ocrhamza.cognitiveservices.azure.com/vision/v2.1/ocr?language=ar')); + request.body = json.encode({"url": imagePathFull}); + request.headers.addAll(headers); + + http.StreamedResponse response = await request.send(); + + if (response.statusCode == 200) { + return await response.stream.bytesToString(); + } else {} + } + + Future getChatGPT({ + required String link, + required String payload, + }) async { + var url = Uri.parse( + link, + ); + var headers = { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ${Env.chatGPTkeySeferNew}' + }; + var data = json.encode({ + "model": "gpt-3.5-turbo", + "messages": [ + { + "role": "user", + "content": + "Extract the desired information from the following passage as json decoded like vin,make,made,year,expiration_date,color,owner,registration_date just in this:\n\n$payload" + } + ], + "temperature": 0.9 + }); + var response = await http.post( + url, + body: data, + headers: headers, + ); + + if (response.statusCode == 200) { + return response.body; + } + return response.statusCode; + } + + Future postStripe({ + required String link, + Map? payload, + }) async { + // String? secretKey = await storage.read(key: BoxName.secretKey); + var url = Uri.parse( + link, + ); + var response = await http.post( + url, + body: payload, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + 'Authorization': 'Bearer ${AK.secretKey}', + }, + ); + if (response.statusCode == 200) { + return response.body; + } else {} + } + + Future post({ + required String link, + Map? payload, + }) async { + // String? basicAuthCredentials = + // await storage.read(key: BoxName.basicAuthCredentials); + var url = Uri.parse( + link, + ); + var response = await http.post( + url, + body: payload, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + }, + ); + + var jsonData = jsonDecode(response.body); + if (response.statusCode == 200) { + if (jsonData['status'] == 'success') { + return response.body; + } else { + return (jsonData['status']); + } + } else { + return response.statusCode; + } + } + + Future kazumiSMS({ + required String link, + Map? payload, + }) async { + var url = Uri.parse( + link, + ); + var headers = {'Content-Type': 'application/json'}; + var request = http.Request('POST', url); + request.body = json.encode({ + "username": "Sefer", + "password": AK.smsPasswordEgypt, + }); + request.headers.addAll(headers); + + http.StreamedResponse response = await request.send(); + + if (response.statusCode == 200) { + var responseBody = await response.stream.bytesToString(); + var data = json.decode(responseBody); + return data; + } else {} + } + + Future postPayMob({ + required String link, + Map? payload, + }) async { + // String? basicAuthCredentials = + // await storage.read(key: BoxName.basicAuthCredentials); + var url = Uri.parse( + link, + ); + var response = await http.post(url, + body: payload, headers: {'Content-Type': 'application/json'}); + + var jsonData = jsonDecode(response.body); + if (response.statusCode == 200) { + if (jsonData['status'] == 'success') { + return response.body; + } else { + return (jsonData['status']); + } + } else { + return response.statusCode; + } + } + + sendEmail( + String link, + Map? payload, + ) async { + var headers = { + "Content-Type": "application/x-www-form-urlencoded", + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + }; + var request = http.Request('POST', Uri.parse(link)); + request.bodyFields = payload!; + request.headers.addAll(headers); + + http.StreamedResponse response = await request.send(); + if (response.statusCode == 200) { + } else {} + } + + Future postFromDialogue({ + required String link, + Map? payload, + }) async { + // String? basicAuthCredentials = + // await storage.read(key: BoxName.basicAuthCredentials); + var url = Uri.parse( + link, + ); + var response = await http.post( + url, + body: payload, + headers: { + "Content-Type": "application/x-www-form-urlencoded", + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + }, + ); + + if (response.body.isNotEmpty) { + var jsonData = jsonDecode(response.body); + if (response.statusCode == 200) { + if (jsonData['status'] == 'success') { + Get.back(); + // Get.snackbar( + // jsonData['status'], + // jsonData['message'], + // ); + + return response.body; + } + } + return (jsonData['status']); + } + } + + Future sendVerificationRequest(String phoneNumber) async { + final accountSid = AK.accountSIDTwillo; + final authToken = AK.authTokenTwillo; + final verifySid = AK.twilloRecoveryCode; + + final Uri verificationUri = Uri.parse( + 'https://verify.twilio.com/v2/Services/$verifySid/Verifications'); + + // Send the verification request + final response = await http.post( + verificationUri, + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode('$accountSid:$authToken'))}', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: { + 'To': phoneNumber, + 'Channel': 'sms', + }, + ); + + if (response.statusCode == 201) { + } else {} + + // Prompt the user to enter the OTP + const otpCode = "123456"; // Replace with user input + + // Check the verification code + final checkUri = Uri.parse( + 'https://verify.twilio.com/v2/Services/$verifySid/VerificationCheck'); + + final checkResponse = await http.post( + checkUri, + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode('$accountSid:$authToken'))}', + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: { + 'To': phoneNumber, + 'Code': otpCode, + }, + ); + + if (checkResponse.statusCode == 201) { + } else {} + } + + Future getGoogleApi({ + required String link, + Map? payload, + }) async { + var url = Uri.parse( + link, + ); + var response = await http.post( + url, + body: payload, + ); + var jsonData = jsonDecode(response.body); + if (jsonData['status'] == 'OK') { + return jsonData; + } + return (jsonData['status']); + } + + Future update({ + required String endpoint, + required Map data, + required String id, + }) async { + // String? basicAuthCredentials = + // await storage.read(key: BoxName.basicAuthCredentials); + var url = Uri.parse('$endpoint/$id'); + var response = await http.put( + url, + body: json.encode(data), + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + }, + ); + return json.decode(response.body); + } + + Future delete({ + required String endpoint, + required String id, + }) async { + // String? basicAuthCredentials = + // await storage.read(key: BoxName.basicAuthCredentials); + var url = Uri.parse('$endpoint/$id'); + var response = await http.delete( + url, + headers: { + 'Authorization': + 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials))}', + }, + ); + return json.decode(response.body); + } +} diff --git a/lib/controller/functions/custom_pant.dart b/lib/controller/functions/custom_pant.dart new file mode 100644 index 0000000..8b85ce4 --- /dev/null +++ b/lib/controller/functions/custom_pant.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +class LineChartPainter extends CustomPainter { + final List data; + + LineChartPainter(this.data); + + @override + void paint(Canvas canvas, Size size) { + // Calculate the scale factor. + final scaleFactor = size.height / 240; + + // Draw the line chart. + for (var i = 0; i < data.length - 1; i++) { + final x1 = i * size.width / data.length; + final y1 = data[i] * scaleFactor; + final x2 = (i + 1) * size.width / data.length; + final y2 = data[i + 1] * scaleFactor; + + canvas.drawLine(Offset(x1, y1), Offset(x2, y2), Paint()); + } + } + + @override + bool shouldRepaint(LineChartPainter oldDelegate) => false; +} diff --git a/lib/controller/functions/device_info.dart b/lib/controller/functions/device_info.dart new file mode 100644 index 0000000..3091394 --- /dev/null +++ b/lib/controller/functions/device_info.dart @@ -0,0 +1,90 @@ +// import 'dart:io'; + +// import 'package:device_info_plus/device_info_plus.dart'; + +// class DeviceInfoPlus { +// static List> deviceDataList = []; + +// static Future>> getDeviceInfo() async { +// final DeviceInfoPlugin deviceInfoPlugin = DeviceInfoPlugin(); + +// try { +// if (Platform.isAndroid) { +// AndroidDeviceInfo androidInfo = await deviceInfoPlugin.androidInfo; +// Map deviceData = { +// 'platform': 'Android', +// 'brand': androidInfo.brand, +// 'model': androidInfo.model, +// 'androidId': androidInfo.device, +// 'versionRelease': androidInfo.version.release, +// 'sdkVersion': androidInfo.version.sdkInt, +// 'manufacturer': androidInfo.manufacturer, +// 'isPhysicalDevice': androidInfo.isPhysicalDevice, +// 'serialNumber': androidInfo.serialNumber, +// 'fingerprint': androidInfo.fingerprint, +// 'type': androidInfo.type, +// 'data': androidInfo.data, +// 'version': androidInfo.version, +// 'tags': androidInfo.tags, +// 'display': androidInfo.display, +// }; +// deviceDataList.add(deviceData); +// } else if (Platform.isIOS) { +// IosDeviceInfo iosInfo = await deviceInfoPlugin.iosInfo; +// Map deviceData = { +// 'brand': 'Apple', +// 'model': iosInfo.model, +// 'systemName': iosInfo.systemName, +// 'systemVersion': iosInfo.systemVersion, +// 'utsname': iosInfo.utsname, +// 'isPhysicalDevice': iosInfo.isPhysicalDevice, +// 'identifierForVendor': iosInfo.identifierForVendor, +// 'name': iosInfo.name, +// 'localizedModel': iosInfo.localizedModel, +// }; +// deviceDataList.add(deviceData); +// } else if (Platform.isMacOS) { +// MacOsDeviceInfo macInfo = await deviceInfoPlugin.macOsInfo; +// Map deviceData = { +// 'platform': 'macOS', +// 'model': macInfo.model, +// 'version': macInfo.systemGUID, +// }; +// deviceDataList.add(deviceData); +// } else if (Platform.isWindows) { +// WindowsDeviceInfo windowsInfo = await deviceInfoPlugin.windowsInfo; +// Map deviceData = { +// 'platform': 'Windows', +// 'manufacturer': windowsInfo.computerName, +// 'version': windowsInfo.majorVersion, +// 'deviceId': windowsInfo.deviceId, +// 'userName': windowsInfo.userName, +// 'productName': windowsInfo.productName, +// 'installDate': windowsInfo.installDate, +// 'productId': windowsInfo.productId, +// 'numberOfCores': windowsInfo.numberOfCores, +// 'systemMemoryInMegabytes': windowsInfo.systemMemoryInMegabytes, +// }; +// deviceDataList.add(deviceData); +// } else if (Platform.isLinux) { +// LinuxDeviceInfo linuxInfo = await deviceInfoPlugin.linuxInfo; +// Map deviceData = { +// 'platform': 'Linux', +// 'manufacturer': linuxInfo.name, +// 'version': linuxInfo.version, +// }; +// deviceDataList.add(deviceData); +// } +// } catch (e) { +// } + +// return deviceDataList; +// } + +// // Method to print all device data +// static void printDeviceInfo() { +// for (Map deviceData in deviceDataList) { +// 'Version: ${deviceData['version'] ?? deviceData['versionRelease'] ?? 'N/A'}'); +// } +// } +// } diff --git a/lib/controller/functions/digit_obsecur_formate.dart b/lib/controller/functions/digit_obsecur_formate.dart new file mode 100644 index 0000000..b5972e4 --- /dev/null +++ b/lib/controller/functions/digit_obsecur_formate.dart @@ -0,0 +1,42 @@ +import 'package:flutter/services.dart'; + +class DigitObscuringFormatter extends TextInputFormatter { + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, TextEditingValue newValue) { + final maskedText = maskDigits(newValue.text); + return newValue.copyWith( + text: maskedText, + selection: updateCursorPosition(maskedText, newValue.selection)); + } + + String maskDigits(String text) { + final totalDigits = text.length; + final visibleDigits = 4; + final hiddenDigits = totalDigits - visibleDigits * 2; + + final firstVisibleDigits = text.substring(0, visibleDigits); + final lastVisibleDigits = text.substring(totalDigits - visibleDigits); + + final maskedDigits = List.filled(hiddenDigits, '*').join(); + + return '$firstVisibleDigits$maskedDigits$lastVisibleDigits'; + } + + TextSelection updateCursorPosition( + String maskedText, TextSelection currentSelection) { + final cursorPosition = currentSelection.baseOffset; + final cursorOffset = + currentSelection.extentOffset - currentSelection.baseOffset; + final totalDigits = maskedText.length; + const visibleDigits = 4; + final hiddenDigits = totalDigits - visibleDigits * 2; + + final updatedPosition = cursorPosition <= visibleDigits + ? cursorPosition + : hiddenDigits + visibleDigits + (cursorPosition - visibleDigits); + + return TextSelection.collapsed( + offset: updatedPosition, affinity: currentSelection.affinity); + } +} diff --git a/lib/controller/functions/document_scanner.dart b/lib/controller/functions/document_scanner.dart new file mode 100644 index 0000000..198992c --- /dev/null +++ b/lib/controller/functions/document_scanner.dart @@ -0,0 +1,41 @@ +// import 'dart:io'; +// +// import 'package:get/get.dart'; +// import 'package:image_picker/image_picker.dart'; +// import 'package:google_ml_kit/google_ml_kit.dart'; +// +// class ImagePickerController extends GetxController { +// RxBool textScanning = false.obs; +// RxString scannedText = ''.obs; +// +// Future getImage(ImageSource source) async { +// try { +// final pickedImage = await ImagePicker().pickImage(source: source); +// if (pickedImage != null) { +// textScanning.value = true; +// final imageFile = File(pickedImage.path); +// getRecognisedText(imageFile); +// } +// } catch (e) { +// textScanning.value = false; +// scannedText.value = "Error occurred while scanning"; +// } +// } +// +// Future getRecognisedText(File image) async { +// final inputImage = InputImage.fromFilePath(image.path); +// final textDetector = GoogleMlKit.vision.textRecognizer(); +// final RecognizedText recognisedText = +// await textDetector.processImage(inputImage); +// await textDetector.close(); +// +// scannedText.value = ''; +// for (TextBlock block in recognisedText.blocks) { +// for (TextLine line in block.lines) { +// scannedText.value += line.text + '\n'; +// } +// } +// +// textScanning.value = false; +// } +// } diff --git a/lib/controller/functions/gemeni.dart b/lib/controller/functions/gemeni.dart new file mode 100644 index 0000000..14bca12 --- /dev/null +++ b/lib/controller/functions/gemeni.dart @@ -0,0 +1,829 @@ +// import 'dart:convert'; +// import 'dart:io'; +// import 'package:get/get.dart'; +// import 'package:image_cropper/image_cropper.dart'; +// import 'package:image_picker/image_picker.dart'; +// import 'package:http/http.dart' as http; +// import 'package:image/image.dart' as img; +// import 'package:path_provider/path_provider.dart'; + +// import '../../constant/api_key.dart'; +// import '../../constant/colors.dart'; + +// class AI extends GetxController { +// final picker = ImagePicker(); +// Map responseMap = {}; +// Map responseCarLicenseMap = {}; +// Map responseBackCarLicenseMap = {}; +// Map responseIdCardeMap = {}; +// bool isloading = false; +// var image; +// CroppedFile? croppedFile; +// DateTime now = DateTime.now(); +// Future pickImage() async { +// final pickedImage = await picker.pickImage(source: ImageSource.gallery); + +// if (pickedImage != null) { +// image = File(pickedImage.path); +// // Crop the image +// croppedFile = await ImageCropper().cropImage( +// sourcePath: image!.path, +// aspectRatioPresets: [ +// CropAspectRatioPreset.square, +// CropAspectRatioPreset.ratio3x2, +// CropAspectRatioPreset.original, +// CropAspectRatioPreset.ratio4x3, +// CropAspectRatioPreset.ratio16x9 +// ], +// uiSettings: [ +// AndroidUiSettings( +// toolbarTitle: 'Cropper'.tr, +// toolbarColor: AppColor.blueColor, +// toolbarWidgetColor: AppColor.yellowColor, +// initAspectRatio: CropAspectRatioPreset.original, +// lockAspectRatio: false), +// IOSUiSettings( +// title: 'Cropper'.tr, +// ), +// ], +// ); +// // image = croppedFile; + +// // Resize the image +// final rawImage = +// img.decodeImage(File(croppedFile!.path).readAsBytesSync()); +// final resizedImage = +// img.copyResize(rawImage!, width: 800); // Adjust the width as needed + +// final appDir = await getTemporaryDirectory(); +// final resizedImagePath = '${appDir.path}/resized_image.jpg'; + +// final resizedImageFile = File(resizedImagePath); +// resizedImageFile.writeAsBytesSync( +// img.encodeJpg(resizedImage)); // Save the resized image as JPEG + +// image = resizedImageFile; +// update(); +// } +// } + +// Future generateContent() async { +// await pickImage(); +// if (image != null) { +// final imageBytes = await image.readAsBytes(); +// final imageData = base64Encode(imageBytes); + +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// { +// 'inlineData': { +// 'mimeType': 'image/jpeg', +// 'data': imageData, +// }, +// }, +// { +// 'text': +// 'write json for all data as first name ,last name,dob,licenseID,expiration date,issued date asdress class type ,output json type', +// }, +// ], +// }, +// ], +// 'generationConfig': { +// 'temperature': 0.4, +// 'topK': 32, +// 'topP': 1, +// 'maxOutputTokens': 4096, +// 'stopSequences': [], +// }, +// 'safetySettings': [ +// { +// 'category': 'HARM_CATEGORY_HARASSMENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_HATE_SPEECH', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// ], +// }); + +// final response = await http.post( +// Uri.parse( +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); + +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed + +// var result = +// responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } else { +// } +// } + +// Future geminiAiExtraction(String prompt, payload) async { +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// // { +// // 'inlineData': { +// // 'mimeType': 'image/jpeg', +// // 'data': imageData, +// // }, +// // }, +// { +// 'text': +// "Extract the desired information from the following passage as json decoded like $prompt .and look for this instruction first name in line 3or 2 ,fullname in line 4 from it written left to right but you modify it rtl,address in line 5 it written left to right but you modify it rtl and 6,dob,nationalid in the last line as just in this:\n\n$payload" +// }, +// ], +// }, +// ], +// 'generationConfig': { +// 'temperature': 0.4, +// 'topK': 32, +// 'topP': 1, +// 'maxOutputTokens': 4096, +// 'stopSequences': [], +// }, +// 'safety_settings': [ +// {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"}, +// {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"}, +// { +// "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", +// "threshold": "BLOCK_NONE" +// }, +// { +// "category": "HARM_CATEGORY_DANGEROUS_CONTENT", +// "threshold": "BLOCK_NONE" +// }, +// ] +// }); + +// final response = await http.post( +// Uri.parse( +// // 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key=AIzaSyCyoLcSkDzK5_SMe00nhut56SSXWPR074w'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); + +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed + +// var result = responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } + +// Future getDriverLicenseJordanContent() async { +// await pickImage(); +// isloading = true; +// update(); +// if (image != null) { +// final imageBytes = await image.readAsBytes(); +// final imageData = base64Encode(imageBytes); + +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// { +// 'inlineData': { +// 'mimeType': 'image/jpeg', +// 'data': imageData, +// }, +// }, +// { +// 'text': +// 'write json for all data as first name ,last name,dob,id ,expiration date,issued date asdress class type,age in years ,output json type in arabic value and stay engish key and make date format like YYYY-MM-DD , for name please extract name in arabic in Name in json plus first_name ', +// }, +// ], +// }, +// ], +// 'generationConfig': { +// 'temperature': 0.4, +// 'topK': 32, +// 'topP': 1, +// 'maxOutputTokens': 4096, +// 'stopSequences': [], +// }, +// 'safetySettings': [ +// { +// 'category': 'HARM_CATEGORY_HARASSMENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_HATE_SPEECH', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// ], +// }); + +// final response = await http.post( +// Uri.parse( +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); +// isloading = false; +// update(); +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed + +// var result = +// responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// responseMap = jsonDecode(jsonString); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } else { +// } +// } + +// Future getCarLicenseJordanContent() async { +// await pickImage(); +// isloading = true; +// update(); +// if (image != null) { +// final imageBytes = await image.readAsBytes(); +// final imageData = base64Encode(imageBytes); + +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// { +// 'inlineData': { +// 'mimeType': 'image/jpeg', +// 'data': imageData, +// }, +// }, +// { +// 'text': +// '''Extract the following information from the front face of the Jordanian ID card: +// Name +// National ID number +// Gender +// Date of birth +// Output the extracted information in the following JSON format''', +// }, +// ], +// }, +// ], +// 'generationConfig': { +// 'temperature': 0.4, +// 'topK': 32, +// 'topP': 1, +// 'maxOutputTokens': 4096, +// 'stopSequences': [], +// }, +// 'safetySettings': [ +// { +// 'category': 'HARM_CATEGORY_HARASSMENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_HATE_SPEECH', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// ], +// }); + +// final response = await http.post( +// Uri.parse( +// // 'https://${API_ENDPOINT}/v1/projects/${PROJECT_ID}/locations/${LOCATION_ID}/publishers/google/models/${MODEL_ID}:streamGenerateContent'), +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); +// isloading = false; +// update(); +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed + +// var result = +// responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// responseCarLicenseMap = jsonDecode(jsonString); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } else { +// } +// } + +// Future jordanID() async { +// await pickImage(); +// isloading = true; +// update(); +// if (image != null) { +// final imageBytes = await image.readAsBytes(); +// final imageData = base64Encode(imageBytes); + +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// { +// 'inlineData': { +// 'mimeType': 'image/jpeg', +// 'data': imageData, +// }, +// }, +// { +// 'text': +// '''Extract the following information from the front face of the Jordanian ID card: +// Name +// National ID number +// Gender +// Date of birth +// Output the extracted information in the following JSON format''', +// }, +// ], +// }, +// ], +// 'generationConfig': { +// 'temperature': 0.4, +// 'topK': 32, +// 'topP': 1, +// 'maxOutputTokens': 4096, +// 'stopSequences': [], +// }, +// 'safetySettings': [ +// { +// 'category': 'HARM_CATEGORY_HARASSMENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_HATE_SPEECH', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// ], +// }); + +// final response = await http.post( +// Uri.parse( +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); +// isloading = false; +// update(); +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed + +// var result = +// responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// responseCarLicenseMap = jsonDecode(jsonString); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } else { +// } +// } + +// Future carLicenseJordan() async { +// await pickImage(); +// isloading = true; +// update(); +// if (image != null) { +// final imageBytes = await image.readAsBytes(); +// final imageData = base64Encode(imageBytes); + +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// { +// 'inlineData': { +// 'mimeType': 'image/jpeg', +// 'data': imageData, +// }, +// }, +// { +// 'text': +// '''Extract the following information from the front face of the car license card in Jordan: + +// * name +// * Address +// * Vehicle type +// * car_kind +// * car_color +// * Vehicle category +// * car_year +// * car_plate +// * Registration type +// * Usage type +// * expire_date_of_license + +// Output the extracted information in the following JSON formate and make date format like YYYY-MM-DD''', +// }, +// ], +// }, +// ], +// 'generationConfig': { +// 'temperature': 0.4, +// 'topK': 32, +// 'topP': 1, +// 'maxOutputTokens': 4096, +// 'stopSequences': [], +// }, +// 'safetySettings': [ +// { +// 'category': 'HARM_CATEGORY_HARASSMENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_HATE_SPEECH', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// ], +// }); + +// final response = await http.post( +// Uri.parse( +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro-vision-latest:generateContent?key=${AK.geminiApi}'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); +// isloading = false; +// update(); +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed + +// var result = +// responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// responseCarLicenseMap = jsonDecode(jsonString); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } else { +// } +// } + +// Future getTextFromCard(String prompt) async { +// await pickImage(); +// isloading = true; +// update(); +// if (image != null) { +// final imageBytes = await image.readAsBytes(); +// final imageData = base64Encode(imageBytes); + +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// { +// 'inlineData': { +// 'mimeType': 'image/jpeg', +// 'data': imageData, +// }, +// }, +// { +// 'text': prompt, +// }, +// ], +// }, +// ], +// 'generationConfig': { +// "temperature": 1, +// "topK": 32, +// "topP": 0.1, +// "maxOutputTokens": 4096, +// "stopSequences": [] +// }, +// 'safetySettings': [ +// { +// 'category': 'HARM_CATEGORY_HARASSMENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_HATE_SPEECH', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// ], +// }); + +// final response = await http.post( +// Uri.parse( +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro-vision-latest:generateContent?key=${AK.geminiApi}'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); +// isloading = false; +// update(); +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed + +// var result = +// responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// responseBackCarLicenseMap = jsonDecode(jsonString); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } else { +// } +// } + +// Future generateBackCarLicenseJordanContent() async { +// await pickImage(); +// isloading = true; +// update(); +// if (image != null) { +// final imageBytes = await image.readAsBytes(); +// final imageData = base64Encode(imageBytes); + +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// { +// 'inlineData': { +// 'mimeType': 'image/jpeg', +// 'data': imageData, +// }, +// }, +// { +// 'text': +// 'write json output from extracting car license back face for these key ,vin,fuelType,passengerType,curbWeight,insuranceCompany,policyNumber,notes,insuranceType and output it json .dont add data else this image', +// }, +// ], +// }, +// ], +// 'generationConfig': { +// 'temperature': 0.4, +// 'topK': 343, +// 'topP': 1, +// 'maxOutputTokens': 4096, +// 'stopSequences': [], +// }, +// 'safetySettings': [ +// { +// 'category': 'HARM_CATEGORY_HARASSMENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_HATE_SPEECH', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// ], +// }); + +// final response = await http.post( +// Uri.parse( +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); +// isloading = false; +// update(); +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed + +// var result = +// responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// responseBackCarLicenseMap = jsonDecode(jsonString); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } else { +// } +// } + +// Future getFromCarRegistration() async { +// await pickImage(); +// if (image != null) { +// final imageBytes = await image.readAsBytes(); +// final imageData = base64Encode(imageBytes); + +// var requestBody = jsonEncode({ +// 'contents': [ +// { +// 'parts': [ +// { +// 'inlineData': { +// 'mimeType': 'image/jpeg', +// 'data': imageData, +// }, +// }, +// { +// 'text': +// 'write output json from image for[ vin, make, model, year, expiration_date, color, owner, registration_date ],output json type ', +// }, +// ], +// }, +// ], +// 'generationConfig': { +// 'temperature': 0.4, +// 'topK': 32, +// 'topP': 1, +// 'maxOutputTokens': 4096, +// 'stopSequences': [], +// }, +// 'safetySettings': [ +// { +// 'category': 'HARM_CATEGORY_HARASSMENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_HATE_SPEECH', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_SEXUALLY_EXPLICIT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// { +// 'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', +// 'threshold': 'BLOCK_MEDIUM_AND_ABOVE', +// }, +// ], +// }); + +// final response = await http.post( +// Uri.parse( +// 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro-vision:generateContent?key=${AK.geminiApi}'), +// headers: {'Content-Type': 'application/json'}, +// body: requestBody, +// ); + +// if (response.statusCode == 200) { +// var responseData = jsonDecode(response.body); +// // Process the responseData as needed +// var result = +// responseData['candidates'][0]['content']['parts'][0]['text']; +// RegExp regex = RegExp(r"```json([^`]*)```"); +// String? jsonString = +// regex.firstMatch(responseData.toString())?.group(1)?.trim(); + +// if (jsonString != null) { +// // Convert the JSON object to a String +// jsonString = jsonEncode(json.decode(jsonString)); +// } else { +// } + +// // Rest of your code... +// } else { +// } +// } else { +// } +// } + +// @override +// void onInit() { +// // generateContent(); +// super.onInit(); +// } +// } diff --git a/lib/controller/functions/launch.dart b/lib/controller/functions/launch.dart new file mode 100644 index 0000000..65b1232 --- /dev/null +++ b/lib/controller/functions/launch.dart @@ -0,0 +1,63 @@ +import 'package:url_launcher/url_launcher.dart'; +import 'dart:io'; + +void showInBrowser(String url) async { + if (await canLaunchUrl(Uri.parse(url))) { + launchUrl(Uri.parse(url)); + } else {} +} + +void launchCommunication( + String method, String contactInfo, String message) async { + String url; + + if (Platform.isIOS) { + switch (method) { + case 'phone': + url = 'tel:$contactInfo'; + break; + + case 'sms': + url = 'sms:$contactInfo?body=$message'; + break; + + case 'whatsapp': + url = 'https://api.whatsapp.com/send?phone=$contactInfo&text=$message'; + break; + + case 'email': + url = 'mailto:$contactInfo?subject=Subject&body=$message'; + break; + + default: + return; + } + } else if (Platform.isAndroid) { + switch (method) { + case 'phone': + url = 'tel:$contactInfo'; + break; + + case 'sms': + url = 'sms:$contactInfo?body=$message'; + break; + + case 'whatsapp': + url = 'whatsapp://send?phone=$contactInfo&text=$message'; + break; + + case 'email': + url = 'mailto:$contactInfo?subject=Subject&body=$message'; + break; + + default: + return; + } + } else { + return; + } + + if (await canLaunchUrl(Uri.parse(url))) { + launchUrl(Uri.parse(url)); + } else {} +} diff --git a/lib/controller/functions/llama_ai.dart b/lib/controller/functions/llama_ai.dart new file mode 100644 index 0000000..60e8c33 --- /dev/null +++ b/lib/controller/functions/llama_ai.dart @@ -0,0 +1,36 @@ +import 'dart:convert'; + +import '../../constant/links.dart'; +import 'crud.dart'; + +class LlamaAi { + Future getCarRegistrationData(String input, prompt) async { + Map exrtatDataFinal = {}; + String oneLine = input.replaceAll('\n', ' '); + // var res = await CRUD().getLlama(link: AppLink.gemini, payload: oneLine); + var res = await CRUD() + .getLlama(link: AppLink.llama, payload: oneLine, prompt: prompt); + + var decod = jsonDecode(res.toString()); + // exrtatDataFinal = jsonDecode(extractDataFromJsonString(decod['choices'])); + extractDataFromJsonString(decod['choices'][0]['message']['content']); + return exrtatDataFinal; + } + + String extractDataFromJsonString(String jsonString) { + // Remove any leading or trailing whitespace from the string + jsonString = jsonString.trim(); + + // Extract the JSON substring from the given string + final startIndex = jsonString.indexOf('{'); + final endIndex = jsonString.lastIndexOf('}'); + final jsonSubstring = jsonString.substring(startIndex, endIndex + 1); + + // Parse the JSON substring into a Map + final jsonData = jsonDecode(jsonSubstring); + + // Return the extracted data + + return jsonEncode(jsonData); + } +} diff --git a/lib/controller/functions/location_controller.dart b/lib/controller/functions/location_controller.dart new file mode 100644 index 0000000..35a57e7 --- /dev/null +++ b/lib/controller/functions/location_controller.dart @@ -0,0 +1,133 @@ +// import 'dart:async'; + +// import 'package:get/get.dart'; +// import 'package:google_maps_flutter/google_maps_flutter.dart'; +// import 'package:location/location.dart'; + +// import '../../constant/box_name.dart'; +// import '../../constant/links.dart'; +// import '../../main.dart'; +// import 'crud.dart'; + +// // LocationController.dart +// class LocationController extends GetxController { +// LocationData? _currentLocation; +// late Location location; +// bool isLoading = false; +// late double heading = 0; +// late double accuracy = 0; +// late double previousTime = 0; +// late double latitude; +// late double totalDistance = 0; +// late double longitude; +// late DateTime time; +// late double speed = 0; +// late double speedAccuracy = 0; +// late double headingAccuracy = 0; +// bool isActive = false; +// late LatLng myLocation; +// String totalPoints = '0'; +// LocationData? get currentLocation => _currentLocation; +// Timer? _locationTimer; + +// @override +// void onInit() async { +// super.onInit(); +// location = Location(); +// getLocation(); +// // startLocationUpdates(); +// } + +// Future startLocationUpdates() async { +// if (box.read(BoxName.driverID) != null) { +// _locationTimer = +// Timer.periodic(const Duration(seconds: 5), (timer) async { +// try { +// // if (isActive) { +// if (double.parse(totalPoints) > -300) { + +// await getLocation(); + +// // if (box.read(BoxName.driverID) != null) { +// await CRUD() +// .post(link: AppLink.addCarsLocationByPassenger, payload: { +// 'driver_id': box.read(BoxName.driverID).toString(), +// 'latitude': myLocation.latitude.toString(), +// 'longitude': myLocation.longitude.toString(), +// 'heading': heading.toString(), +// 'speed': (speed * 3.6).toStringAsFixed(1), +// 'distance': totalDistance == 0 +// ? '0' +// : totalDistance < 1 +// ? totalDistance.toStringAsFixed(3) +// : totalDistance.toStringAsFixed(1), +// 'status': box.read(BoxName.statusDriverLocation).toString() +// }); +// } +// } catch (e) { +// // Handle the error gracefully +// } +// }); +// } +// } + +// void stopLocationUpdates() { +// _locationTimer?.cancel(); +// } + +// Future getLocation() async { +// // isLoading = true; +// // update(); +// bool serviceEnabled; +// PermissionStatus permissionGranted; + +// // Check if location services are enabled +// serviceEnabled = await location.serviceEnabled(); +// if (!serviceEnabled) { +// serviceEnabled = await location.requestService(); +// if (!serviceEnabled) { +// // Location services are still not enabled, handle the error +// return; +// } +// } + +// // Check if the app has permission to access location +// permissionGranted = await location.hasPermission(); +// if (permissionGranted == PermissionStatus.denied) { +// permissionGranted = await location.requestPermission(); +// if (permissionGranted != PermissionStatus.granted) { +// // Location permission is still not granted, handle the error +// return; +// } +// } + +// // Configure location accuracy +// // LocationAccuracy desiredAccuracy = LocationAccuracy.high; + +// // Get the current location +// LocationData _locationData = await location.getLocation(); +// myLocation = +// (_locationData.latitude != null && _locationData.longitude != null +// ? LatLng(_locationData.latitude!, _locationData.longitude!) +// : null)!; +// speed = _locationData.speed!; +// heading = _locationData.heading!; + +// // isLoading = false; +// update(); +// } + +// double calculateDistanceInKmPerHour( +// double? startTime, double? endTime, double speedInMetersPerSecond) { +// // Calculate the time difference in hours +// double timeDifferenceInHours = (endTime! - startTime!) / 1000 / 3600; + +// // Convert speed to kilometers per hour +// double speedInKmPerHour = speedInMetersPerSecond * 3.6; + +// // Calculate the distance in kilometers +// double distanceInKilometers = speedInKmPerHour * timeDifferenceInHours; + +// return distanceInKilometers; +// } +// } diff --git a/lib/controller/functions/location_permission.dart b/lib/controller/functions/location_permission.dart new file mode 100644 index 0000000..9bbf33c --- /dev/null +++ b/lib/controller/functions/location_permission.dart @@ -0,0 +1,16 @@ +import 'package:location/location.dart'; +import 'package:get/get.dart'; + +class LocationPermissions { + late Location location; + + Future locationPermissions() async { + location = Location(); + var permissionStatus = await location.requestPermission(); + if (permissionStatus == PermissionStatus.denied) { + // The user denied the location permission. + Get.defaultDialog(title: 'GPS Required Allow !.'.tr, middleText: ''); + return null; + } + } +} diff --git a/lib/controller/functions/log_out.dart b/lib/controller/functions/log_out.dart new file mode 100644 index 0000000..3143884 --- /dev/null +++ b/lib/controller/functions/log_out.dart @@ -0,0 +1,181 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../constant/box_name.dart'; +import '../../constant/colors.dart'; +import '../../constant/links.dart'; +import '../../constant/style.dart'; +import '../../main.dart'; +import '../../views/widgets/elevated_btn.dart'; +import '../../views/widgets/my_textField.dart'; +import 'crud.dart'; + +class LogOutController extends GetxController { + TextEditingController checkTxtController = TextEditingController(); + final formKey = GlobalKey(); + final formKey1 = GlobalKey(); + final emailTextController = TextEditingController(); + + Future deleteMyAccountDriver(String id) async { + await CRUD().post(link: AppLink.removeUser, payload: {'id': id}).then( + (value) => Get.snackbar('Deleted'.tr, 'Your Account is Deleted', + backgroundColor: AppColor.redColor)); + } + + checkBeforeDelete() async { + var res = await CRUD().post( + link: AppLink.deletecaptainAccounr, + payload: {'id': box.read(BoxName.driverID)}).then((value) => exit(0)); + } + + deletecaptainAccount() { + Get.defaultDialog( + backgroundColor: AppColor.yellowColor, + title: 'Are you sure to delete your account?'.tr, + middleText: + 'Your data will be erased after 2 weeks\nAnd you will can\'t return to use app after 1 month ', + titleStyle: AppStyle.title, + content: Column( + children: [ + Container( + width: Get.width, + decoration: AppStyle.boxDecoration, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'Your data will be erased after 2 weeks\nAnd you will can\'t return to use app after 1 month' + .tr, + style: AppStyle.title.copyWith(color: AppColor.redColor), + ), + ), + ), + const SizedBox( + height: 20, + ), + Form( + key: formKey, + child: SizedBox( + width: Get.width, + child: MyTextForm( + controller: checkTxtController, + label: 'Enter Your First Name'.tr, + hint: 'Enter Your First Name'.tr, + type: TextInputType.name, + ), + )) + ], + ), + confirm: MyElevatedButton( + title: 'Delete'.tr, + onPressed: () { + if (checkTxtController.text == box.read(BoxName.nameDriver)) { + deletecaptainAccount(); + } + })); + } + + Future logOutPassenger() async { + Get.defaultDialog( + title: 'Are you Sure to LogOut?'.tr, + content: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + MyElevatedButton( + title: 'Cancel'.tr, + onPressed: () => Get.back(), + ), + ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(AppColor.redColor), + ), + onPressed: () { + // box.remove(BoxName.agreeTerms); + box.remove(BoxName.driverID); + box.remove(BoxName.email); + box.remove(BoxName.lang); + box.remove(BoxName.name); + box.remove(BoxName.passengerID); + box.remove(BoxName.phone); + box.remove(BoxName.tokenFCM); + box.remove(BoxName.tokens); + box.remove(BoxName.addHome); + box.remove(BoxName.addWork); + box.remove(BoxName.agreeTerms); + box.remove(BoxName.apiKeyRun); + box.remove(BoxName.countryCode); + box.remove(BoxName.accountIdStripeConnect); + box.remove(BoxName.passengerWalletTotal); + Get.offAll(const MainApp()); + }, + child: Text( + 'Sign Out'.tr, + style: + AppStyle.title.copyWith(color: AppColor.secondaryColor), + )) + ], + )); + } + + Future logOutCaptain() async { + Get.defaultDialog( + title: 'Are you Sure to LogOut?'.tr, + titleStyle: AppStyle.title, + content: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + MyElevatedButton( + title: 'Cancel'.tr, + onPressed: () => Get.back(), + ), + ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(AppColor.redColor), + ), + onPressed: () { + // box.remove(BoxName.agreeTerms); + box.remove(BoxName.driverID); + box.remove(BoxName.sexDriver); + box.remove(BoxName.dobDriver); + box.remove(BoxName.nameDriver); + box.remove(BoxName.emailDriver); + box.remove(BoxName.phoneDriver); + box.remove(BoxName.statusDriverLocation); + box.remove(BoxName.cvvCodeDriver); + box.remove(BoxName.lastNameDriver); + box.remove(BoxName.passwordDriver); + box.remove(BoxName.cardNumberDriver); + box.remove(BoxName.expiryDateDriver); + box.remove(BoxName.cardHolderNameDriver); + box.remove(BoxName.vin); + box.remove(BoxName.make); + box.remove(BoxName.year); + box.remove(BoxName.owner); + box.remove(BoxName.onBoarding); + box.remove(BoxName.agreeTerms); + Get.offAll(const MainApp()); + }, + child: Text( + 'Sign Out'.tr, + style: + AppStyle.title.copyWith(color: AppColor.secondaryColor), + )) + ], + )); + } + + deletePassengerAccount() async { + if (formKey1.currentState!.validate()) { + if (box.read(BoxName.email).toString() == emailTextController.text) { + await CRUD().post(link: AppLink.passengerRemovedAccountEmail, payload: { + 'email': box.read(BoxName.email), + }); + } else { + Get.snackbar('Email Wrong'.tr, 'Email you inserted is Wrong.'.tr, + snackPosition: SnackPosition.BOTTOM, + backgroundColor: AppColor.redColor); + } + } + } +} diff --git a/lib/controller/functions/scan_id_card.dart b/lib/controller/functions/scan_id_card.dart new file mode 100644 index 0000000..b0e6336 --- /dev/null +++ b/lib/controller/functions/scan_id_card.dart @@ -0,0 +1,25 @@ +// import 'package:credit_card_scanner/credit_card_scanner.dart'; +// import 'package:get/get.dart'; +// +// class ScanIdCard extends GetxController { +// CardDetails? _cardDetails; +// CardScanOptions scanOptions = const CardScanOptions( +// scanCardHolderName: true, +// enableDebugLogs: true, +// validCardsToScanBeforeFinishingScan: 5, +// possibleCardHolderNamePositions: [ +// CardHolderNameScanPosition.aboveCardNumber, +// ], +// ); +// +// Future scanCard() async { +// final CardDetails? cardDetails = +// await CardScanner.scanCard(scanOptions: scanOptions); +// if (cardDetails == null) { +// return; +// } +// +// _cardDetails = cardDetails; +// update(); +// } +// } diff --git a/lib/controller/functions/secure_storage.dart b/lib/controller/functions/secure_storage.dart new file mode 100644 index 0000000..364dced --- /dev/null +++ b/lib/controller/functions/secure_storage.dart @@ -0,0 +1,14 @@ +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; + +class SecureStorage { + final FlutterSecureStorage _storage = const FlutterSecureStorage(); + + void saveData(String key, value) async { + await _storage.write(key: key, value: value); + } + + Future readData(String boxName) async { + final String? value = await _storage.read(key: boxName); + return value; + } +} diff --git a/lib/controller/functions/upload_image.dart b/lib/controller/functions/upload_image.dart new file mode 100644 index 0000000..635b3c2 --- /dev/null +++ b/lib/controller/functions/upload_image.dart @@ -0,0 +1,108 @@ +// import 'dart:convert'; +// import 'dart:io'; + +// import 'package:get/get.dart'; +// import 'package:http/http.dart' as http; +// import 'package:image_cropper/image_cropper.dart'; +// import 'package:image_picker/image_picker.dart'; +// import 'package:path/path.dart'; + +// import '../../constant/api_key.dart'; +// import '../../constant/box_name.dart'; +// import '../../constant/colors.dart'; +// import '../../main.dart'; + +// class ImageController extends GetxController { +// File? myImage; +// bool isloading = false; +// CroppedFile? croppedFile; +// final picker = ImagePicker(); +// var image; +// choosImage(String link, String imageType) async { +// final pickedImage = await picker.pickImage(source: ImageSource.gallery); +// image = File(pickedImage!.path); +// croppedFile = await ImageCropper().cropImage( +// sourcePath: image!.path, +// aspectRatioPresets: [ +// CropAspectRatioPreset.square, +// CropAspectRatioPreset.ratio3x2, +// CropAspectRatioPreset.original, +// CropAspectRatioPreset.ratio4x3, +// CropAspectRatioPreset.ratio16x9 +// ], +// uiSettings: [ +// AndroidUiSettings( +// toolbarTitle: 'Cropper'.tr, +// toolbarColor: AppColor.blueColor, +// toolbarWidgetColor: AppColor.yellowColor, +// initAspectRatio: CropAspectRatioPreset.original, +// lockAspectRatio: false), +// IOSUiSettings( +// title: 'Cropper'.tr, +// ), +// ], +// ); +// myImage = File(pickedImage.path); +// isloading = true; +// update(); +// // Save the cropped image +// File savedCroppedImage = File(croppedFile!.path); +// try { +// await uploadImage( +// savedCroppedImage, +// { +// 'driverID': +// box.read(BoxName.driverID) ?? box.read(BoxName.passengerID), +// 'imageType': imageType +// }, +// link, +// ); +// } catch (e) { +// Get.snackbar('Image Upload Failed'.tr, e.toString(), +// backgroundColor: AppColor.redColor); +// } finally { +// isloading = false; +// update(); +// } +// } + +// uploadImage(File file, Map data, String link) async { +// var request = http.MultipartRequest( +// 'POST', +// Uri.parse(link), //'https://ride.mobile-app.store/uploadImage1.php' +// ); + +// var length = await file.length(); +// var stream = http.ByteStream(file.openRead()); +// var multipartFile = http.MultipartFile( +// 'image', +// stream, +// length, +// filename: basename(file.path), +// ); +// request.headers.addAll({ +// 'Authorization': +// 'Basic ${base64Encode(utf8.encode(AK.basicAuthCredentials.toString()))}', +// }); +// // Set the file name to the driverID +// request.files.add( +// http.MultipartFile( +// 'image', +// stream, +// length, +// filename: '${box.read(BoxName.driverID)}.jpg', +// ), +// ); +// data.forEach((key, value) { +// request.fields[key] = value; +// }); +// var myrequest = await request.send(); +// var res = await http.Response.fromStream(myrequest); +// if (res.statusCode == 200) { +// return jsonDecode(res.body); +// } else { +// throw Exception( +// 'Failed to upload image: ${res.statusCode} - ${res.body}'); +// } +// } +// } diff --git a/lib/controller/notification_controller.dart b/lib/controller/notification_controller.dart new file mode 100644 index 0000000..998a9b8 --- /dev/null +++ b/lib/controller/notification_controller.dart @@ -0,0 +1,115 @@ +import 'package:flutter/widgets.dart'; +import 'package:get/get.dart'; +import 'package:sefer_admin1/constant/box_name.dart'; +import 'package:sefer_admin1/controller/firebase/firbase_messge.dart'; +import 'package:sefer_admin1/main.dart'; +import 'package:sefer_admin1/views/widgets/elevated_btn.dart'; +import 'package:sefer_admin1/views/widgets/my_textField.dart'; + +import '../constant/style.dart'; + +class NotificationController extends GetxController { + final formKey = GlobalKey(); + final title = TextEditingController(); + final body = TextEditingController(); + List tokensDriver = []; + List tokensPassengers = []; + + getTokensDrivers() async { + await FirebaseMessagesController().getAllTokenDrivers(); + } + + getTokensPassengers() async { + await FirebaseMessagesController().getAllTokenPassengers(); + } + + Future sendNotificationDrivers() { + return Get.defaultDialog( + title: 'send notification'.tr, + titleStyle: AppStyle.title, + content: Form( + key: formKey, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: MyTextForm( + controller: title, + label: 'title notification'.tr, + hint: 'title notification'.tr, + type: TextInputType.name), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: MyTextForm( + controller: body, + label: 'body notification'.tr, + hint: 'body notification'.tr, + type: TextInputType.name), + ), + ], + ), + ), + confirm: MyElevatedButton( + title: 'send'.tr, + onPressed: () async { + tokensDriver = box.read(BoxName.tokensDrivers); + if (formKey.currentState!.validate()) { + for (var i = 0; i < tokensDriver.length; i++) { + FirebaseMessagesController().sendNotificationToAnyWithoutData( + title.text, body.text, tokensDriver[i]); + } + } + }), + cancel: MyElevatedButton( + title: 'cancel', + onPressed: () { + Get.back(); + })); + } + + Future sendNotificationPassengers() { + return Get.defaultDialog( + title: 'send notification'.tr, + titleStyle: AppStyle.title, + content: Form( + key: formKey, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: MyTextForm( + controller: title, + label: 'title notification'.tr, + hint: 'title notification'.tr, + type: TextInputType.name), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: MyTextForm( + controller: body, + label: 'body notification'.tr, + hint: 'body notification'.tr, + type: TextInputType.name), + ), + ], + ), + ), + confirm: MyElevatedButton( + title: 'send'.tr, + onPressed: () async { + tokensPassengers = box.read(BoxName.tokensPassengers); + for (var i = 0; i < tokensPassengers.length; i++) { + if (formKey.currentState!.validate()) { + FirebaseMessagesController().sendNotificationToAnyWithoutData( + title.text, body.text, tokensPassengers[i]); + } + } + }), + cancel: MyElevatedButton( + title: 'cancel', + onPressed: () { + Get.back(); + })); + } +} diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart new file mode 100644 index 0000000..3974baf --- /dev/null +++ b/lib/firebase_options.dart @@ -0,0 +1,70 @@ +// File generated by FlutterFire CLI. +// ignore_for_file: type=lint +import 'package:firebase_core/firebase_core.dart' show FirebaseOptions; +import 'package:flutter/foundation.dart' + show defaultTargetPlatform, kIsWeb, TargetPlatform; + +/// Default [FirebaseOptions] for use with your Firebase apps. +/// +/// Example: +/// ```dart +/// import 'firebase_options.dart'; +/// // ... +/// await Firebase.initializeApp( +/// options: DefaultFirebaseOptions.currentPlatform, +/// ); +/// ``` +class DefaultFirebaseOptions { + static FirebaseOptions get currentPlatform { + if (kIsWeb) { + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for web - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + } + switch (defaultTargetPlatform) { + case TargetPlatform.android: + return android; + case TargetPlatform.iOS: + return ios; + case TargetPlatform.macOS: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for macos - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.windows: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for windows - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + case TargetPlatform.linux: + throw UnsupportedError( + 'DefaultFirebaseOptions have not been configured for linux - ' + 'you can reconfigure this by running the FlutterFire CLI again.', + ); + default: + throw UnsupportedError( + 'DefaultFirebaseOptions are not supported for this platform.', + ); + } + } + + static const FirebaseOptions android = FirebaseOptions( + apiKey: 'AIzaSyCyfwRXTwSTLOFQSQgN5p7QZgGJVZnEKq0', + appId: '1:594687661098:android:8ec72f5f8b0b0ab8595f53', + messagingSenderId: '594687661098', + projectId: 'ride-b1bd8', + storageBucket: 'ride-b1bd8.appspot.com', + ); + + static const FirebaseOptions ios = FirebaseOptions( + apiKey: 'AIzaSyCf2mW2h0HD8ZYjwh4VOa2ladw6MJkCDTM', + appId: '1:594687661098:ios:9f46a169fad13752595f53', + messagingSenderId: '594687661098', + projectId: 'ride-b1bd8', + storageBucket: 'ride-b1bd8.appspot.com', + androidClientId: '594687661098-2dhoogl7be9phobfbu8bbg1sj567iv88.apps.googleusercontent.com', + iosClientId: '594687661098-aj48k038fjst4k8jiprfbq8895b11cci.apps.googleusercontent.com', + iosBundleId: 'com.example.seferAdmin1', + ); +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..27ebffc --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,64 @@ +import 'dart:io'; + +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; + +import 'controller/firebase/firbase_messge.dart'; +import 'firebase_options.dart'; +import 'models/db_sql.dart'; +import 'views/admin/admin_home_page.dart'; + +final box = GetStorage(); +const storage = FlutterSecureStorage(); +@pragma('vm:entry-point') +Future backgroundMessageHandler(RemoteMessage message) async { + await Firebase.initializeApp(); + if (message.data.isNotEmpty && message.notification != null) { + FirebaseMessagesController().fireBaseTitles(message); + } +} + +DbSql sql = DbSql.instance; + +void main() async { + WidgetsFlutterBinding.ensureInitialized(); + await GetStorage.init(); + if (Platform.isAndroid || Platform.isIOS) { + await Firebase.initializeApp( + options: DefaultFirebaseOptions.currentPlatform, + ); + await FirebaseMessagesController().requestFirebaseMessagingPermission(); + + FirebaseMessaging.onBackgroundMessage(backgroundMessageHandler); + + List initializationTasks = [ + FirebaseMessagesController().getNotificationSettings(), + FirebaseMessagesController().getToken(), + ]; + + await Future.wait(initializationTasks); + SystemChrome.setPreferredOrientations([ + DeviceOrientation.portraitUp, + DeviceOrientation.portraitDown, + ]); + } + + runApp(const MainApp()); +} + +class MainApp extends StatelessWidget { + const MainApp({super.key}); + + @override + Widget build(BuildContext context) { + return const GetMaterialApp( + debugShowCheckedModeBanner: false, + home: AdminHomePage(), + ); + } +} diff --git a/lib/models/db_sql.dart b/lib/models/db_sql.dart new file mode 100644 index 0000000..7f0bb18 --- /dev/null +++ b/lib/models/db_sql.dart @@ -0,0 +1,116 @@ +import 'package:sqflite/sqflite.dart'; +import 'package:path/path.dart'; + +import '../constant/table_names.dart'; + +class DbSql { + static final DbSql instance = DbSql._(); + + static Database? _database; + + DbSql._(); + + Future get database async { + if (_database != null) return _database!; + _database = await _initDatabase(); + return _database!; + } + + Future _initDatabase() async { + String path = join(await getDatabasesPath(), 'my_database.db'); + return await openDatabase( + path, + version: 1, + onCreate: (db, version) async { + await db.execute(''' + CREATE TABLE IF NOT EXISTS ${TableName.carLocations}( + id INTEGER PRIMARY KEY AUTOINCREMENT, + driver_id TEXT, + latitude REAL, + longitude REAL, + created_at TEXT, + updated_at TEXT + ) + '''); + await db.execute(''' + CREATE TABLE IF NOT EXISTS ${TableName.placesFavorite}( + id INTEGER PRIMARY KEY AUTOINCREMENT, + latitude REAL, + longitude REAL, + name TEXT UNIQUE, + rate TEXT + ) + '''); + await db.execute(''' + CREATE TABLE IF NOT EXISTS ${TableName.recentLocations}( + id INTEGER PRIMARY KEY AUTOINCREMENT, + latitude REAL, + longitude REAL, + name TEXT , + rate TEXT + ) + '''); + await db.execute(''' + CREATE TABLE IF NOT EXISTS ${TableName.driverOrdersRefuse}( + id INTEGER PRIMARY KEY AUTOINCREMENT, + order_id TEXT UNIQUE, + created_at TEXT, + driver_id TEXT + ) + '''); + await db.execute(''' + CREATE TABLE IF NOT EXISTS ${TableName.rideLocation}( + id INTEGER PRIMARY KEY AUTOINCREMENT, + order_id TEXT , + created_at TEXT, + lat TEXT, + lng TEXT + ) + '''); + await db.execute(''' + CREATE TABLE IF NOT EXISTS ${TableName.faceDetectTimes}( + id INTEGER PRIMARY KEY AUTOINCREMENT, + faceDetectTimes INTEGER + ) + '''); + await db.execute(''' + CREATE TABLE IF NOT EXISTS ${TableName.captainNotification}( + id INTEGER PRIMARY KEY AUTOINCREMENT, + faceDetectTimes INTEGER + ) + '''); + }, + ); + } + + Future>> getAllData(String table) async { + Database db = await instance.database; + return await db.query(table); + } + + Future>> getCustomQuery(String query) async { + Database db = await instance.database; + return await db.rawQuery(query); + } + + Future insertData(Map map, String table) async { + Database db = await instance.database; + return await db.insert(table, map); + } + + Future updateData(Map map, String table, int id) async { + Database db = await instance.database; + + return await db.update(table, map, where: 'id = ?', whereArgs: [id]); + } + + Future deleteData(String table, int id) async { + Database db = await instance.database; + return await db.delete(table, where: 'id = ?', whereArgs: [id]); + } + + Future deleteAllData(String table) async { + Database db = await instance.database; + return await db.delete(table); + } +} diff --git a/lib/models/feedback_qury.sql b/lib/models/feedback_qury.sql new file mode 100644 index 0000000..a05fe96 --- /dev/null +++ b/lib/models/feedback_qury.sql @@ -0,0 +1,40 @@ +-- Frequent Complaint Passengers +SELECT + passengers.id AS passenger_id, + passengers.first_name, + passengers.last_name, + passengers.phone, + COUNT(`feedBack`.id) AS complaint_count +FROM + passengers +JOIN `feedBack` ON passengers.id = `feedBack`.`passengerId` +GROUP BY + passengers.id +ORDER BY + complaint_count +DESC +LIMIT 10; +--========== +-- to get all driver payment to pay to them +SELECT + p.driverID, + COALESCE(SUM(p.amount), 0) AS total_amount, + COALESCE(SUM(p.amount), 0) + COALESCE(pd.total_points, 0) AS diff +FROM + payments p +JOIN ( + SELECT + driverID, + SUM(amount) AS total_points + FROM + paymentsDriverPoints + WHERE + payment_method = 'fromBudgetToPoints' + GROUP BY + driverID +) pd ON p.driverID = pd.driverID +WHERE + p.isGiven = 'waiting' + AND p.payment_method IN ('visa-in', 'visa', 'visaRide', 'TransferFrom', 'payout', 'TransferTo') +GROUP BY + p.driverID; diff --git a/lib/models/model/admin/monthly_ride.dart b/lib/models/model/admin/monthly_ride.dart new file mode 100644 index 0000000..df4d600 --- /dev/null +++ b/lib/models/model/admin/monthly_ride.dart @@ -0,0 +1,21 @@ +class MonthlyDataModel { + final int year; + final int month; + final int day; + final int ridesCount; + + MonthlyDataModel({ + required this.year, + required this.month, + required this.day, + required this.ridesCount, + }); + + factory MonthlyDataModel.fromJson(Map json) => + MonthlyDataModel( + year: json['year'] as int, + month: json['month'] as int, + day: json['day'] as int, + ridesCount: json['rides_count'] as int, + ); +} diff --git a/lib/models/model/admin/passenger_model.dart b/lib/models/model/admin/passenger_model.dart new file mode 100644 index 0000000..ed920bb --- /dev/null +++ b/lib/models/model/admin/passenger_model.dart @@ -0,0 +1,79 @@ +class Passenger { + String id; + String phone; + String email; + String gender; + String status; + String birthdate; + String site; + String firstName; + String lastName; + String sosPhone; + String education; + String employmentType; + String maritalStatus; + String createdAt; + String updatedAt; + int countPassenger; + int countFeedback; + double ratingPassenger; + int countDriverRate; + int countPassengerCancel; + double passengerAverageRating; + int countPassengerRate; + int countPassengerRide; + + Passenger({ + required this.id, + required this.phone, + required this.email, + required this.gender, + required this.status, + required this.birthdate, + required this.site, + required this.firstName, + required this.lastName, + required this.sosPhone, + required this.education, + required this.employmentType, + required this.maritalStatus, + required this.createdAt, + required this.updatedAt, + required this.countPassenger, + required this.countFeedback, + required this.ratingPassenger, + required this.countDriverRate, + required this.countPassengerCancel, + required this.passengerAverageRating, + required this.countPassengerRate, + required this.countPassengerRide, + }); + + factory Passenger.fromJson(Map json) { + return Passenger( + id: json['id'], + phone: json['phone'], + email: json['email'], + gender: json['gender'], + status: json['status'], + birthdate: json['birthdate'], + site: json['site'], + firstName: json['first_name'], + lastName: json['last_name'], + sosPhone: json['sosPhone'], + education: json['education'], + employmentType: json['employmentType'], + maritalStatus: json['maritalStatus'], + createdAt: json['created_at'], + updatedAt: json['updated_at'], + countPassenger: json['countPassenger'], + countFeedback: json['countFeedback'], + ratingPassenger: json['ratingPassenger'].toDouble(), + countDriverRate: json['countDriverRate'], + countPassengerCancel: json['countPassengerCancel'], + passengerAverageRating: json['passengerAverageRating'].toDouble(), + countPassengerRate: json['countPassengerRate'], + countPassengerRide: json['countPassengerRide'], + ); + } +} diff --git a/lib/models/model/admin/rides_summary_model.dart b/lib/models/model/admin/rides_summary_model.dart new file mode 100644 index 0000000..b3b1113 --- /dev/null +++ b/lib/models/model/admin/rides_summary_model.dart @@ -0,0 +1,12 @@ +class MonthlyDataModel { + int day; + int totalDuration; + + MonthlyDataModel({required this.day, required this.totalDuration}); + + factory MonthlyDataModel.fromJson(Map json) => + MonthlyDataModel( + day: int.parse(json['day'].toString().split('-')[2]), + totalDuration: + int.parse(json['total_duration'].toString().split(':')[0])); +} diff --git a/lib/models/model/locations.dart b/lib/models/model/locations.dart new file mode 100644 index 0000000..3b18b60 --- /dev/null +++ b/lib/models/model/locations.dart @@ -0,0 +1,34 @@ +class CarLocationModel { + String id; + String driverId; + double latitude; + double heading; + double speed; + double longitude; + DateTime createdAt; + DateTime updatedAt; + + CarLocationModel({ + required this.id, + required this.driverId, + required this.latitude, + required this.longitude, + required this.heading, + required this.speed, + required this.createdAt, + required this.updatedAt, + }); + + factory CarLocationModel.fromJson(Map json) { + return CarLocationModel( + id: json['id'], + driverId: json['driver_id'], + latitude: double.parse(json['latitude'].toString()), + longitude: double.parse(json['longitude'].toString()), + heading: double.parse(json['heading'].toString()), + speed: double.parse(json['speed'].toString()), + createdAt: DateTime.parse(json['created_at']), + updatedAt: DateTime.parse(json['updated_at']), + ); + } +} diff --git a/lib/models/model/onboarding_model.dart b/lib/models/model/onboarding_model.dart new file mode 100644 index 0000000..199909f --- /dev/null +++ b/lib/models/model/onboarding_model.dart @@ -0,0 +1,30 @@ +import 'package:get/get.dart'; + +List onBoardingList = [ + OnBoardingModel( + title: 'Welcome to Sefer!'.tr, + image: 'assets/images/on1.png', + body: + 'Sefer is the ride-hailing app that is safe, reliable, and accessible.' + .tr, + ), + OnBoardingModel( + title: 'Get to your destination quickly and easily.'.tr, + image: 'assets/images/on2.png', + body: 'With Sefer, you can get a ride to your destination in minutes.'.tr, + ), + OnBoardingModel( + title: 'Enjoy a safe and comfortable ride.'.tr, + image: 'assets/images/on3.png', + body: + 'Sefer is committed to safety, and all of our captains are carefully screened and background checked.' + .tr, + ), +]; + +class OnBoardingModel { + final String? title; + final String? image; + final String? body; + OnBoardingModel({this.body, this.title, this.image}); +} diff --git a/lib/print.dart b/lib/print.dart new file mode 100644 index 0000000..ccc2fb5 --- /dev/null +++ b/lib/print.dart @@ -0,0 +1,13 @@ +import 'dart:developer' as developer; + +class Log { + Log._(); + + static void print(String value, {StackTrace? stackTrace}) { + developer.log(value, name: 'LOG', stackTrace: stackTrace); + } + + static Object? inspect(Object? object) { + return developer.inspect(object); + } +} diff --git a/lib/views/admin/admin_home_page.dart b/lib/views/admin/admin_home_page.dart new file mode 100644 index 0000000..d5f85a6 --- /dev/null +++ b/lib/views/admin/admin_home_page.dart @@ -0,0 +1,393 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:get/get_rx/src/rx_typedefs/rx_typedefs.dart'; +import 'package:sefer_admin1/controller/admin/dashboard_controller.dart'; +import 'package:sefer_admin1/controller/notification_controller.dart'; +import 'package:sefer_admin1/views/widgets/mycircular.dart'; + +import '../../constant/links.dart'; +import '../../constant/style.dart'; +import '../../controller/functions/crud.dart'; +import '../../controller/functions/gemeni.dart'; +import '../widgets/my_scafold.dart'; +import 'captain/captain.dart'; +import 'passenger/passenger.dart'; +import 'rides/rides.dart'; +import 'static/static.dart'; +import 'wallet/wallet.dart'; + +class AdminHomePage extends StatelessWidget { + const AdminHomePage({super.key}); + + @override + Widget build(BuildContext context) { + Get.put(DashboardController()); + + return MyScafolld( + title: 'Admin Home Page', + body: [ + GetBuilder(builder: (dashboardController) { + return dashboardController.dashbord.isEmpty + ? const MyCircularProgressIndicator() + : Padding( + padding: const EdgeInsets.all(8.0), + child: ListView( + // crossAxisAlignment: WrapCrossAlignment.center, + // alignment: WrapAlignment.center, + children: [ + Container( + width: Get.width, + height: Get.height * .6, + decoration: AppStyle.boxDecoration1, + child: Wrap( + spacing: 6, + alignment: WrapAlignment.spaceBetween, + runAlignment: WrapAlignment.spaceBetween, + children: [ + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Sms', + style: AppStyle.title, + ), + Text(dashboardController.creditSMS + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Passengers', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['countPassengers'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Drivers', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['countDriver'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Rides this month', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['countRideThisMonth'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'avg costs', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['avg_passenger_price'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'completed ride', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['completed_rides'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'cancelled ride', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['cancelled_rides'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'payments to driver', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['payments'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'sefer wallet', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['seferWallet'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'count of transfer', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['transfer_from_count'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Morning', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['morning_ride_count'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'evening', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['evening_ride_count'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'night', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['night_ride_count'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'comfort', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['comfort'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Speed', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['speed'] + .toString()), + ], + ), + )), + Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Lady', + style: AppStyle.title, + ), + Text(dashboardController.dashbord[0] + ['lady'] + .toString()), + ], + ), + )), + ], + )), + AdminWidgetsDashBoard( + title: 'Passengers', + onPressed: () => Get.to(() => Passengrs(), + transition: Transition.topLevel)), + AdminWidgetsDashBoard( + title: 'Captains', + onPressed: () => Get.to(() => Captain(), + transition: Transition.size)), + AdminWidgetsDashBoard( + title: 'Wallet', + onPressed: () => Get.to(() => Wallet(), + transition: Transition.fade)), + AdminWidgetsDashBoard( + title: 'Rides', + onPressed: () => Get.to(() => Rides(), + transition: Transition.downToUp)), + AdminWidgetsDashBoard( + title: 'Static', + onPressed: () => Get.to(() => const StaticDash())), + AdminWidgetsDashBoard( + title: 'send notification Drivers', + onPressed: () async { + await Get.put(NotificationController()) + .getTokensDrivers(); + NotificationController() + .sendNotificationDrivers(); + }), + AdminWidgetsDashBoard( + title: 'send notification Passengers', + onPressed: () async { + await Get.put(NotificationController()) + .getTokensPassengers(); + NotificationController() + .sendNotificationPassengers(); + }), + // AdminWidgetsDashBoard( + // title: 'JordanID', onPressed: () => AI().jordanID()), + // AdminWidgetsDashBoard( + // title: 'Llama', + // onPressed: () => + // CarRegistrationRecognizerController().scanText()), + AdminWidgetsDashBoard( + title: 'Add device to be Admin', + onPressed: () async { + // Map device = DeviceInfoPlus.deviceData; + await CRUD() + .post(link: AppLink.addAdminUser, payload: { + // 'deviceNumber': device['serialNumber'].toString(), + 'name': 'b', + }); + }), + ], + ), + ); + }) + ], + isleading: false); + } +} + +class AdminWidgetsDashBoard extends StatelessWidget { + const AdminWidgetsDashBoard({ + super.key, + required this.title, + required this.onPressed, + }); + final String title; + final Callback onPressed; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: InkWell( + onTap: onPressed, + child: Container( + decoration: AppStyle.boxDecoration, + height: 50, + width: Get.width * .4, + child: Center( + child: Text( + title.tr, + style: AppStyle.title, + ), + ), + ), + ), + ); + } +} diff --git a/lib/views/admin/captain/captain.dart b/lib/views/admin/captain/captain.dart new file mode 100644 index 0000000..2a3ac66 --- /dev/null +++ b/lib/views/admin/captain/captain.dart @@ -0,0 +1,222 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/admin/captain_admin_controller.dart'; +import '../../widgets/elevated_btn.dart'; +import '../../widgets/my_scafold.dart'; +import '../../widgets/my_textField.dart'; +import '../../widgets/mycircular.dart'; +import 'captain_details.dart'; +import 'form_captain.dart'; + +class Captain extends StatelessWidget { + Captain({super.key}); + final CaptainAdminController captainAdminController = + Get.put(CaptainAdminController()); + @override + Widget build(BuildContext context) { + return MyScafolld( + title: 'Captain'.tr, + body: [ + GetBuilder( + builder: (captainAdminController) => Column( + children: [ + captainAdminController.isLoading + ? const MyCircularProgressIndicator() + : Column( + children: [ + Padding( + padding: const EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + captainAdmin( + captainAdminController, + 'Captains Count', + 'countPassenger', + ), + MyElevatedButton( + title: 'Add Prize to Gold Captains', + onPressed: () { + var date = DateTime.now(); + var day = date.weekday; + + if (day == 6) { + // Saturday is 6 + Get.defaultDialog( + title: + 'Add Prize to Gold Captains', + titleStyle: AppStyle.title, + content: Column( + children: [ + Text( + 'Add Points to their wallet as prize' + .tr, + style: AppStyle.title, + ), + Form( + key: captainAdminController + .formCaptainPrizeKey, + child: MyTextForm( + controller: + captainAdminController + .captainPrizeController, + label: + 'Count of prize' + .tr, + hint: 'Count of prize' + .tr, + type: TextInputType + .number)) + ], + ), + confirm: MyElevatedButton( + title: 'Add', + onPressed: () async { + if (captainAdminController + .formCaptainPrizeKey + .currentState! + .validate()) { + captainAdminController + .addCaptainsPrizeToWalletSecure(); + } + }, + ), + ); + } else { + Get.defaultDialog( + title: + 'This day is not allowed', + titleStyle: AppStyle.title, + middleText: + 'Saturday only Allowed day', + middleTextStyle: AppStyle.title, + confirm: MyElevatedButton( + title: 'Ok'.tr, + onPressed: () { + Get.back(); + })); + } + }) + ], + ), + ), + const SizedBox( + height: 10, + ), + InkWell( + onTap: () { + //todo search + }, + child: Padding( + padding: const EdgeInsets.all(3), + child: Container( + width: Get.width, + height: 110, + decoration: BoxDecoration( + border: Border.all( + width: 2, + color: AppColor.greenColor)), + child: formSearchCaptain() + // ], + // ), + ), + ), + ), + SizedBox( + height: Get.height * .5, + child: ListView.builder( + itemCount: captainAdminController + .captainData['message'].length, + itemBuilder: (context, index) { + final user = captainAdminController + .captainData['message'][index]; + + return InkWell( + onTap: () { + Get.to(const CaptainsDetailsPage(), + arguments: { + 'data': user, + }); + }, + child: Padding( + padding: const EdgeInsets.all(3), + child: Container( + decoration: BoxDecoration( + border: Border.all(width: 2)), + child: ListTile( + title: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'Name : ${user['first_name']} ${user['last_name']}', + style: AppStyle.title, + ), + Text( + 'Rating : ${user['ratingPassenger']}', + style: AppStyle.title, + ), + ], + ), + subtitle: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'Count Trip : ${user['countPassengerRide']}', + style: AppStyle.title, + ), + Text( + 'Count Driver Rate : ${user['countDriverRate']}', + style: AppStyle.title, + ), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ], + ), + ], + )) + ], + isleading: true, + ); + } + + Container captainAdmin(CaptainAdminController captainAdminController, + String title, String jsonField) { + return Container( + height: Get.height * .1, + decoration: BoxDecoration(border: Border.all(width: 2)), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () {}, + child: Column( + children: [ + Text( + title.tr, + style: AppStyle.title, + ), + Text( + captainAdminController.captainData['message'][0][jsonField] + .toString(), + style: AppStyle.title, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/views/admin/captain/captain_details.dart b/lib/views/admin/captain/captain_details.dart new file mode 100644 index 0000000..4b0b877 --- /dev/null +++ b/lib/views/admin/captain/captain_details.dart @@ -0,0 +1,167 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/admin/captain_admin_controller.dart'; +import '../../../controller/firebase/firbase_messge.dart'; +import '../../widgets/elevated_btn.dart'; +import '../../widgets/my_scafold.dart'; +import '../../widgets/my_textField.dart'; + +class CaptainsDetailsPage extends StatelessWidget { + const CaptainsDetailsPage({super.key}); + + @override + Widget build(BuildContext context) { + final arguments = Get.arguments; + final Map data = arguments['data']; + var key = Get.find().formCaptainPrizeKey; + var titleNotify = Get.find().titleNotify; + var bodyNotify = Get.find().bodyNotify; + return MyScafolld( + title: data['first_name'] + ' ' + data['last_name'], + body: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Email is ${data['email']}', + style: AppStyle.title, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Phone is ${data['phone']}', + style: AppStyle.title, + ), + Text( + 'gender is ${data['gender']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'status is ${data['status']}', + style: AppStyle.title, + ), + Text( + 'birthdate is ${data['birthdate']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'site is ${data['site']}', + style: AppStyle.title, + ), + // Text( + // 'sosPhone is ${data['sosPhone']}', + // style: AppStyle.title, + // ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Count Feedback is ${data['countFeedback']}', + style: AppStyle.title, + ), + Text( + 'Count Driver Rate is ${data['countDriverRate']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Count Cancel is ${data['countPassengerCancel']}', + style: AppStyle.title, + ), + Text( + 'Count Ride is ${data['countPassengerRide']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Rating Captain Avarage is ${data['passengerAverageRating']}', + style: AppStyle.title, + ), + Text( + 'Rating is ${data['ratingPassenger']}', + style: AppStyle.title, + ), + ], + ), + Container( + decoration: BoxDecoration( + border: Border.all(width: 3, color: AppColor.yellowColor)), + child: TextButton( + onPressed: () async { + Get.defaultDialog( + title: 'Send Notification'.tr, + titleStyle: AppStyle.title, + content: Form( + key: key, + child: Column( + children: [ + MyTextForm( + controller: titleNotify, + label: 'title'.tr, + hint: 'title notificaton'.tr, + type: TextInputType.name), + const SizedBox( + height: 10, + ), + MyTextForm( + controller: bodyNotify, + label: 'body'.tr, + hint: 'body notificaton'.tr, + type: TextInputType.name) + ], + ), + ), + confirm: MyElevatedButton( + title: 'Send', + onPressed: () { + if (key.currentState!.validate()) { + FirebaseMessagesController() + .sendNotificationToAnyWithoutData( + titleNotify.text, + bodyNotify.text, + data['passengerToken'], + ); + Get.back(); + } + })); + }, + child: Text( + "Send Notificaion to Captains ".tr, + style: AppStyle.title, + ), + ), + ) + ], + ), + ) + ], + isleading: true, + ); + } +} diff --git a/lib/views/admin/captain/form_captain.dart b/lib/views/admin/captain/form_captain.dart new file mode 100644 index 0000000..8856434 --- /dev/null +++ b/lib/views/admin/captain/form_captain.dart @@ -0,0 +1,84 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/admin/captain_admin_controller.dart'; +import '../../widgets/elevated_btn.dart'; +import 'captain_details.dart'; + +GetBuilder formSearchCaptain() { + // DbSql sql = DbSql.instance; + return GetBuilder( + builder: (controller) => Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Container( + decoration: + const BoxDecoration(color: AppColor.secondaryColor), + child: TextField( + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.only(), + gapPadding: 4, + borderSide: BorderSide( + color: AppColor.redColor, + width: 2, + )), + suffixIcon: InkWell( + onTap: () async { + if (controller.captainController.text.length > 4) { + await controller.getCaptains(); + + Get.defaultDialog( + title: controller.captain['message'][0] + ['email'], + titleStyle: AppStyle.title, + content: Column( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Name is ${controller.captain['message'][0]['first_name']} ${controller.captain['message'][0]['last_name']}', + style: AppStyle.title, + ), + Text( + 'phone is ${controller.captain['message'][0]['phone']}', + style: AppStyle.title, + ), + ], + ), + confirm: MyElevatedButton( + title: 'Go To Details'.tr, + onPressed: () { + Get.to( + () => const CaptainsDetailsPage(), + arguments: { + 'data': controller + .captain['message'][0], + }); + })); + } + }, + child: const Icon(Icons.search)), + hintText: 'Search for Passenger'.tr, + hintStyle: AppStyle.title, + hintMaxLines: 1, + prefixIcon: IconButton( + onPressed: () async { + controller.captainController.clear(); + // controller.clearPlaces(); + }, + icon: Icon( + Icons.clear, + color: Colors.red[300], + ), + ), + ), + controller: controller.captainController, + ), + ), + ) + ], + )); +} diff --git a/lib/views/admin/passenger/form_passenger.dart b/lib/views/admin/passenger/form_passenger.dart new file mode 100644 index 0000000..886a320 --- /dev/null +++ b/lib/views/admin/passenger/form_passenger.dart @@ -0,0 +1,86 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/admin/passenger_admin_controller.dart'; +import '../../widgets/elevated_btn.dart'; +import 'passenger_details_page.dart'; + +GetBuilder formSearchPassengers() { + // DbSql sql = DbSql.instance; + return GetBuilder( + builder: (controller) => Column( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Container( + decoration: + const BoxDecoration(color: AppColor.secondaryColor), + child: TextField( + decoration: InputDecoration( + border: const OutlineInputBorder( + borderRadius: BorderRadius.only(), + gapPadding: 4, + borderSide: BorderSide( + color: AppColor.redColor, + width: 2, + )), + suffixIcon: InkWell( + onTap: () async { + if (controller.passengerController.text.length > + 4) { + await controller.getPassengers(); + + Get.defaultDialog( + title: controller.passengers['message'][0] + ['email'], + titleStyle: AppStyle.title, + content: Column( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Name is ${controller.passengers['message'][0]['first_name']} ${controller.passengers['message'][0]['last_name']}', + style: AppStyle.title, + ), + Text( + 'phone is ${controller.passengers['message'][0]['phone']}', + style: AppStyle.title, + ), + ], + ), + confirm: MyElevatedButton( + title: 'Go To Details'.tr, + onPressed: () { + Get.to( + () => const PassengerDetailsPage(), + arguments: { + 'data': controller + .passengers['message'][0], + }); + })); + } + }, + child: const Icon(Icons.search)), + hintText: 'Search for Passenger'.tr, + hintStyle: AppStyle.title, + hintMaxLines: 1, + prefixIcon: IconButton( + onPressed: () async { + controller.passengerController.clear(); + controller.clearPlaces(); + }, + icon: Icon( + Icons.clear, + color: Colors.red[300], + ), + ), + ), + controller: controller.passengerController, + ), + ), + ) + ], + )); +} diff --git a/lib/views/admin/passenger/passenger.dart b/lib/views/admin/passenger/passenger.dart new file mode 100644 index 0000000..9ea0951 --- /dev/null +++ b/lib/views/admin/passenger/passenger.dart @@ -0,0 +1,204 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../constant/style.dart'; +import '../../../controller/admin/passenger_admin_controller.dart'; +import '../../widgets/elevated_btn.dart'; +import '../../widgets/my_scafold.dart'; +import '../../widgets/my_textField.dart'; +import '../../widgets/mycircular.dart'; +import 'form_passenger.dart'; +import 'passenger_details_page.dart'; + +class Passengrs extends StatelessWidget { + Passengrs({super.key}); + final PassengerAdminController passengerAdminController = + Get.put(PassengerAdminController()); + @override + Widget build(BuildContext context) { + return MyScafolld( + title: 'Passengrs'.tr, + isleading: true, + body: [ + GetBuilder( + builder: (passengerAdminController) => Column( + children: [ + passengerAdminController.isLoading + ? const MyCircularProgressIndicator() + : Column( + children: [ + Padding( + padding: const EdgeInsets.all(5), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + passengerAdmin( + passengerAdminController, + 'Passengers Count', + 'countPassenger', + ), + MyElevatedButton( + title: 'Add Prize to Gold Passengers', + onPressed: () { + var date = DateTime.now(); + var day = date.weekday; + + if (day == 6) { + // Saturday is 6 + Get.defaultDialog( + title: + 'Add Prize to Gold Passengers', + titleStyle: AppStyle.title, + content: Column( + children: [ + Text( + 'Add Points to their wallet as prize' + .tr, + style: AppStyle.title, + ), + Form( + key: + passengerAdminController + .formPrizeKey, + child: MyTextForm( + controller: + passengerAdminController + .passengerPrizeController, + label: + 'Count of prize' + .tr, + hint: 'Count of prize' + .tr, + type: TextInputType + .number)) + ], + ), + confirm: MyElevatedButton( + title: 'Add', + onPressed: () async { + if (passengerAdminController + .formPrizeKey + .currentState! + .validate()) { + passengerAdminController + .addPassengerPrizeToWalletSecure(); + } + }, + ), + ); + } else { + Get.defaultDialog( + title: + 'This day is not allowed', + titleStyle: AppStyle.title, + middleText: + 'Saturday only Allowed day', + middleTextStyle: AppStyle.title, + confirm: MyElevatedButton( + title: 'Ok'.tr, + onPressed: () { + Get.back(); + })); + } + }) + ], + ), + ), + const SizedBox( + height: 10, + ), + formSearchPassengers(), + SizedBox( + height: Get.height * .5, + child: ListView.builder( + itemCount: passengerAdminController + .passengersData['message'].length, + itemBuilder: (context, index) { + final user = passengerAdminController + .passengersData['message'][index]; + + return InkWell( + onTap: () { + Get.to(const PassengerDetailsPage(), + arguments: { + 'data': user, + }); + }, + child: Padding( + padding: const EdgeInsets.all(3), + child: Container( + decoration: BoxDecoration( + border: Border.all(width: 2)), + child: ListTile( + title: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'Name : ${user['first_name']} ${user['last_name']}', + style: AppStyle.title, + ), + Text( + 'Rating : ${user['ratingPassenger']}', + style: AppStyle.title, + ), + ], + ), + subtitle: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + 'Count Trip : ${user['countPassengerRide']}', + style: AppStyle.title, + ), + Text( + 'Count Driver Rate : ${user['countDriverRate']}', + style: AppStyle.title, + ), + ], + ), + ), + ), + ), + ); + }, + ), + ), + ], + ), + ], + )) + ], + ); + } + + Container passengerAdmin(PassengerAdminController passengerAdminController, + String title, String jsonField) { + return Container( + height: Get.height * .1, + decoration: BoxDecoration(border: Border.all(width: 2)), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: GestureDetector( + onTap: () {}, + child: Column( + children: [ + Text( + title.tr, + style: AppStyle.title, + ), + Text( + passengerAdminController.passengersData['message'][0][jsonField] + .toString(), + style: AppStyle.title, + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/views/admin/passenger/passenger_details_page.dart b/lib/views/admin/passenger/passenger_details_page.dart new file mode 100644 index 0000000..1140721 --- /dev/null +++ b/lib/views/admin/passenger/passenger_details_page.dart @@ -0,0 +1,167 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/admin/passenger_admin_controller.dart'; +import '../../../controller/firebase/firbase_messge.dart'; +import '../../widgets/elevated_btn.dart'; +import '../../widgets/my_scafold.dart'; +import '../../widgets/my_textField.dart'; + +class PassengerDetailsPage extends StatelessWidget { + const PassengerDetailsPage({super.key}); + + @override + Widget build(BuildContext context) { + final arguments = Get.arguments; + final Map data = arguments['data']; + var key = Get.find().formPrizeKey; + var titleNotify = Get.find().titleNotify; + var bodyNotify = Get.find().bodyNotify; + return MyScafolld( + title: data['first_name'], + body: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Email is ${data['email']}', + style: AppStyle.title, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Phone is ${data['phone']}', + style: AppStyle.title, + ), + Text( + 'gender is ${data['gender']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'status is ${data['status']}', + style: AppStyle.title, + ), + Text( + 'birthdate is ${data['birthdate']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'site is ${data['site']}', + style: AppStyle.title, + ), + Text( + 'sosPhone is ${data['sosPhone']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Count Feedback is ${data['countFeedback']}', + style: AppStyle.title, + ), + Text( + 'Count Driver Rate is ${data['countDriverRate']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Count Cancel is ${data['countPassengerCancel']}', + style: AppStyle.title, + ), + Text( + 'Count Ride is ${data['countPassengerRide']}', + style: AppStyle.title, + ), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Rating Captain Avarage is ${data['passengerAverageRating']}', + style: AppStyle.title, + ), + Text( + 'Rating is ${data['ratingPassenger']}', + style: AppStyle.title, + ), + ], + ), + Container( + decoration: BoxDecoration( + border: Border.all(width: 3, color: AppColor.yellowColor)), + child: TextButton( + onPressed: () async { + Get.defaultDialog( + title: 'Send Notification'.tr, + titleStyle: AppStyle.title, + content: Form( + key: key, + child: Column( + children: [ + MyTextForm( + controller: titleNotify, + label: 'title'.tr, + hint: 'title notificaton'.tr, + type: TextInputType.name), + const SizedBox( + height: 10, + ), + MyTextForm( + controller: bodyNotify, + label: 'body'.tr, + hint: 'body notificaton'.tr, + type: TextInputType.name) + ], + ), + ), + confirm: MyElevatedButton( + title: 'Send', + onPressed: () { + if (key.currentState!.validate()) { + FirebaseMessagesController() + .sendNotificationToAnyWithoutData( + titleNotify.text, + bodyNotify.text, + data['passengerToken'], + ); + Get.back(); + } + })); + }, + child: Text( + "Send Notificaion to Passenger ".tr, + style: AppStyle.title, + ), + ), + ) + ], + ), + ) + ], + isleading: true, + ); + } +} diff --git a/lib/views/admin/rides/rides.dart b/lib/views/admin/rides/rides.dart new file mode 100644 index 0000000..2ef76da --- /dev/null +++ b/lib/views/admin/rides/rides.dart @@ -0,0 +1,236 @@ +import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import '../../../constant/colors.dart'; +import '../../../constant/style.dart'; +import '../../../controller/admin/ride_admin_controller.dart'; +import '../../widgets/my_scafold.dart'; +import '../../widgets/mycircular.dart'; + +class Rides extends StatelessWidget { + Rides({super.key}); + RideAdminController rideAdminController = Get.put(RideAdminController()); + @override + Widget build(BuildContext context) { + return MyScafolld(title: 'Rides'.tr, isleading: true, body: [ + GetBuilder( + builder: (rideAdminController) => rideAdminController.isLoading + ? const Center(child: MyCircularProgressIndicator()) + : Column( + children: [ + SizedBox( + height: Get.height * .4, + child: LineChart( + duration: const Duration(milliseconds: 150), + curve: Curves.ease, + LineChartData( + lineBarsData: [ + LineChartBarData( + spots: rideAdminController.chartData, + isCurved: true, + color: Colors.deepPurpleAccent, // Custom color + barWidth: 3, // Thinner line + dotData: const FlDotData( + show: true), // Show dots on each point + belowBarData: BarAreaData( + // Add gradient fill below the line + show: true, + color: AppColor.deepPurpleAccent, + ), + isStrokeJoinRound: true, + shadow: const BoxShadow( + color: AppColor.yellowColor, + blurRadius: 4, + offset: Offset(2, 2), + ), + ), + ], + showingTooltipIndicators: const [], + titlesData: FlTitlesData( + show: true, + topTitles: AxisTitles( + axisNameWidget: Text( + 'Days', + style: AppStyle.title, + ), + axisNameSize: 30, + sideTitles: const SideTitles( + reservedSize: 30, showTitles: true)), + bottomTitles: AxisTitles( + axisNameWidget: Text( + 'Total Trips on month'.tr, + style: AppStyle.title, + ), + axisNameSize: 30, + sideTitles: const SideTitles( + reservedSize: 30, showTitles: true)), + leftTitles: AxisTitles( + axisNameWidget: Text( + 'Counts of Trips on month'.tr, + style: AppStyle.title, + ), + axisNameSize: 30, + sideTitles: const SideTitles( + reservedSize: 30, showTitles: true)), + ), + gridData: const FlGridData( + show: true, + ), + borderData: FlBorderData( + show: true, + border: const Border( + bottom: BorderSide(color: AppColor.accentColor), + left: BorderSide(color: AppColor.accentColor), + ), + ), + ), + ), + ), + // SizedBox( + // height: Get.height * .4, + // child: PieChart( + // PieChartData( + // sectionsSpace: 4, // Adjust spacing between sections + // centerSpaceRadius: + // 40, // Adjust radius of center space + // sections: [ + // for (final rideData in rideAdminController.rideData) + // PieChartSectionData( + // value: rideData.ridesCount.toDouble(), + // title: '${rideData.day}', showTitle: true, + // titleStyle: + // AppStyle.subtitle, // Display day as title + // radius: 60, // Adjust radius of each section + // color: + // AppColor.deepPurpleAccent, // Custom color + // ), + // ], + // ), + // ), + // ), + + // SizedBox( + // // height: 400, + // child: SfCartesianChart( + // legend: const Legend( + // isVisible: true, + // position: LegendPosition.bottom, + // overflowMode: LegendItemOverflowMode.wrap, + // textStyle: TextStyle( + // color: Colors.white, + // fontSize: 12, + // fontWeight: FontWeight.bold, + // ), + // ), + // borderWidth: 2, + // borderColor: AppColor.blueColor, + // plotAreaBorderColor: AppColor.deepPurpleAccent, + // enableAxisAnimation: true, + // primaryXAxis: CategoryAxis( + // borderColor: AppColor.accentColor, borderWidth: 2, + // title: AxisTitle( + // text: 'Total Trips on month'.tr, + // textStyle: AppStyle.title, + // ), + // // labelRotation: 45, + // majorGridLines: const MajorGridLines(width: 0), + // ), + // primaryYAxis: const NumericAxis(isVisible: false), + // series: >[ + // LineSeries( + // dataSource: rideAdminController.chartDatasync, + // xValueMapper: (ChartDataS data, _) => '${data.day}', + // yValueMapper: (ChartDataS data, _) => + // data.ridesCount, + // dataLabelSettings: + // const DataLabelSettings(isVisible: true), + // ), + // ], + // ), + // ), + + const SizedBox( + height: 20, + ), + Card( + elevation: 4, + color: AppColor.deepPurpleAccent, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Text( + 'Total Trips on this Month is ${rideAdminController.jsonResponse['message'][0]['current_month_rides_count']}', + style: AppStyle.title, + ), + ), + ), + const SizedBox( + height: 20, + ), + Card( + elevation: 4, + color: AppColor.yellowColor, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + 'Driver Average Duration: ${rideAdminController.ridesDetails[0]['driver_avg_duration']}', + style: AppStyle.subtitle, + ), + Text( + 'Number of Drivers: ${rideAdminController.ridesDetails[0]['num_Driver']}', + style: AppStyle.subtitle, + ), + Text( + 'Total Rides: ${rideAdminController.ridesDetails[0]['total_rides']}', + style: AppStyle.subtitle, + ), + Text( + 'Ongoing Rides: ${rideAdminController.ridesDetails[0]['ongoing_rides']}', + style: AppStyle.subtitle, + ), + Text( + 'Completed Rides: ${rideAdminController.ridesDetails[0]['completed_rides']}', + style: AppStyle.subtitle, + ), + Text( + 'Cancelled Rides: ${rideAdminController.ridesDetails[0]['cancelled_rides']}', + style: AppStyle.subtitle, + ), + Text( + 'Longest Duration: ${rideAdminController.ridesDetails[0]['longest_duration']}', + style: AppStyle.subtitle, + ), + Text( + 'Total Distance: ${rideAdminController.ridesDetails[0]['total_distance']} km', + style: AppStyle.subtitle, + ), + Text( + 'Average Distance: ${rideAdminController.ridesDetails[0]['average_distance']} km', + style: AppStyle.subtitle, + ), + Text( + 'Longest Distance: ${rideAdminController.ridesDetails[0]['longest_distance']} km', + style: AppStyle.subtitle, + ), + Text( + 'Total Driver Earnings: \$${rideAdminController.ridesDetails[0]['total_driver_earnings']}', + style: AppStyle.subtitle, + ), + Text( + 'Total Company Earnings: \$${rideAdminController.ridesDetails[0]['total_company_earnings']}', + style: AppStyle.subtitle, + ), + Text( + 'Company Percentage: ${rideAdminController.ridesDetails[0]['companyPercent']} %', + style: AppStyle.subtitle, + ), + ], + ), + ), + ) + ], + )) + ]); + } +} diff --git a/lib/views/admin/static/static.dart b/lib/views/admin/static/static.dart new file mode 100644 index 0000000..6578c79 --- /dev/null +++ b/lib/views/admin/static/static.dart @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../widgets/my_scafold.dart'; + +class StaticDash extends StatelessWidget { + const StaticDash({super.key}); + + @override + Widget build(BuildContext context) { + return MyScafolld(title: 'Static Dash'.tr, body: [], isleading: true); + } +} diff --git a/lib/views/admin/wallet/wallet.dart b/lib/views/admin/wallet/wallet.dart new file mode 100644 index 0000000..ca46975 --- /dev/null +++ b/lib/views/admin/wallet/wallet.dart @@ -0,0 +1,83 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:sefer_admin1/constant/style.dart'; +import 'package:sefer_admin1/views/widgets/elevated_btn.dart'; +import 'package:sefer_admin1/views/widgets/mycircular.dart'; + +import '../../../controller/admin/wallet_admin_controller.dart'; +import '../../widgets/my_scafold.dart'; + +class Wallet extends StatelessWidget { + Wallet({super.key}); + WalletAdminController walletAdminController = + Get.put(WalletAdminController()); + @override + Widget build(BuildContext context) { + return MyScafolld( + title: 'Wallet'.tr, + body: [ + GetBuilder(builder: (walletAdminController) { + return Center( + child: walletAdminController.isLoading + ? const MyCircularProgressIndicator() + : Column( + children: [ + MyElevatedButton( + title: 'Pay to them to banks'.tr, + onPressed: () async { + await walletAdminController.payToBankDriverAll(); + }), + SizedBox( + height: Get.height * .8, + child: ListView.builder( + itemCount: + walletAdminController.driversWalletPoints.length, + itemBuilder: (BuildContext context, int index) { + var res = walletAdminController + .driversWalletPoints[index]; + + if (res != null && res['name_arabic'] != null) { + return Padding( + padding: const EdgeInsets.all(4.0), + child: Container( + decoration: AppStyle.boxDecoration1, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 10), + child: Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + 'driver name: ${res['name_arabic'].toString()}'), + Text( + 'Amount: ${res['total_amount'].toString()}'), + ], + ), + ), + ), + ); + } else { + return Container(); // Return an empty container if the data is null + } + }, + ), + ) + ], + ), + ); + }) + ], + isleading: true, + action: IconButton( + onPressed: () async { + walletAdminController.getWalletForEachDriverToPay(); + }, + icon: const Icon( + Icons.refresh, + color: Colors.black, + ), + ), + ); + } +} diff --git a/lib/views/widgets/circle_container.dart b/lib/views/widgets/circle_container.dart new file mode 100644 index 0000000..9702b34 --- /dev/null +++ b/lib/views/widgets/circle_container.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../constant/colors.dart'; + +class MyCircleContainer extends StatelessWidget { + final Widget child; + final Color backgroundColor; + final Color borderColor; + + MyCircleContainer({ + Key? key, + required this.child, + this.backgroundColor = AppColor.secondaryColor, + this.borderColor = AppColor.accentColor, + }) : super(key: key); + + final controller = Get.put(CircleController()); + + @override + Widget build(BuildContext context) { + return GetBuilder( + builder: ((controller) => GestureDetector( + onTap: () { + controller.changeColor(); + }, + child: AnimatedContainer( + onEnd: () { + controller.onEnd(); + }, + duration: const Duration(milliseconds: 300), + width: controller.size, + height: controller.size, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: controller.backgroundColor, + border: Border.all( + color: borderColor, + width: 1, + ), + ), + child: Center(child: child), + ), + ))); + } +} + +class CircleController extends GetxController { + Color backgroundColor = AppColor.secondaryColor; + double size = 40; + void changeColor() { + backgroundColor = backgroundColor == AppColor.secondaryColor + ? AppColor.accentColor + : AppColor.secondaryColor; + size = 60; + update(); + } + + void onEnd() { + size = 40; + update(); + } +} diff --git a/lib/views/widgets/elevated_btn.dart b/lib/views/widgets/elevated_btn.dart new file mode 100644 index 0000000..8ca37b5 --- /dev/null +++ b/lib/views/widgets/elevated_btn.dart @@ -0,0 +1,47 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +import '../../constant/colors.dart'; +import '../../constant/style.dart'; + +class MyElevatedButton extends StatelessWidget { + final String title; + final VoidCallback onPressed; + final Color kolor; + final int vibrateDuration; + const MyElevatedButton({ + Key? key, + required this.title, + required this.onPressed, + this.kolor = AppColor.primaryColor, + this.vibrateDuration = 100, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.all(kolor), + ), + onPressed: () async { + // Handle haptic feedback for both iOS and Android + if (Platform.isIOS) { + HapticFeedback.selectionClick(); + } else { + // Vibration.vibrate(duration: 100); + // Vibrate.vibrateWithPauses(pauses); + } + + // Ensure the onPressed callback is called after haptic feedback + onPressed(); + }, + child: Text( + title, + textAlign: TextAlign.center, + style: AppStyle.title.copyWith(color: AppColor.secondaryColor), + ), + ); + } +} diff --git a/lib/views/widgets/icon_widget_menu.dart b/lib/views/widgets/icon_widget_menu.dart new file mode 100644 index 0000000..604aa40 --- /dev/null +++ b/lib/views/widgets/icon_widget_menu.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; + +import '../../constant/colors.dart'; +import '../../constant/style.dart'; + +class IconWidgetMenu extends StatelessWidget { + const IconWidgetMenu({ + Key? key, + required this.onpressed, + required this.icon, + required this.title, + }) : super(key: key); + + final VoidCallback onpressed; + final IconData icon; + final String title; + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onpressed, + child: Padding( + padding: const EdgeInsets.only(top: 25), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 50, + decoration: const BoxDecoration( + color: AppColor.secondaryColor, + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: AppColor.secondaryColor, + offset: Offset(-2, -2), + blurRadius: 0, + spreadRadius: 0, + blurStyle: BlurStyle.outer, + ), + BoxShadow( + color: AppColor.accentColor, + offset: Offset(3, 3), + blurRadius: 0, + spreadRadius: 0, + blurStyle: BlurStyle.outer, + ), + ], + ), + child: Center( + child: Icon( + icon, + size: 30, + color: AppColor.primaryColor, + ), + ), + ), + Text( + title, + style: AppStyle.subtitle, + ) + ], + ), + ), + ); + } +} diff --git a/lib/views/widgets/my_scafold.dart b/lib/views/widgets/my_scafold.dart new file mode 100644 index 0000000..fe50446 --- /dev/null +++ b/lib/views/widgets/my_scafold.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; + +import '../../constant/colors.dart'; +import '../../constant/style.dart'; + +class MyScafolld extends StatelessWidget { + const MyScafolld({ + super.key, + required this.title, + required this.body, + this.action = const Icon( + Icons.clear, + color: AppColor.secondaryColor, + ), + required this.isleading, + }); + + final String title; + final List body; + final Widget action; + final bool isleading; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppColor.secondaryColor, + appBar: AppBar( + backgroundColor: AppColor.secondaryColor, + elevation: 0, + leading: isleading + ? IconButton( + onPressed: () { + Get.back(); + }, + icon: const Icon( + Icons.arrow_back_ios_new, + color: AppColor.primaryColor, + ), + ) + : const SizedBox(), + actions: [action], + title: Text( + title, + style: AppStyle.title.copyWith(fontSize: 30), + ), + ), + body: SafeArea(child: Stack(children: body))); + } +} diff --git a/lib/views/widgets/my_textField.dart b/lib/views/widgets/my_textField.dart new file mode 100644 index 0000000..54f2bf0 --- /dev/null +++ b/lib/views/widgets/my_textField.dart @@ -0,0 +1,65 @@ +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; +import 'package:get_storage/get_storage.dart'; + +import '../../constant/colors.dart'; + +class MyTextForm extends StatelessWidget { + const MyTextForm({ + super.key, + required this.controller, + required this.label, + required this.hint, + required this.type, + }); + final TextEditingController controller; + final String label, hint; + final TextInputType type; + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: SizedBox( + width: Get.width * .8, + child: TextFormField( + keyboardType: type, + cursorColor: AppColor.accentColor, + controller: controller, + decoration: InputDecoration( + focusedBorder: OutlineInputBorder( + borderSide: const BorderSide( + color: AppColor.primaryColor, + width: 2.0, + ), + borderRadius: BorderRadius.circular(10), + ), + focusColor: AppColor.accentColor, + fillColor: AppColor.accentColor, + border: const OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(12))), + labelText: label.tr, + hintText: hint.tr, + ), + validator: (value) { + if (value!.isEmpty) { + return 'Please enter $label.'.tr; + } + + if (type == TextInputType.emailAddress) { + if (!value.contains('@')) { + return 'Please enter a valid email.'.tr; + } + } else if (type == TextInputType.phone) { + if (value.length != 10) { + return 'Please enter a valid phone number.'.tr; + } + } + + return null; + }, + ), + ), + ); + } +} diff --git a/lib/views/widgets/mycircular.dart b/lib/views/widgets/mycircular.dart new file mode 100644 index 0000000..366d81a --- /dev/null +++ b/lib/views/widgets/mycircular.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; + +class MyCircularProgressIndicator extends StatelessWidget { + final Color backgroundColor; + + const MyCircularProgressIndicator({ + super.key, + this.backgroundColor = Colors.transparent, + }); + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + width: 110, + height: 110, + decoration: BoxDecoration( + color: backgroundColor, + shape: BoxShape.circle, + ), + child: Stack( + children: [ + const Center(child: CircularProgressIndicator()), + Column( + children: [ + Align( + alignment: Alignment.center, + child: Image.asset('assets/images/logo.png'), + ), + ], + ), + ], + ), + ), + ); + } +} 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..c69d6ce --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,145 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.10) +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 "sefer_admin1") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.sefer_admin1") + +# 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) + +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Define the application target. To change its name, change BINARY_NAME above, +# 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 dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +# 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..38dd0bc --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,19 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include + +void fl_register_plugins(FlPluginRegistry* registry) { + g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); + flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_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..65240e9 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,25 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + flutter_secure_storage_linux + url_launcher_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/main.cc b/linux/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/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/my_application.cc b/linux/my_application.cc new file mode 100644 index 0000000..4480642 --- /dev/null +++ b/linux/my_application.cc @@ -0,0 +1,124 @@ +#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, "sefer_admin1"); + 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, "sefer_admin1"); + } + + 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() { + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, + "flags", G_APPLICATION_NON_UNIQUE, + nullptr)); +} diff --git a/linux/my_application.h b/linux/my_application.h new file mode 100644 index 0000000..72271d5 --- /dev/null +++ b/linux/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..4b81f9b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#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..5caa9d1 --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1,2 @@ +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..d17c3a1 --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,26 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import firebase_core +import firebase_messaging +import flutter_secure_storage_macos +import google_sign_in_ios +import location +import path_provider_foundation +import sqflite +import url_launcher_macos + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) + FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) + LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) +} diff --git a/macos/Podfile b/macos/Podfile new file mode 100644 index 0000000..c795730 --- /dev/null +++ b/macos/Podfile @@ -0,0 +1,43 @@ +platform :osx, '10.14' + +# CocoaPods analytics sends network stats synchronously affecting flutter build latency. +ENV['COCOAPODS_DISABLE_STATS'] = 'true' + +project 'Runner', { + 'Debug' => :debug, + 'Profile' => :release, + 'Release' => :release, +} + +def flutter_root + generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'ephemeral', 'Flutter-Generated.xcconfig'), __FILE__) + unless File.exist?(generated_xcode_build_settings_path) + raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure \"flutter pub get\" is executed first" + end + + File.foreach(generated_xcode_build_settings_path) do |line| + matches = line.match(/FLUTTER_ROOT\=(.*)/) + return matches[1].strip if matches + end + raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Flutter-Generated.xcconfig, then run \"flutter pub get\"" +end + +require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root) + +flutter_macos_podfile_setup + +target 'Runner' do + use_frameworks! + use_modular_headers! + + flutter_install_all_macos_pods File.dirname(File.realpath(__FILE__)) + target 'RunnerTests' do + inherit! :search_paths + end +end + +post_install do |installer| + installer.pods_project.targets.each do |target| + flutter_additional_macos_build_settings(target) + end +end diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..5e4052c --- /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 /* sefer_admin1.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "sefer_admin1.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 /* sefer_admin1.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 /* sefer_admin1.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.seferAdmin1.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sefer_admin1.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/sefer_admin1"; + }; + 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.seferAdmin1.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sefer_admin1.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/sefer_admin1"; + }; + 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.seferAdmin1.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sefer_admin1.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/sefer_admin1"; + }; + 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..dcc9887 --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..d53ef64 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,9 @@ +import Cocoa +import FlutterMacOS + +@NSApplicationMain +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: 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 0000000..82b6f9d Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ 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 0000000..13b35eb Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ 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 0000000..0a3f5fa Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000..bdb5722 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000..f083318 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000..326c0e7 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ 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 0000000..2f1632c Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..80e867a --- /dev/null +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..1c22b12 --- /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 = sefer_admin1 + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.seferAdmin1 + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2024 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..5418c9f --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import FlutterMacOS +import Cocoa +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..143ca34 --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,1138 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: "0b2f2bd91ba804e53a61d757b986f89f1f9eaed5b11e4b2f5a2468d86d6c9fc7" + url: "https://pub.dev" + source: hosted + version: "67.0.0" + _flutterfire_internals: + dependency: transitive + description: + name: _flutterfire_internals + sha256: "37a42d06068e2fe3deddb2da079a8c4d105f241225ba27b7122b37e9865fd8f7" + url: "https://pub.dev" + source: hosted + version: "1.3.35" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "37577842a27e4338429a1cbc32679d508836510b056f1eedf0c8d20e39c1383d" + url: "https://pub.dev" + source: hosted + version: "6.4.1" + archive: + dependency: transitive + description: + name: archive + sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d + url: "https://pub.dev" + source: hosted + version: "3.6.1" + args: + dependency: transitive + description: + name: args + sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a" + url: "https://pub.dev" + source: hosted + version: "2.5.0" + async: + dependency: transitive + description: + name: async + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" + source: hosted + version: "2.11.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "3ac61a79bfb6f6cc11f693591063a7f19a7af628dc52f141743edac5c16e8c22" + url: "https://pub.dev" + source: hosted + version: "2.4.9" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" + url: "https://pub.dev" + source: hosted + version: "7.3.0" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c7913a9737ee4007efedaffc968c049fd0f3d0e49109e778edc10de9426005cb + url: "https://pub.dev" + source: hosted + version: "8.9.2" + characters: + dependency: transitive + description: + name: characters + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" + source: hosted + version: "1.3.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: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 + url: "https://pub.dev" + source: hosted + version: "0.4.1" + clock: + dependency: transitive + description: + name: clock + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" + source: hosted + version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" + collection: + dependency: transitive + description: + name: collection + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + convert: + dependency: transitive + description: + name: convert + sha256: "0f08b14755d163f6e2134cb58222dd25ea2a2ee8a195e53983d57c075324d592" + url: "https://pub.dev" + source: hosted + version: "3.1.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab + url: "https://pub.dev" + source: hosted + version: "3.0.3" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "99e066ce75c89d6b29903d788a7bb9369cf754f7b24bf70bf4b6d6d6b26853b9" + url: "https://pub.dev" + source: hosted + version: "2.3.6" + dio: + dependency: "direct main" + description: + name: dio + sha256: "11e40df547d418cc0c4900a9318b26304e665da6fa4755399a9ff9efd09034b5" + url: "https://pub.dev" + source: hosted + version: "5.4.3+1" + envied: + dependency: "direct main" + description: + name: envied + sha256: bbff9c76120e4dc5e2e36a46690cf0a26feb65e7765633f4e8d916bcd173a450 + url: "https://pub.dev" + source: hosted + version: "0.5.4+1" + envied_generator: + dependency: "direct dev" + description: + name: envied_generator + sha256: "517b70de08d13dcd40e97b4e5347e216a0b1c75c99e704f3c85c0474a392d14a" + url: "https://pub.dev" + source: hosted + version: "0.5.4+1" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" + source: hosted + version: "1.3.1" + ffi: + dependency: transitive + description: + name: ffi + sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + file: + dependency: transitive + description: + name: file + sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + url: "https://pub.dev" + source: hosted + version: "7.0.0" + firebase_core: + dependency: "direct main" + description: + name: firebase_core + sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c" + url: "https://pub.dev" + source: hosted + version: "2.32.0" + firebase_core_platform_interface: + dependency: transitive + description: + name: firebase_core_platform_interface + sha256: "1003a5a03a61fc9a22ef49f37cbcb9e46c86313a7b2e7029b9390cf8c6fc32cb" + url: "https://pub.dev" + source: hosted + version: "5.1.0" + firebase_core_web: + dependency: transitive + description: + name: firebase_core_web + sha256: "6643fe3dbd021e6ccfb751f7882b39df355708afbdeb4130fc50f9305a9d1a3d" + url: "https://pub.dev" + source: hosted + version: "2.17.2" + firebase_messaging: + dependency: "direct main" + description: + name: firebase_messaging + sha256: a1662cc95d9750a324ad9df349b873360af6f11414902021f130c68ec02267c4 + url: "https://pub.dev" + source: hosted + version: "14.9.4" + firebase_messaging_platform_interface: + dependency: transitive + description: + name: firebase_messaging_platform_interface + sha256: "87c4a922cb6f811cfb7a889bdbb3622702443c52a0271636cbc90d813ceac147" + url: "https://pub.dev" + source: hosted + version: "4.5.37" + firebase_messaging_web: + dependency: transitive + description: + name: firebase_messaging_web + sha256: "0d34dca01a7b103ed7f20138bffbb28eb0e61a677bf9e78a028a932e2c7322d5" + url: "https://pub.dev" + source: hosted + version: "3.8.7" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "2b7c1f5d867da9a054661641c8f499c55c47c39acccb97b3bc673f5fa9a39e74" + url: "https://pub.dev" + source: hosted + version: "0.67.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_launcher_icons: + dependency: "direct main" + description: + name: flutter_launcher_icons + sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea" + url: "https://pub.dev" + source: hosted + version: "0.13.1" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + flutter_paypal: + dependency: "direct main" + description: + name: flutter_paypal + sha256: "783d52ca84528b4b7a1213db5195e6946a2d27b2192f4fcd6d0b04b8c37e359e" + url: "https://pub.dev" + source: hosted + version: "0.2.0" + flutter_plugin_android_lifecycle: + dependency: transitive + description: + name: flutter_plugin_android_lifecycle + sha256: "8cf40eebf5dec866a6d1956ad7b4f7016e6c0cc69847ab946833b7d43743809f" + url: "https://pub.dev" + source: hosted + version: "2.0.19" + flutter_secure_storage: + dependency: "direct main" + description: + name: flutter_secure_storage + sha256: "165164745e6afb5c0e3e3fcc72a012fb9e58496fb26ffb92cf22e16a821e85d0" + url: "https://pub.dev" + source: hosted + version: "9.2.2" + flutter_secure_storage_linux: + dependency: transitive + description: + name: flutter_secure_storage_linux + sha256: "4d91bfc23047422cbcd73ac684bc169859ee766482517c22172c86596bf1464b" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + flutter_secure_storage_macos: + dependency: transitive + description: + name: flutter_secure_storage_macos + sha256: "1693ab11121a5f925bbea0be725abfcfbbcf36c1e29e571f84a0c0f436147a81" + url: "https://pub.dev" + source: hosted + version: "3.1.2" + flutter_secure_storage_platform_interface: + dependency: transitive + description: + name: flutter_secure_storage_platform_interface + sha256: cf91ad32ce5adef6fba4d736a542baca9daf3beac4db2d04be350b87f69ac4a8 + url: "https://pub.dev" + source: hosted + version: "1.1.2" + flutter_secure_storage_web: + dependency: transitive + description: + name: flutter_secure_storage_web + sha256: f4ebff989b4f07b2656fb16b47852c0aab9fed9b4ec1c70103368337bc1886a9 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + flutter_secure_storage_windows: + dependency: transitive + description: + name: flutter_secure_storage_windows + sha256: b20b07cb5ed4ed74fc567b78a72936203f587eba460af1df11281c9326cd3709 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + flutter_spinkit: + dependency: transitive + description: + name: flutter_spinkit + sha256: d2696eed13732831414595b98863260e33e8882fc069ee80ec35d4ac9ddb0472 + url: "https://pub.dev" + source: hosted + version: "5.2.1" + 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" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + get: + dependency: "direct main" + description: + name: get + sha256: e4e7335ede17452b391ed3b2ede016545706c01a02292a6c97619705e7d2a85e + url: "https://pub.dev" + source: hosted + version: "4.6.6" + get_storage: + dependency: "direct main" + description: + name: get_storage + sha256: "39db1fffe779d0c22b3a744376e86febe4ade43bf65e06eab5af707dc84185a2" + url: "https://pub.dev" + source: hosted + version: "2.1.1" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + sha256: "6b6f10f0ce3c42f6552d1c70d2c28d764cf22bb487f50f66cca31dcd5194f4d6" + url: "https://pub.dev" + source: hosted + version: "4.0.4" + google_identity_services_web: + dependency: transitive + description: + name: google_identity_services_web + sha256: "9482364c9f8b7bd36902572ebc3a7c2b5c8ee57a9c93e6eb5099c1a9ec5265d8" + url: "https://pub.dev" + source: hosted + version: "0.3.1+1" + google_sign_in: + dependency: "direct main" + description: + name: google_sign_in + sha256: "0b8787cb9c1a68ad398e8010e8c8766bfa33556d2ab97c439fb4137756d7308f" + url: "https://pub.dev" + source: hosted + version: "6.2.1" + google_sign_in_android: + dependency: transitive + description: + name: google_sign_in_android + sha256: "7647893c65e6720973f0e579051c8f84b877b486614d9f70a404259c41a4632e" + url: "https://pub.dev" + source: hosted + version: "6.1.23" + google_sign_in_ios: + dependency: transitive + description: + name: google_sign_in_ios + sha256: a058c9880be456f21e2e8571c1126eaacd570bdc5b6c6d9d15aea4bdf22ca9fe + url: "https://pub.dev" + source: hosted + version: "5.7.6" + google_sign_in_platform_interface: + dependency: transitive + description: + name: google_sign_in_platform_interface + sha256: "1f6e5787d7a120cc0359ddf315c92309069171306242e181c09472d1b00a2971" + url: "https://pub.dev" + source: hosted + version: "2.4.5" + google_sign_in_web: + dependency: transitive + description: + name: google_sign_in_web + sha256: d606264c7a1a526a3aa79d938b85a601d8589731a478bd4a3dcbdeb14a572228 + url: "https://pub.dev" + source: hosted + version: "0.12.4+1" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" + http: + dependency: "direct main" + description: + name: http + sha256: "5895291c13fa8a3bd82e76d5627f69e0d85ca6a30dcac95c4ea19a5d555879c2" + url: "https://pub.dev" + source: hosted + version: "0.13.6" + http_auth: + dependency: transitive + description: + name: http_auth + sha256: b7625acba2987fa69140d9600c679819f33227d665f525fbb2f394e08cf917d1 + url: "https://pub.dev" + source: hosted + version: "1.0.4" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" + url: "https://pub.dev" + source: hosted + version: "4.0.2" + image: + dependency: transitive + description: + name: image + sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8" + url: "https://pub.dev" + source: hosted + version: "4.2.0" + intl: + dependency: "direct main" + description: + name: intl + sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf + url: "https://pub.dev" + source: hosted + version: "0.19.0" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + js: + dependency: transitive + description: + name: js + sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 + url: "https://pub.dev" + source: hosted + version: "0.6.7" + 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: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + lints: + dependency: transitive + description: + name: lints + sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290 + url: "https://pub.dev" + source: hosted + version: "3.0.0" + local_auth: + dependency: "direct main" + description: + name: local_auth + sha256: "280421b416b32de31405b0a25c3bd42dfcef2538dfbb20c03019e02a5ed55ed0" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + local_auth_android: + dependency: transitive + description: + name: local_auth_android + sha256: e0e5b1ea247c5a0951c13a7ee13dc1beae69750e6a2e1910d1ed6a3cd4d56943 + url: "https://pub.dev" + source: hosted + version: "1.0.38" + local_auth_darwin: + dependency: transitive + description: + name: local_auth_darwin + sha256: e424ebf90d5233452be146d4a7da4bcd7a70278b67791592f3fde1bda8eef9e2 + url: "https://pub.dev" + source: hosted + version: "1.3.1" + local_auth_platform_interface: + dependency: transitive + description: + name: local_auth_platform_interface + sha256: "1b842ff177a7068442eae093b64abe3592f816afd2a533c0ebcdbe40f9d2075a" + url: "https://pub.dev" + source: hosted + version: "1.0.10" + local_auth_windows: + dependency: transitive + description: + name: local_auth_windows + sha256: "505ba3367ca781efb1c50d3132e44a2446bccc4163427bc203b9b4d8994d97ea" + url: "https://pub.dev" + source: hosted + version: "1.0.10" + location: + dependency: "direct main" + description: + name: location + sha256: "37ffdadcd4b1498b769824f45ebb4de8ed46663a4a67ac27b33a590ee486579f" + url: "https://pub.dev" + source: hosted + version: "6.0.2" + location_platform_interface: + dependency: transitive + description: + name: location_platform_interface + sha256: "2ecde6bb0f88032b0bbbde37e18975b4468711dd92619c2235cc0c0ee93b4b8e" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + location_web: + dependency: transitive + description: + name: location_web + sha256: "15ad7b4c8a9f55abee513373755e093a40c04d7e24fc1b4f89676fe99523d034" + url: "https://pub.dev" + source: hosted + version: "5.0.1" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" + source: hosted + version: "0.12.16+1" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + meta: + dependency: transitive + description: + name: meta + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + url: "https://pub.dev" + source: hosted + version: "1.11.0" + mime: + dependency: transitive + description: + name: mime + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" + url: "https://pub.dev" + source: hosted + version: "1.0.5" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + path: + dependency: "direct main" + description: + name: path + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" + source: hosted + version: "1.9.0" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161 + url: "https://pub.dev" + source: hosted + version: "2.1.3" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d + url: "https://pub.dev" + source: hosted + version: "2.2.4" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16 + url: "https://pub.dev" + source: hosted + version: "2.4.0" + 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: "8bc9f22eee8690981c22aa7fc602f5c85b497a6fb2ceb35ee5a5e5ed85ad8170" + url: "https://pub.dev" + source: hosted + version: "2.2.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: c15605cd28af66339f8eb6fbe0e541bfe2d1b72d5825efc6598f3e0a31b9ad27 + url: "https://pub.dev" + source: hosted + version: "6.0.2" + platform: + dependency: transitive + description: + name: platform + sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + url: "https://pub.dev" + source: hosted + version: "3.1.5" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c799b721d79eb6ee6fa56f00c04b472dcd44a30d258fac2174a6ec57302678f8 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + recase: + dependency: transitive + description: + name: recase + sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 + url: "https://pub.dev" + source: hosted + version: "4.1.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" + source: hosted + version: "1.10.0" + sqflite: + dependency: "direct main" + description: + name: sqflite + sha256: a43e5a27235518c03ca238e7b4732cf35eabe863a369ceba6cbefa537a66f16d + url: "https://pub.dev" + source: hosted + version: "2.3.3+1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "3da423ce7baf868be70e2c0976c28a1bb2f73644268b7ffa7d2e08eab71f16a4" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" + source: hosted + version: "1.11.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" + source: hosted + version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" + source: hosted + version: "1.2.0" + synchronized: + dependency: transitive + description: + name: synchronized + sha256: "539ef412b170d65ecdafd780f924e5be3f60032a1128df156adad6c5b373d558" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" + source: hosted + version: "1.2.1" + test_api: + dependency: transitive + description: + name: test_api + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c + url: "https://pub.dev" + source: hosted + version: "1.3.2" + url_launcher: + dependency: "direct main" + description: + name: url_launcher + sha256: "21b704ce5fa560ea9f3b525b43601c678728ba46725bab9b01187b4831377ed3" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + url_launcher_android: + dependency: transitive + description: + name: url_launcher_android + sha256: "17cd5e205ea615e2c6ea7a77323a11712dffa0720a8a90540db57a01347f9ad9" + url: "https://pub.dev" + source: hosted + version: "6.3.2" + url_launcher_ios: + dependency: transitive + description: + name: url_launcher_ios + sha256: "7068716403343f6ba4969b4173cbf3b84fc768042124bc2c011e5d782b24fe89" + url: "https://pub.dev" + source: hosted + version: "6.3.0" + url_launcher_linux: + dependency: transitive + description: + name: url_launcher_linux + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 + url: "https://pub.dev" + source: hosted + version: "3.1.1" + url_launcher_macos: + dependency: transitive + description: + name: url_launcher_macos + sha256: "9a1a42d5d2d95400c795b2914c36fdcb525870c752569438e4ebb09a2b5d90de" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + url_launcher_platform_interface: + dependency: transitive + description: + name: url_launcher_platform_interface + sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + url_launcher_web: + dependency: transitive + description: + name: url_launcher_web + sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" + url: "https://pub.dev" + source: hosted + version: "2.3.1" + url_launcher_windows: + dependency: transitive + description: + name: url_launcher_windows + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 + url: "https://pub.dev" + source: hosted + version: "3.1.1" + 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: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" + source: hosted + version: "13.0.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: "58c6666b342a38816b2e7e50ed0f1e261959630becd4c879c4f26bfa14aa5a42" + url: "https://pub.dev" + source: hosted + version: "2.4.5" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + sha256: "6869c8786d179f929144b4a1f86e09ac0eddfe475984951ea6c634774c16b522" + url: "https://pub.dev" + source: hosted + version: "4.8.0" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "0d21cfc3bfdd2e30ab2ebeced66512b91134b39e72e97b43db2d47dda1c4e53a" + url: "https://pub.dev" + source: hosted + version: "3.16.3" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d + url: "https://pub.dev" + source: hosted + version: "2.10.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: "7affdf9d680c015b11587181171d3cad8093e449db1f7d9f0f08f4f33d24f9a0" + url: "https://pub.dev" + source: hosted + version: "3.13.1" + win32: + dependency: transitive + description: + name: win32 + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + url: "https://pub.dev" + source: hosted + version: "5.5.0" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d + url: "https://pub.dev" + source: hosted + version: "1.0.4" + 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: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5" + url: "https://pub.dev" + source: hosted + version: "3.1.2" +sdks: + dart: ">=3.3.2 <4.0.0" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..2c95c4a --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,91 @@ +name: sefer_admin1 +description: "A new Flutter project." +# 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+1 + +environment: + sdk: ">=3.3.2 <4.0.0" + +# 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: + # agora_rtc_engine: ^6.3.0 + # device_info_plus: ^10.1.0 + dio: ^5.4.3+1 + envied: ^0.5.4+1 + firebase_core: ^2.30.1 + firebase_messaging: ^14.9.1 + fl_chart: ^0.67.0 + flutter: + sdk: flutter + flutter_launcher_icons: ^0.13.1 + # flutter_local_notifications: ^17.1.1 + flutter_paypal: ^0.2.0 + flutter_secure_storage: ^9.0.0 +# flutter_stripe: ^10.1.1 + get: ^4.6.6 + get_storage: ^2.1.1 + google_fonts: ^4.0.4 + # google_maps_flutter: ^2.6.1 + google_sign_in: ^6.2.1 + http: ^0.13.6 + # image: ^4.1.7 + # image_cropper: ^4.0.1 + # image_picker: ^1.1.1 + intl: ^0.19.0 + local_auth: ^2.2.0 + location: ^6.0.1 + path: ^1.9.0 + sqflite: ^2.3.3+1 + url_launcher: ^6.2.6 + webview_flutter: ^4.7.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^ 3.0.1 + envied_generator: ^0.5.2 + build_runner: ^2.4.6 + +flutter_launcher_icons: + android: "launcher_icon" + ios: true + image_path: "assets/images/logo.png" + min_sdk_android: 21 + web: + generate: true + image_path: "assets/images/logo.png" + background_color: "#hexcode" + theme_color: "#hexcode" + windows: + generate: true + image_path: "assets/images/logo.png" + icon_size: 48 + macos: + generate: true + image_path: "assets/images/logo.png" + +flutter: + uses-material-design: true + assets: + - assets/ + - assets/images/ diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..37961b4 --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,30 @@ +// This is a basic Flutter widget test. +// +// To perform an interaction with a widget in your test, use the WidgetTester +// utility in the flutter_test package. For example, you can send tap and scroll +// gestures. You can also use WidgetTester to find child widgets in the widget +// tree, read text, and verify that the values of widget properties are correct. + +import 'package:flutter/material.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'package:sefer_admin1/main.dart'; + +void main() { + testWidgets('Counter increments smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(MainApp()); + + // Verify that our counter starts at 0. + expect(find.text('0'), findsOneWidget); + expect(find.text('1'), findsNothing); + + // Tap the '+' icon and trigger a frame. + await tester.tap(find.byIcon(Icons.add)); + await tester.pump(); + + // Verify that our counter has incremented. + expect(find.text('0'), findsNothing); + expect(find.text('1'), findsOneWidget); + }); +} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..9b142b5 --- /dev/null +++ b/web/index.html @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + sefer_admin1 + + + + + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..363aad1 --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "sefer_admin1", + "short_name": "sefer_admin1", + "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" + } + ] +} 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..e7a47b5 --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(sefer_admin1 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 "sefer_admin1") + +# 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..028ccd2 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,23 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + +#include +#include +#include +#include + +void RegisterPlugins(flutter::PluginRegistry* registry) { + FirebaseCorePluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FirebaseCorePluginCApi")); + FlutterSecureStorageWindowsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + LocalAuthPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("LocalAuthPlugin")); + UrlLauncherWindowsRegisterWithRegistrar( + registry->GetRegistrarForPlugin("UrlLauncherWindows")); +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..5df1253 --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,27 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST + firebase_core + flutter_secure_storage_windows + local_auth_windows + url_launcher_windows +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..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..e1fa16d --- /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", "sefer_admin1" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "sefer_admin1" "\0" + VALUE "LegalCopyright", "Copyright (C) 2024 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "sefer_admin1.exe" "\0" + VALUE "ProductName", "sefer_admin1" "\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..ee789a8 --- /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"sefer_admin1", 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 0000000..c04e20c Binary files /dev/null and b/windows/runner/resources/app_icon.ico differ diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..a42ea76 --- /dev/null +++ b/windows/runner/runner.exe.manifest @@ -0,0 +1,20 @@ + + + + + PerMonitorV2 + + + + + + + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000..b2b0873 --- /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(); + } + 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_