UAE pass
This commit is contained in:
parent
001334819e
commit
933b154961
25
.metadata
25
.metadata
@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled and should not be manually edited.
|
# This file should be version controlled and should not be manually edited.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: "a14f74ff3a1cbd521163c5f03d68113d50af93d3"
|
revision: "adc901062556672b4138e18a4dc62a4be8f4b3c2"
|
||||||
channel: "stable"
|
channel: "stable"
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
@ -13,11 +13,26 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
|
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
|
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
- platform: android
|
- platform: android
|
||||||
create_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
|
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
base_revision: a14f74ff3a1cbd521163c5f03d68113d50af93d3
|
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
- platform: ios
|
||||||
|
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
- platform: linux
|
||||||
|
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
- platform: macos
|
||||||
|
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
- platform: web
|
||||||
|
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
- platform: windows
|
||||||
|
create_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
base_revision: adc901062556672b4138e18a4dc62a4be8f4b3c2
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|||||||
@ -20,12 +20,12 @@ if (project.hasProperty('google-services.json')) {
|
|||||||
|
|
||||||
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
||||||
if (flutterVersionCode == null) {
|
if (flutterVersionCode == null) {
|
||||||
flutterVersionCode = "7"
|
flutterVersionCode = "14"
|
||||||
}
|
}
|
||||||
|
|
||||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||||
if (flutterVersionName == null) {
|
if (flutterVersionName == null) {
|
||||||
flutterVersionName = "1.1.0"
|
flutterVersionName = "1.2.6"
|
||||||
}
|
}
|
||||||
|
|
||||||
def keystorePropertiesFile = rootProject.file("key.properties")
|
def keystorePropertiesFile = rootProject.file("key.properties")
|
||||||
@ -35,15 +35,15 @@ keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
|||||||
android {
|
android {
|
||||||
namespace = "ae.gov.fcsc.stats"
|
namespace = "ae.gov.fcsc.stats"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
// ndkVersion = flutter.ndkVersion
|
ndkVersion = flutter.ndkVersion
|
||||||
ndkVersion = "25.1.8937393"
|
// ndkVersion = "25.1.8937393"
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_21
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_21
|
||||||
}
|
}
|
||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = "17"
|
jvmTarget = "21"
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
|
|||||||
44
android/app/build.gradle.kts
Normal file
44
android/app/build.gradle.kts
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
plugins {
|
||||||
|
id("com.android.application")
|
||||||
|
id("kotlin-android")
|
||||||
|
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||||
|
id("dev.flutter.flutter-gradle-plugin")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "ae.gov.fcsc.uae_stat"
|
||||||
|
compileSdk = flutter.compileSdkVersion
|
||||||
|
ndkVersion = flutter.ndkVersion
|
||||||
|
|
||||||
|
compileOptions {
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
|
}
|
||||||
|
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
|
||||||
|
applicationId = "ae.gov.fcsc.uae_stat"
|
||||||
|
// You can update the following values to match your application needs.
|
||||||
|
// For more information, see: https://flutter.dev/to/review-gradle-config.
|
||||||
|
minSdk = flutter.minSdkVersion
|
||||||
|
targetSdk = flutter.targetSdkVersion
|
||||||
|
versionCode = flutter.versionCode
|
||||||
|
versionName = flutter.versionName
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
// TODO: Add your own signing config for the release build.
|
||||||
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
|
signingConfig = signingConfigs.getByName("debug")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
flutter {
|
||||||
|
source = "../.."
|
||||||
|
}
|
||||||
@ -33,17 +33,22 @@
|
|||||||
android:value="true"/>
|
android:value="true"/>
|
||||||
<meta-data android:name="com.appsflyer.sdk.ONE_LINK_ID"
|
<meta-data android:name="com.appsflyer.sdk.ONE_LINK_ID"
|
||||||
android:value="LI5k"/>
|
android:value="LI5k"/>
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<!-- UAE PASS custom URI scheme -->
|
||||||
|
<data
|
||||||
|
android:scheme="fcscUaeStats"
|
||||||
|
android:host="callback" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<!-- Keep your OneLink integration separate -->
|
||||||
<intent-filter android:autoVerify="true">
|
<intent-filter android:autoVerify="true">
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<!-- <data android:scheme="https" android:host="fcscstats.onelink.me" />-->
|
<data android:scheme="https" android:host="https://fcscstats.onelink.me/V6mR/t40b32al" />,
|
||||||
<data android:scheme="https" android:host="fcscstats.onelink.me" android:pathPrefix="/V6mR/t40b32al"/>
|
|
||||||
<!-- 👇 Fallback custom scheme -->
|
|
||||||
<data
|
|
||||||
android:scheme="fcscstats"
|
|
||||||
android:host="authorization"
|
|
||||||
android:path="/return" />
|
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
<!-- <intent-filter>-->
|
<!-- <intent-filter>-->
|
||||||
<!-- <action android:name="android.intent.action.VIEW" />-->
|
<!-- <action android:name="android.intent.action.VIEW" />-->
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
package ae.gov.fcsc.uae_stat
|
||||||
|
|
||||||
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
|
||||||
|
class MainActivity : FlutterActivity()
|
||||||
12
android/app/src/main/res/drawable-v21/launch_background.xml
Normal file
12
android/app/src/main/res/drawable-v21/launch_background.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="?android:colorBackground" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
||||||
12
android/app/src/main/res/drawable/launch_background.xml
Normal file
12
android/app/src/main/res/drawable/launch_background.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Modify this file to customize your launch splash screen -->
|
||||||
|
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:drawable="@android:color/white" />
|
||||||
|
|
||||||
|
<!-- You can insert your own image assets here -->
|
||||||
|
<!-- <item>
|
||||||
|
<bitmap
|
||||||
|
android:gravity="center"
|
||||||
|
android:src="@mipmap/launch_image" />
|
||||||
|
</item> -->
|
||||||
|
</layer-list>
|
||||||
@ -4,7 +4,7 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:8.6.0' // Update this if needed
|
classpath 'com.android.tools.build:gradle:8.7.1' // Update this if needed
|
||||||
classpath 'com.google.gms:google-services:4.3.10' // ✅ Required for Firebase
|
classpath 'com.google.gms:google-services:4.3.10' // ✅ Required for Firebase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
android/build.gradle.kts
Normal file
24
android/build.gradle.kts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val newBuildDir: Directory =
|
||||||
|
rootProject.layout.buildDirectory
|
||||||
|
.dir("../../build")
|
||||||
|
.get()
|
||||||
|
rootProject.layout.buildDirectory.value(newBuildDir)
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name)
|
||||||
|
project.layout.buildDirectory.value(newSubprojectBuildDir)
|
||||||
|
}
|
||||||
|
subprojects {
|
||||||
|
project.evaluationDependsOn(":app")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register<Delete>("clean") {
|
||||||
|
delete(rootProject.layout.buildDirectory)
|
||||||
|
}
|
||||||
@ -1,4 +1,13 @@
|
|||||||
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
|
# Enable 16KB memory page support
|
||||||
android.useAndroidX=true
|
android.bundle.enableNativeCodeCompression=false
|
||||||
android.enableJetifier=true
|
android.experimental.enable16kPages=true
|
||||||
org.gradleorg.gradle.java.home=/usr/lib/jvm/openlogic-openjdk-17.0.13+11-linux-x64
|
org.gradleorg.gradle.java.home=/usr/lib/jvm/openlogic-openjdk-17.0.13+11-linux-x64
|
||||||
|
# Ensure compatibility
|
||||||
|
org.gradle.jvmargs=-Xmx4G -XX:+UseParallelGC -XX:MaxMetaspaceSize=1G
|
||||||
|
org.gradle.caching=true
|
||||||
|
org.gradle.daemon=true
|
||||||
|
org.gradle.parallel=true
|
||||||
|
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=false
|
||||||
|
kotlin.code.style=official
|
||||||
@ -2,4 +2,5 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
|
||||||
|
|
||||||
|
|||||||
@ -18,8 +18,8 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
id "com.android.application" version "8.2.1" apply false
|
id "com.android.application" version "8.6.0" apply false
|
||||||
id "org.jetbrains.kotlin.android" version "1.9.24" apply false
|
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
|
||||||
id("com.google.gms.google-services") version "4.4.2" apply false
|
id("com.google.gms.google-services") version "4.4.2" apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
android/settings.gradle.kts
Normal file
26
android/settings.gradle.kts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
pluginManagement {
|
||||||
|
val flutterSdkPath =
|
||||||
|
run {
|
||||||
|
val properties = java.util.Properties()
|
||||||
|
file("local.properties").inputStream().use { properties.load(it) }
|
||||||
|
val flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
|
require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" }
|
||||||
|
flutterSdkPath
|
||||||
|
}
|
||||||
|
|
||||||
|
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||||
|
id("com.android.application") version "8.9.1" apply false
|
||||||
|
id("org.jetbrains.kotlin.android") version "2.1.0" apply false
|
||||||
|
}
|
||||||
|
|
||||||
|
include(":app")
|
||||||
109
ios/Podfile.lock
109
ios/Podfile.lock
@ -1,5 +1,5 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- app_links (0.0.2):
|
- app_links (6.4.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- app_settings (5.1.1):
|
- app_settings (5.1.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
@ -13,47 +13,49 @@ PODS:
|
|||||||
- GoogleUtilities/Environment (~> 8.0)
|
- GoogleUtilities/Environment (~> 8.0)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
- GoogleUtilities/UserDefaults (~> 8.0)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- appsflyer_sdk (6.16.2):
|
- appsflyer_sdk (6.17.7):
|
||||||
- AppsFlyerFramework (= 6.16.2)
|
- appsflyer_sdk/Core (= 6.17.7)
|
||||||
|
- appsflyer_sdk/Core (6.17.7):
|
||||||
|
- AppsFlyerFramework (= 6.17.7)
|
||||||
- Flutter
|
- Flutter
|
||||||
- AppsFlyerFramework (6.16.2):
|
- AppsFlyerFramework (6.17.7):
|
||||||
- AppsFlyerFramework/Main (= 6.16.2)
|
- AppsFlyerFramework/Main (= 6.17.7)
|
||||||
- AppsFlyerFramework/Main (6.16.2)
|
- AppsFlyerFramework/Main (6.17.7)
|
||||||
- connectivity_plus (0.0.1):
|
- connectivity_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Firebase/CoreOnly (11.10.0):
|
- Firebase/CoreOnly (11.15.0):
|
||||||
- FirebaseCore (~> 11.10.0)
|
- FirebaseCore (~> 11.15.0)
|
||||||
- Firebase/Messaging (11.10.0):
|
- Firebase/Messaging (11.15.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 11.10.0)
|
- FirebaseMessaging (~> 11.15.0)
|
||||||
- firebase_core (3.13.0):
|
- firebase_core (3.15.2):
|
||||||
- Firebase/CoreOnly (= 11.10.0)
|
- Firebase/CoreOnly (= 11.15.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_messaging (15.2.5):
|
- firebase_messaging (15.2.10):
|
||||||
- Firebase/Messaging (= 11.10.0)
|
- Firebase/Messaging (= 11.15.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- FirebaseCore (11.10.0):
|
- FirebaseCore (11.15.0):
|
||||||
- FirebaseCoreInternal (~> 11.10.0)
|
- FirebaseCoreInternal (~> 11.15.0)
|
||||||
- GoogleUtilities/Environment (~> 8.0)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Logger (~> 8.0)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- FirebaseCoreInternal (11.10.0):
|
- FirebaseCoreInternal (11.15.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.0)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- FirebaseInstallations (11.10.0):
|
- FirebaseInstallations (11.15.0):
|
||||||
- FirebaseCore (~> 11.10.0)
|
- FirebaseCore (~> 11.15.0)
|
||||||
- GoogleUtilities/Environment (~> 8.0)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseMessaging (11.10.0):
|
- FirebaseMessaging (11.15.0):
|
||||||
- FirebaseCore (~> 11.10.0)
|
- FirebaseCore (~> 11.15.0)
|
||||||
- FirebaseInstallations (~> 11.0)
|
- FirebaseInstallations (~> 11.0)
|
||||||
- GoogleDataTransport (~> 10.0)
|
- GoogleDataTransport (~> 10.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.0)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Environment (~> 8.0)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Reachability (~> 8.0)
|
- GoogleUtilities/Reachability (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.0)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
- flutter_native_splash (2.4.3):
|
- flutter_native_splash (2.4.3):
|
||||||
@ -63,8 +65,6 @@ PODS:
|
|||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- flutter_uae_pass (0.0.1):
|
- flutter_uae_pass (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_web_auth_2 (3.0.0):
|
|
||||||
- Flutter
|
|
||||||
- fluttertoast (0.0.2):
|
- fluttertoast (0.0.2):
|
||||||
- Flutter
|
- Flutter
|
||||||
- google_sign_in_ios (0.0.1):
|
- google_sign_in_ios (0.0.1):
|
||||||
@ -135,9 +135,6 @@ PODS:
|
|||||||
- video_player_avfoundation (0.0.1):
|
- video_player_avfoundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- webview_flutter_wkwebview (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- FlutterMacOS
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- app_links (from `.symlinks/plugins/app_links/ios`)
|
- app_links (from `.symlinks/plugins/app_links/ios`)
|
||||||
@ -151,7 +148,6 @@ DEPENDENCIES:
|
|||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
- flutter_secure_storage_darwin (from `.symlinks/plugins/flutter_secure_storage_darwin/darwin`)
|
||||||
- flutter_uae_pass (from `.symlinks/plugins/flutter_uae_pass/ios`)
|
- flutter_uae_pass (from `.symlinks/plugins/flutter_uae_pass/ios`)
|
||||||
- flutter_web_auth_2 (from `.symlinks/plugins/flutter_web_auth_2/ios`)
|
|
||||||
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
- fluttertoast (from `.symlinks/plugins/fluttertoast/ios`)
|
||||||
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`)
|
- google_sign_in_ios (from `.symlinks/plugins/google_sign_in_ios/darwin`)
|
||||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||||
@ -161,7 +157,6 @@ DEPENDENCIES:
|
|||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
|
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
|
||||||
- webview_flutter_wkwebview (from `.symlinks/plugins/webview_flutter_wkwebview/darwin`)
|
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
@ -204,8 +199,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
|
:path: ".symlinks/plugins/flutter_secure_storage_darwin/darwin"
|
||||||
flutter_uae_pass:
|
flutter_uae_pass:
|
||||||
:path: ".symlinks/plugins/flutter_uae_pass/ios"
|
:path: ".symlinks/plugins/flutter_uae_pass/ios"
|
||||||
flutter_web_auth_2:
|
|
||||||
:path: ".symlinks/plugins/flutter_web_auth_2/ios"
|
|
||||||
fluttertoast:
|
fluttertoast:
|
||||||
:path: ".symlinks/plugins/fluttertoast/ios"
|
:path: ".symlinks/plugins/fluttertoast/ios"
|
||||||
google_sign_in_ios:
|
google_sign_in_ios:
|
||||||
@ -224,47 +217,43 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
video_player_avfoundation:
|
video_player_avfoundation:
|
||||||
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
|
:path: ".symlinks/plugins/video_player_avfoundation/darwin"
|
||||||
webview_flutter_wkwebview:
|
|
||||||
:path: ".symlinks/plugins/webview_flutter_wkwebview/darwin"
|
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
app_links: 76b66b60cc809390ca1ad69bfd66b998d2387ac7
|
app_links: 3dbc685f76b1693c66a6d9dd1e9ab6f73d97dc0a
|
||||||
app_settings: 5127ae0678de1dcc19f2293271c51d37c89428b2
|
app_settings: 5127ae0678de1dcc19f2293271c51d37c89428b2
|
||||||
AppAuth: 1c1a8afa7e12f2ec3a294d9882dfa5ab7d3cb063
|
AppAuth: 1c1a8afa7e12f2ec3a294d9882dfa5ab7d3cb063
|
||||||
AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f
|
AppCheckCore: cc8fd0a3a230ddd401f326489c99990b013f0c4f
|
||||||
appsflyer_sdk: ebe94dc3f00b07bdd001251dbc87879bda3c494a
|
appsflyer_sdk: 01d0cd834fe2fffd7f2372ab38690f7483587720
|
||||||
AppsFlyerFramework: fe5303bffcdfd941d5f570c2d21eaaea982e7bdc
|
AppsFlyerFramework: ae7caf1688348f2d7a742037bd4fc6966d39d362
|
||||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||||
Firebase: 1fe1c0a7d9aaea32efe01fbea5f0ebd8d70e53a2
|
Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e
|
||||||
firebase_core: 2d4534e7b489907dcede540c835b48981d890943
|
firebase_core: 995454a784ff288be5689b796deb9e9fa3601818
|
||||||
firebase_messaging: 75bc93a4df25faccad67f6662ae872ac9ae69b64
|
firebase_messaging: f4a41dd102ac18b840eba3f39d67e77922d3f707
|
||||||
FirebaseCore: 8344daef5e2661eb004b177488d6f9f0f24251b7
|
FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e
|
||||||
FirebaseCoreInternal: ef4505d2afb1d0ebbc33162cb3795382904b5679
|
FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4
|
||||||
FirebaseInstallations: 9980995bdd06ec8081dfb6ab364162bdd64245c3
|
FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843
|
||||||
FirebaseMessaging: 2b9f56aa4ed286e1f0ce2ee1d413aabb8f9f5cb9
|
FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09
|
||||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_native_splash: 6cad9122ea0fad137d23137dd14b937f3e90b145
|
flutter_native_splash: 6cad9122ea0fad137d23137dd14b937f3e90b145
|
||||||
flutter_secure_storage_darwin: ce237a8775b39723566dc72571190a3769d70468
|
flutter_secure_storage_darwin: ce237a8775b39723566dc72571190a3769d70468
|
||||||
flutter_uae_pass: 49160e01023a9815164b94a07b6f6ce3c79b1e56
|
flutter_uae_pass: b643f2272a11abd3d1167f1760ad0adf35b31979
|
||||||
flutter_web_auth_2: 5c8d9dcd7848b5a9efb086d24e7a9adcae979c80
|
|
||||||
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
fluttertoast: 2c67e14dce98bbdb200df9e1acf610d7a6264ea1
|
||||||
google_sign_in_ios: 205742c688aea0e64db9da03c33121694a365109
|
google_sign_in_ios: 00dfa94252eb10278b64828c81bcb7158a81a53a
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleSignIn: c7f09cfbc85a1abf69187be091997c317cc33b77
|
GoogleSignIn: c7f09cfbc85a1abf69187be091997c317cc33b77
|
||||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
GTMAppAuth: 217a876b249c3c585a54fd6f73e6b58c4f5c4238
|
GTMAppAuth: 217a876b249c3c585a54fd6f73e6b58c4f5c4238
|
||||||
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
|
GTMSessionFetcher: 5aea5ba6bd522a239e236100971f10cb71b96ab6
|
||||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
video_player_avfoundation: 2cef49524dd1f16c5300b9cd6efd9611ce03639b
|
video_player_avfoundation: dd410b52df6d2466a42d28550e33e4146928280a
|
||||||
webview_flutter_wkwebview: 8ebf4fded22593026f7dbff1fbff31ea98573c8d
|
|
||||||
|
|
||||||
PODFILE CHECKSUM: 1959d098c91d8a792531a723c4a9d7e9f6a01e38
|
PODFILE CHECKSUM: 1959d098c91d8a792531a723c4a9d7e9f6a01e38
|
||||||
|
|
||||||
|
|||||||
774
ios/Runner.xcodeproj/project.pbxproj
Normal file
774
ios/Runner.xcodeproj/project.pbxproj
Normal file
@ -0,0 +1,774 @@
|
|||||||
|
// !$*UTF8*$!
|
||||||
|
{
|
||||||
|
archiveVersion = 1;
|
||||||
|
classes = {
|
||||||
|
};
|
||||||
|
objectVersion = 54;
|
||||||
|
objects = {
|
||||||
|
|
||||||
|
/* Begin PBXBuildFile section */
|
||||||
|
0158C53D8729FF3CAEDD63E1 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D8321227CAF760684DE6073D /* Pods_RunnerTests.framework */; };
|
||||||
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
|
A77EABEF04180C888228A6B6 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8FCB8E98366ECE496F9C6593 /* 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 = "<group>"; };
|
||||||
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
|
190F5FA1FAFE050ABAB22E9B /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
36245650E9027DB0317FE314 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
7692EB83BCA20EB7DB6148D9 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
78330B354D57D0C89C5DB6C4 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
8FCB8E98366ECE496F9C6593 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
938AA2808E77FAEF6A979134 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
|
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
CC3BC78662DC6B354B36AB2C /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
D8321227CAF760684DE6073D /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
A77EABEF04180C888228A6B6 /* Pods_Runner.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
B24AA7490A694194BE125B19 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
0158C53D8729FF3CAEDD63E1 /* Pods_RunnerTests.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXGroup section */
|
||||||
|
128B0E4DC68FEAA53D10ACCE /* Pods */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
36245650E9027DB0317FE314 /* Pods-Runner.debug.xcconfig */,
|
||||||
|
78330B354D57D0C89C5DB6C4 /* Pods-Runner.release.xcconfig */,
|
||||||
|
7692EB83BCA20EB7DB6148D9 /* Pods-Runner.profile.xcconfig */,
|
||||||
|
938AA2808E77FAEF6A979134 /* Pods-RunnerTests.debug.xcconfig */,
|
||||||
|
190F5FA1FAFE050ABAB22E9B /* Pods-RunnerTests.release.xcconfig */,
|
||||||
|
CC3BC78662DC6B354B36AB2C /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
|
);
|
||||||
|
path = Pods;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||||
|
);
|
||||||
|
path = RunnerTests;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||||
|
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||||
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||||
|
9740EEB31CF90195004384FC /* Generated.xcconfig */,
|
||||||
|
);
|
||||||
|
name = Flutter;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146E51CF9000F007C117D = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
|
128B0E4DC68FEAA53D10ACCE /* Pods */,
|
||||||
|
C2DC67BE57D93B775E1BD572 /* Frameworks */,
|
||||||
|
);
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146EF1CF9000F007C117D /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
|
||||||
|
97C147021CF9000F007C117D /* Info.plist */,
|
||||||
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||||
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||||
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||||
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||||
|
);
|
||||||
|
path = Runner;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
C2DC67BE57D93B775E1BD572 /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
8FCB8E98366ECE496F9C6593 /* Pods_Runner.framework */,
|
||||||
|
D8321227CAF760684DE6073D /* Pods_RunnerTests.framework */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXGroup section */
|
||||||
|
|
||||||
|
/* Begin PBXNativeTarget section */
|
||||||
|
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||||
|
buildPhases = (
|
||||||
|
73A2074E472182151AB9ED7A /* [CP] Check Pods Manifest.lock */,
|
||||||
|
331C807D294A63A400263BE5 /* Sources */,
|
||||||
|
331C807F294A63A400263BE5 /* Resources */,
|
||||||
|
B24AA7490A694194BE125B19 /* 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 = (
|
||||||
|
93BC14D0999CE33FAEA7EEE6 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
|
544AE9F477D1ED5A9363807B /* [CP] Embed Pods Frameworks */,
|
||||||
|
4FA0629056C68E3C8427B28F /* [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 */,
|
||||||
|
);
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
4FA0629056C68E3C8427B28F /* [CP] Copy Pods Resources */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Copy Pods Resources";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
544AE9F477D1ED5A9363807B /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
73A2074E472182151AB9ED7A /* [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;
|
||||||
|
};
|
||||||
|
93BC14D0999CE33FAEA7EEE6 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "Run Script";
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
|
};
|
||||||
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
331C807D294A63A400263BE5 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||||
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
|
/* Begin PBXTargetDependency section */
|
||||||
|
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||||
|
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
|
/* Begin PBXVariantGroup section */
|
||||||
|
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
97C146FB1CF9000F007C117D /* Base */,
|
||||||
|
);
|
||||||
|
name = Main.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
97C147001CF9000F007C117D /* Base */,
|
||||||
|
);
|
||||||
|
name = LaunchScreen.storyboard;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* 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 = 13.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
249021D4217E4FDB00AE95B9 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 9N5SRFUGK2;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = FCSC;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.2.5;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
SUPPORTS_MACCATALYST = NO;
|
||||||
|
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
|
331C8088294A63A400263BE5 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 938AA2808E77FAEF6A979134 /* 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 = ae.gov.fcsc.uaeStat.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 = 190F5FA1FAFE050ABAB22E9B /* 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 = ae.gov.fcsc.uaeStat.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 = CC3BC78662DC6B354B36AB2C /* 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 = ae.gov.fcsc.uaeStat.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 = 13.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 = 13.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
|
SDKROOT = iphoneos;
|
||||||
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VALIDATE_PRODUCT = YES;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
97C147061CF9000F007C117D /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 9N5SRFUGK2;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = FCSC;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.2.5;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
SUPPORTS_MACCATALYST = NO;
|
||||||
|
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
97C147071CF9000F007C117D /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
|
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||||
|
DEVELOPMENT_TEAM = 9N5SRFUGK2;
|
||||||
|
ENABLE_BITCODE = NO;
|
||||||
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = FCSC;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
MARKETING_VERSION = 1.2.5;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = ae.gov.fcsc.frontend.ios;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
|
SUPPORTS_MACCATALYST = NO;
|
||||||
|
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
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 */;
|
||||||
|
}
|
||||||
7
ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "self:">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
101
ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
Normal file
101
ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1510"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO"
|
||||||
|
parallelizable = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "331C8080294A63A400263BE5"
|
||||||
|
BuildableName = "RunnerTests.xctest"
|
||||||
|
BlueprintName = "RunnerTests"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
enableGPUValidationMode = "1"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Profile"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||||
|
BuildableName = "Runner.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
10
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
10
ios/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:Runner.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
<FileRef
|
||||||
|
location = "group:Pods/Pods.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>IDEDidComputeMac32BitWarning</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>PreviewsEnabled</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
13
ios/Runner/AppDelegate.swift
Normal file
13
ios/Runner/AppDelegate.swift
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import Flutter
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
@main
|
||||||
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
|
override func application(
|
||||||
|
_ application: UIApplication,
|
||||||
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
|
) -> Bool {
|
||||||
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
|
}
|
||||||
|
}
|
||||||
37
ios/Runner/Base.lproj/LaunchScreen.storyboard
Normal file
37
ios/Runner/Base.lproj/LaunchScreen.storyboard
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--View Controller-->
|
||||||
|
<scene sceneID="EHf-IW-A2E">
|
||||||
|
<objects>
|
||||||
|
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
|
||||||
|
</imageView>
|
||||||
|
</subviews>
|
||||||
|
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
|
||||||
|
<constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
|
||||||
|
</constraints>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="53" y="375"/>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
<resources>
|
||||||
|
<image name="LaunchImage" width="168" height="185"/>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
26
ios/Runner/Base.lproj/Main.storyboard
Normal file
26
ios/Runner/Base.lproj/Main.storyboard
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||||
|
</dependencies>
|
||||||
|
<scenes>
|
||||||
|
<!--Flutter View Controller-->
|
||||||
|
<scene sceneID="tne-QT-ifu">
|
||||||
|
<objects>
|
||||||
|
<viewController id="BYZ-38-t0r" customClass="FlutterViewController" sceneMemberID="viewController">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
|
</viewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
</scene>
|
||||||
|
</scenes>
|
||||||
|
</document>
|
||||||
@ -22,13 +22,6 @@
|
|||||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>LSApplicationQueriesSchemes</key>
|
|
||||||
<array>
|
|
||||||
<string>uaepass</string>
|
|
||||||
<string>uaepassqa</string>
|
|
||||||
<string>uaepassdev</string>
|
|
||||||
<string>uaepassstg</string>
|
|
||||||
</array>
|
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
@ -56,6 +49,13 @@
|
|||||||
</array>
|
</array>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>LSApplicationQueriesSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>uaepass</string>
|
||||||
|
<string>uaepassqa</string>
|
||||||
|
<string>uaepassdev</string>
|
||||||
|
<string>uaepassstg</string>
|
||||||
|
</array>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSAppTransportSecurity</key>
|
<key>NSAppTransportSecurity</key>
|
||||||
@ -84,6 +84,8 @@
|
|||||||
<string>Main</string>
|
<string>Main</string>
|
||||||
<key>UIStatusBarHidden</key>
|
<key>UIStatusBarHidden</key>
|
||||||
<false/>
|
<false/>
|
||||||
|
<key>UIStatusBarStyle</key>
|
||||||
|
<string></string>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
|
|||||||
1
ios/Runner/Runner-Bridging-Header.h
Normal file
1
ios/Runner/Runner-Bridging-Header.h
Normal file
@ -0,0 +1 @@
|
|||||||
|
#import "GeneratedPluginRegistrant.h"
|
||||||
@ -13,6 +13,7 @@ import 'package:uae_stat/presentation/Screens/auth_verification/registration.dar
|
|||||||
import 'package:uae_stat/presentation/Screens/auth_verification/terms&conditions.dart';
|
import 'package:uae_stat/presentation/Screens/auth_verification/terms&conditions.dart';
|
||||||
import 'package:uae_stat/presentation/Screens/charts/screens/chart_screen.dart';
|
import 'package:uae_stat/presentation/Screens/charts/screens/chart_screen.dart';
|
||||||
import 'package:uae_stat/presentation/Screens/online_offline_verification/internet_check.dart';
|
import 'package:uae_stat/presentation/Screens/online_offline_verification/internet_check.dart';
|
||||||
|
import 'package:uae_stat/presentation/routes/auth_routes/checkingUAEPass.dart';
|
||||||
import 'package:uae_stat/presentation/routes/auth_routes/fcsc_profile_linking.dart';
|
import 'package:uae_stat/presentation/routes/auth_routes/fcsc_profile_linking.dart';
|
||||||
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/Competitiveness/Detailedcompetitiveness.dart';
|
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/Competitiveness/Detailedcompetitiveness.dart';
|
||||||
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/Competitiveness/competitiveness.dart';
|
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/Competitiveness/competitiveness.dart';
|
||||||
@ -132,6 +133,10 @@ final GoRouter router = GoRouter(
|
|||||||
path: '/myhomepage',
|
path: '/myhomepage',
|
||||||
builder: (context, state) => MyHomePage(),
|
builder: (context, state) => MyHomePage(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: '/checkingUAEPass',
|
||||||
|
builder: (context, state) => checkingUAEPass(),
|
||||||
|
),
|
||||||
|
|
||||||
// GoRoute(
|
// GoRoute(
|
||||||
// path: '/DemoHome/:dataSets',
|
// path: '/DemoHome/:dataSets',
|
||||||
@ -406,10 +411,24 @@ final GoRouter router = GoRouter(
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
redirect: (context, state) async {
|
redirect: (context, state) async {
|
||||||
|
// If UAE PASS redirected here with ?code=
|
||||||
|
final uri = state.uri;
|
||||||
|
|
||||||
|
// UAE PASS returned here with /login?code=xxxx
|
||||||
|
if (uri.path == '/login' && uri.queryParameters.containsKey('code')) {
|
||||||
|
final code = uri.queryParameters['code']!;
|
||||||
|
print("✨ UAE PASS Authorization Code Received: $code");
|
||||||
|
|
||||||
|
// Send user to /login with new param (so UI can read it)
|
||||||
|
return '/login?uaeCode=$code';
|
||||||
|
}
|
||||||
|
|
||||||
if (state.uri.path == '/SessionCheckScreen' ||
|
if (state.uri.path == '/SessionCheckScreen' ||
|
||||||
state.uri.path == '/login' ||
|
state.uri.path == '/login' ||
|
||||||
|
state.uri.path == '/checkingUAEPass' ||
|
||||||
state.uri.path == '/register' ||
|
state.uri.path == '/register' ||
|
||||||
state.uri.path.startsWith('/forgot-password/') ||
|
state.uri.path.startsWith('/forgot-password/') ||
|
||||||
|
state.uri.path.startsWith('/forgot-password/') ||
|
||||||
state.uri.path == '/termsandconditions' ||
|
state.uri.path == '/termsandconditions' ||
|
||||||
state.uri.path == '/privacy_policy' ||
|
state.uri.path == '/privacy_policy' ||
|
||||||
state.uri.path == '/fcscprofilelinking') {
|
state.uri.path == '/fcscprofilelinking') {
|
||||||
|
|||||||
@ -1569,19 +1569,19 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: screenwidth / 1,
|
width: screenwidth / 1,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
// onPressed: isRegistering
|
onPressed: isRegistering
|
||||||
// ? null
|
? null
|
||||||
// : _registerUser?
|
: _registerUser,
|
||||||
onPressed: () {
|
// onPressed: () {
|
||||||
if (isRegistering) {
|
// if (isRegistering) {
|
||||||
_registerUser;
|
// _registerUser;
|
||||||
} else if (cameFromLinking) {
|
// } else if (cameFromLinking) {
|
||||||
oAuthOIDCLogin(context, ref,
|
// oAuthOIDCLogin(context, ref,
|
||||||
'oidc'); //Open ID connect
|
// 'oidc'); //Open ID connect
|
||||||
} else {
|
// } else {
|
||||||
null;
|
// null;
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: Color(
|
backgroundColor: Color(
|
||||||
0xFFB68A34), // Brownish color for Register
|
0xFFB68A34), // Brownish color for Register
|
||||||
|
|||||||
133
lib/presentation/routes/auth_routes/OAthuLogin.dart
Normal file
133
lib/presentation/routes/auth_routes/OAthuLogin.dart
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:pocketbase/pocketbase.dart';
|
||||||
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
|
|
||||||
|
/// ===============================
|
||||||
|
/// CONFIG
|
||||||
|
/// ===============================
|
||||||
|
const String pocketBaseUrl = 'https://pocket.fcsc.gov.ae'; // 🔁 change if needed
|
||||||
|
|
||||||
|
/// ===============================
|
||||||
|
/// LOGIN PAGE
|
||||||
|
/// ===============================
|
||||||
|
class LoginOAuthPage extends HookConsumerWidget
|
||||||
|
with WidgetsBindingObserver {
|
||||||
|
LoginOAuthPage({super.key});
|
||||||
|
|
||||||
|
final PocketBase pb = PocketBase(pocketBaseUrl);
|
||||||
|
|
||||||
|
/// ===============================
|
||||||
|
/// OAuth Auto-Close (App Resume)
|
||||||
|
/// ===============================
|
||||||
|
void _initOAuthAutoClose(BuildContext context) {
|
||||||
|
WidgetsBinding.instance.addObserver(
|
||||||
|
_OAuthLifecycle(
|
||||||
|
pb: pb,
|
||||||
|
context: context,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
/// Init lifecycle listener once
|
||||||
|
useEffect(() {
|
||||||
|
_initOAuthAutoClose(context);
|
||||||
|
return null;
|
||||||
|
}, const []);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('Login'),
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(24),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
/// GOOGLE LOGIN
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await _startOAuth('google');
|
||||||
|
},
|
||||||
|
child: const Text('Sign in with Google'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
/// APPLE LOGIN
|
||||||
|
SizedBox(
|
||||||
|
width: double.infinity,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: () async {
|
||||||
|
await _startOAuth('apple');
|
||||||
|
},
|
||||||
|
child: const Text('Sign in with Apple'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ===============================
|
||||||
|
/// Start OAuth (NON-BLOCKING)
|
||||||
|
/// ===============================
|
||||||
|
Future<void> _startOAuth(String provider) async {
|
||||||
|
try {
|
||||||
|
final methods = await pb.collection('users').listAuthMethods();
|
||||||
|
|
||||||
|
final authProvider = methods.authProviders.firstWhere(
|
||||||
|
(p) => p.name == provider,
|
||||||
|
);
|
||||||
|
|
||||||
|
await launchUrl(
|
||||||
|
Uri.parse(authProvider.authUrl),
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('❌ OAuth launch error: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ===============================
|
||||||
|
/// Lifecycle Observer
|
||||||
|
/// ===============================
|
||||||
|
class _OAuthLifecycle with WidgetsBindingObserver {
|
||||||
|
final PocketBase pb;
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
_OAuthLifecycle({
|
||||||
|
required this.pb,
|
||||||
|
required this.context,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
|
if (state == AppLifecycleState.resumed) {
|
||||||
|
_handleResume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleResume() {
|
||||||
|
if (pb.authStore.isValid) {
|
||||||
|
debugPrint('✅ OAuth login detected');
|
||||||
|
|
||||||
|
final user = pb.authStore.model;
|
||||||
|
debugPrint('User ID: ${user?.id}');
|
||||||
|
debugPrint('Email: ${user?.data['email']}');
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
context.go('/myhomepage'); // 🔁 change route if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
112
lib/presentation/routes/auth_routes/checkingUAEPass.dart
Normal file
112
lib/presentation/routes/auth_routes/checkingUAEPass.dart
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_uae_pass/flutter_uae_pass.dart';
|
||||||
|
|
||||||
|
class checkingUAEPass extends StatefulWidget {
|
||||||
|
const checkingUAEPass({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<checkingUAEPass> createState() => _checkingUAEPassState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _checkingUAEPassState extends State<checkingUAEPass> {
|
||||||
|
String? authCode;
|
||||||
|
String? accessToken;
|
||||||
|
ProfileData? profileData;
|
||||||
|
|
||||||
|
final _uaePass = UaePass();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
// _uaePass.setUpSandbox(); // This uses staging - correct for your staging app
|
||||||
|
_uaePass.setUpEnvironment(
|
||||||
|
clientId: "sandbox_stage", // from UAE PASS console
|
||||||
|
clientSecret: "sandbox_stage", // from UAE PASS console
|
||||||
|
isProduction: false, // staging environment
|
||||||
|
urlScheme: "fcscUaeStats", // 👈 this must match the scheme below
|
||||||
|
redirectUri: "fcscUaeStats://callback", // 👈 must match manifest + UAE PASS
|
||||||
|
scope: "urn:uae:digitalid:profile:general",
|
||||||
|
language: "en",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return MaterialApp(
|
||||||
|
home: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('UAE Pass'),
|
||||||
|
centerTitle: true,
|
||||||
|
),
|
||||||
|
body: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
MaterialButton(
|
||||||
|
onPressed: () => login(),
|
||||||
|
child: const Text('Sign in with UAE Pass'),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 100),
|
||||||
|
if (authCode != null)
|
||||||
|
ListTile(
|
||||||
|
title: const Text('Auth Code'),
|
||||||
|
subtitle: Text('${authCode?.substring(0, 6)}............'),
|
||||||
|
),
|
||||||
|
if (accessToken != null)
|
||||||
|
ListTile(
|
||||||
|
title: const Text('Access Token'),
|
||||||
|
subtitle: Text('${accessToken?.substring(0, 6)}............'),
|
||||||
|
),
|
||||||
|
if (profileData != null)
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
title: const Text('Emirates Id'),
|
||||||
|
subtitle: Text(profileData?.idn ?? ""),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('Full Name EN'),
|
||||||
|
subtitle: Text(profileData?.fullnameEN ?? ""),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('Full Name AR'),
|
||||||
|
subtitle: Text(profileData?.fullnameAR ?? ""),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('Mobile'),
|
||||||
|
subtitle: Text(profileData?.mobile ?? ""),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('Nationality EN'),
|
||||||
|
subtitle: Text(profileData?.nationalityEN ?? ""),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> login() async {
|
||||||
|
authCode = null;
|
||||||
|
accessToken = null;
|
||||||
|
profileData = null;
|
||||||
|
setState(() {});
|
||||||
|
try {
|
||||||
|
authCode = await _uaePass.signIn();
|
||||||
|
accessToken = await _uaePass.getAccessToken(authCode ?? "");
|
||||||
|
profileData = await _uaePass.getProfile(accessToken ?? "");
|
||||||
|
|
||||||
|
setState(() {});
|
||||||
|
} catch (e) {
|
||||||
|
if (kDebugMode) {
|
||||||
|
print(e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -46,7 +46,7 @@ import 'package:uae_stat/config/api_config.dart';
|
|||||||
import '../../components/indicators/locale_provider.dart';
|
import '../../components/indicators/locale_provider.dart';
|
||||||
import '../../components/my_toggle.dart';
|
import '../../components/my_toggle.dart';
|
||||||
|
|
||||||
class LoginRoute extends HookConsumerWidget {
|
class LoginRoute extends HookConsumerWidget with WidgetsBindingObserver{
|
||||||
final String? fromPage;
|
final String? fromPage;
|
||||||
final Map<String, dynamic>? userInfo;
|
final Map<String, dynamic>? userInfo;
|
||||||
|
|
||||||
@ -438,33 +438,46 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> login(BuildContext context, ref) async {
|
Future<void> login(BuildContext context, ref) async {
|
||||||
final email = profileData?.email ?? 'surendarsuri3450@gmail.com';
|
// final email = profileData?.email ?? 'surendarsuri3450@gmail.com';
|
||||||
final uuid = profileData?.uuid ?? 'eac45287-5e1b-4251-b338-6aa7f49464a0';
|
// final uuid = profileData?.uuid ?? 'eac45287-5e1b-4251-b338-6aa7f49464a0';
|
||||||
await checkUserWithUhid(
|
// await checkUserWithUhid(
|
||||||
email: email ?? '',
|
// email: email ?? '',
|
||||||
uuid: uuid ?? '',
|
// uuid: uuid ?? '',
|
||||||
context: context,
|
// context: context,
|
||||||
userInfo: profileData,
|
// userInfo: profileData,
|
||||||
);
|
// );
|
||||||
authCode = null;
|
authCode = null;
|
||||||
accessToken = null;
|
accessToken = null;
|
||||||
profileData = null;
|
profileData = null;
|
||||||
try {
|
try {
|
||||||
authCode = await _uaePass.signIn();
|
authCode = await _uaePass.signIn();
|
||||||
print('authCode $authCode');
|
print('authCode $authCode');
|
||||||
accessToken = await _uaePass.getAccessToken(authCode ?? "");
|
showDialog(
|
||||||
print('accessToken $accessToken');
|
|
||||||
profileData = await _uaePass.getProfile(accessToken ?? "");
|
|
||||||
print('profileData $profileData');
|
|
||||||
final email = profileData?.email ?? 'surendarsuri30@gmail.com';
|
|
||||||
final uuid = profileData?.uuid ?? 'eac45287-5e1b-4251-b338-6aa7f49464a0';
|
|
||||||
|
|
||||||
await checkUserWithUhid(
|
|
||||||
email: email ?? '',
|
|
||||||
uuid: uuid ?? '',
|
|
||||||
context: context,
|
context: context,
|
||||||
userInfo: profileData,
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Text('Auth Code'),
|
||||||
|
content: Text('authCode: $authCode'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('OK'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
// accessToken = await _uaePass.getAccessToken(authCode ?? "");
|
||||||
|
// print('accessToken $accessToken');
|
||||||
|
// profileData = await _uaePass.getProfile(accessToken ?? "");
|
||||||
|
// print('profileData $profileData');
|
||||||
|
// final email = profileData?.email ?? '';
|
||||||
|
// final uuid = profileData?.uuid ?? '';
|
||||||
|
|
||||||
|
// await checkUserWithUhid(
|
||||||
|
// email: email ?? '',
|
||||||
|
// uuid: uuid ?? '',
|
||||||
|
// context: context,
|
||||||
|
// userInfo: profileData,
|
||||||
|
// );
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
print(e.toString());
|
print(e.toString());
|
||||||
@ -490,27 +503,26 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
print('platform $platform');
|
print('platform $platform');
|
||||||
try {
|
try {
|
||||||
print('platform $platform');
|
print('platform $platform');
|
||||||
|
// final methods = await pb.collection('users').listAuthMethods();
|
||||||
|
// print(methods);
|
||||||
|
// final authProvider = methods.authProviders.firstWhere((p) => p.name == platform);
|
||||||
|
// print(authProvider);
|
||||||
|
// await launchUrl(
|
||||||
|
// Uri.parse(authProvider.authUrl),
|
||||||
|
// mode: LaunchMode.externalApplication,
|
||||||
|
// );
|
||||||
final authData =
|
final authData =
|
||||||
await pb.collection('users').authWithOAuth2(platform, (url) async {
|
await pb.collection('users').authWithOAuth2(platform, (url) async {
|
||||||
await launchUrl(url);
|
await launchUrl(url);
|
||||||
});
|
});
|
||||||
// final authData = await pb.collection('users').authWithOAuth2(
|
// final authData =
|
||||||
// platform, // 'google' or 'apple'
|
// await pb.collection('users').authWithOAuth2(platform, (url) async {
|
||||||
// (providerUrl) async {
|
// await launchUrl(
|
||||||
// final Uri uri = Uri.parse(providerUrl.toString());
|
// Uri.parse(url.toString()),
|
||||||
//
|
// mode: LaunchMode.platformDefault,
|
||||||
// // Inject redirect_url so PocketBase will redirect to the app when done
|
|
||||||
// final newUri = uri.replace(queryParameters: {
|
|
||||||
// ...uri.queryParameters,
|
|
||||||
// 'redirect_url': deepLinkRedirect,
|
|
||||||
// });
|
|
||||||
//
|
|
||||||
// // Open in external browser (ensures OS handles returning to app)
|
|
||||||
// if (!await launchUrl(newUri, mode: LaunchMode.externalApplication)) {
|
|
||||||
// throw 'Could not launch OAuth URL';
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// );
|
// );
|
||||||
|
// });
|
||||||
|
|
||||||
print('authData $authData');
|
print('authData $authData');
|
||||||
// ✅ Check if authData is valid
|
// ✅ Check if authData is valid
|
||||||
if (authData.token.isNotEmpty && authData.record != null) {
|
if (authData.token.isNotEmpty && authData.record != null) {
|
||||||
@ -771,13 +783,15 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
Future<void> checkUserWithUhid1({
|
Future<void> checkUserWithUhid({
|
||||||
required String email,
|
required String code,
|
||||||
required String uuid,
|
required ref,
|
||||||
|
// required String email,
|
||||||
|
// required String uuid,
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required userInfo,
|
// required userInfo,
|
||||||
}) async {
|
}) async {
|
||||||
final url = Uri.parse('$apiUrl/api/checkUserWithUhid');
|
final url = Uri.parse('${apiUrl}api/checkUserWithUhid');
|
||||||
|
|
||||||
final headers = {
|
final headers = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
@ -785,38 +799,135 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
};
|
};
|
||||||
|
|
||||||
final body = jsonEncode({
|
final body = jsonEncode({
|
||||||
'email': email,
|
// 'email': email,
|
||||||
'uuid': uuid,
|
// 'uuid': uuid,
|
||||||
|
'code' : code
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final response = await http.post(url, headers: headers, body: body);
|
final response = await http.post(url, headers: headers, body: body);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
final data = jsonDecode(response.body);
|
// final data = jsonDecode(response.body);
|
||||||
print('✅ Success: $data');
|
final apiParam = {
|
||||||
// final Map<String, dynamic> userInfoDetails = userInfo;
|
"data": {
|
||||||
final Map<String, dynamic> userInfoDetails = {
|
"avatar": "",
|
||||||
"sub": "eac45287-5e1b-4251-b338-6aa7f49464a0",
|
"collectionId": "_pb_users_auth_",
|
||||||
"fullnameAR": "سوريندر سوري",
|
"collectionName": "users",
|
||||||
"gender": "Male",
|
"country_region": "",
|
||||||
"spuuid": "ASdfsfdsgfg-4672n-4284jjbjvbckjsx",
|
"created": "2025-09-27 04:39:48.639Z",
|
||||||
"mobile": "918056103381",
|
"device_token": "",
|
||||||
"lastnameEN": "suri",
|
"dob": "",
|
||||||
"fullnameEN": "surendar suri",
|
"emailVisibility": false,
|
||||||
"uuid": "eac45287-5e1b-4251-b338-6aa7f49464a0",
|
"full_name": "",
|
||||||
"lastnameAR": "سوري",
|
"id": "iwxvax2m3ra8vry",
|
||||||
"idn": "784000000009632",
|
"is_oauth_login": 0,
|
||||||
"nationalityEN": "ARE",
|
"is_profile_completed": false,
|
||||||
"firstnameEN": "surendar",
|
"language": "",
|
||||||
"userType": "SOP2",
|
"login_count": 4,
|
||||||
"nationalityAR": "اماراتى",
|
"pushed_notification": null,
|
||||||
"firstnameAR": "سوريندر",
|
"pw_reset_token": "",
|
||||||
"email": "surendarsuri30@gmail.com"
|
"pw_reset_token_expiry": "",
|
||||||
};
|
"reviewed": false,
|
||||||
|
"role": "",
|
||||||
|
"status": "",
|
||||||
|
"theme": "",
|
||||||
|
"uname": "",
|
||||||
|
"updated": "2025-11-25 09:12:01.746Z",
|
||||||
|
"user_mail_verify": false,
|
||||||
|
"username": "users45431",
|
||||||
|
"verified": true
|
||||||
|
},
|
||||||
|
"expiresOn": 1765271521,
|
||||||
|
"message": "User found by email and UUID updated",
|
||||||
|
"status": "success",
|
||||||
|
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2xsZWN0aW9uSWQiOiJfcGJfdXNlcnNfYXV0aF8iLCJleHAiOjE3NjUyNzE1MjEsImlkIjoiaXd4dmF4Mm0zcmE4dnJ5IiwidHlwZSI6ImF1dGhSZWNvcmQifQ.jSXeGByFWsPTv70nW2YvahZi8fYCzfibF8nWqhKYPA0"
|
||||||
|
|
||||||
GoRouter.of(context).go('/fcscprofilelinking', extra: userInfoDetails);
|
};
|
||||||
|
print('✅ Success: $apiParam');
|
||||||
|
if (apiParam['token'] != null &&
|
||||||
|
apiParam['token'].toString().isNotEmpty &&
|
||||||
|
apiParam['status'] == 'success') {
|
||||||
|
|
||||||
|
print("✔ Token exists & login success!");
|
||||||
|
|
||||||
|
// final metaDetails = authData.meta;
|
||||||
|
final userDetails = apiParam['data'] as Map<String, dynamic>;
|
||||||
|
final token = apiParam['token'];
|
||||||
|
final userId = userDetails['id'];
|
||||||
|
final email = userDetails['email'] ?? '';
|
||||||
|
final uname = userDetails['uname'] ?? '';
|
||||||
|
final isProfileComplete = userDetails['is_profile_completed'] ?? false;
|
||||||
|
final loginCount = userDetails['login_count'] ?? 0;
|
||||||
|
// final expiresOn = apiParam['expiresOn'];
|
||||||
|
|
||||||
|
print("User ID: ${userId}");
|
||||||
|
print("Email: ${email}");
|
||||||
|
print("Email: ${isProfileComplete}");
|
||||||
|
print("Email: ${loginCount}");
|
||||||
|
|
||||||
|
final session = await context.loaderWithErrorDialog(
|
||||||
|
() => ref
|
||||||
|
.read(
|
||||||
|
authUseCaseProvider.notifier,
|
||||||
|
)
|
||||||
|
.googleAndAppleAuthencation(apiParam),
|
||||||
|
errorDialogBuilder: (
|
||||||
|
error, [
|
||||||
|
StackTrace? stackTrace,
|
||||||
|
]) {
|
||||||
|
if (error == LoginError.invalidEmailPw) {
|
||||||
|
return context.simpleDialog(
|
||||||
|
title: context.translate(
|
||||||
|
'Incorrect Credentials',
|
||||||
|
'أوراق غير صحيحة',
|
||||||
|
),
|
||||||
|
content: context.translate(
|
||||||
|
'Your email or password is invalid. Please try again.',
|
||||||
|
'بريدك الإلكتروني أو كلمة المرور غير صالحة. حاول مرة اخرى.',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return context.simpleDialog();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
print("sessionTST - $session");
|
||||||
|
|
||||||
|
await loginCountApi(userId!);
|
||||||
|
await updateOAuthUserDetails(userId!, uname, ref, token);
|
||||||
|
// await saveUserId(userId!, loginCount);
|
||||||
|
await getDeviceToken(context, userId, ref, token);
|
||||||
|
await initializeTheme(context, ref, userId);
|
||||||
|
|
||||||
|
// final se = _sessionEntityFromPocketbaseRecord(authData);
|
||||||
|
// await _LocalAuthRepo.storeLocally(se);
|
||||||
|
|
||||||
|
// Extract intendedPath from query parameters (if coming from redirect)
|
||||||
|
final String? intendedPath =
|
||||||
|
GoRouterState.of(context).uri.queryParameters['intendedPath'];
|
||||||
|
print("Extracted intendedPath after login: $intendedPath");
|
||||||
|
|
||||||
|
if (isProfileComplete) {
|
||||||
|
print('Redirecting to Home / Intended Path');
|
||||||
|
// **Set Default Locale in Provider**
|
||||||
|
if (preferredLanguage == 'ar') {
|
||||||
|
ref.read(localeProvider.notifier).setLocale(const Locale('ar'));
|
||||||
} else {
|
} else {
|
||||||
|
ref.read(localeProvider.notifier).setLocale(const Locale('en'));
|
||||||
|
}
|
||||||
|
|
||||||
|
context.go(intendedPath ?? '/myhomepage');
|
||||||
|
} else {
|
||||||
|
print('Redirecting to Profile Setup');
|
||||||
|
|
||||||
|
context.go('/profile/$userId');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print("❌ Login failed: Invalid authData");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
GoRouter.of(context).go('/fcscprofilelinking', extra: userInfo);
|
||||||
print('❌ Error: ${response.statusCode} - ${response.body}');
|
print('❌ Error: ${response.statusCode} - ${response.body}');
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -824,17 +935,166 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> checkUserWithUhid({
|
String buildUaepassAuthorizationUrl() {
|
||||||
required String email,
|
const String authorizeEndpoint = "https://stg-id.uaepass.ae/idshub/authorize";
|
||||||
required String uuid,
|
const String clientId = "sandbox_stage";
|
||||||
required BuildContext context,
|
const String scope = "urn:uae:digitalid:profile:general";
|
||||||
required userInfo,
|
const String redirectUri = "http://localhost:56215/#/login";
|
||||||
}) async {
|
const String acrValues = "urn:safelayer:tws:policies:authentication:level:low";
|
||||||
print('checkUserWithUhid');
|
|
||||||
|
|
||||||
signInWithUAEPASS();
|
// Generate random state (recommended)
|
||||||
|
final String state = DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
|
|
||||||
|
final Uri uri = Uri.parse(authorizeEndpoint).replace(
|
||||||
|
queryParameters: {
|
||||||
|
"response_type": "code",
|
||||||
|
"client_id": clientId,
|
||||||
|
"scope": scope,
|
||||||
|
"redirect_uri": redirectUri,
|
||||||
|
"state": state,
|
||||||
|
"acr_values": acrValues,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
print('UAEPASS URL : $uri');
|
||||||
|
return uri.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> openUaepassLogin(BuildContext context) async {
|
||||||
|
final authUrl = buildUaepassAuthorizationUrl(); // Now this exists
|
||||||
|
|
||||||
|
print('UAE Pass :$authUrl');
|
||||||
|
|
||||||
|
final uri = Uri.parse(authUrl);
|
||||||
|
|
||||||
|
if (!await launchUrl(uri, mode: LaunchMode.externalApplication)) {
|
||||||
|
throw 'Could not launch UAE PASS URL';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigator.push(
|
||||||
|
// context,
|
||||||
|
// MaterialPageRoute(
|
||||||
|
// builder: (_) => Scaffold(
|
||||||
|
// appBar: AppBar(title: const Text("UAE PASS Login")),
|
||||||
|
// body: InAppWebView(
|
||||||
|
// initialUrlRequest: URLRequest(
|
||||||
|
// url: WebUri.uri(Uri.parse(authUrl)),
|
||||||
|
// ),
|
||||||
|
// initialOptions: InAppWebViewGroupOptions(
|
||||||
|
// crossPlatform: InAppWebViewOptions(
|
||||||
|
// useShouldOverrideUrlLoading: true,
|
||||||
|
// javaScriptEnabled: true,
|
||||||
|
// ),
|
||||||
|
// android: AndroidInAppWebViewOptions(),
|
||||||
|
// ios: IOSInAppWebViewOptions(),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> fetchUaepassToken(String code) async {
|
||||||
|
const String tokenUrl = "https://stg-id.uaepass.ae/idshub/token";
|
||||||
|
|
||||||
|
const String clientId = "sandbox_stage";
|
||||||
|
const String clientSecret = "sandbox_stage"; // For POC both are same
|
||||||
|
const String redirectUri = "http://localhost:55227/#/login"; // use your redirect URI
|
||||||
|
|
||||||
|
// Encode Basic Auth: base64(clientId:clientSecret)
|
||||||
|
final String basicAuth =
|
||||||
|
'Basic ${base64Encode(utf8.encode("$clientId:$clientSecret"))}';
|
||||||
|
|
||||||
|
final response = await http.post(
|
||||||
|
Uri.parse(tokenUrl),
|
||||||
|
headers: {
|
||||||
|
"Authorization": basicAuth,
|
||||||
|
"Content-Type": "application/x-www-form-urlencoded",
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
"grant_type": "authorization_code",
|
||||||
|
"redirect_uri": redirectUri,
|
||||||
|
"code": code,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
print("🔍 UAE PASS TOKEN RESPONSE → ${response.statusCode}");
|
||||||
|
print("📩 Response Body → ${response.body}");
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
return jsonDecode(response.body);
|
||||||
|
} else {
|
||||||
|
throw Exception("Failed to fetch token: ${response.body}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _callUaepassTokenAPI(BuildContext context,WidgetRef ref, String code) async {
|
||||||
|
try {
|
||||||
|
final String safeCode = (code is String) ? code : code?.toString() ?? '';
|
||||||
|
|
||||||
|
print("🔐 Calling UAE PASS Token API with code: $safeCode");
|
||||||
|
|
||||||
|
// TODO: Implement your API call here
|
||||||
|
// Example:
|
||||||
|
// final token = await ref.read(authProvider.notifier).loginWithUaepass(code);
|
||||||
|
|
||||||
|
// final tokenData = await fetchUaepassToken(code);
|
||||||
|
//
|
||||||
|
// final accessToken = tokenData['access_token'];
|
||||||
|
// final refreshToken = tokenData['refresh_token'];
|
||||||
|
// print("✅ Access Token: $accessToken");
|
||||||
|
// print("🔄 Refresh Token: $refreshToken");
|
||||||
|
// final userInfo = await fetchUaepassUserInfo(accessToken);
|
||||||
|
//
|
||||||
|
// print("👤 UAE PASS User Info:");
|
||||||
|
// print(userInfo);
|
||||||
|
//
|
||||||
|
await checkUserWithUhid(
|
||||||
|
code: safeCode,
|
||||||
|
ref:ref,
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
print("✅ Token received and processed successfully");
|
||||||
|
} catch (e) {
|
||||||
|
print("❌ UAE PASS token exchange failed: $e");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<Map<String, dynamic>> fetchUaepassUserInfo(String accessToken) async {
|
||||||
|
const String userInfoUrl = "https://stg-id.uaepass.ae/idshub/userinfo";
|
||||||
|
|
||||||
|
final response = await http.get(
|
||||||
|
Uri.parse(userInfoUrl),
|
||||||
|
headers: {
|
||||||
|
"Authorization": "Bearer $accessToken",
|
||||||
|
"Accept": "application/json",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
print("🔍 USER INFO RESPONSE → ${response.statusCode}");
|
||||||
|
print("📩 Response Body → ${response.body}");
|
||||||
|
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
return jsonDecode(response.body);
|
||||||
|
} else {
|
||||||
|
throw Exception("Failed to fetch user info: ${response.body}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> loginWithProviderAllInOne(String provider) async {
|
||||||
|
try {
|
||||||
|
// NOTE: no redirectUrl named parameter here
|
||||||
|
final authData =
|
||||||
|
await pb.collection('users').authWithOAuth2(provider, (url) async {
|
||||||
|
await launchUrl(url);
|
||||||
|
});
|
||||||
|
print('PB token: ${pb.authStore.token}');
|
||||||
|
print('User: ${pb.authStore.model}');
|
||||||
|
} catch (e) {
|
||||||
|
print('OAuth error: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
double screenHeight = MediaQuery.of(context).size.height;
|
double screenHeight = MediaQuery.of(context).size.height;
|
||||||
@ -844,15 +1104,27 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
final uaePass = useMemoized(() => UaePass());
|
final uaePass = useMemoized(() => UaePass());
|
||||||
final isInit = useState(false);
|
final isInit = useState(false);
|
||||||
|
|
||||||
|
final params = GoRouterState.of(context).uri.queryParameters;
|
||||||
|
final uaePassCode = params['uaeCode'];
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
if (uaePassCode != null) {
|
||||||
|
print("🚀 UAE PASS code received: $uaePassCode");
|
||||||
|
_callUaepassTokenAPI(context,ref, uaePassCode);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}, [uaePassCode]);
|
||||||
|
|
||||||
// Initialize UAE PASS once when widget loads
|
// Initialize UAE PASS once when widget loads
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
Future.microtask(() async {
|
Future.microtask(() async {
|
||||||
|
// await uaePass.setUpSandbox();
|
||||||
await uaePass.setUpEnvironment(
|
await uaePass.setUpEnvironment(
|
||||||
clientId: "sandbox_stage",
|
clientId: "sandbox_stage",
|
||||||
clientSecret: "sandbox_stage",
|
clientSecret: "sandbox_stage",
|
||||||
isProduction: false,
|
isProduction: false,
|
||||||
urlScheme: "fcscapp", // fallback for Android custom scheme
|
urlScheme: "fcscUaeStats", // fallback for Android custom scheme
|
||||||
redirectUri: "https://fcscapp.onelink.me/LI5k/tdh3znpf",
|
redirectUri: "http://localhost:55227/#/login",
|
||||||
scope: "urn:uae:digitalid:profile",
|
scope: "urn:uae:digitalid:profile",
|
||||||
language: "en",
|
language: "en",
|
||||||
); // or setUpEnvironment(...) for prod
|
); // or setUpEnvironment(...) for prod
|
||||||
@ -860,6 +1132,27 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
/// -------------------------------------------------------
|
||||||
|
/// POCKETBASE OAUTH AUTO-CLOSE (RESUME DETECTION)
|
||||||
|
/// -------------------------------------------------------
|
||||||
|
useEffect(() {
|
||||||
|
final observer = _OAuthLifecycleObserver(
|
||||||
|
pb: pb,
|
||||||
|
context: context,
|
||||||
|
);
|
||||||
|
|
||||||
|
WidgetsBinding.instance.addObserver(observer);
|
||||||
|
return () => WidgetsBinding.instance.removeObserver(observer);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
if (!isInit.value) {
|
||||||
|
return const Scaffold(
|
||||||
|
body: Center(child: CircularProgressIndicator()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// useEffect(() {
|
// useEffect(() {
|
||||||
// _uaePass.setUpSandbox(); // equivalent to initState()
|
// _uaePass.setUpSandbox(); // equivalent to initState()
|
||||||
// return null; // no cleanup needed
|
// return null; // no cleanup needed
|
||||||
@ -1721,7 +2014,10 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
child: OutlinedButton(
|
child: OutlinedButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
// signInWithUAEPASS();
|
// signInWithUAEPASS();
|
||||||
login(context, ref);
|
openUaepassLogin(context);
|
||||||
|
// login(context, ref);
|
||||||
|
// loginWithProviderAllInOne('oidc');
|
||||||
|
|
||||||
// Navigator.push(
|
// Navigator.push(
|
||||||
// context,
|
// context,
|
||||||
// MaterialPageRoute(builder: (context) => const UAEPassSignInPage()),
|
// MaterialPageRoute(builder: (context) => const UAEPassSignInPage()),
|
||||||
@ -1856,10 +2152,10 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
// continueAsGuestBtn,
|
// continueAsGuestBtn,
|
||||||
// 15.verticalSpace,
|
// 15.verticalSpace,
|
||||||
// orText,
|
// orText,
|
||||||
15.verticalSpace,
|
// 15.verticalSpace,
|
||||||
signInWithUAEPassBtn,
|
// signInWithUAEPassBtn,
|
||||||
15.verticalSpace,
|
// 15.verticalSpace,
|
||||||
orText,
|
// orText,
|
||||||
15.verticalSpace,
|
15.verticalSpace,
|
||||||
signInWithGoogleBtn,
|
signInWithGoogleBtn,
|
||||||
15.verticalSpace,
|
15.verticalSpace,
|
||||||
@ -1954,6 +2250,49 @@ class LoginRoute extends HookConsumerWidget {
|
|||||||
// ),
|
// ),
|
||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// =======================================================
|
||||||
|
/// APP LIFECYCLE OBSERVER (AUTO-CLOSE LOGIC)
|
||||||
|
/// =======================================================
|
||||||
|
class _OAuthLifecycleObserver extends WidgetsBindingObserver {
|
||||||
|
final PocketBase pb;
|
||||||
|
final BuildContext context;
|
||||||
|
|
||||||
|
_OAuthLifecycleObserver({
|
||||||
|
required this.pb,
|
||||||
|
required this.context,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||||
|
if (state == AppLifecycleState.resumed) {
|
||||||
|
_handleResume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleResume() {
|
||||||
|
if (pb.authStore.isValid) {
|
||||||
|
debugPrint('✅ PocketBase OAuth login detected');
|
||||||
|
|
||||||
|
print("✅ OAuth success detected on resume");
|
||||||
|
|
||||||
|
final userDetails = pb.authStore.model;
|
||||||
|
final token = pb.authStore.token;
|
||||||
|
|
||||||
|
print(userDetails);
|
||||||
|
|
||||||
|
if (userDetails == null || token.isEmpty) {
|
||||||
|
print("❌ Invalid authStore data");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.mounted) {
|
||||||
|
context.go('/myhomepage');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// abstract class _LocalAuthRepo {
|
// abstract class _LocalAuthRepo {
|
||||||
|
|||||||
@ -279,7 +279,7 @@ class _EditProfileState extends ConsumerState<EditProfile> {
|
|||||||
});
|
});
|
||||||
print(pickedFile);
|
print(pickedFile);
|
||||||
final String fileExtension =
|
final String fileExtension =
|
||||||
pickedFile.path.split('.').last.toLowerCase();
|
pickedFile.name.split('.').last.toLowerCase();
|
||||||
print('fileExtension $fileExtension');
|
print('fileExtension $fileExtension');
|
||||||
if (fileExtension == 'jpg' ||
|
if (fileExtension == 'jpg' ||
|
||||||
fileExtension == 'jpeg' ||
|
fileExtension == 'jpeg' ||
|
||||||
@ -519,6 +519,101 @@ class _EditProfileState extends ConsumerState<EditProfile> {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Future<void> showConfirmationDialog(BuildContext context) async {
|
||||||
|
// // String? _validateDropdown(ISOCountry? value) {
|
||||||
|
// // if (value == null) {
|
||||||
|
// // return context.translate('Please select a country', 'يرجى اختيار دولة');
|
||||||
|
// // }
|
||||||
|
// // return null;
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// // if (_validateDropdown(_selectedCountry) == null &&
|
||||||
|
// // _validatePreferredLang(_selectedLanguage) == null) {
|
||||||
|
// //
|
||||||
|
// // }
|
||||||
|
// try {
|
||||||
|
// setState(() => isLoader = true);
|
||||||
|
//
|
||||||
|
// // String userID = userId;
|
||||||
|
// // final userId = pb.authStore.model!.id;
|
||||||
|
//
|
||||||
|
// print('checkin');
|
||||||
|
//
|
||||||
|
// final body = {
|
||||||
|
// 'country_region': context.translate(
|
||||||
|
// _selectedCountry?.nameEN ?? '',
|
||||||
|
// _selectedCountry?.nameAR ?? '',
|
||||||
|
// ),
|
||||||
|
// 'language': _selectedLanguage == 'English' ? 'en' : 'ar',
|
||||||
|
// };
|
||||||
|
// print('checkin $body');
|
||||||
|
//
|
||||||
|
// final List<http.MultipartFile> files = [];
|
||||||
|
//
|
||||||
|
// if (_profileImage != null) {
|
||||||
|
// final Uint8List bytes = await _profileImage!.readAsBytes();
|
||||||
|
// print('Uint8List $bytes');
|
||||||
|
//
|
||||||
|
// files.add(
|
||||||
|
// http.MultipartFile.fromBytes(
|
||||||
|
// 'avatar',
|
||||||
|
// bytes,
|
||||||
|
// filename: _profileImage!.path.split('/').last, // ✅ FIX
|
||||||
|
// ),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// print('_profileImage $body');
|
||||||
|
//
|
||||||
|
// await pb.collection('users').update(
|
||||||
|
// userId,
|
||||||
|
// body: body,
|
||||||
|
// files: files,
|
||||||
|
// );
|
||||||
|
//
|
||||||
|
// if (!mounted) return;
|
||||||
|
// setState(() => isLoader = false);
|
||||||
|
// print('mounted');
|
||||||
|
// String preferredLang = _selectedLanguage ?? '';
|
||||||
|
// if (changedPreferredLanguage == 1) {
|
||||||
|
// print(_selectedLanguage);
|
||||||
|
// preferredLang = _selectedLanguage == 'English' ? 'en' : 'ar';
|
||||||
|
// if (preferredLang == 'ar') {
|
||||||
|
// ref.read(localeProvider.notifier).setLocale(const Locale('ar'));
|
||||||
|
// } else {
|
||||||
|
// ref.read(localeProvider.notifier).setLocale(const Locale('en'));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// _resetFormFields();
|
||||||
|
//
|
||||||
|
// SchedulerBinding.instance.addPostFrameCallback((_) {
|
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
// SnackBar(
|
||||||
|
// content: Text(
|
||||||
|
// AppLocalizations.of(context)!.profile_updated_successfully,
|
||||||
|
// style: TextStyle(
|
||||||
|
// fontFamily: context.translate(
|
||||||
|
// 'Roboto',
|
||||||
|
// 'NotoKufi',
|
||||||
|
// )),
|
||||||
|
// )),
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// context.go('/myhomepage');
|
||||||
|
// } catch (e, st) {
|
||||||
|
// debugPrint('❌ Update error: $e');
|
||||||
|
// debugPrint('$st');
|
||||||
|
//
|
||||||
|
// if (!mounted) return;
|
||||||
|
// setState(() => isLoader = false);
|
||||||
|
//
|
||||||
|
// ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
// const SnackBar(content: Text('Failed to update profile')),
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
void _resetFormFields() {
|
void _resetFormFields() {
|
||||||
print('reset');
|
print('reset');
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import 'package:uae_stat/config/theme/theme_provider.dart';
|
|||||||
import 'package:uae_stat/config/toggle_lang_service.dart';
|
import 'package:uae_stat/config/toggle_lang_service.dart';
|
||||||
import 'package:uae_stat/domain/use_cases/language.dart';
|
import 'package:uae_stat/domain/use_cases/language.dart';
|
||||||
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart';
|
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart';
|
||||||
|
import 'package:uae_stat/infrastructure/services/pocketbase_service.dart';
|
||||||
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
|
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
|
||||||
|
|
||||||
import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart';
|
import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart';
|
||||||
@ -55,60 +56,50 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_userService = UserService();
|
_userService = UserService();
|
||||||
fetchUnverifiedUsers();
|
fetchAllUsers();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetchUnverifiedUsers() async {
|
Future<void> fetchAllUsers() async {
|
||||||
try {
|
try {
|
||||||
// await _pb.admins
|
setState(() => isLoading = true);
|
||||||
// .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
|
|
||||||
|
|
||||||
final auth = ref.watch(authProvider);
|
// await _pb.admins.authWithPassword(
|
||||||
|
// 'pb@venbainfotech.com',
|
||||||
// await pb.admins.authWithPassword(
|
// 'pb@venbainfotech.com',
|
||||||
// auth.email,
|
|
||||||
// auth.password,
|
|
||||||
// );
|
// );
|
||||||
|
|
||||||
final themeService = ThemeBaseService();
|
final records = await _pb.collection('users').getFullList(
|
||||||
// final adminToken = await themeService.getAdminToken(
|
|
||||||
// email: auth.email,
|
|
||||||
// password: auth.password,
|
|
||||||
// );
|
|
||||||
final result = await _pb.collection('users').getFullList(
|
|
||||||
filter: 'role="user"',
|
filter: 'role="user"',
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ${PocketBaseService.authStore.token}',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
setState(() {
|
final users = records.map((record) {
|
||||||
userData = result.map((record) {
|
|
||||||
final createdDate = DateTime.parse(record.created)
|
|
||||||
.add(Duration(hours: 4)); // Parse the created date
|
|
||||||
final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate);
|
|
||||||
return User(
|
return User(
|
||||||
id: record.id, // Correctly passing the ID
|
id: record.id,
|
||||||
userName: record.getStringValue('uname'),
|
userName: record.data['uname'] ?? '',
|
||||||
emailId: record.getStringValue('email'),
|
emailId: record.data['email'] ?? '',
|
||||||
registrationDate: formattedDate,
|
registrationDate: DateFormat('dd/MM/yyyy')
|
||||||
status: record.getStringValue('status'),
|
.format(DateTime.parse(record.created)),
|
||||||
|
status: record.data['status'] ?? 'Pending',
|
||||||
);
|
);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
userData.sort((a, b) {
|
setState(() {
|
||||||
DateTime dateA = DateFormat('dd/MM/yyyy').parse(a.registrationDate);
|
userData = users;
|
||||||
DateTime dateB = DateFormat('dd/MM/yyyy').parse(b.registrationDate);
|
filteredUserData = users;
|
||||||
return dateB.compareTo(dateA);
|
|
||||||
});
|
|
||||||
|
|
||||||
filteredUserData = List.from(userData);
|
|
||||||
|
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e, st) {
|
||||||
isLoading = false;
|
debugPrint('❌ ERROR FETCHING USERS: $e');
|
||||||
print('Error fetching unverified users: $e');
|
debugPrint('$st');
|
||||||
|
setState(() => isLoading = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Method to filter the list based on the search input
|
// Method to filter the list based on the search input
|
||||||
void filterUsers(String query) {
|
void filterUsers(String query) {
|
||||||
print('Filterd User: $query');
|
print('Filterd User: $query');
|
||||||
@ -159,16 +150,18 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
|
|||||||
'verified': newStatus == 'Approved' ? true : false,
|
'verified': newStatus == 'Approved' ? true : false,
|
||||||
'reviewed': true,
|
'reviewed': true,
|
||||||
},
|
},
|
||||||
|
headers: {
|
||||||
|
'Authorization': 'Bearer ${PocketBaseService.authStore.token}',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// Update local state
|
// Update local state
|
||||||
// setState(() {
|
// setState(() {
|
||||||
// user.status = newStatus;
|
// user.status = newStatus;
|
||||||
// });
|
// });
|
||||||
fetchUnverifiedUsers();
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() => isLoading = false);
|
||||||
isLoading = false;
|
fetchAllUsers();
|
||||||
});
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
@ -182,6 +175,7 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (!mounted) return;
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
});
|
});
|
||||||
@ -371,7 +365,7 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
|
|||||||
MediaQuery.of(context).platformBrightness == Brightness.dark);
|
MediaQuery.of(context).platformBrightness == Brightness.dark);
|
||||||
|
|
||||||
final themeString = isDark ? 'dark' : 'light';
|
final themeString = isDark ? 'dark' : 'light';
|
||||||
fetchUnverifiedUsers();
|
fetchAllUsers();
|
||||||
// fetchBookmarks(localeCode, themeString);
|
// fetchBookmarks(localeCode, themeString);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -391,7 +385,7 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
|
|||||||
MediaQuery.of(context).platformBrightness == Brightness.dark);
|
MediaQuery.of(context).platformBrightness == Brightness.dark);
|
||||||
|
|
||||||
final themeString = isDark ? 'dark' : 'light';
|
final themeString = isDark ? 'dark' : 'light';
|
||||||
fetchUnverifiedUsers();
|
fetchAllUsers();
|
||||||
// fetchBookmarks(localeCode, themeString);
|
// fetchBookmarks(localeCode, themeString);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -692,38 +686,32 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
|
|||||||
)),
|
)),
|
||||||
DataCell(
|
DataCell(
|
||||||
DropdownButton<String>(
|
DropdownButton<String>(
|
||||||
value: user.status,
|
value: statusOptions.containsKey(user.status)
|
||||||
items: statusOptions.entries
|
? user.status
|
||||||
.map((status) {
|
: null,
|
||||||
return DropdownMenuItem<
|
items: statusOptions.entries.map((status) {
|
||||||
String>(
|
return DropdownMenuItem<String>(
|
||||||
value: status.key,
|
value: status.key,
|
||||||
child: Text(
|
child: Text(
|
||||||
status.value,
|
status.value,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily:
|
fontFamily: context.translate('Roboto', 'NotoKufi'),
|
||||||
context.translate(
|
color: getStatusColor(status.key),
|
||||||
'Roboto',
|
|
||||||
'NotoKufi',
|
|
||||||
),
|
|
||||||
color: getStatusColor(
|
|
||||||
status.key),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
onChanged: (newStatus) {
|
onChanged: (newStatus) {
|
||||||
print(user);
|
|
||||||
if (newStatus != null) {
|
if (newStatus != null) {
|
||||||
_showConfirmationDialog(
|
_showConfirmationDialog(
|
||||||
user,
|
user,
|
||||||
newStatus,
|
newStatus,
|
||||||
statusOptions[
|
statusOptions[newStatus]!,
|
||||||
newStatus]!,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
1
linux/.gitignore
vendored
Normal file
1
linux/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
flutter/ephemeral
|
||||||
128
linux/CMakeLists.txt
Normal file
128
linux/CMakeLists.txt
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
# Project-level configuration.
|
||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
project(runner LANGUAGES CXX)
|
||||||
|
|
||||||
|
# The name of the executable created for the application. Change this to change
|
||||||
|
# the on-disk name of your application.
|
||||||
|
set(BINARY_NAME "uae_stat")
|
||||||
|
# The unique GTK application identifier for this application. See:
|
||||||
|
# https://wiki.gnome.org/HowDoI/ChooseApplicationID
|
||||||
|
set(APPLICATION_ID "ae.gov.fcsc.uae_stat")
|
||||||
|
|
||||||
|
# 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 "$<$<NOT:$<CONFIG:Debug>>:-O3>")
|
||||||
|
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Flutter library and tool build rules.
|
||||||
|
set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter")
|
||||||
|
add_subdirectory(${FLUTTER_MANAGED_DIR})
|
||||||
|
|
||||||
|
# System-level dependencies.
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
|
||||||
|
|
||||||
|
# Application build; see runner/CMakeLists.txt.
|
||||||
|
add_subdirectory("runner")
|
||||||
|
|
||||||
|
# Run the Flutter tool portions of the build. This must not be removed.
|
||||||
|
add_dependencies(${BINARY_NAME} flutter_assemble)
|
||||||
|
|
||||||
|
# Only the install-generated bundle's copy of the executable will launch
|
||||||
|
# correctly, since the resources must in the right relative locations. To avoid
|
||||||
|
# people trying to run the unbundled copy, put it in a subdirectory instead of
|
||||||
|
# the default top-level location.
|
||||||
|
set_target_properties(${BINARY_NAME}
|
||||||
|
PROPERTIES
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Generated plugin build rules, which manage building the plugins and adding
|
||||||
|
# them to the application.
|
||||||
|
include(flutter/generated_plugins.cmake)
|
||||||
|
|
||||||
|
|
||||||
|
# === Installation ===
|
||||||
|
# By default, "installing" just makes a relocatable bundle in the build
|
||||||
|
# directory.
|
||||||
|
set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle")
|
||||||
|
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Start with a clean build bundle directory every time.
|
||||||
|
install(CODE "
|
||||||
|
file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\")
|
||||||
|
" COMPONENT Runtime)
|
||||||
|
|
||||||
|
set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data")
|
||||||
|
set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||||
|
|
||||||
|
install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES})
|
||||||
|
install(FILES "${bundled_library}"
|
||||||
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
endforeach(bundled_library)
|
||||||
|
|
||||||
|
# Copy the native assets provided by the build.dart from all packages.
|
||||||
|
set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/")
|
||||||
|
install(DIRECTORY "${NATIVE_ASSETS_DIR}"
|
||||||
|
DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
|
||||||
|
# Fully re-copy the assets directory on each build to avoid having stale files
|
||||||
|
# from a previous install.
|
||||||
|
set(FLUTTER_ASSET_DIR_NAME "flutter_assets")
|
||||||
|
install(CODE "
|
||||||
|
file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\")
|
||||||
|
" COMPONENT Runtime)
|
||||||
|
install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}"
|
||||||
|
DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
|
# Install the AOT library on non-Debug builds only.
|
||||||
|
if(NOT CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
|
install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}"
|
||||||
|
COMPONENT Runtime)
|
||||||
|
endif()
|
||||||
88
linux/flutter/CMakeLists.txt
Normal file
88
linux/flutter/CMakeLists.txt
Normal file
@ -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}
|
||||||
|
)
|
||||||
27
linux/flutter/generated_plugin_registrant.cc
Normal file
27
linux/flutter/generated_plugin_registrant.cc
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <file_selector_linux/file_selector_plugin.h>
|
||||||
|
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||||
|
#include <gtk/gtk_plugin.h>
|
||||||
|
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||||
|
|
||||||
|
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||||
|
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||||
|
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||||
|
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) gtk_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "GtkPlugin");
|
||||||
|
gtk_plugin_register_with_registrar(gtk_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);
|
||||||
|
}
|
||||||
15
linux/flutter/generated_plugin_registrant.h
Normal file
15
linux/flutter/generated_plugin_registrant.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
#define GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
|
||||||
|
// Registers Flutter plugins.
|
||||||
|
void fl_register_plugins(FlPluginRegistry* registry);
|
||||||
|
|
||||||
|
#endif // GENERATED_PLUGIN_REGISTRANT_
|
||||||
27
linux/flutter/generated_plugins.cmake
Normal file
27
linux/flutter/generated_plugins.cmake
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
file_selector_linux
|
||||||
|
flutter_secure_storage_linux
|
||||||
|
gtk
|
||||||
|
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 $<TARGET_FILE:${plugin}_plugin>)
|
||||||
|
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)
|
||||||
26
linux/runner/CMakeLists.txt
Normal file
26
linux/runner/CMakeLists.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
project(runner LANGUAGES CXX)
|
||||||
|
|
||||||
|
# Define the application target. To change its name, change BINARY_NAME in the
|
||||||
|
# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
|
||||||
|
# work.
|
||||||
|
#
|
||||||
|
# Any new source files that you add to the application should be added here.
|
||||||
|
add_executable(${BINARY_NAME}
|
||||||
|
"main.cc"
|
||||||
|
"my_application.cc"
|
||||||
|
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply the standard set of build settings. This can be removed for applications
|
||||||
|
# that need different build settings.
|
||||||
|
apply_standard_settings(${BINARY_NAME})
|
||||||
|
|
||||||
|
# Add preprocessor definitions for the application ID.
|
||||||
|
add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}")
|
||||||
|
|
||||||
|
# Add dependency libraries. Add any application-specific dependencies here.
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE flutter)
|
||||||
|
target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK)
|
||||||
|
|
||||||
|
target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
|
||||||
6
linux/runner/main.cc
Normal file
6
linux/runner/main.cc
Normal file
@ -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);
|
||||||
|
}
|
||||||
144
linux/runner/my_application.cc
Normal file
144
linux/runner/my_application.cc
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#include "my_application.h"
|
||||||
|
|
||||||
|
#include <flutter_linux/flutter_linux.h>
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
#include <gdk/gdkx.h>
|
||||||
|
#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)
|
||||||
|
|
||||||
|
// Called when first Flutter frame received.
|
||||||
|
static void first_frame_cb(MyApplication* self, FlView *view)
|
||||||
|
{
|
||||||
|
gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, "uae_stat");
|
||||||
|
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, "uae_stat");
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_window_set_default_size(window, 1280, 720);
|
||||||
|
|
||||||
|
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);
|
||||||
|
GdkRGBA background_color;
|
||||||
|
// Background defaults to black, override it here if necessary, e.g. #00000000 for transparent.
|
||||||
|
gdk_rgba_parse(&background_color, "#000000");
|
||||||
|
fl_view_set_background_color(view, &background_color);
|
||||||
|
gtk_widget_show(GTK_WIDGET(view));
|
||||||
|
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view));
|
||||||
|
|
||||||
|
// Show the window when Flutter renders.
|
||||||
|
// Requires the view to be realized so we can start rendering.
|
||||||
|
g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), self);
|
||||||
|
gtk_widget_realize(GTK_WIDGET(view));
|
||||||
|
|
||||||
|
fl_register_plugins(FL_PLUGIN_REGISTRY(view));
|
||||||
|
|
||||||
|
gtk_widget_grab_focus(GTK_WIDGET(view));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements GApplication::local_command_line.
|
||||||
|
static gboolean my_application_local_command_line(GApplication* application, gchar*** arguments, int* exit_status) {
|
||||||
|
MyApplication* self = MY_APPLICATION(application);
|
||||||
|
// Strip out the first argument as it is the binary name.
|
||||||
|
self->dart_entrypoint_arguments = g_strdupv(*arguments + 1);
|
||||||
|
|
||||||
|
g_autoptr(GError) error = nullptr;
|
||||||
|
if (!g_application_register(application, nullptr, &error)) {
|
||||||
|
g_warning("Failed to register: %s", error->message);
|
||||||
|
*exit_status = 1;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_application_activate(application);
|
||||||
|
*exit_status = 0;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements GApplication::startup.
|
||||||
|
static void my_application_startup(GApplication* application) {
|
||||||
|
//MyApplication* self = MY_APPLICATION(object);
|
||||||
|
|
||||||
|
// Perform any actions required at application startup.
|
||||||
|
|
||||||
|
G_APPLICATION_CLASS(my_application_parent_class)->startup(application);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements GApplication::shutdown.
|
||||||
|
static void my_application_shutdown(GApplication* application) {
|
||||||
|
//MyApplication* self = MY_APPLICATION(object);
|
||||||
|
|
||||||
|
// Perform any actions required at application shutdown.
|
||||||
|
|
||||||
|
G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implements GObject::dispose.
|
||||||
|
static void my_application_dispose(GObject* object) {
|
||||||
|
MyApplication* self = MY_APPLICATION(object);
|
||||||
|
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
|
||||||
|
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_application_class_init(MyApplicationClass* klass) {
|
||||||
|
G_APPLICATION_CLASS(klass)->activate = my_application_activate;
|
||||||
|
G_APPLICATION_CLASS(klass)->local_command_line = my_application_local_command_line;
|
||||||
|
G_APPLICATION_CLASS(klass)->startup = my_application_startup;
|
||||||
|
G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown;
|
||||||
|
G_OBJECT_CLASS(klass)->dispose = my_application_dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void my_application_init(MyApplication* self) {}
|
||||||
|
|
||||||
|
MyApplication* my_application_new() {
|
||||||
|
// Set the program name to the application ID, which helps various systems
|
||||||
|
// like GTK and desktop environments map this running application to its
|
||||||
|
// corresponding .desktop file. This ensures better integration by allowing
|
||||||
|
// the application to be recognized beyond its binary name.
|
||||||
|
g_set_prgname(APPLICATION_ID);
|
||||||
|
|
||||||
|
return MY_APPLICATION(g_object_new(my_application_get_type(),
|
||||||
|
"application-id", APPLICATION_ID,
|
||||||
|
"flags", G_APPLICATION_NON_UNIQUE,
|
||||||
|
nullptr));
|
||||||
|
}
|
||||||
18
linux/runner/my_application.h
Normal file
18
linux/runner/my_application.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef FLUTTER_MY_APPLICATION_H_
|
||||||
|
#define FLUTTER_MY_APPLICATION_H_
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
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_
|
||||||
@ -20,7 +20,6 @@ import share_plus
|
|||||||
import shared_preferences_foundation
|
import shared_preferences_foundation
|
||||||
import url_launcher_macos
|
import url_launcher_macos
|
||||||
import video_player_avfoundation
|
import video_player_avfoundation
|
||||||
import webview_flutter_wkwebview
|
|
||||||
|
|
||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
|
AppLinksMacosPlugin.register(with: registry.registrar(forPlugin: "AppLinksMacosPlugin"))
|
||||||
@ -38,5 +37,4 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||||
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
|
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
|
||||||
WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin"))
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1510"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||||
|
BuildableName = "uae_stat.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||||
|
BuildableName = "uae_stat.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO"
|
||||||
|
parallelizable = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "331C80D4294CF70F00263BE5"
|
||||||
|
BuildableName = "RunnerTests.xctest"
|
||||||
|
BlueprintName = "RunnerTests"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
enableGPUValidationMode = "1"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||||
|
BuildableName = "uae_stat.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Profile"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "33CC10EC2044A3C60003C045"
|
||||||
|
BuildableName = "uae_stat.app"
|
||||||
|
BlueprintName = "Runner"
|
||||||
|
ReferencedContainer = "container:Runner.xcodeproj">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
||||||
7
macos/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
7
macos/Runner.xcworkspace/contents.xcworkspacedata
generated
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Workspace
|
||||||
|
version = "1.0">
|
||||||
|
<FileRef
|
||||||
|
location = "group:Runner.xcodeproj">
|
||||||
|
</FileRef>
|
||||||
|
</Workspace>
|
||||||
12
macos/Runner/DebugProfile.entitlements
Normal file
12
macos/Runner/DebugProfile.entitlements
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.network.server</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
8
macos/Runner/Release.entitlements
Normal file
8
macos/Runner/Release.entitlements
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>com.apple.security.app-sandbox</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
452
pubspec.lock
452
pubspec.lock
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
|||||||
name: uae_stat
|
name: uae_stat
|
||||||
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
|
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 1.1.0+7
|
version: 1.2.6+14
|
||||||
#version: 1.0.16+17
|
#version: 1.0.16+17
|
||||||
#version: 1.0.6+6
|
#version: 1.0.6+6
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ dependencies:
|
|||||||
flutter_secure_storage: ^10.0.0-beta.4
|
flutter_secure_storage: ^10.0.0-beta.4
|
||||||
jwt_decoder: ^2.0.1
|
jwt_decoder: ^2.0.1
|
||||||
fluttertoast: ^8.2.11
|
fluttertoast: ^8.2.11
|
||||||
webview_flutter: ^4.13.0
|
# webview_flutter: ^4.13.0
|
||||||
video_player: ^2.8.5
|
video_player: ^2.8.5
|
||||||
flutter_carousel_widget: ^3.1.0
|
flutter_carousel_widget: ^3.1.0
|
||||||
share_plus: ^10.1.1
|
share_plus: ^10.1.1
|
||||||
@ -81,6 +81,7 @@ dependencies:
|
|||||||
google_sign_in: ^7.1.1
|
google_sign_in: ^7.1.1
|
||||||
# flutter_web_auth_2: ^4.1.0
|
# flutter_web_auth_2: ^4.1.0
|
||||||
flutter_uae_pass: ^1.1.0
|
flutter_uae_pass: ^1.1.0
|
||||||
|
# flutter_inappwebview: ^6.1.5
|
||||||
# webview_flutter_wkwebview: ^3.23.1
|
# webview_flutter_wkwebview: ^3.23.1
|
||||||
# flutter_appauth: ^10.0.0
|
# flutter_appauth: ^10.0.0
|
||||||
|
|
||||||
|
|||||||
17
windows/.gitignore
vendored
Normal file
17
windows/.gitignore
vendored
Normal file
@ -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/
|
||||||
108
windows/CMakeLists.txt
Normal file
108
windows/CMakeLists.txt
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# Project-level configuration.
|
||||||
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
project(uae_stat 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 "uae_stat")
|
||||||
|
|
||||||
|
# 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 "$<$<CONFIG:Debug>:_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 "$<TARGET_FILE_DIR:${BINARY_NAME}>")
|
||||||
|
# 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)
|
||||||
109
windows/flutter/CMakeLists.txt
Normal file
109
windows/flutter/CMakeLists.txt
Normal file
@ -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} $<CONFIG>
|
||||||
|
VERBATIM
|
||||||
|
)
|
||||||
|
add_custom_target(flutter_assemble DEPENDS
|
||||||
|
"${FLUTTER_LIBRARY}"
|
||||||
|
${FLUTTER_LIBRARY_HEADERS}
|
||||||
|
${CPP_WRAPPER_SOURCES_CORE}
|
||||||
|
${CPP_WRAPPER_SOURCES_PLUGIN}
|
||||||
|
${CPP_WRAPPER_SOURCES_APP}
|
||||||
|
)
|
||||||
32
windows/flutter/generated_plugin_registrant.cc
Normal file
32
windows/flutter/generated_plugin_registrant.cc
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
|
#include <app_links/app_links_plugin_c_api.h>
|
||||||
|
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||||
|
#include <file_selector_windows/file_selector_windows.h>
|
||||||
|
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||||
|
#include <flutter_secure_storage_windows/flutter_secure_storage_windows_plugin.h>
|
||||||
|
#include <share_plus/share_plus_windows_plugin_c_api.h>
|
||||||
|
#include <url_launcher_windows/url_launcher_windows.h>
|
||||||
|
|
||||||
|
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||||
|
AppLinksPluginCApiRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("AppLinksPluginCApi"));
|
||||||
|
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
||||||
|
FileSelectorWindowsRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||||
|
FirebaseCorePluginCApiRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FirebaseCorePluginCApi"));
|
||||||
|
FlutterSecureStorageWindowsPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin"));
|
||||||
|
SharePlusWindowsPluginCApiRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("SharePlusWindowsPluginCApi"));
|
||||||
|
UrlLauncherWindowsRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("UrlLauncherWindows"));
|
||||||
|
}
|
||||||
15
windows/flutter/generated_plugin_registrant.h
Normal file
15
windows/flutter/generated_plugin_registrant.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Generated file. Do not edit.
|
||||||
|
//
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#ifndef GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
#define GENERATED_PLUGIN_REGISTRANT_
|
||||||
|
|
||||||
|
#include <flutter/plugin_registry.h>
|
||||||
|
|
||||||
|
// Registers Flutter plugins.
|
||||||
|
void RegisterPlugins(flutter::PluginRegistry* registry);
|
||||||
|
|
||||||
|
#endif // GENERATED_PLUGIN_REGISTRANT_
|
||||||
30
windows/flutter/generated_plugins.cmake
Normal file
30
windows/flutter/generated_plugins.cmake
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#
|
||||||
|
# Generated file, do not edit.
|
||||||
|
#
|
||||||
|
|
||||||
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
|
app_links
|
||||||
|
connectivity_plus
|
||||||
|
file_selector_windows
|
||||||
|
firebase_core
|
||||||
|
flutter_secure_storage_windows
|
||||||
|
share_plus
|
||||||
|
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 $<TARGET_FILE:${plugin}_plugin>)
|
||||||
|
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)
|
||||||
40
windows/runner/CMakeLists.txt
Normal file
40
windows/runner/CMakeLists.txt
Normal file
@ -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)
|
||||||
121
windows/runner/Runner.rc
Normal file
121
windows/runner/Runner.rc
Normal file
@ -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", "ae.gov.fcsc" "\0"
|
||||||
|
VALUE "FileDescription", "uae_stat" "\0"
|
||||||
|
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||||
|
VALUE "InternalName", "uae_stat" "\0"
|
||||||
|
VALUE "LegalCopyright", "Copyright (C) 2025 ae.gov.fcsc. All rights reserved." "\0"
|
||||||
|
VALUE "OriginalFilename", "uae_stat.exe" "\0"
|
||||||
|
VALUE "ProductName", "uae_stat" "\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
|
||||||
71
windows/runner/flutter_window.cpp
Normal file
71
windows/runner/flutter_window.cpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "flutter_window.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#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<flutter::FlutterViewController>(
|
||||||
|
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<LRESULT> 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);
|
||||||
|
}
|
||||||
33
windows/runner/flutter_window.h
Normal file
33
windows/runner/flutter_window.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef RUNNER_FLUTTER_WINDOW_H_
|
||||||
|
#define RUNNER_FLUTTER_WINDOW_H_
|
||||||
|
|
||||||
|
#include <flutter/dart_project.h>
|
||||||
|
#include <flutter/flutter_view_controller.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#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::FlutterViewController> flutter_controller_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // RUNNER_FLUTTER_WINDOW_H_
|
||||||
43
windows/runner/main.cpp
Normal file
43
windows/runner/main.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#include <flutter/dart_project.h>
|
||||||
|
#include <flutter/flutter_view_controller.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#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<std::string> 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"uae_stat", origin, size)) {
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
window.SetQuitOnClose(true);
|
||||||
|
|
||||||
|
::MSG msg;
|
||||||
|
while (::GetMessage(&msg, nullptr, 0, 0)) {
|
||||||
|
::TranslateMessage(&msg);
|
||||||
|
::DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
::CoUninitialize();
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
16
windows/runner/resource.h
Normal file
16
windows/runner/resource.h
Normal file
@ -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
|
||||||
BIN
windows/runner/resources/app_icon.ico
Normal file
BIN
windows/runner/resources/app_icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
14
windows/runner/runner.exe.manifest
Normal file
14
windows/runner/runner.exe.manifest
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||||
|
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||||
|
<windowsSettings>
|
||||||
|
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||||
|
</windowsSettings>
|
||||||
|
</application>
|
||||||
|
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
|
||||||
|
<application>
|
||||||
|
<!-- Windows 10 and Windows 11 -->
|
||||||
|
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
|
||||||
|
</application>
|
||||||
|
</compatibility>
|
||||||
|
</assembly>
|
||||||
65
windows/runner/utils.cpp
Normal file
65
windows/runner/utils.cpp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#include <flutter_windows.h>
|
||||||
|
#include <io.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
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<std::string> 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::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> command_line_arguments;
|
||||||
|
|
||||||
|
// Skip the first argument as it's the binary name.
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
::LocalFree(argv);
|
||||||
|
|
||||||
|
return command_line_arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Utf8FromUtf16(const wchar_t* utf16_string) {
|
||||||
|
if (utf16_string == nullptr) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
unsigned int target_length = ::WideCharToMultiByte(
|
||||||
|
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||||
|
-1, nullptr, 0, nullptr, nullptr)
|
||||||
|
-1; // remove the trailing null character
|
||||||
|
int input_length = (int)wcslen(utf16_string);
|
||||||
|
std::string utf8_string;
|
||||||
|
if (target_length == 0 || target_length > utf8_string.max_size()) {
|
||||||
|
return utf8_string;
|
||||||
|
}
|
||||||
|
utf8_string.resize(target_length);
|
||||||
|
int converted_length = ::WideCharToMultiByte(
|
||||||
|
CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
|
||||||
|
input_length, utf8_string.data(), target_length, nullptr, nullptr);
|
||||||
|
if (converted_length == 0) {
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
return utf8_string;
|
||||||
|
}
|
||||||
19
windows/runner/utils.h
Normal file
19
windows/runner/utils.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef RUNNER_UTILS_H_
|
||||||
|
#define RUNNER_UTILS_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
// 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<std::string>,
|
||||||
|
// encoded in UTF-8. Returns an empty std::vector<std::string> on failure.
|
||||||
|
std::vector<std::string> GetCommandLineArguments();
|
||||||
|
|
||||||
|
#endif // RUNNER_UTILS_H_
|
||||||
288
windows/runner/win32_window.cpp
Normal file
288
windows/runner/win32_window.cpp
Normal file
@ -0,0 +1,288 @@
|
|||||||
|
#include "win32_window.h"
|
||||||
|
|
||||||
|
#include <dwmapi.h>
|
||||||
|
#include <flutter_windows.h>
|
||||||
|
|
||||||
|
#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<int>(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<EnableNonClientDpiScaling*>(
|
||||||
|
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<LONG>(origin.x),
|
||||||
|
static_cast<LONG>(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<CREATESTRUCT*>(lparam);
|
||||||
|
SetWindowLongPtr(window, GWLP_USERDATA,
|
||||||
|
reinterpret_cast<LONG_PTR>(window_struct->lpCreateParams));
|
||||||
|
|
||||||
|
auto that = static_cast<Win32Window*>(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<RECT*>(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<Win32Window*>(
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
102
windows/runner/win32_window.h
Normal file
102
windows/runner/win32_window.h
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
#ifndef RUNNER_WIN32_WINDOW_H_
|
||||||
|
#define RUNNER_WIN32_WINDOW_H_
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// 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_
|
||||||
Loading…
Reference in New Issue
Block a user